diff --git a/core/api/system-current.txt b/core/api/system-current.txt index cbda97e76c9e3..b4cc89e08c839 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -3183,6 +3183,7 @@ package android.hardware.location { public class ContextHubClientCallback { ctor public ContextHubClientCallback(); + method public void onClientAuthorizationChanged(@NonNull android.hardware.location.ContextHubClient, long, int); method public void onHubReset(android.hardware.location.ContextHubClient); method public void onMessageFromNanoApp(android.hardware.location.ContextHubClient, android.hardware.location.NanoAppMessage); method public void onNanoAppAborted(android.hardware.location.ContextHubClient, long, int); @@ -3219,6 +3220,7 @@ package android.hardware.location { public class ContextHubIntentEvent { method @NonNull public static android.hardware.location.ContextHubIntentEvent fromIntent(@NonNull android.content.Intent); + method public int getClientAuthorizationState(); method @NonNull public android.hardware.location.ContextHubInfo getContextHubInfo(); method public int getEventType(); method public int getNanoAppAbortCode(); @@ -3227,8 +3229,10 @@ package android.hardware.location { } public final class ContextHubManager { + method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.ACCESS_CONTEXT_HUB}) public android.hardware.location.ContextHubClient createClient(@Nullable android.content.Context, @NonNull android.hardware.location.ContextHubInfo, @NonNull java.util.concurrent.Executor, @NonNull android.hardware.location.ContextHubClientCallback); method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.ACCESS_CONTEXT_HUB}) public android.hardware.location.ContextHubClient createClient(@NonNull android.hardware.location.ContextHubInfo, @NonNull android.hardware.location.ContextHubClientCallback, @NonNull java.util.concurrent.Executor); method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.ACCESS_CONTEXT_HUB}) public android.hardware.location.ContextHubClient createClient(@NonNull android.hardware.location.ContextHubInfo, @NonNull android.hardware.location.ContextHubClientCallback); + method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.ACCESS_CONTEXT_HUB}) public android.hardware.location.ContextHubClient createClient(@Nullable android.content.Context, @NonNull android.hardware.location.ContextHubInfo, @NonNull android.app.PendingIntent, long); method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.ACCESS_CONTEXT_HUB}) public android.hardware.location.ContextHubClient createClient(@NonNull android.hardware.location.ContextHubInfo, @NonNull android.app.PendingIntent, long); method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.ACCESS_CONTEXT_HUB}) public android.hardware.location.ContextHubTransaction disableNanoApp(@NonNull android.hardware.location.ContextHubInfo, long); method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.ACCESS_CONTEXT_HUB}) public android.hardware.location.ContextHubTransaction enableNanoApp(@NonNull android.hardware.location.ContextHubInfo, long); @@ -3246,6 +3250,10 @@ package android.hardware.location { method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.ACCESS_CONTEXT_HUB}) public int unloadNanoApp(int); method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.ACCESS_CONTEXT_HUB}) public android.hardware.location.ContextHubTransaction unloadNanoApp(@NonNull android.hardware.location.ContextHubInfo, long); method @Deprecated public int unregisterCallback(@NonNull android.hardware.location.ContextHubManager.Callback); + field public static final int AUTHORIZATION_DENIED = 0; // 0x0 + field public static final int AUTHORIZATION_DENIED_GRACE_PERIOD = 1; // 0x1 + field public static final int AUTHORIZATION_GRANTED = 2; // 0x2 + field public static final int EVENT_CLIENT_AUTHORIZATION = 7; // 0x7 field public static final int EVENT_HUB_RESET = 6; // 0x6 field public static final int EVENT_NANOAPP_ABORTED = 4; // 0x4 field public static final int EVENT_NANOAPP_DISABLED = 3; // 0x3 @@ -3253,6 +3261,7 @@ package android.hardware.location { field public static final int EVENT_NANOAPP_LOADED = 0; // 0x0 field public static final int EVENT_NANOAPP_MESSAGE = 5; // 0x5 field public static final int EVENT_NANOAPP_UNLOADED = 1; // 0x1 + field public static final String EXTRA_CLIENT_AUTHORIZATION_STATE = "android.hardware.location.extra.CLIENT_AUTHORIZATION_STATE"; field public static final String EXTRA_CONTEXT_HUB_INFO = "android.hardware.location.extra.CONTEXT_HUB_INFO"; field public static final String EXTRA_EVENT_TYPE = "android.hardware.location.extra.EVENT_TYPE"; field public static final String EXTRA_MESSAGE = "android.hardware.location.extra.MESSAGE"; @@ -3491,8 +3500,10 @@ package android.hardware.location { public final class NanoAppState implements android.os.Parcelable { ctor public NanoAppState(long, int, boolean); + ctor public NanoAppState(long, int, boolean, @NonNull java.util.List); method public int describeContents(); method public long getNanoAppId(); + method @NonNull public java.util.List getNanoAppPermissions(); method public long getNanoAppVersion(); method public boolean isEnabled(); method public void writeToParcel(android.os.Parcel, int); diff --git a/core/java/android/hardware/location/ContextHubClientCallback.java b/core/java/android/hardware/location/ContextHubClientCallback.java index 20fa7538e2d5f..b31b85fdabf67 100644 --- a/core/java/android/hardware/location/ContextHubClientCallback.java +++ b/core/java/android/hardware/location/ContextHubClientCallback.java @@ -15,6 +15,7 @@ */ package android.hardware.location; +import android.annotation.NonNull; import android.annotation.SystemApi; import java.util.concurrent.Executor; @@ -101,4 +102,34 @@ public class ContextHubClientCallback { * @param nanoAppId the ID of the nanoapp that had been disabled */ public void onNanoAppDisabled(ContextHubClient client, long nanoAppId) {} + + /** + * Callback invoked when a {@link ContextHubClient}'s authorization to communicate with a + * nanoapp changes. This typically happens as a result of the app that created the + * {@link ContextHubClient} gaining or losing the permissions required to communicate with a + * nanoapp. + * + * An example of the connection callbacks looks like: + * 1) {@link ContextHubClient} sends message to nanoapp and holds required permissions + * 2) {@link ContextHubClient} loses required permissions + * 3) Callback invoked with the nanoapp ID and + * {@link ContextHubManager#AUTHORIZATION_DENIED_GRACE_PERIOD} + * 4) {@link ContextHubClient} performs any cleanup required with the nanoapp + * 5) Callback invoked with the nanoapp ID and {@link ContextHubManager#AUTHORIZATION_DENIED}. + * At this point, any further attempts of communication between the nanoapp and the + * {@link ContextHubClient} will be dropped by the contexthub along with + * {@link ContextHubManager#AUTHORIZATION_DENIED} being sent. The {@link ContextHubClient} + * should assume no communciation can happen again until + * {@link ContextHubManager#AUTHORIZATION_GRANTED} is received. + * + * @param client the client that is associated with this callback + * @param nanoAppId the ID of the nanoapp associated with the new + * authorization state + * @param authorization the authorization state denoting the ability of the + * client to communicate with the nanoapp + */ + public void onClientAuthorizationChanged( + @NonNull ContextHubClient client, + long nanoAppId, + @ContextHubManager.AuthorizationState int authorization) {} } diff --git a/core/java/android/hardware/location/ContextHubIntentEvent.java b/core/java/android/hardware/location/ContextHubIntentEvent.java index 917f62bc6cbf5..3e8f4219a485c 100644 --- a/core/java/android/hardware/location/ContextHubIntentEvent.java +++ b/core/java/android/hardware/location/ContextHubIntentEvent.java @@ -43,39 +43,45 @@ public class ContextHubIntentEvent { private final int mNanoAppAbortCode; + private final int mClientAuthorizationState; + private ContextHubIntentEvent( @NonNull ContextHubInfo contextHubInfo, @ContextHubManager.Event int eventType, - long nanoAppId, NanoAppMessage nanoAppMessage, int nanoAppAbortCode) { + long nanoAppId, NanoAppMessage nanoAppMessage, int nanoAppAbortCode, + @ContextHubManager.AuthorizationState int clientAuthorizationState) { mContextHubInfo = contextHubInfo; mEventType = eventType; mNanoAppId = nanoAppId; mNanoAppMessage = nanoAppMessage; mNanoAppAbortCode = nanoAppAbortCode; + mClientAuthorizationState = clientAuthorizationState; } private ContextHubIntentEvent( @NonNull ContextHubInfo contextHubInfo, @ContextHubManager.Event int eventType) { this(contextHubInfo, eventType, -1 /* nanoAppId */, null /* nanoAppMessage */, - -1 /* nanoAppAbortCode */); + -1 /* nanoAppAbortCode */, 0 /* clientAuthorizationState */); } private ContextHubIntentEvent( @NonNull ContextHubInfo contextHubInfo, @ContextHubManager.Event int eventType, long nanoAppId) { this(contextHubInfo, eventType, nanoAppId, null /* nanoAppMessage */, - -1 /* nanoAppAbortCode */); + -1 /* nanoAppAbortCode */, 0 /* clientAuthorizationState */); } private ContextHubIntentEvent( @NonNull ContextHubInfo contextHubInfo, @ContextHubManager.Event int eventType, long nanoAppId, @NonNull NanoAppMessage nanoAppMessage) { - this(contextHubInfo, eventType, nanoAppId, nanoAppMessage, -1 /* nanoAppAbortCode */); + this(contextHubInfo, eventType, nanoAppId, nanoAppMessage, -1 /* nanoAppAbortCode */, + 0 /* clientAuthorizationState */); } private ContextHubIntentEvent( @NonNull ContextHubInfo contextHubInfo, @ContextHubManager.Event int eventType, long nanoAppId, int nanoAppAbortCode) { - this(contextHubInfo, eventType, nanoAppId, null /* nanoAppMessage */, nanoAppAbortCode); + this(contextHubInfo, eventType, nanoAppId, null /* nanoAppMessage */, nanoAppAbortCode, + 0 /* clientAuthorizationState */); } /** @@ -105,7 +111,8 @@ public class ContextHubIntentEvent { case ContextHubManager.EVENT_NANOAPP_ENABLED: case ContextHubManager.EVENT_NANOAPP_DISABLED: case ContextHubManager.EVENT_NANOAPP_ABORTED: - case ContextHubManager.EVENT_NANOAPP_MESSAGE: // fall through + case ContextHubManager.EVENT_NANOAPP_MESSAGE: + case ContextHubManager.EVENT_CLIENT_AUTHORIZATION: // fall through long nanoAppId = getLongExtraOrThrow(intent, ContextHubManager.EXTRA_NANOAPP_ID); if (eventType == ContextHubManager.EVENT_NANOAPP_MESSAGE) { hasExtraOrThrow(intent, ContextHubManager.EXTRA_MESSAGE); @@ -120,6 +127,11 @@ public class ContextHubIntentEvent { int nanoAppAbortCode = getIntExtraOrThrow( intent, ContextHubManager.EXTRA_NANOAPP_ABORT_CODE); event = new ContextHubIntentEvent(info, eventType, nanoAppId, nanoAppAbortCode); + } else if (eventType == ContextHubManager.EVENT_CLIENT_AUTHORIZATION) { + int authState = getIntExtraOrThrow( + intent, ContextHubManager.EXTRA_CLIENT_AUTHORIZATION_STATE); + event = new ContextHubIntentEvent(info, eventType, nanoAppId, + null /* nanoAppMessage */, -1 /* nanoAppAbortCode */, authState); } else { event = new ContextHubIntentEvent(info, eventType, nanoAppId); } @@ -192,6 +204,21 @@ public class ContextHubIntentEvent { return mNanoAppMessage; } + /** + * @return the client authorization state + * + * @throws UnsupportedOperationException if this was not a client authorization state event + */ + @ContextHubManager.AuthorizationState + public int getClientAuthorizationState() { + if (mEventType != ContextHubManager.EVENT_CLIENT_AUTHORIZATION) { + throw new UnsupportedOperationException( + "Cannot invoke getClientAuthorizationState() on non-authorization event: " + + mEventType); + } + return mClientAuthorizationState; + } + @NonNull @Override public String toString() { @@ -207,6 +234,9 @@ public class ContextHubIntentEvent { if (mEventType == ContextHubManager.EVENT_NANOAPP_MESSAGE) { out += ", nanoAppMessage = " + mNanoAppMessage; } + if (mEventType == ContextHubManager.EVENT_CLIENT_AUTHORIZATION) { + out += ", clientAuthState = " + mClientAuthorizationState; + } return out + "]"; } @@ -233,6 +263,9 @@ public class ContextHubIntentEvent { if (mEventType == ContextHubManager.EVENT_NANOAPP_MESSAGE) { isEqual &= other.getNanoAppMessage().equals(mNanoAppMessage); } + if (mEventType == ContextHubManager.EVENT_CLIENT_AUTHORIZATION) { + isEqual &= other.getClientAuthorizationState() == mClientAuthorizationState; + } } catch (UnsupportedOperationException e) { isEqual = false; } diff --git a/core/java/android/hardware/location/ContextHubManager.java b/core/java/android/hardware/location/ContextHubManager.java index d44480796d756..ebb3021bf083d 100644 --- a/core/java/android/hardware/location/ContextHubManager.java +++ b/core/java/android/hardware/location/ContextHubManager.java @@ -58,6 +58,12 @@ import java.util.concurrent.Executor; public final class ContextHubManager { private static final String TAG = "ContextHubManager"; + /** + * An extra of type int describing the client's authorization state. + */ + public static final String EXTRA_CLIENT_AUTHORIZATION_STATE = + "android.hardware.location.extra.CLIENT_AUTHORIZATION_STATE"; + /** * An extra of type {@link ContextHubInfo} describing the source of the event. */ @@ -85,6 +91,42 @@ public final class ContextHubManager { */ public static final String EXTRA_MESSAGE = "android.hardware.location.extra.MESSAGE"; + /** + * Constants describing if a {@link ContextHubClient} and a {@link NanoApp} are authorized to + * communicate. + * + * @hide + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = { "AUTHORIZATION_" }, value = { + AUTHORIZATION_DENIED, + AUTHORIZATION_DENIED_GRACE_PERIOD, + AUTHORIZATION_GRANTED, + }) + public @interface AuthorizationState { } + + /** + * Indicates that the {@link ContextHubClient} can no longer communicate with a nanoapp. If the + * {@link ContextHubClient} attempts to send messages to the nanoapp, it will continue to + * receive this authorization state if the connection is still closed. + */ + public static final int AUTHORIZATION_DENIED = 0; + + /** + * Indicates the {@link ContextHubClient} will soon lose its authorization to communicate with a + * nanoapp. The {@link ContextHubClient} must perform any cleanup with the nanoapp as soon as + * possible. + * + * Note that the time between this state event and {@link AUTHORIZATION_DENIED} must be enough + * for the {@link ContextHubClient} to send at least one message to the nanoapp. + */ + public static final int AUTHORIZATION_DENIED_GRACE_PERIOD = 1; + + /** + * The {@link ContextHubClient} is authorized to communicate with the nanoapp. + */ + public static final int AUTHORIZATION_GRANTED = 2; + /** * Constants describing the type of events from a Context Hub. * {@hide} @@ -98,6 +140,7 @@ public final class ContextHubManager { EVENT_NANOAPP_ABORTED, EVENT_NANOAPP_MESSAGE, EVENT_HUB_RESET, + EVENT_CLIENT_AUTHORIZATION, }) public @interface Event { } @@ -138,6 +181,14 @@ public final class ContextHubManager { */ public static final int EVENT_HUB_RESET = 6; + /** + * An event describing a client authorization state change. See + * {@link ContextHubClientCallback#onClientAuthorizationChanged} for more details on when this + * event will be sent. Contains the EXTRA_NANOAPP_ID and EXTRA_CLIENT_AUTHORIZATION_STATE + * extras. + */ + public static final int EVENT_CLIENT_AUTHORIZATION = 7; + private final Looper mMainLooper; private final IContextHubService mService; private Callback mCallback; @@ -747,6 +798,14 @@ public final class ContextHubManager { public void onNanoAppDisabled(long nanoAppId) { executor.execute(() -> callback.onNanoAppDisabled(client, nanoAppId)); } + + @Override + public void onClientAuthorizationChanged( + long nanoAppId, @ContextHubManager.AuthorizationState int authorization) { + executor.execute( + () -> callback.onClientAuthorizationChanged( + client, nanoAppId, authorization)); + } }; } @@ -757,9 +816,10 @@ public final class ContextHubManager { * registration succeeds, the client can send messages to nanoapps through the returned * {@link ContextHubClient} object, and receive notifications through the provided callback. * + * @param context the context of the application * @param hubInfo the hub to attach this client to - * @param callback the notification callback to register * @param executor the executor to invoke the callback + * @param callback the notification callback to register * @return the registered client object * * @throws IllegalArgumentException if hubInfo does not represent a valid hub @@ -773,8 +833,9 @@ public final class ContextHubManager { android.Manifest.permission.ACCESS_CONTEXT_HUB }) @NonNull public ContextHubClient createClient( - @NonNull ContextHubInfo hubInfo, @NonNull ContextHubClientCallback callback, - @NonNull @CallbackExecutor Executor executor) { + @Nullable Context context, @NonNull ContextHubInfo hubInfo, + @NonNull @CallbackExecutor Executor executor, + @NonNull ContextHubClientCallback callback) { Objects.requireNonNull(callback, "Callback cannot be null"); Objects.requireNonNull(hubInfo, "ContextHubInfo cannot be null"); Objects.requireNonNull(executor, "Executor cannot be null"); @@ -783,9 +844,14 @@ public final class ContextHubManager { IContextHubClientCallback clientInterface = createClientCallback( client, callback, executor); + String attributionTag = null; + if (context != null) { + attributionTag = context.getAttributionTag(); + } + IContextHubClient clientProxy; try { - clientProxy = mService.createClient(hubInfo.getId(), clientInterface); + clientProxy = mService.createClient(hubInfo.getId(), clientInterface, attributionTag); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -794,19 +860,25 @@ public final class ContextHubManager { return client; } + + /** + * Equivalent to + * {@link #createClient(ContextHubInfo, Executor, String, ContextHubClientCallback)} + * with the {@link Context} being set to null. + */ + @RequiresPermission(anyOf = { + android.Manifest.permission.LOCATION_HARDWARE, + android.Manifest.permission.ACCESS_CONTEXT_HUB + }) + @NonNull public ContextHubClient createClient( + @NonNull ContextHubInfo hubInfo, @NonNull ContextHubClientCallback callback, + @NonNull @CallbackExecutor Executor executor) { + return createClient(null /* context */, hubInfo, executor, callback); + } + /** * Equivalent to {@link #createClient(ContextHubInfo, ContextHubClientCallback, Executor)} * with the executor using the main thread's Looper. - * - * @param hubInfo the hub to attach this client to - * @param callback the notification callback to register - * @return the registered client object - * - * @throws IllegalArgumentException if hubInfo does not represent a valid hub - * @throws IllegalStateException if there were too many registered clients at the service - * @throws NullPointerException if callback or hubInfo is null - * - * @see ContextHubClientCallback */ @RequiresPermission(anyOf = { android.Manifest.permission.LOCATION_HARDWARE, @@ -814,7 +886,8 @@ public final class ContextHubManager { }) @NonNull public ContextHubClient createClient( @NonNull ContextHubInfo hubInfo, @NonNull ContextHubClientCallback callback) { - return createClient(hubInfo, callback, new HandlerExecutor(Handler.getMain())); + return createClient(null /* context */, hubInfo, new HandlerExecutor(Handler.getMain()), + callback); } /** @@ -848,6 +921,8 @@ public final class ContextHubManager { * on the provided PendingIntent, then the client will be automatically unregistered by the * service. * + * @param context the context of the application. If a PendingIntent client is recreated, + * the latest state in the context will be used and old state will be discarded * @param hubInfo the hub to attach this client to * @param pendingIntent the PendingIntent to register to the client * @param nanoAppId the ID of the nanoapp that Intent events will be generated for @@ -862,16 +937,22 @@ public final class ContextHubManager { android.Manifest.permission.ACCESS_CONTEXT_HUB }) @NonNull public ContextHubClient createClient( - @NonNull ContextHubInfo hubInfo, @NonNull PendingIntent pendingIntent, long nanoAppId) { + @Nullable Context context, @NonNull ContextHubInfo hubInfo, + @NonNull PendingIntent pendingIntent, long nanoAppId) { Objects.requireNonNull(pendingIntent); Objects.requireNonNull(hubInfo); ContextHubClient client = new ContextHubClient(hubInfo, true /* persistent */); + String attributionTag = null; + if (context != null) { + attributionTag = context.getAttributionTag(); + } + IContextHubClient clientProxy; try { clientProxy = mService.createPendingIntentClient( - hubInfo.getId(), pendingIntent, nanoAppId); + hubInfo.getId(), pendingIntent, nanoAppId, attributionTag); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -880,6 +961,19 @@ public final class ContextHubManager { return client; } + /** + * Equivalent to {@link #createClient(ContextHubInfo, PendingIntent, long, String)} + * with {@link Context} being set to null. + */ + @RequiresPermission(anyOf = { + android.Manifest.permission.LOCATION_HARDWARE, + android.Manifest.permission.ACCESS_CONTEXT_HUB + }) + @NonNull public ContextHubClient createClient( + @NonNull ContextHubInfo hubInfo, @NonNull PendingIntent pendingIntent, long nanoAppId) { + return createClient(null /* context */, hubInfo, pendingIntent, nanoAppId); + } + /** * Unregister a callback for receive messages from the context hub. * diff --git a/core/java/android/hardware/location/IContextHubClientCallback.aidl b/core/java/android/hardware/location/IContextHubClientCallback.aidl index 1c76bcbe18ce4..bcd6b087a276a 100644 --- a/core/java/android/hardware/location/IContextHubClientCallback.aidl +++ b/core/java/android/hardware/location/IContextHubClientCallback.aidl @@ -46,4 +46,7 @@ oneway interface IContextHubClientCallback { // Callback invoked when a nanoapp is disabled at the attached Context Hub. void onNanoAppDisabled(long nanoAppId); + + // Callback invoked when the authorization state of a client changes. + void onClientAuthorizationChanged(long nanoAppId, int authorization); } diff --git a/core/java/android/hardware/location/IContextHubService.aidl b/core/java/android/hardware/location/IContextHubService.aidl index 04cc5634bf2cf..4961195a3017a 100644 --- a/core/java/android/hardware/location/IContextHubService.aidl +++ b/core/java/android/hardware/location/IContextHubService.aidl @@ -59,11 +59,13 @@ interface IContextHubService { int sendMessage(int contextHubHandle, int nanoAppHandle, in ContextHubMessage msg); // Creates a client to send and receive messages - IContextHubClient createClient(int contextHubId, in IContextHubClientCallback client); + IContextHubClient createClient( + int contextHubId, in IContextHubClientCallback client, in String attributionTag); // Creates a PendingIntent-based client to send and receive messages IContextHubClient createPendingIntentClient( - int contextHubId, in PendingIntent pendingIntent, long nanoAppId); + int contextHubId, in PendingIntent pendingIntent, long nanoAppId, + in String attributionTag); // Returns a list of ContextHub objects of available hubs List getContextHubs(); diff --git a/core/java/android/hardware/location/NanoAppState.java b/core/java/android/hardware/location/NanoAppState.java index 8de7ecd6b2b31..96b1f19a9cd57 100644 --- a/core/java/android/hardware/location/NanoAppState.java +++ b/core/java/android/hardware/location/NanoAppState.java @@ -15,10 +15,14 @@ */ package android.hardware.location; +import android.annotation.NonNull; import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; +import java.util.ArrayList; +import java.util.List; + /** * A class describing the nanoapp state information resulting from a query to a Context Hub. * @@ -29,11 +33,21 @@ public final class NanoAppState implements Parcelable { private long mNanoAppId; private int mNanoAppVersion; private boolean mIsEnabled; + private List mNanoAppPermissions; public NanoAppState(long nanoAppId, int appVersion, boolean enabled) { mNanoAppId = nanoAppId; mNanoAppVersion = appVersion; mIsEnabled = enabled; + mNanoAppPermissions = new ArrayList(); + } + + public NanoAppState(long nanoAppId, int appVersion, boolean enabled, + @NonNull List nanoAppPermissions) { + mNanoAppId = nanoAppId; + mNanoAppVersion = appVersion; + mIsEnabled = enabled; + mNanoAppPermissions = nanoAppPermissions; } /** @@ -57,10 +71,19 @@ public final class NanoAppState implements Parcelable { return mIsEnabled; } + /** + * @return List of Android permissions that are required to communicate with this app. + */ + public @NonNull List getNanoAppPermissions() { + return mNanoAppPermissions; + } + private NanoAppState(Parcel in) { mNanoAppId = in.readLong(); mNanoAppVersion = in.readInt(); mIsEnabled = (in.readInt() == 1); + mNanoAppPermissions = new ArrayList(); + in.readStringList(mNanoAppPermissions); } @Override @@ -73,6 +96,7 @@ public final class NanoAppState implements Parcelable { out.writeLong(mNanoAppId); out.writeInt(mNanoAppVersion); out.writeInt(mIsEnabled ? 1 : 0); + out.writeStringList(mNanoAppPermissions); } public static final @android.annotation.NonNull Creator CREATOR = diff --git a/services/core/java/com/android/server/location/contexthub/ContextHubService.java b/services/core/java/com/android/server/location/contexthub/ContextHubService.java index dc1a26ae6fea5..785e6745087f7 100644 --- a/services/core/java/com/android/server/location/contexthub/ContextHubService.java +++ b/services/core/java/com/android/server/location/contexthub/ContextHubService.java @@ -16,6 +16,7 @@ package com.android.server.location.contexthub; +import android.annotation.Nullable; import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; @@ -320,6 +321,10 @@ public class ContextHubService extends IContextHubService.Stub { @Override public void onNanoAppDisabled(long nanoAppId) { } + + @Override + public void onClientAuthorizationChanged(long nanoAppId, int authorization) { + } }; } @@ -697,6 +702,7 @@ public class ContextHubService extends IContextHubService.Stub { * * @param contextHubId the ID of the hub this client is attached to * @param clientCallback the client interface to register with the service + * @param attributionTag an optional attribution tag within the given package * @return the generated client interface, null if registration was unsuccessful * @throws IllegalArgumentException if contextHubId is not a valid ID * @throws IllegalStateException if max number of clients have already registered @@ -704,7 +710,8 @@ public class ContextHubService extends IContextHubService.Stub { */ @Override public IContextHubClient createClient( - int contextHubId, IContextHubClientCallback clientCallback) throws RemoteException { + int contextHubId, IContextHubClientCallback clientCallback, + @Nullable String attributionTag) throws RemoteException { checkPermissions(); if (!isValidContextHubId(contextHubId)) { throw new IllegalArgumentException("Invalid context hub ID " + contextHubId); @@ -723,13 +730,15 @@ public class ContextHubService extends IContextHubService.Stub { * @param contextHubId the ID of the hub this client is attached to * @param pendingIntent the PendingIntent associated with this client * @param nanoAppId the ID of the nanoapp PendingIntent events will be sent for + * @param attributionTag an optional attribution tag within the given package * @return the generated client interface * @throws IllegalArgumentException if hubInfo does not represent a valid hub * @throws IllegalStateException if there were too many registered clients at the service */ @Override public IContextHubClient createPendingIntentClient( - int contextHubId, PendingIntent pendingIntent, long nanoAppId) throws RemoteException { + int contextHubId, PendingIntent pendingIntent, long nanoAppId, + @Nullable String attributionTag) throws RemoteException { checkPermissions(); if (!isValidContextHubId(contextHubId)) { throw new IllegalArgumentException("Invalid context hub ID " + contextHubId);