Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d87dacf8 authored by Anthony Stange's avatar Anthony Stange Committed by Android (Google) Code Review
Browse files

Merge changes I7b0ba9a9,I37e475a1 into sc-dev

* changes:
  Add attribution tag parameter to createClient
  Add new callback / intent type to ContextHub APIs
parents 7672f255 b6b7b423
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -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<java.lang.Void> 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<java.lang.Void> 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<java.lang.Void> 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<java.lang.String>);
    method public int describeContents();
    method public long getNanoAppId();
    method @NonNull public java.util.List<java.lang.String> getNanoAppPermissions();
    method public long getNanoAppVersion();
    method public boolean isEnabled();
    method public void writeToParcel(android.os.Parcel, int);
+31 −0
Original line number Diff line number Diff line
@@ -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) {}
}
+39 −6
Original line number Diff line number Diff line
@@ -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;
                }
+111 −17
Original line number Diff line number Diff line
@@ -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.
     *
+3 −0
Original line number Diff line number Diff line
@@ -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);
}
Loading