Merge "AmbientContextManager API changes to support quick-tap detection" into tm-qpr-dev
This commit is contained in:
@@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package android.app.ambientcontext;
|
||||||
|
|
||||||
|
import android.annotation.NonNull;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback for listening to Ambient Context events and status changes. See {@link
|
||||||
|
* AmbientContextManager#registerObserver(AmbientContextEventRequest, AmbientContextCallback,
|
||||||
|
* Executor)}
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public interface AmbientContextCallback {
|
||||||
|
/**
|
||||||
|
* Called when AmbientContextManager service detects events.
|
||||||
|
*
|
||||||
|
* @param events a list of detected events.
|
||||||
|
*/
|
||||||
|
void onEvents(@NonNull List<AmbientContextEvent> events);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called with a statusCode when
|
||||||
|
* {@link AmbientContextManager#registerObserver(AmbientContextEventRequest,
|
||||||
|
* Executor, AmbientContextCallback)} completes, to indicate if the registration is successful
|
||||||
|
*
|
||||||
|
* @param statusCode the status of the service.
|
||||||
|
*/
|
||||||
|
void onRegistrationComplete(@NonNull @AmbientContextManager.StatusCode int statusCode);
|
||||||
|
}
|
||||||
@@ -59,11 +59,21 @@ public final class AmbientContextEvent implements Parcelable {
|
|||||||
*/
|
*/
|
||||||
public static final int EVENT_SNORE = 2;
|
public static final int EVENT_SNORE = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The integer indicating a double-tap event was detected.
|
||||||
|
* For detecting this event type, there's no specific consent activity to request access, but
|
||||||
|
* the consent is implied through the double tap toggle in the Settings app.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public static final int EVENT_BACK_DOUBLE_TAP = 3;
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
@IntDef(prefix = { "EVENT_" }, value = {
|
@IntDef(prefix = { "EVENT_" }, value = {
|
||||||
EVENT_UNKNOWN,
|
EVENT_UNKNOWN,
|
||||||
EVENT_COUGH,
|
EVENT_COUGH,
|
||||||
EVENT_SNORE,
|
EVENT_SNORE,
|
||||||
|
EVENT_BACK_DOUBLE_TAP,
|
||||||
}) public @interface EventCode {}
|
}) public @interface EventCode {}
|
||||||
|
|
||||||
/** The integer indicating an unknown level. */
|
/** The integer indicating an unknown level. */
|
||||||
@@ -150,7 +160,8 @@ public final class AmbientContextEvent implements Parcelable {
|
|||||||
@IntDef(prefix = "EVENT_", value = {
|
@IntDef(prefix = "EVENT_", value = {
|
||||||
EVENT_UNKNOWN,
|
EVENT_UNKNOWN,
|
||||||
EVENT_COUGH,
|
EVENT_COUGH,
|
||||||
EVENT_SNORE
|
EVENT_SNORE,
|
||||||
|
EVENT_BACK_DOUBLE_TAP
|
||||||
})
|
})
|
||||||
@Retention(RetentionPolicy.SOURCE)
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
@DataClass.Generated.Member
|
@DataClass.Generated.Member
|
||||||
@@ -166,6 +177,8 @@ public final class AmbientContextEvent implements Parcelable {
|
|||||||
return "EVENT_COUGH";
|
return "EVENT_COUGH";
|
||||||
case EVENT_SNORE:
|
case EVENT_SNORE:
|
||||||
return "EVENT_SNORE";
|
return "EVENT_SNORE";
|
||||||
|
case EVENT_BACK_DOUBLE_TAP:
|
||||||
|
return "EVENT_BACK_DOUBLE_TAP";
|
||||||
default: return Integer.toHexString(value);
|
default: return Integer.toHexString(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -478,10 +491,10 @@ public final class AmbientContextEvent implements Parcelable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@DataClass.Generated(
|
@DataClass.Generated(
|
||||||
time = 1642040319323L,
|
time = 1659950304931L,
|
||||||
codegenVersion = "1.0.23",
|
codegenVersion = "1.0.23",
|
||||||
sourceFile = "frameworks/base/core/java/android/app/ambientcontext/AmbientContextEvent.java",
|
sourceFile = "frameworks/base/core/java/android/app/ambientcontext/AmbientContextEvent.java",
|
||||||
inputSignatures = "public static final int EVENT_UNKNOWN\npublic static final int EVENT_COUGH\npublic static final int EVENT_SNORE\npublic static final int LEVEL_UNKNOWN\npublic static final int LEVEL_LOW\npublic static final int LEVEL_MEDIUM_LOW\npublic static final int LEVEL_MEDIUM\npublic static final int LEVEL_MEDIUM_HIGH\npublic static final int LEVEL_HIGH\nprivate final @android.app.ambientcontext.AmbientContextEvent.EventCode int mEventType\nprivate final @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInstant.class) @android.annotation.NonNull java.time.Instant mStartTime\nprivate final @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInstant.class) @android.annotation.NonNull java.time.Instant mEndTime\nprivate final @android.app.ambientcontext.AmbientContextEvent.LevelValue int mConfidenceLevel\nprivate final @android.app.ambientcontext.AmbientContextEvent.LevelValue int mDensityLevel\nprivate static int defaultEventType()\nprivate static @android.annotation.NonNull java.time.Instant defaultStartTime()\nprivate static @android.annotation.NonNull java.time.Instant defaultEndTime()\nprivate static int defaultConfidenceLevel()\nprivate static int defaultDensityLevel()\nclass AmbientContextEvent extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genBuilder=true, genConstructor=false, genHiddenConstDefs=true, genParcelable=true, genToString=true)")
|
inputSignatures = "public static final int EVENT_UNKNOWN\npublic static final int EVENT_COUGH\npublic static final int EVENT_SNORE\npublic static final int EVENT_BACK_DOUBLE_TAP\npublic static final int LEVEL_UNKNOWN\npublic static final int LEVEL_LOW\npublic static final int LEVEL_MEDIUM_LOW\npublic static final int LEVEL_MEDIUM\npublic static final int LEVEL_MEDIUM_HIGH\npublic static final int LEVEL_HIGH\nprivate final @android.app.ambientcontext.AmbientContextEvent.EventCode int mEventType\nprivate final @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInstant.class) @android.annotation.NonNull java.time.Instant mStartTime\nprivate final @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInstant.class) @android.annotation.NonNull java.time.Instant mEndTime\nprivate final @android.app.ambientcontext.AmbientContextEvent.LevelValue int mConfidenceLevel\nprivate final @android.app.ambientcontext.AmbientContextEvent.LevelValue int mDensityLevel\nprivate static int defaultEventType()\nprivate static @android.annotation.NonNull java.time.Instant defaultStartTime()\nprivate static @android.annotation.NonNull java.time.Instant defaultEndTime()\nprivate static int defaultConfidenceLevel()\nprivate static int defaultDensityLevel()\nclass AmbientContextEvent extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genBuilder=true, genConstructor=false, genHiddenConstDefs=true, genParcelable=true, genToString=true)")
|
||||||
@Deprecated
|
@Deprecated
|
||||||
private void __metadata() {}
|
private void __metadata() {}
|
||||||
|
|
||||||
|
|||||||
@@ -282,7 +282,7 @@ public final class AmbientContextManager {
|
|||||||
Preconditions.checkArgument(!resultPendingIntent.isImmutable());
|
Preconditions.checkArgument(!resultPendingIntent.isImmutable());
|
||||||
try {
|
try {
|
||||||
RemoteCallback callback = new RemoteCallback(result -> {
|
RemoteCallback callback = new RemoteCallback(result -> {
|
||||||
int statusCode = result.getInt(STATUS_RESPONSE_BUNDLE_KEY);
|
int statusCode = result.getInt(STATUS_RESPONSE_BUNDLE_KEY);
|
||||||
final long identity = Binder.clearCallingIdentity();
|
final long identity = Binder.clearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
executor.execute(() -> statusConsumer.accept(statusCode));
|
executor.execute(() -> statusConsumer.accept(statusCode));
|
||||||
@@ -296,6 +296,72 @@ public final class AmbientContextManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows app to register as a {@link AmbientContextEvent} observer. Same as {@link
|
||||||
|
* #registerObserver(AmbientContextEventRequest, PendingIntent, Executor, Consumer)},
|
||||||
|
* but use {@link AmbientContextCallback} instead of {@link PendingIntent} as a callback on
|
||||||
|
* detected events.
|
||||||
|
* Registering another observer from the same package that has already been
|
||||||
|
* registered will override the previous observer. If the same app previously calls
|
||||||
|
* {@link #registerObserver(AmbientContextEventRequest, AmbientContextCallback, Executor)},
|
||||||
|
* and now calls
|
||||||
|
* {@link #registerObserver(AmbientContextEventRequest, PendingIntent, Executor, Consumer)},
|
||||||
|
* the previous observer will be replaced with the new observer with the PendingIntent callback.
|
||||||
|
* Or vice versa.
|
||||||
|
*
|
||||||
|
* When the registration completes, a status will be returned to client through
|
||||||
|
* {@link AmbientContextCallback#onRegistrationComplete(int)}.
|
||||||
|
* If the AmbientContextManager service is not enabled yet, or the underlying detection service
|
||||||
|
* is not running yet, {@link AmbientContextManager#STATUS_SERVICE_UNAVAILABLE} will be
|
||||||
|
* returned, and the detection won't be really started.
|
||||||
|
* If the underlying detection service feature is not enabled, or the requested event type is
|
||||||
|
* not enabled yet, {@link AmbientContextManager#STATUS_NOT_SUPPORTED} will be returned, and the
|
||||||
|
* detection won't be really started.
|
||||||
|
* If there is no user consent, {@link AmbientContextManager#STATUS_ACCESS_DENIED} will be
|
||||||
|
* returned, and the detection won't be really started.
|
||||||
|
* Otherwise, it will try to start the detection. And if it starts successfully, it will return
|
||||||
|
* {@link AmbientContextManager#STATUS_SUCCESS}. If it fails to start the detection, then
|
||||||
|
* it will return {@link AmbientContextManager#STATUS_SERVICE_UNAVAILABLE}
|
||||||
|
* After registerObserver succeeds and when the service detects an event, the service will
|
||||||
|
* trigger {@link AmbientContextCallback#onEvents(List)}.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@RequiresPermission(Manifest.permission.ACCESS_AMBIENT_CONTEXT_EVENT)
|
||||||
|
public void registerObserver(
|
||||||
|
@NonNull AmbientContextEventRequest request,
|
||||||
|
@NonNull @CallbackExecutor Executor executor,
|
||||||
|
@NonNull AmbientContextCallback ambientContextCallback) {
|
||||||
|
try {
|
||||||
|
IAmbientContextObserver observer = new IAmbientContextObserver.Stub() {
|
||||||
|
@Override
|
||||||
|
public void onEvents(List<AmbientContextEvent> events) throws RemoteException {
|
||||||
|
final long identity = Binder.clearCallingIdentity();
|
||||||
|
try {
|
||||||
|
executor.execute(() -> ambientContextCallback.onEvents(events));
|
||||||
|
} finally {
|
||||||
|
Binder.restoreCallingIdentity(identity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRegistrationComplete(int statusCode) throws RemoteException {
|
||||||
|
final long identity = Binder.clearCallingIdentity();
|
||||||
|
try {
|
||||||
|
executor.execute(
|
||||||
|
() -> ambientContextCallback.onRegistrationComplete(statusCode));
|
||||||
|
} finally {
|
||||||
|
Binder.restoreCallingIdentity(identity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
mService.registerObserverWithCallback(request, mContext.getPackageName(), observer);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
throw e.rethrowFromSystemServer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unregisters the requesting app as an {@code AmbientContextEvent} observer. Unregistering an
|
* Unregisters the requesting app as an {@code AmbientContextEvent} observer. Unregistering an
|
||||||
* observer that was already unregistered or never registered will have no effect.
|
* observer that was already unregistered or never registered will have no effect.
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package android.app.ambientcontext;
|
|||||||
|
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.app.ambientcontext.AmbientContextEventRequest;
|
import android.app.ambientcontext.AmbientContextEventRequest;
|
||||||
|
import android.app.ambientcontext.IAmbientContextObserver;
|
||||||
import android.os.RemoteCallback;
|
import android.os.RemoteCallback;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -29,6 +30,11 @@ interface IAmbientContextManager {
|
|||||||
void registerObserver(in AmbientContextEventRequest request,
|
void registerObserver(in AmbientContextEventRequest request,
|
||||||
in PendingIntent resultPendingIntent,
|
in PendingIntent resultPendingIntent,
|
||||||
in RemoteCallback statusCallback);
|
in RemoteCallback statusCallback);
|
||||||
|
|
||||||
|
@JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.ACCESS_AMBIENT_CONTEXT_EVENT)")
|
||||||
|
void registerObserverWithCallback(in AmbientContextEventRequest request,
|
||||||
|
String packageName,
|
||||||
|
in IAmbientContextObserver observer);
|
||||||
void unregisterObserver(in String callingPackage);
|
void unregisterObserver(in String callingPackage);
|
||||||
void queryServiceStatus(in int[] eventTypes, in String callingPackage,
|
void queryServiceStatus(in int[] eventTypes, in String callingPackage,
|
||||||
in RemoteCallback statusCallback);
|
in RemoteCallback statusCallback);
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package android.app.ambientcontext;
|
||||||
|
|
||||||
|
import android.app.ambientcontext.AmbientContextEvent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback interface of AmbientContextManager.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
oneway interface IAmbientContextObserver {
|
||||||
|
void onEvents(in List<AmbientContextEvent> events);
|
||||||
|
void onRegistrationComplete(in int statusCode);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -29,6 +29,7 @@ import android.app.PendingIntent;
|
|||||||
import android.app.ambientcontext.AmbientContextEvent;
|
import android.app.ambientcontext.AmbientContextEvent;
|
||||||
import android.app.ambientcontext.AmbientContextEventRequest;
|
import android.app.ambientcontext.AmbientContextEventRequest;
|
||||||
import android.app.ambientcontext.AmbientContextManager;
|
import android.app.ambientcontext.AmbientContextManager;
|
||||||
|
import android.app.ambientcontext.IAmbientContextObserver;
|
||||||
import android.content.ActivityNotFoundException;
|
import android.content.ActivityNotFoundException;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@@ -53,6 +54,8 @@ import com.android.server.infra.AbstractPerUserSystemService;
|
|||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Per-user manager service for {@link AmbientContextEvent}s.
|
* Per-user manager service for {@link AmbientContextEvent}s.
|
||||||
@@ -165,20 +168,17 @@ final class AmbientContextManagerPerUserService extends
|
|||||||
* package. A new registration from the same package will overwrite the previous registration.
|
* package. A new registration from the same package will overwrite the previous registration.
|
||||||
*/
|
*/
|
||||||
public void onRegisterObserver(AmbientContextEventRequest request,
|
public void onRegisterObserver(AmbientContextEventRequest request,
|
||||||
PendingIntent pendingIntent, RemoteCallback clientStatusCallback) {
|
String packageName, IAmbientContextObserver observer) {
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
if (!setUpServiceIfNeeded()) {
|
if (!setUpServiceIfNeeded()) {
|
||||||
Slog.w(TAG, "Detection service is not available at this moment.");
|
Slog.w(TAG, "Detection service is not available at this moment.");
|
||||||
sendStatusCallback(
|
completeRegistration(observer, AmbientContextManager.STATUS_SERVICE_UNAVAILABLE);
|
||||||
clientStatusCallback,
|
|
||||||
AmbientContextManager.STATUS_SERVICE_UNAVAILABLE);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register package and add to existing ClientRequests cache
|
// Register package and add to existing ClientRequests cache
|
||||||
startDetection(request, pendingIntent.getCreatorPackage(),
|
startDetection(request, packageName, observer);
|
||||||
createDetectionResultRemoteCallback(), clientStatusCallback);
|
mMaster.newClientAdded(mUserId, request, packageName, observer);
|
||||||
mMaster.newClientAdded(mUserId, request, pendingIntent, clientStatusCallback);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,49 +186,46 @@ final class AmbientContextManagerPerUserService extends
|
|||||||
* Returns a RemoteCallback that handles the status from the detection service, and
|
* Returns a RemoteCallback that handles the status from the detection service, and
|
||||||
* sends results to the client callback.
|
* sends results to the client callback.
|
||||||
*/
|
*/
|
||||||
private RemoteCallback getServerStatusCallback(RemoteCallback clientStatusCallback) {
|
private RemoteCallback getServerStatusCallback(Consumer<Integer> statusConsumer) {
|
||||||
return new RemoteCallback(result -> {
|
return new RemoteCallback(result -> {
|
||||||
AmbientContextDetectionServiceStatus serviceStatus =
|
AmbientContextDetectionServiceStatus serviceStatus =
|
||||||
(AmbientContextDetectionServiceStatus) result.get(
|
(AmbientContextDetectionServiceStatus) result.get(
|
||||||
AmbientContextDetectionServiceStatus.STATUS_RESPONSE_BUNDLE_KEY);
|
AmbientContextDetectionServiceStatus.STATUS_RESPONSE_BUNDLE_KEY);
|
||||||
final long token = Binder.clearCallingIdentity();
|
final long token = Binder.clearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
String packageName = serviceStatus.getPackageName();
|
|
||||||
Bundle bundle = new Bundle();
|
|
||||||
bundle.putInt(
|
|
||||||
AmbientContextManager.STATUS_RESPONSE_BUNDLE_KEY,
|
|
||||||
serviceStatus.getStatusCode());
|
|
||||||
clientStatusCallback.sendResult(bundle);
|
|
||||||
int statusCode = serviceStatus.getStatusCode();
|
int statusCode = serviceStatus.getStatusCode();
|
||||||
|
statusConsumer.accept(statusCode);
|
||||||
Slog.i(TAG, "Got detection status of " + statusCode
|
Slog.i(TAG, "Got detection status of " + statusCode
|
||||||
+ " for " + packageName);
|
+ " for " + serviceStatus.getPackageName());
|
||||||
} finally {
|
} finally {
|
||||||
Binder.restoreCallingIdentity(token);
|
Binder.restoreCallingIdentity(token);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
void startDetection(AmbientContextEventRequest request, String callingPackage,
|
void startDetection(AmbientContextEventRequest request, String callingPackage,
|
||||||
RemoteCallback detectionResultCallback, RemoteCallback clientStatusCallback) {
|
IAmbientContextObserver observer) {
|
||||||
Slog.d(TAG, "Requested detection of " + request.getEventTypes());
|
Slog.d(TAG, "Requested detection of " + request.getEventTypes());
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
if (setUpServiceIfNeeded()) {
|
if (setUpServiceIfNeeded()) {
|
||||||
ensureRemoteServiceInitiated();
|
ensureRemoteServiceInitiated();
|
||||||
mRemoteService.startDetection(request, callingPackage, detectionResultCallback,
|
mRemoteService.startDetection(request, callingPackage,
|
||||||
getServerStatusCallback(clientStatusCallback));
|
createDetectionResultRemoteCallback(),
|
||||||
|
getServerStatusCallback(
|
||||||
|
statusCode -> completeRegistration(observer, statusCode)));
|
||||||
} else {
|
} else {
|
||||||
Slog.w(TAG, "No valid component found for AmbientContextDetectionService");
|
Slog.w(TAG, "No valid component found for AmbientContextDetectionService");
|
||||||
sendStatusToCallback(clientStatusCallback,
|
completeRegistration(observer,
|
||||||
AmbientContextManager.STATUS_NOT_SUPPORTED);
|
AmbientContextManager.STATUS_NOT_SUPPORTED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends an intent with a status code and empty events.
|
* Sends the result response with the specified status to the callback.
|
||||||
*/
|
*/
|
||||||
void sendStatusCallback(RemoteCallback statusCallback, int statusCode) {
|
static void sendStatusCallback(RemoteCallback statusCallback,
|
||||||
|
@AmbientContextManager.StatusCode int statusCode) {
|
||||||
Bundle bundle = new Bundle();
|
Bundle bundle = new Bundle();
|
||||||
bundle.putInt(
|
bundle.putInt(
|
||||||
AmbientContextManager.STATUS_RESPONSE_BUNDLE_KEY,
|
AmbientContextManager.STATUS_RESPONSE_BUNDLE_KEY,
|
||||||
@@ -236,6 +233,15 @@ final class AmbientContextManagerPerUserService extends
|
|||||||
statusCallback.sendResult(bundle);
|
statusCallback.sendResult(bundle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void completeRegistration(IAmbientContextObserver observer, int statusCode) {
|
||||||
|
try {
|
||||||
|
observer.onRegistrationComplete(statusCode);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Slog.w(TAG, "Failed to call IAmbientContextObserver.onRegistrationComplete: "
|
||||||
|
+ e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unregisters the client from all previously registered events by removing from the
|
* Unregisters the client from all previously registered events by removing from the
|
||||||
* mExistingRequests map, and unregister events from the service if those events are not
|
* mExistingRequests map, and unregister events from the service if those events are not
|
||||||
@@ -255,7 +261,7 @@ final class AmbientContextManagerPerUserService extends
|
|||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
if (!setUpServiceIfNeeded()) {
|
if (!setUpServiceIfNeeded()) {
|
||||||
Slog.w(TAG, "Detection service is not available at this moment.");
|
Slog.w(TAG, "Detection service is not available at this moment.");
|
||||||
sendStatusToCallback(statusCallback,
|
sendStatusCallback(statusCallback,
|
||||||
AmbientContextManager.STATUS_NOT_SUPPORTED);
|
AmbientContextManager.STATUS_NOT_SUPPORTED);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -263,7 +269,8 @@ final class AmbientContextManagerPerUserService extends
|
|||||||
mRemoteService.queryServiceStatus(
|
mRemoteService.queryServiceStatus(
|
||||||
eventTypes,
|
eventTypes,
|
||||||
callingPackage,
|
callingPackage,
|
||||||
getServerStatusCallback(statusCallback));
|
getServerStatusCallback(
|
||||||
|
statusCode -> sendStatusCallback(statusCallback, statusCode)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -350,18 +357,6 @@ final class AmbientContextManagerPerUserService extends
|
|||||||
return ComponentName.unflattenFromString(consentComponent);
|
return ComponentName.unflattenFromString(consentComponent);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Sends the result response with the specified status to the callback.
|
|
||||||
*/
|
|
||||||
void sendStatusToCallback(RemoteCallback callback,
|
|
||||||
@AmbientContextManager.StatusCode int status) {
|
|
||||||
Bundle bundle = new Bundle();
|
|
||||||
bundle.putInt(
|
|
||||||
AmbientContextManager.STATUS_RESPONSE_BUNDLE_KEY,
|
|
||||||
status);
|
|
||||||
callback.sendResult(bundle);
|
|
||||||
}
|
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
void stopDetection(String packageName) {
|
void stopDetection(String packageName) {
|
||||||
Slog.d(TAG, "Stop detection for " + packageName);
|
Slog.d(TAG, "Stop detection for " + packageName);
|
||||||
@@ -377,13 +372,13 @@ final class AmbientContextManagerPerUserService extends
|
|||||||
* Sends out the Intent to the client after the event is detected.
|
* Sends out the Intent to the client after the event is detected.
|
||||||
*
|
*
|
||||||
* @param pendingIntent Client's PendingIntent for callback
|
* @param pendingIntent Client's PendingIntent for callback
|
||||||
* @param result result from the detection service
|
* @param events detected events from the detection service
|
||||||
*/
|
*/
|
||||||
private void sendDetectionResultIntent(PendingIntent pendingIntent,
|
void sendDetectionResultIntent(PendingIntent pendingIntent,
|
||||||
AmbientContextDetectionResult result) {
|
List<AmbientContextEvent> events) {
|
||||||
Intent intent = new Intent();
|
Intent intent = new Intent();
|
||||||
intent.putExtra(AmbientContextManager.EXTRA_AMBIENT_CONTEXT_EVENTS,
|
intent.putExtra(AmbientContextManager.EXTRA_AMBIENT_CONTEXT_EVENTS,
|
||||||
new ArrayList(result.getEvents()));
|
new ArrayList(events));
|
||||||
// Explicitly disallow the receiver from starting activities, to prevent apps from utilizing
|
// Explicitly disallow the receiver from starting activities, to prevent apps from utilizing
|
||||||
// the PendingIntent as a backdoor to do this.
|
// the PendingIntent as a backdoor to do this.
|
||||||
BroadcastOptions options = BroadcastOptions.makeBasic();
|
BroadcastOptions options = BroadcastOptions.makeBasic();
|
||||||
@@ -392,7 +387,7 @@ final class AmbientContextManagerPerUserService extends
|
|||||||
pendingIntent.send(getContext(), 0, intent, null, null, null,
|
pendingIntent.send(getContext(), 0, intent, null, null, null,
|
||||||
options.toBundle());
|
options.toBundle());
|
||||||
Slog.i(TAG, "Sending PendingIntent to " + pendingIntent.getCreatorPackage() + ": "
|
Slog.i(TAG, "Sending PendingIntent to " + pendingIntent.getCreatorPackage() + ": "
|
||||||
+ result);
|
+ events);
|
||||||
} catch (PendingIntent.CanceledException e) {
|
} catch (PendingIntent.CanceledException e) {
|
||||||
Slog.w(TAG, "Couldn't deliver pendingIntent:" + pendingIntent);
|
Slog.w(TAG, "Couldn't deliver pendingIntent:" + pendingIntent);
|
||||||
}
|
}
|
||||||
@@ -405,16 +400,19 @@ final class AmbientContextManagerPerUserService extends
|
|||||||
(AmbientContextDetectionResult) result.get(
|
(AmbientContextDetectionResult) result.get(
|
||||||
AmbientContextDetectionResult.RESULT_RESPONSE_BUNDLE_KEY);
|
AmbientContextDetectionResult.RESULT_RESPONSE_BUNDLE_KEY);
|
||||||
String packageName = detectionResult.getPackageName();
|
String packageName = detectionResult.getPackageName();
|
||||||
PendingIntent pendingIntent = mMaster.getPendingIntent(mUserId, packageName);
|
IAmbientContextObserver observer = mMaster.getClientRequestObserver(
|
||||||
if (pendingIntent == null) {
|
mUserId, packageName);
|
||||||
|
if (observer == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final long token = Binder.clearCallingIdentity();
|
final long token = Binder.clearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
sendDetectionResultIntent(pendingIntent, detectionResult);
|
observer.onEvents(detectionResult.getEvents());
|
||||||
Slog.i(TAG, "Got detection result of " + detectionResult.getEvents()
|
Slog.i(TAG, "Got detection result of " + detectionResult.getEvents()
|
||||||
+ " for " + packageName);
|
+ " for " + packageName);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Slog.w(TAG, "Failed to call IAmbientContextObserver.onEvents: " + e.getMessage());
|
||||||
} finally {
|
} finally {
|
||||||
Binder.restoreCallingIdentity(token);
|
Binder.restoreCallingIdentity(token);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,10 +27,12 @@ import android.app.ambientcontext.AmbientContextEvent;
|
|||||||
import android.app.ambientcontext.AmbientContextEventRequest;
|
import android.app.ambientcontext.AmbientContextEventRequest;
|
||||||
import android.app.ambientcontext.AmbientContextManager;
|
import android.app.ambientcontext.AmbientContextManager;
|
||||||
import android.app.ambientcontext.IAmbientContextManager;
|
import android.app.ambientcontext.IAmbientContextManager;
|
||||||
|
import android.app.ambientcontext.IAmbientContextObserver;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.pm.PackageManagerInternal;
|
import android.content.pm.PackageManagerInternal;
|
||||||
import android.os.RemoteCallback;
|
import android.os.RemoteCallback;
|
||||||
|
import android.os.RemoteException;
|
||||||
import android.os.ResultReceiver;
|
import android.os.ResultReceiver;
|
||||||
import android.os.ShellCallback;
|
import android.os.ShellCallback;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
@@ -48,6 +50,7 @@ import com.android.server.pm.KnownPackages;
|
|||||||
|
|
||||||
import java.io.FileDescriptor;
|
import java.io.FileDescriptor;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@@ -67,31 +70,27 @@ public class AmbientContextManagerService extends
|
|||||||
static class ClientRequest {
|
static class ClientRequest {
|
||||||
private final int mUserId;
|
private final int mUserId;
|
||||||
private final AmbientContextEventRequest mRequest;
|
private final AmbientContextEventRequest mRequest;
|
||||||
private final PendingIntent mPendingIntent;
|
private final String mPackageName;
|
||||||
private final RemoteCallback mClientStatusCallback;
|
private final IAmbientContextObserver mObserver;
|
||||||
|
|
||||||
ClientRequest(int userId, AmbientContextEventRequest request,
|
ClientRequest(int userId, AmbientContextEventRequest request,
|
||||||
PendingIntent pendingIntent, RemoteCallback clientStatusCallback) {
|
String packageName, IAmbientContextObserver observer) {
|
||||||
this.mUserId = userId;
|
this.mUserId = userId;
|
||||||
this.mRequest = request;
|
this.mRequest = request;
|
||||||
this.mPendingIntent = pendingIntent;
|
this.mPackageName = packageName;
|
||||||
this.mClientStatusCallback = clientStatusCallback;
|
this.mObserver = observer;
|
||||||
}
|
}
|
||||||
|
|
||||||
String getPackageName() {
|
String getPackageName() {
|
||||||
return mPendingIntent.getCreatorPackage();
|
return mPackageName;
|
||||||
}
|
}
|
||||||
|
|
||||||
AmbientContextEventRequest getRequest() {
|
AmbientContextEventRequest getRequest() {
|
||||||
return mRequest;
|
return mRequest;
|
||||||
}
|
}
|
||||||
|
|
||||||
PendingIntent getPendingIntent() {
|
IAmbientContextObserver getObserver() {
|
||||||
return mPendingIntent;
|
return mObserver;
|
||||||
}
|
|
||||||
|
|
||||||
RemoteCallback getClientStatusCallback() {
|
|
||||||
return mClientStatusCallback;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean hasUserId(int userId) {
|
boolean hasUserId(int userId) {
|
||||||
@@ -139,16 +138,16 @@ public class AmbientContextManagerService extends
|
|||||||
}
|
}
|
||||||
|
|
||||||
void newClientAdded(int userId, AmbientContextEventRequest request,
|
void newClientAdded(int userId, AmbientContextEventRequest request,
|
||||||
PendingIntent pendingIntent, RemoteCallback clientStatusCallback) {
|
String callingPackage, IAmbientContextObserver observer) {
|
||||||
Slog.d(TAG, "New client added: " + pendingIntent.getCreatorPackage());
|
Slog.d(TAG, "New client added: " + callingPackage);
|
||||||
|
|
||||||
// Remove any existing ClientRequest for this user and package.
|
// Remove any existing ClientRequest for this user and package.
|
||||||
mExistingClientRequests.removeAll(
|
mExistingClientRequests.removeAll(
|
||||||
findExistingRequests(userId, pendingIntent.getCreatorPackage()));
|
findExistingRequests(userId, callingPackage));
|
||||||
|
|
||||||
// Add to existing ClientRequests
|
// Add to existing ClientRequests
|
||||||
mExistingClientRequests.add(
|
mExistingClientRequests.add(
|
||||||
new ClientRequest(userId, request, pendingIntent, clientStatusCallback));
|
new ClientRequest(userId, request, callingPackage, observer));
|
||||||
}
|
}
|
||||||
|
|
||||||
void clientRemoved(int userId, String packageName) {
|
void clientRemoved(int userId, String packageName) {
|
||||||
@@ -167,10 +166,10 @@ public class AmbientContextManagerService extends
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
PendingIntent getPendingIntent(int userId, String packageName) {
|
IAmbientContextObserver getClientRequestObserver(int userId, String packageName) {
|
||||||
for (ClientRequest clientRequest : mExistingClientRequests) {
|
for (ClientRequest clientRequest : mExistingClientRequests) {
|
||||||
if (clientRequest.hasUserIdAndPackageName(userId, packageName)) {
|
if (clientRequest.hasUserIdAndPackageName(userId, packageName)) {
|
||||||
return clientRequest.getPendingIntent();
|
return clientRequest.getObserver();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@@ -236,15 +235,13 @@ public class AmbientContextManagerService extends
|
|||||||
* Requires ACCESS_AMBIENT_CONTEXT_EVENT permission.
|
* Requires ACCESS_AMBIENT_CONTEXT_EVENT permission.
|
||||||
*/
|
*/
|
||||||
void startDetection(@UserIdInt int userId, AmbientContextEventRequest request,
|
void startDetection(@UserIdInt int userId, AmbientContextEventRequest request,
|
||||||
String packageName, RemoteCallback detectionResultCallback,
|
String packageName, IAmbientContextObserver observer) {
|
||||||
RemoteCallback statusCallback) {
|
|
||||||
mContext.enforceCallingOrSelfPermission(
|
mContext.enforceCallingOrSelfPermission(
|
||||||
Manifest.permission.ACCESS_AMBIENT_CONTEXT_EVENT, TAG);
|
Manifest.permission.ACCESS_AMBIENT_CONTEXT_EVENT, TAG);
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
final AmbientContextManagerPerUserService service = getServiceForUserLocked(userId);
|
final AmbientContextManagerPerUserService service = getServiceForUserLocked(userId);
|
||||||
if (service != null) {
|
if (service != null) {
|
||||||
service.startDetection(request, packageName, detectionResultCallback,
|
service.startDetection(request, packageName, observer);
|
||||||
statusCallback);
|
|
||||||
} else {
|
} else {
|
||||||
Slog.i(TAG, "service not available for user_id: " + userId);
|
Slog.i(TAG, "service not available for user_id: " + userId);
|
||||||
}
|
}
|
||||||
@@ -297,8 +294,7 @@ public class AmbientContextManagerService extends
|
|||||||
Slog.d(TAG, "Restoring detection for " + clientRequest.getPackageName());
|
Slog.d(TAG, "Restoring detection for " + clientRequest.getPackageName());
|
||||||
service.startDetection(clientRequest.getRequest(),
|
service.startDetection(clientRequest.getRequest(),
|
||||||
clientRequest.getPackageName(),
|
clientRequest.getPackageName(),
|
||||||
service.createDetectionResultRemoteCallback(),
|
clientRequest.getObserver());
|
||||||
clientRequest.getClientStatusCallback());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -328,16 +324,45 @@ public class AmbientContextManagerService extends
|
|||||||
Objects.requireNonNull(request);
|
Objects.requireNonNull(request);
|
||||||
Objects.requireNonNull(resultPendingIntent);
|
Objects.requireNonNull(resultPendingIntent);
|
||||||
Objects.requireNonNull(statusCallback);
|
Objects.requireNonNull(statusCallback);
|
||||||
|
// Wrap the PendingIntent and statusCallback in a IAmbientContextObserver to make the
|
||||||
|
// code unified
|
||||||
|
IAmbientContextObserver observer = new IAmbientContextObserver.Stub() {
|
||||||
|
@Override
|
||||||
|
public void onEvents(List<AmbientContextEvent> events) throws RemoteException {
|
||||||
|
mService.sendDetectionResultIntent(resultPendingIntent, events);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRegistrationComplete(int statusCode) throws RemoteException {
|
||||||
|
AmbientContextManagerPerUserService.sendStatusCallback(statusCallback,
|
||||||
|
statusCode);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
registerObserverWithCallback(request, resultPendingIntent.getCreatorPackage(),
|
||||||
|
observer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register an observer for Ambient Context events.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void registerObserverWithCallback(AmbientContextEventRequest request,
|
||||||
|
String packageName,
|
||||||
|
IAmbientContextObserver observer) {
|
||||||
|
Slog.i(TAG, "AmbientContextManagerService registerObserverWithCallback.");
|
||||||
|
Objects.requireNonNull(request);
|
||||||
|
Objects.requireNonNull(packageName);
|
||||||
|
Objects.requireNonNull(observer);
|
||||||
mContext.enforceCallingOrSelfPermission(
|
mContext.enforceCallingOrSelfPermission(
|
||||||
Manifest.permission.ACCESS_AMBIENT_CONTEXT_EVENT, TAG);
|
Manifest.permission.ACCESS_AMBIENT_CONTEXT_EVENT, TAG);
|
||||||
assertCalledByPackageOwner(resultPendingIntent.getCreatorPackage());
|
assertCalledByPackageOwner(packageName);
|
||||||
if (!mIsServiceEnabled) {
|
if (!mIsServiceEnabled) {
|
||||||
Slog.w(TAG, "Service not available.");
|
Slog.w(TAG, "Service not available.");
|
||||||
mService.sendStatusCallback(statusCallback,
|
AmbientContextManagerPerUserService.completeRegistration(observer,
|
||||||
AmbientContextManager.STATUS_SERVICE_UNAVAILABLE);
|
AmbientContextManager.STATUS_SERVICE_UNAVAILABLE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mService.onRegisterObserver(request, resultPendingIntent, statusCallback);
|
mService.onRegisterObserver(request, packageName, observer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -359,7 +384,7 @@ public class AmbientContextManagerService extends
|
|||||||
assertCalledByPackageOwner(callingPackage);
|
assertCalledByPackageOwner(callingPackage);
|
||||||
if (!mIsServiceEnabled) {
|
if (!mIsServiceEnabled) {
|
||||||
Slog.w(TAG, "Detection service not available.");
|
Slog.w(TAG, "Detection service not available.");
|
||||||
mService.sendStatusToCallback(statusCallback,
|
AmbientContextManagerPerUserService.sendStatusCallback(statusCallback,
|
||||||
AmbientContextManager.STATUS_SERVICE_UNAVAILABLE);
|
AmbientContextManager.STATUS_SERVICE_UNAVAILABLE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,13 +22,15 @@ import android.annotation.NonNull;
|
|||||||
import android.app.ambientcontext.AmbientContextEvent;
|
import android.app.ambientcontext.AmbientContextEvent;
|
||||||
import android.app.ambientcontext.AmbientContextEventRequest;
|
import android.app.ambientcontext.AmbientContextEventRequest;
|
||||||
import android.app.ambientcontext.AmbientContextManager;
|
import android.app.ambientcontext.AmbientContextManager;
|
||||||
|
import android.app.ambientcontext.IAmbientContextObserver;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.RemoteCallback;
|
import android.os.RemoteCallback;
|
||||||
|
import android.os.RemoteException;
|
||||||
import android.os.ShellCommand;
|
import android.os.ShellCommand;
|
||||||
import android.service.ambientcontext.AmbientContextDetectionResult;
|
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shell command for {@link AmbientContextManagerService}.
|
* Shell command for {@link AmbientContextManagerService}.
|
||||||
@@ -39,6 +41,7 @@ final class AmbientContextShellCommand extends ShellCommand {
|
|||||||
new AmbientContextEventRequest.Builder()
|
new AmbientContextEventRequest.Builder()
|
||||||
.addEventType(AmbientContextEvent.EVENT_COUGH)
|
.addEventType(AmbientContextEvent.EVENT_COUGH)
|
||||||
.addEventType(AmbientContextEvent.EVENT_SNORE)
|
.addEventType(AmbientContextEvent.EVENT_SNORE)
|
||||||
|
.addEventType(AmbientContextEvent.EVENT_BACK_DOUBLE_TAP)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@@ -50,11 +53,11 @@ final class AmbientContextShellCommand extends ShellCommand {
|
|||||||
|
|
||||||
/** Callbacks for AmbientContextEventService results used internally for testing. */
|
/** Callbacks for AmbientContextEventService results used internally for testing. */
|
||||||
static class TestableCallbackInternal {
|
static class TestableCallbackInternal {
|
||||||
private AmbientContextDetectionResult mLastResult;
|
private List<AmbientContextEvent> mLastEvents;
|
||||||
private int mLastStatus;
|
private int mLastStatus;
|
||||||
|
|
||||||
public AmbientContextDetectionResult getLastResult() {
|
public List<AmbientContextEvent> getLastEvents() {
|
||||||
return mLastResult;
|
return mLastEvents;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getLastStatus() {
|
public int getLastStatus() {
|
||||||
@@ -62,19 +65,19 @@ final class AmbientContextShellCommand extends ShellCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private RemoteCallback createRemoteDetectionResultCallback() {
|
private IAmbientContextObserver createAmbientContextObserver() {
|
||||||
return new RemoteCallback(result -> {
|
return new IAmbientContextObserver.Stub() {
|
||||||
AmbientContextDetectionResult detectionResult =
|
@Override
|
||||||
(AmbientContextDetectionResult) result.get(
|
public void onEvents(List<AmbientContextEvent> events) throws RemoteException {
|
||||||
AmbientContextDetectionResult.RESULT_RESPONSE_BUNDLE_KEY);
|
mLastEvents = events;
|
||||||
final long token = Binder.clearCallingIdentity();
|
out.println("Detection events available: " + events);
|
||||||
try {
|
|
||||||
mLastResult = detectionResult;
|
|
||||||
out.println("Detection result available: " + detectionResult);
|
|
||||||
} finally {
|
|
||||||
Binder.restoreCallingIdentity(token);
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
@Override
|
||||||
|
public void onRegistrationComplete(int statusCode) throws RemoteException {
|
||||||
|
mLastStatus = statusCode;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@@ -123,8 +126,7 @@ final class AmbientContextShellCommand extends ShellCommand {
|
|||||||
final String packageName = getNextArgRequired();
|
final String packageName = getNextArgRequired();
|
||||||
mService.startDetection(
|
mService.startDetection(
|
||||||
userId, REQUEST, packageName,
|
userId, REQUEST, packageName,
|
||||||
sTestableCallbackInternal.createRemoteDetectionResultCallback(),
|
sTestableCallbackInternal.createAmbientContextObserver());
|
||||||
sTestableCallbackInternal.createRemoteStatusCallback());
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ import static com.google.common.truth.Truth.assertThat;
|
|||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.app.ambientcontext.AmbientContextEvent;
|
import android.app.ambientcontext.AmbientContextEvent;
|
||||||
import android.app.ambientcontext.AmbientContextEventRequest;
|
import android.app.ambientcontext.AmbientContextEventRequest;
|
||||||
|
import android.app.ambientcontext.IAmbientContextObserver;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.RemoteCallback;
|
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
|
|
||||||
import androidx.test.InstrumentationRegistry;
|
import androidx.test.InstrumentationRegistry;
|
||||||
@@ -30,6 +30,8 @@ import androidx.test.filters.SmallTest;
|
|||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unit test for {@link AmbientContextManagerService}.
|
* Unit test for {@link AmbientContextManagerService}.
|
||||||
* atest FrameworksServicesTests:AmbientContextManagerServiceTest
|
* atest FrameworksServicesTests:AmbientContextManagerServiceTest
|
||||||
@@ -48,12 +50,22 @@ public class AmbientContextManagerServiceTest {
|
|||||||
PendingIntent pendingIntent = PendingIntent.getBroadcast(
|
PendingIntent pendingIntent = PendingIntent.getBroadcast(
|
||||||
InstrumentationRegistry.getTargetContext(), 0,
|
InstrumentationRegistry.getTargetContext(), 0,
|
||||||
intent, PendingIntent.FLAG_IMMUTABLE);
|
intent, PendingIntent.FLAG_IMMUTABLE);
|
||||||
|
IAmbientContextObserver observer = new IAmbientContextObserver.Stub() {
|
||||||
|
@Override
|
||||||
|
public void onEvents(List<AmbientContextEvent> events) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRegistrationComplete(int statusCode) {
|
||||||
|
}
|
||||||
|
};
|
||||||
AmbientContextManagerService.ClientRequest clientRequest =
|
AmbientContextManagerService.ClientRequest clientRequest =
|
||||||
new AmbientContextManagerService.ClientRequest(USER_ID, request,
|
new AmbientContextManagerService.ClientRequest(USER_ID, request,
|
||||||
pendingIntent, new RemoteCallback(result -> {}));
|
pendingIntent.getCreatorPackage(), observer);
|
||||||
|
|
||||||
assertThat(clientRequest.getRequest()).isEqualTo(request);
|
assertThat(clientRequest.getRequest()).isEqualTo(request);
|
||||||
assertThat(clientRequest.getPackageName()).isEqualTo(SYSTEM_PACKAGE_NAME);
|
assertThat(clientRequest.getPackageName()).isEqualTo(SYSTEM_PACKAGE_NAME);
|
||||||
|
assertThat(clientRequest.getObserver()).isEqualTo(observer);
|
||||||
assertThat(clientRequest.hasUserId(USER_ID)).isTrue();
|
assertThat(clientRequest.hasUserId(USER_ID)).isTrue();
|
||||||
assertThat(clientRequest.hasUserId(-1)).isFalse();
|
assertThat(clientRequest.hasUserId(-1)).isFalse();
|
||||||
assertThat(clientRequest.hasUserIdAndPackageName(USER_ID, SYSTEM_PACKAGE_NAME)).isTrue();
|
assertThat(clientRequest.hasUserIdAndPackageName(USER_ID, SYSTEM_PACKAGE_NAME)).isTrue();
|
||||||
|
|||||||
Reference in New Issue
Block a user