Add new callback / intent type to ContextHub APIs
Updates the ContextHub APIs to support notifying clients (either through traditional callbacks or via PendingIntent) that their ability to communicate with nanoapps has changed. Also, adds the ability for clients to discover the permissions required to communicate with nanoapps so they know whether their initial or subsequent nanoapp messages will successfully be delivered. Bug: 166846988 Test: compile Change-Id: I37e475a1457a031890693d2858b5d5f7de34de26
This commit is contained in:
@@ -3168,6 +3168,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);
|
||||
@@ -3204,6 +3205,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();
|
||||
@@ -3231,6 +3233,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
|
||||
@@ -3238,6 +3244,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";
|
||||
@@ -3476,8 +3483,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);
|
||||
|
||||
@@ -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) {}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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<String> mNanoAppPermissions;
|
||||
|
||||
public NanoAppState(long nanoAppId, int appVersion, boolean enabled) {
|
||||
mNanoAppId = nanoAppId;
|
||||
mNanoAppVersion = appVersion;
|
||||
mIsEnabled = enabled;
|
||||
mNanoAppPermissions = new ArrayList<String>();
|
||||
}
|
||||
|
||||
public NanoAppState(long nanoAppId, int appVersion, boolean enabled,
|
||||
@NonNull List<String> 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<String> getNanoAppPermissions() {
|
||||
return mNanoAppPermissions;
|
||||
}
|
||||
|
||||
private NanoAppState(Parcel in) {
|
||||
mNanoAppId = in.readLong();
|
||||
mNanoAppVersion = in.readInt();
|
||||
mIsEnabled = (in.readInt() == 1);
|
||||
mNanoAppPermissions = new ArrayList<String>();
|
||||
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<NanoAppState> CREATOR =
|
||||
|
||||
@@ -320,6 +320,10 @@ public class ContextHubService extends IContextHubService.Stub {
|
||||
@Override
|
||||
public void onNanoAppDisabled(long nanoAppId) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClientAuthorizationChanged(long nanoAppId, int authorization) {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user