Adding proximity endpoints to Attention Service
Test: atest AttentionManagerServiceTest Bug: 214395649 Change-Id: I821fa883a2a23da664913e7a831b59701393903f
This commit is contained in:
@@ -10417,6 +10417,8 @@ package android.service.attention {
|
||||
method @Nullable public final android.os.IBinder onBind(@NonNull android.content.Intent);
|
||||
method public abstract void onCancelAttentionCheck(@NonNull android.service.attention.AttentionService.AttentionCallback);
|
||||
method public abstract void onCheckAttention(@NonNull android.service.attention.AttentionService.AttentionCallback);
|
||||
method public void onStartProximityUpdates(@NonNull android.service.attention.AttentionService.ProximityCallback);
|
||||
method public void onStopProximityUpdates();
|
||||
field public static final int ATTENTION_FAILURE_CAMERA_PERMISSION_ABSENT = 6; // 0x6
|
||||
field public static final int ATTENTION_FAILURE_CANCELLED = 3; // 0x3
|
||||
field public static final int ATTENTION_FAILURE_PREEMPTED = 4; // 0x4
|
||||
@@ -10424,6 +10426,7 @@ package android.service.attention {
|
||||
field public static final int ATTENTION_FAILURE_UNKNOWN = 2; // 0x2
|
||||
field public static final int ATTENTION_SUCCESS_ABSENT = 0; // 0x0
|
||||
field public static final int ATTENTION_SUCCESS_PRESENT = 1; // 0x1
|
||||
field public static final double PROXIMITY_UNKNOWN = -1.0;
|
||||
field public static final String SERVICE_INTERFACE = "android.service.attention.AttentionService";
|
||||
}
|
||||
|
||||
@@ -10432,6 +10435,10 @@ package android.service.attention {
|
||||
method public void onSuccess(int, long);
|
||||
}
|
||||
|
||||
public static final class AttentionService.ProximityCallback {
|
||||
method public void onProximityUpdate(double);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
package android.service.autofill {
|
||||
|
||||
@@ -46,6 +46,25 @@ public abstract class AttentionManagerInternal {
|
||||
*/
|
||||
public abstract void cancelAttentionCheck(AttentionCallbackInternal callback);
|
||||
|
||||
/**
|
||||
* Requests the continuous updates of proximity signal via the provided callback,
|
||||
* until the given callback is unregistered. Currently, AttentionManagerService only
|
||||
* anticipates one client and updates one client at a time. If a new client wants to
|
||||
* onboard to receiving Proximity updates, please make a feature request to make proximity
|
||||
* feature multi-client before depending on this feature.
|
||||
*
|
||||
* @param callback a callback that receives the proximity updates
|
||||
* @return {@code true} if the registration should succeed.
|
||||
*/
|
||||
public abstract boolean onStartProximityUpdates(ProximityCallbackInternal callback);
|
||||
|
||||
/**
|
||||
* Requests to stop providing continuous updates until the callback is registered.
|
||||
*
|
||||
* @param callback a callback that was used in {@link #onStartProximityUpdates}
|
||||
*/
|
||||
public abstract void onStopProximityUpdates(ProximityCallbackInternal callback);
|
||||
|
||||
/** Internal interface for attention callback. */
|
||||
public abstract static class AttentionCallbackInternal {
|
||||
/**
|
||||
@@ -64,4 +83,13 @@ public abstract class AttentionManagerInternal {
|
||||
*/
|
||||
public abstract void onFailure(int error);
|
||||
}
|
||||
|
||||
/** Internal interface for proximity callback. */
|
||||
public abstract static class ProximityCallbackInternal {
|
||||
/**
|
||||
* @param distance the estimated distance of the user (in meter)
|
||||
* The distance will be PROXIMITY_UNKNOWN if the proximity sensing was inconclusive.
|
||||
*/
|
||||
public abstract void onProximityUpdate(double distance);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,11 +24,14 @@ import android.app.Service;
|
||||
import android.content.Intent;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.internal.util.Preconditions;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Objects;
|
||||
|
||||
|
||||
/**
|
||||
@@ -51,6 +54,7 @@ import java.lang.annotation.RetentionPolicy;
|
||||
*/
|
||||
@SystemApi
|
||||
public abstract class AttentionService extends Service {
|
||||
private static final String LOG_TAG = "AttentionService";
|
||||
/**
|
||||
* The {@link Intent} that must be declared as handled by the service. To be supported, the
|
||||
* service must also require the {@link android.Manifest.permission#BIND_ATTENTION_SERVICE}
|
||||
@@ -80,6 +84,9 @@ public abstract class AttentionService extends Service {
|
||||
/** Camera permission is not granted. */
|
||||
public static final int ATTENTION_FAILURE_CAMERA_PERMISSION_ABSENT = 6;
|
||||
|
||||
/** Users’ proximity is unknown (proximity sensing was inconclusive and is unsupported). */
|
||||
public static final double PROXIMITY_UNKNOWN = -1;
|
||||
|
||||
/**
|
||||
* Result codes for when attention check was successful.
|
||||
*
|
||||
@@ -118,6 +125,20 @@ public abstract class AttentionService extends Service {
|
||||
Preconditions.checkNotNull(callback);
|
||||
AttentionService.this.onCancelAttentionCheck(new AttentionCallback(callback));
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void onStartProximityUpdates(IProximityCallback callback) {
|
||||
Objects.requireNonNull(callback);
|
||||
AttentionService.this.onStartProximityUpdates(new ProximityCallback(callback));
|
||||
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void onStopProximityUpdates() {
|
||||
AttentionService.this.onStopProximityUpdates();
|
||||
}
|
||||
};
|
||||
|
||||
@Nullable
|
||||
@@ -143,6 +164,23 @@ public abstract class AttentionService extends Service {
|
||||
*/
|
||||
public abstract void onCancelAttentionCheck(@NonNull AttentionCallback callback);
|
||||
|
||||
/**
|
||||
* Requests the continuous updates of proximity signal via the provided callback,
|
||||
* until the given callback is unregistered.
|
||||
*
|
||||
* @param callback the callback to return the result to
|
||||
*/
|
||||
public void onStartProximityUpdates(@NonNull ProximityCallback callback) {
|
||||
Slog.w(LOG_TAG, "Override this method.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests to stop providing continuous updates until the callback is registered.
|
||||
*/
|
||||
public void onStopProximityUpdates() {
|
||||
Slog.w(LOG_TAG, "Override this method.");
|
||||
}
|
||||
|
||||
/** Callbacks for AttentionService results. */
|
||||
public static final class AttentionCallback {
|
||||
@NonNull private final IAttentionCallback mCallback;
|
||||
@@ -174,4 +212,26 @@ public abstract class AttentionService extends Service {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Callbacks for ProximityCallback results. */
|
||||
public static final class ProximityCallback {
|
||||
@NonNull private final WeakReference<IProximityCallback> mCallback;
|
||||
|
||||
private ProximityCallback(@NonNull IProximityCallback callback) {
|
||||
mCallback = new WeakReference<>(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param distance the estimated distance of the user (in meter)
|
||||
* The distance will be PROXIMITY_UNKNOWN if the proximity sensing was inconclusive.
|
||||
*
|
||||
*/
|
||||
public void onProximityUpdate(double distance) {
|
||||
try {
|
||||
mCallback.get().onProximityUpdate(distance);
|
||||
} catch (RemoteException e) {
|
||||
e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package android.service.attention;
|
||||
|
||||
import android.service.attention.IAttentionCallback;
|
||||
import android.service.attention.IProximityCallback;
|
||||
|
||||
/**
|
||||
* Interface for a concrete implementation to provide to the AttentionManagerService.
|
||||
@@ -26,4 +27,6 @@ import android.service.attention.IAttentionCallback;
|
||||
oneway interface IAttentionService {
|
||||
void checkAttention(IAttentionCallback callback);
|
||||
void cancelAttentionCheck(IAttentionCallback callback);
|
||||
void onStartProximityUpdates(IProximityCallback callback);
|
||||
void onStopProximityUpdates();
|
||||
}
|
||||
10
core/java/android/service/attention/IProximityCallback.aidl
Normal file
10
core/java/android/service/attention/IProximityCallback.aidl
Normal file
@@ -0,0 +1,10 @@
|
||||
package android.service.attention;
|
||||
|
||||
/**
|
||||
* Callback for onStartProximityUpdates request.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
oneway interface IProximityCallback {
|
||||
void onProximityUpdate(double distance);
|
||||
}
|
||||
@@ -22,6 +22,7 @@ import static android.content.Context.BIND_INCLUDE_CAPABILITIES;
|
||||
import static android.provider.DeviceConfig.NAMESPACE_ATTENTION_MANAGER_SERVICE;
|
||||
import static android.service.attention.AttentionService.ATTENTION_FAILURE_CANCELLED;
|
||||
import static android.service.attention.AttentionService.ATTENTION_FAILURE_UNKNOWN;
|
||||
import static android.service.attention.AttentionService.PROXIMITY_UNKNOWN;
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.NonNull;
|
||||
@@ -29,6 +30,7 @@ import android.annotation.Nullable;
|
||||
import android.app.ActivityThread;
|
||||
import android.attention.AttentionManagerInternal;
|
||||
import android.attention.AttentionManagerInternal.AttentionCallbackInternal;
|
||||
import android.attention.AttentionManagerInternal.ProximityCallbackInternal;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
@@ -57,6 +59,7 @@ import android.service.attention.AttentionService.AttentionFailureCodes;
|
||||
import android.service.attention.AttentionService.AttentionSuccessCodes;
|
||||
import android.service.attention.IAttentionCallback;
|
||||
import android.service.attention.IAttentionService;
|
||||
import android.service.attention.IProximityCallback;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Slog;
|
||||
|
||||
@@ -134,6 +137,15 @@ public class AttentionManagerService extends SystemService {
|
||||
@GuardedBy("mLock")
|
||||
AttentionCheck mCurrentAttentionCheck;
|
||||
|
||||
/**
|
||||
* A proxy for relaying proximity information between the Attention Service and the client.
|
||||
* The proxy will be initialized when the client calls onStartProximityUpdates and will be
|
||||
* disabled only when the client calls onStopProximityUpdates.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
@GuardedBy("mLock")
|
||||
ProximityUpdate mCurrentProximityUpdate;
|
||||
|
||||
public AttentionManagerService(Context context) {
|
||||
this(context, (PowerManager) context.getSystemService(Context.POWER_SERVICE),
|
||||
new Object(), null);
|
||||
@@ -315,6 +327,77 @@ public class AttentionManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests the continuous updates of proximity signal via the provided callback,
|
||||
* until the given callback is stopped.
|
||||
*
|
||||
* Calling this multiple times for duplicate requests will be no-ops, returning true.
|
||||
*
|
||||
* @return {@code true} if the framework was able to dispatch the request
|
||||
*/
|
||||
@VisibleForTesting
|
||||
boolean onStartProximityUpdates(ProximityCallbackInternal callbackInternal) {
|
||||
Objects.requireNonNull(callbackInternal);
|
||||
if (!mIsServiceEnabled) {
|
||||
Slog.w(LOG_TAG, "Trying to call onProximityUpdate() on an unsupported device.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isServiceAvailable()) {
|
||||
Slog.w(LOG_TAG, "Service is not available at this moment.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// don't allow proximity request in screen off state.
|
||||
// This behavior might change in the future.
|
||||
if (!mPowerManager.isInteractive()) {
|
||||
Slog.w(LOG_TAG, "Proximity Service is unavailable during screen off at this moment.");
|
||||
return false;
|
||||
}
|
||||
|
||||
synchronized (mLock) {
|
||||
// schedule shutting down the connection if no one resets this timer
|
||||
freeIfInactiveLocked();
|
||||
|
||||
// lazily start the service, which should be very lightweight to start
|
||||
bindLocked();
|
||||
|
||||
/*
|
||||
Prevent spamming with multiple requests, only one at a time is allowed.
|
||||
If there are use-cases for keeping track of multiple requests, we
|
||||
can refactor ProximityUpdate object to keep track of multiple internal callbacks.
|
||||
*/
|
||||
if (mCurrentProximityUpdate != null && mCurrentProximityUpdate.mStartedUpdates) {
|
||||
if (mCurrentProximityUpdate.mCallbackInternal == callbackInternal) {
|
||||
Slog.w(LOG_TAG, "Provided callback is already registered. Skipping.");
|
||||
return true;
|
||||
} else {
|
||||
// reject the new request since the old request is still alive.
|
||||
Slog.w(LOG_TAG, "New proximity update cannot be processed because there is "
|
||||
+ "already an ongoing update");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
mCurrentProximityUpdate = new ProximityUpdate(callbackInternal);
|
||||
return mCurrentProximityUpdate.startUpdates();
|
||||
}
|
||||
}
|
||||
|
||||
/** Cancels the specified proximity registration. */
|
||||
@VisibleForTesting
|
||||
void onStopProximityUpdates(ProximityCallbackInternal callbackInternal) {
|
||||
synchronized (mLock) {
|
||||
if (mCurrentProximityUpdate == null
|
||||
|| !mCurrentProximityUpdate.mCallbackInternal.equals(callbackInternal)
|
||||
|| !mCurrentProximityUpdate.mStartedUpdates) {
|
||||
Slog.w(LOG_TAG, "Cannot stop a non-current callback");
|
||||
return;
|
||||
}
|
||||
mCurrentProximityUpdate.cancelUpdates();
|
||||
mCurrentProximityUpdate = null;
|
||||
}
|
||||
}
|
||||
|
||||
@GuardedBy("mLock")
|
||||
@VisibleForTesting
|
||||
protected void freeIfInactiveLocked() {
|
||||
@@ -390,15 +473,18 @@ public class AttentionManagerService extends SystemService {
|
||||
ipw.println("Class=" + mComponentName.getClassName());
|
||||
ipw.decreaseIndent();
|
||||
}
|
||||
ipw.println("binding=" + mBinding);
|
||||
ipw.println("current attention check:");
|
||||
synchronized (mLock) {
|
||||
ipw.println("binding=" + mBinding);
|
||||
ipw.println("current attention check:");
|
||||
if (mCurrentAttentionCheck != null) {
|
||||
mCurrentAttentionCheck.dump(ipw);
|
||||
}
|
||||
if (mAttentionCheckCacheBuffer != null) {
|
||||
mAttentionCheckCacheBuffer.dump(ipw);
|
||||
}
|
||||
if (mCurrentProximityUpdate != null) {
|
||||
mCurrentProximityUpdate.dump(ipw);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -417,6 +503,17 @@ public class AttentionManagerService extends SystemService {
|
||||
public void cancelAttentionCheck(AttentionCallbackInternal callbackInternal) {
|
||||
AttentionManagerService.this.cancelAttentionCheck(callbackInternal);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onStartProximityUpdates(
|
||||
ProximityCallbackInternal callback) {
|
||||
return AttentionManagerService.this.onStartProximityUpdates(callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopProximityUpdates(ProximityCallbackInternal callback) {
|
||||
AttentionManagerService.this.onStopProximityUpdates(callback);
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@@ -536,6 +633,71 @@ public class AttentionManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
final class ProximityUpdate {
|
||||
private final ProximityCallbackInternal mCallbackInternal;
|
||||
private final IProximityCallback mIProximityCallback;
|
||||
private boolean mStartedUpdates;
|
||||
|
||||
ProximityUpdate(ProximityCallbackInternal callbackInternal) {
|
||||
mCallbackInternal = callbackInternal;
|
||||
mIProximityCallback = new IProximityCallback.Stub() {
|
||||
@Override
|
||||
public void onProximityUpdate(double distance) {
|
||||
synchronized (mLock) {
|
||||
mCallbackInternal.onProximityUpdate(distance);
|
||||
freeIfInactiveLocked();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
boolean startUpdates() {
|
||||
synchronized (mLock) {
|
||||
if (mStartedUpdates) {
|
||||
Slog.w(LOG_TAG, "Already registered to a proximity service.");
|
||||
return false;
|
||||
}
|
||||
if (mService == null) {
|
||||
Slog.w(LOG_TAG,
|
||||
"There is no service bound. Proximity update request rejected.");
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
mService.onStartProximityUpdates(mIProximityCallback);
|
||||
mStartedUpdates = true;
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(LOG_TAG, "Cannot call into the AttentionService", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void cancelUpdates() {
|
||||
synchronized (mLock) {
|
||||
if (mStartedUpdates) {
|
||||
if (mService == null) {
|
||||
mStartedUpdates = false;
|
||||
return;
|
||||
}
|
||||
try {
|
||||
mService.onStopProximityUpdates();
|
||||
mStartedUpdates = false;
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(LOG_TAG, "Cannot call into the AttentionService", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dump(IndentingPrintWriter ipw) {
|
||||
ipw.increaseIndent();
|
||||
ipw.println("is StartedUpdates=" + mStartedUpdates);
|
||||
ipw.decreaseIndent();
|
||||
}
|
||||
}
|
||||
|
||||
private void appendResultToAttentionCacheBuffer(AttentionCheckCache cache) {
|
||||
synchronized (mLock) {
|
||||
if (mAttentionCheckCacheBuffer == null) {
|
||||
@@ -593,6 +755,18 @@ public class AttentionManagerService extends SystemService {
|
||||
mCurrentAttentionCheck.mCallbackInternal.onFailure(ATTENTION_FAILURE_UNKNOWN);
|
||||
}
|
||||
}
|
||||
if (mCurrentProximityUpdate != null && mCurrentProximityUpdate.mStartedUpdates) {
|
||||
if (mService != null) {
|
||||
try {
|
||||
mService.onStartProximityUpdates(mCurrentProximityUpdate.mIProximityCallback);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(LOG_TAG, "Cannot call into the AttentionService", e);
|
||||
}
|
||||
} else {
|
||||
mCurrentProximityUpdate.cancelUpdates();
|
||||
mCurrentProximityUpdate = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@@ -609,7 +783,9 @@ public class AttentionManagerService extends SystemService {
|
||||
switch (msg.what) {
|
||||
// Do not occupy resources when not in use - unbind proactively.
|
||||
case CHECK_CONNECTION_EXPIRATION: {
|
||||
cancelAndUnbindLocked();
|
||||
synchronized (mLock) {
|
||||
cancelAndUnbindLocked();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -653,10 +829,15 @@ public class AttentionManagerService extends SystemService {
|
||||
@GuardedBy("mLock")
|
||||
private void cancelAndUnbindLocked() {
|
||||
synchronized (mLock) {
|
||||
if (mCurrentAttentionCheck == null) {
|
||||
if (mCurrentAttentionCheck == null && mCurrentProximityUpdate == null) {
|
||||
return;
|
||||
}
|
||||
cancel();
|
||||
if (mCurrentAttentionCheck != null) {
|
||||
cancel();
|
||||
}
|
||||
if (mCurrentProximityUpdate != null) {
|
||||
mCurrentProximityUpdate.cancelUpdates();
|
||||
}
|
||||
if (mService == null) {
|
||||
return;
|
||||
}
|
||||
@@ -702,7 +883,9 @@ public class AttentionManagerService extends SystemService {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (Intent.ACTION_SCREEN_OFF.equals(intent.getAction())) {
|
||||
cancelAndUnbindLocked();
|
||||
synchronized (mLock) {
|
||||
cancelAndUnbindLocked();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -730,8 +913,27 @@ public class AttentionManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
class TestableProximityCallbackInternal extends ProximityCallbackInternal {
|
||||
private double mLastCallbackCode = PROXIMITY_UNKNOWN;
|
||||
|
||||
@Override
|
||||
public void onProximityUpdate(double distance) {
|
||||
mLastCallbackCode = distance;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
mLastCallbackCode = PROXIMITY_UNKNOWN;
|
||||
}
|
||||
|
||||
public double getLastCallbackCode() {
|
||||
return mLastCallbackCode;
|
||||
}
|
||||
}
|
||||
|
||||
final TestableAttentionCallbackInternal mTestableAttentionCallback =
|
||||
new TestableAttentionCallbackInternal();
|
||||
final TestableProximityCallbackInternal mTestableProximityCallback =
|
||||
new TestableProximityCallbackInternal();
|
||||
|
||||
@Override
|
||||
public int onCommand(@Nullable final String cmd) {
|
||||
@@ -749,6 +951,10 @@ public class AttentionManagerService extends SystemService {
|
||||
return cmdCallCheckAttention();
|
||||
case "cancelCheckAttention":
|
||||
return cmdCallCancelAttention();
|
||||
case "onStartProximityUpdates":
|
||||
return cmdCallOnStartProximityUpdates();
|
||||
case "onStopProximityUpdates":
|
||||
return cmdCallOnStopProximityUpdates();
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid argument");
|
||||
}
|
||||
@@ -758,6 +964,8 @@ public class AttentionManagerService extends SystemService {
|
||||
return cmdClearTestableAttentionService();
|
||||
case "getLastTestCallbackCode":
|
||||
return cmdGetLastTestCallbackCode();
|
||||
case "getLastTestProximityCallbackCode":
|
||||
return cmdGetLastTestProximityCallbackCode();
|
||||
default:
|
||||
return handleDefaultCommands(cmd);
|
||||
}
|
||||
@@ -782,6 +990,7 @@ public class AttentionManagerService extends SystemService {
|
||||
private int cmdClearTestableAttentionService() {
|
||||
sTestAttentionServicePackage = "";
|
||||
mTestableAttentionCallback.reset();
|
||||
mTestableProximityCallback.reset();
|
||||
resetStates();
|
||||
return 0;
|
||||
}
|
||||
@@ -800,6 +1009,20 @@ public class AttentionManagerService extends SystemService {
|
||||
return 0;
|
||||
}
|
||||
|
||||
private int cmdCallOnStartProximityUpdates() {
|
||||
final PrintWriter out = getOutPrintWriter();
|
||||
boolean calledSuccessfully = onStartProximityUpdates(mTestableProximityCallback);
|
||||
out.println(calledSuccessfully ? "true" : "false");
|
||||
return 0;
|
||||
}
|
||||
|
||||
private int cmdCallOnStopProximityUpdates() {
|
||||
final PrintWriter out = getOutPrintWriter();
|
||||
onStopProximityUpdates(mTestableProximityCallback);
|
||||
out.println("true");
|
||||
return 0;
|
||||
}
|
||||
|
||||
private int cmdResolveAttentionServiceComponent() {
|
||||
final PrintWriter out = getOutPrintWriter();
|
||||
ComponentName resolvedComponent = resolveAttentionService(mContext);
|
||||
@@ -813,7 +1036,16 @@ public class AttentionManagerService extends SystemService {
|
||||
return 0;
|
||||
}
|
||||
|
||||
private int cmdGetLastTestProximityCallbackCode() {
|
||||
final PrintWriter out = getOutPrintWriter();
|
||||
out.println(mTestableProximityCallback.getLastCallbackCode());
|
||||
return 0;
|
||||
}
|
||||
|
||||
private void resetStates() {
|
||||
synchronized (mLock) {
|
||||
mCurrentProximityUpdate = null;
|
||||
}
|
||||
mComponentName = resolveAttentionService(mContext);
|
||||
}
|
||||
|
||||
@@ -844,11 +1076,24 @@ public class AttentionManagerService extends SystemService {
|
||||
+ " (to see the result, call getLastTestCallbackCode)");
|
||||
out.println(" := false, otherwise");
|
||||
out.println(" call cancelCheckAttention: Cancels check attention");
|
||||
out.println(" call onStartProximityUpdates: Calls onStartProximityUpdates");
|
||||
out.println(" ---returns:");
|
||||
out.println(
|
||||
" := true, if the request was successfully dispatched to the service "
|
||||
+ "implementation."
|
||||
+ " (to see the result, call getLastTestProximityCallbackCode)");
|
||||
out.println(" := false, otherwise");
|
||||
out.println(" call onStopProximityUpdates: Cancels proximity updates");
|
||||
out.println(" getLastTestCallbackCode");
|
||||
out.println(" ---returns:");
|
||||
out.println(
|
||||
" := An integer, representing the last callback code received from the "
|
||||
+ "bounded implementation. If none, it will return -1");
|
||||
out.println(" getLastTestProximityCallbackCode");
|
||||
out.println(" ---returns:");
|
||||
out.println(
|
||||
" := A double, representing the last proximity value received from the "
|
||||
+ "bounded implementation. If none, it will return -1.0");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,14 +24,20 @@ import static com.android.server.attention.AttentionManagerService.KEY_STALE_AFT
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static junit.framework.Assert.fail;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||
|
||||
import android.attention.AttentionManagerInternal.AttentionCallbackInternal;
|
||||
import android.attention.AttentionManagerInternal.ProximityCallbackInternal;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.os.IBinder;
|
||||
@@ -42,6 +48,7 @@ import android.os.RemoteException;
|
||||
import android.provider.DeviceConfig;
|
||||
import android.service.attention.IAttentionCallback;
|
||||
import android.service.attention.IAttentionService;
|
||||
import android.service.attention.IProximityCallback;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
@@ -49,6 +56,7 @@ import com.android.server.attention.AttentionManagerService.AttentionCheck;
|
||||
import com.android.server.attention.AttentionManagerService.AttentionCheckCache;
|
||||
import com.android.server.attention.AttentionManagerService.AttentionCheckCacheBuffer;
|
||||
import com.android.server.attention.AttentionManagerService.AttentionHandler;
|
||||
import com.android.server.attention.AttentionManagerService.ProximityUpdate;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -59,10 +67,13 @@ import org.mockito.MockitoAnnotations;
|
||||
/**
|
||||
* Tests for {@link com.android.server.attention.AttentionManagerService}
|
||||
*/
|
||||
@SuppressWarnings("GuardedBy")
|
||||
@SmallTest
|
||||
public class AttentionManagerServiceTest {
|
||||
private static final double PROXIMITY_SUCCESS_STATE = 1.0;
|
||||
private AttentionManagerService mSpyAttentionManager;
|
||||
private final int mTimeout = 1000;
|
||||
private final Object mLock = new Object();
|
||||
@Mock
|
||||
private AttentionCallbackInternal mMockAttentionCallbackInternal;
|
||||
@Mock
|
||||
@@ -73,6 +84,8 @@ public class AttentionManagerServiceTest {
|
||||
private IThermalService mMockIThermalService;
|
||||
@Mock
|
||||
Context mContext;
|
||||
@Mock
|
||||
private ProximityCallbackInternal mMockProximityCallbackInternal;
|
||||
|
||||
@Before
|
||||
public void setUp() throws RemoteException {
|
||||
@@ -84,7 +97,6 @@ public class AttentionManagerServiceTest {
|
||||
doReturn(true).when(mMockIPowerManager).isInteractive();
|
||||
mPowerManager = new PowerManager(mContext, mMockIPowerManager, mMockIThermalService, null);
|
||||
|
||||
Object mLock = new Object();
|
||||
// setup a spy on attention manager
|
||||
AttentionManagerService attentionManager = new AttentionManagerService(
|
||||
mContext,
|
||||
@@ -100,6 +112,119 @@ public class AttentionManagerServiceTest {
|
||||
mSpyAttentionManager);
|
||||
mSpyAttentionManager.mCurrentAttentionCheck = attentionCheck;
|
||||
mSpyAttentionManager.mService = new MockIAttentionService();
|
||||
doNothing().when(mSpyAttentionManager).freeIfInactiveLocked();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegisterProximityUpdates_returnFalseWhenServiceDisabled() {
|
||||
mSpyAttentionManager.mIsServiceEnabled = false;
|
||||
|
||||
assertThat(mSpyAttentionManager.onStartProximityUpdates(mMockProximityCallbackInternal))
|
||||
.isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegisterProximityUpdates_returnFalseWhenServiceUnavailable() {
|
||||
mSpyAttentionManager.mIsServiceEnabled = true;
|
||||
doReturn(false).when(mSpyAttentionManager).isServiceAvailable();
|
||||
|
||||
assertThat(mSpyAttentionManager.onStartProximityUpdates(mMockProximityCallbackInternal))
|
||||
.isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegisterProximityUpdates_returnFalseWhenPowerManagerNotInteract()
|
||||
throws RemoteException {
|
||||
mSpyAttentionManager.mIsServiceEnabled = true;
|
||||
doReturn(true).when(mSpyAttentionManager).isServiceAvailable();
|
||||
doReturn(false).when(mMockIPowerManager).isInteractive();
|
||||
|
||||
assertThat(mSpyAttentionManager.onStartProximityUpdates(mMockProximityCallbackInternal))
|
||||
.isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegisterProximityUpdates_callOnSuccess() throws RemoteException {
|
||||
mSpyAttentionManager.mIsServiceEnabled = true;
|
||||
doReturn(true).when(mSpyAttentionManager).isServiceAvailable();
|
||||
doReturn(true).when(mMockIPowerManager).isInteractive();
|
||||
|
||||
assertThat(mSpyAttentionManager.onStartProximityUpdates(mMockProximityCallbackInternal))
|
||||
.isTrue();
|
||||
verify(mMockProximityCallbackInternal, times(1))
|
||||
.onProximityUpdate(PROXIMITY_SUCCESS_STATE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegisterProximityUpdates_callOnSuccessTwiceInARow() throws RemoteException {
|
||||
mSpyAttentionManager.mIsServiceEnabled = true;
|
||||
doReturn(true).when(mSpyAttentionManager).isServiceAvailable();
|
||||
doReturn(true).when(mMockIPowerManager).isInteractive();
|
||||
|
||||
assertThat(mSpyAttentionManager.onStartProximityUpdates(mMockProximityCallbackInternal))
|
||||
.isTrue();
|
||||
|
||||
ProximityUpdate prevProximityUpdate = mSpyAttentionManager.mCurrentProximityUpdate;
|
||||
assertThat(mSpyAttentionManager.onStartProximityUpdates(mMockProximityCallbackInternal))
|
||||
.isTrue();
|
||||
assertThat(mSpyAttentionManager.mCurrentProximityUpdate).isEqualTo(prevProximityUpdate);
|
||||
verify(mMockProximityCallbackInternal, times(1))
|
||||
.onProximityUpdate(PROXIMITY_SUCCESS_STATE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnregisterProximityUpdates_noCrashWhenNoCallbackIsRegistered() {
|
||||
mSpyAttentionManager.onStopProximityUpdates(mMockProximityCallbackInternal);
|
||||
verifyZeroInteractions(mMockProximityCallbackInternal);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnregisterProximityUpdates_noCrashWhenCallbackMismatched()
|
||||
throws RemoteException {
|
||||
mSpyAttentionManager.mIsServiceEnabled = true;
|
||||
doReturn(true).when(mSpyAttentionManager).isServiceAvailable();
|
||||
doReturn(true).when(mMockIPowerManager).isInteractive();
|
||||
mSpyAttentionManager.onStartProximityUpdates(mMockProximityCallbackInternal);
|
||||
verify(mMockProximityCallbackInternal, times(1))
|
||||
.onProximityUpdate(PROXIMITY_SUCCESS_STATE);
|
||||
|
||||
ProximityCallbackInternal mismatchedCallback = new ProximityCallbackInternal() {
|
||||
@Override
|
||||
public void onProximityUpdate(double distance) {
|
||||
fail("Callback shouldn't have responded.");
|
||||
}
|
||||
};
|
||||
mSpyAttentionManager.onStopProximityUpdates(mismatchedCallback);
|
||||
|
||||
verifyNoMoreInteractions(mMockProximityCallbackInternal);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnregisterProximityUpdates_cancelRegistrationWhenMatched()
|
||||
throws RemoteException {
|
||||
mSpyAttentionManager.mIsServiceEnabled = true;
|
||||
doReturn(true).when(mSpyAttentionManager).isServiceAvailable();
|
||||
doReturn(true).when(mMockIPowerManager).isInteractive();
|
||||
mSpyAttentionManager.onStartProximityUpdates(mMockProximityCallbackInternal);
|
||||
mSpyAttentionManager.onStopProximityUpdates(mMockProximityCallbackInternal);
|
||||
|
||||
assertThat(mSpyAttentionManager.mCurrentProximityUpdate).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnregisterProximityUpdates_noCrashWhenTwiceInARow() throws RemoteException {
|
||||
// Attention Service registers proximity updates.
|
||||
mSpyAttentionManager.mIsServiceEnabled = true;
|
||||
doReturn(true).when(mSpyAttentionManager).isServiceAvailable();
|
||||
doReturn(true).when(mMockIPowerManager).isInteractive();
|
||||
mSpyAttentionManager.onStartProximityUpdates(mMockProximityCallbackInternal);
|
||||
verify(mMockProximityCallbackInternal, times(1))
|
||||
.onProximityUpdate(PROXIMITY_SUCCESS_STATE);
|
||||
|
||||
// Attention Service unregisters the proximity update twice in a row.
|
||||
mSpyAttentionManager.onStopProximityUpdates(mMockProximityCallbackInternal);
|
||||
mSpyAttentionManager.onStopProximityUpdates(mMockProximityCallbackInternal);
|
||||
verifyNoMoreInteractions(mMockProximityCallbackInternal);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -127,7 +252,6 @@ public class AttentionManagerServiceTest {
|
||||
mSpyAttentionManager.mIsServiceEnabled = true;
|
||||
doReturn(true).when(mSpyAttentionManager).isServiceAvailable();
|
||||
doReturn(true).when(mMockIPowerManager).isInteractive();
|
||||
doNothing().when(mSpyAttentionManager).freeIfInactiveLocked();
|
||||
mSpyAttentionManager.mCurrentAttentionCheck = null;
|
||||
|
||||
AttentionCallbackInternal callback = Mockito.mock(AttentionCallbackInternal.class);
|
||||
@@ -213,6 +337,13 @@ public class AttentionManagerServiceTest {
|
||||
public void cancelAttentionCheck(IAttentionCallback callback) {
|
||||
}
|
||||
|
||||
public void onStartProximityUpdates(IProximityCallback callback) throws RemoteException {
|
||||
callback.onProximityUpdate(PROXIMITY_SUCCESS_STATE);
|
||||
}
|
||||
|
||||
public void onStopProximityUpdates() throws RemoteException {
|
||||
}
|
||||
|
||||
public IBinder asBinder() {
|
||||
return null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user