summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Kenneth Ford <kennethford@google.com> 2022-01-29 22:54:38 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2022-01-29 22:54:38 +0000
commit3523eab795973aaa0bd52f9a0fcc7af9f69f7c3c (patch)
tree011a09008eb9f0968690164aec7b7f4fa02427c1
parente1d6e207276628011cb43a60216f7e7832fdfd4f (diff)
parentf18a8b8534e20eb1c39364e1aebc67fa87257b4d (diff)
Merge changes from topic "device_state_manager"
* changes: Rename cancelRequest API to cancelStateRequest and remove the request parameter Updates OverrideRequestController to allow for one override request at max
-rw-r--r--core/api/test-current.txt2
-rw-r--r--core/java/android/hardware/devicestate/DeviceStateManager.java13
-rw-r--r--core/java/android/hardware/devicestate/DeviceStateManagerGlobal.java39
-rw-r--r--core/java/android/hardware/devicestate/DeviceStateRequest.java3
-rw-r--r--core/java/android/hardware/devicestate/IDeviceStateManager.aidl16
-rw-r--r--core/java/android/hardware/devicestate/IDeviceStateManagerCallback.aidl10
-rw-r--r--core/tests/devicestatetests/src/android/hardware/devicestate/DeviceStateManagerGlobalTest.java35
-rw-r--r--services/core/java/com/android/server/devicestate/DeviceStateManagerService.java69
-rw-r--r--services/core/java/com/android/server/devicestate/DeviceStateManagerShellCommand.java5
-rw-r--r--services/core/java/com/android/server/devicestate/OverrideRequestController.java215
-rw-r--r--services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java19
-rw-r--r--services/tests/servicestests/src/com/android/server/devicestate/OverrideRequestControllerTest.java93
12 files changed, 144 insertions, 375 deletions
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index c39394bb1e4f..15148a93cbe7 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -1104,7 +1104,7 @@ package android.hardware.camera2 {
package android.hardware.devicestate {
public final class DeviceStateManager {
- method @RequiresPermission(value=android.Manifest.permission.CONTROL_DEVICE_STATE, conditional=true) public void cancelRequest(@NonNull android.hardware.devicestate.DeviceStateRequest);
+ method @RequiresPermission(value=android.Manifest.permission.CONTROL_DEVICE_STATE, conditional=true) public void cancelStateRequest();
method @NonNull public int[] getSupportedStates();
method public void registerCallback(@NonNull java.util.concurrent.Executor, @NonNull android.hardware.devicestate.DeviceStateManager.DeviceStateCallback);
method @RequiresPermission(value=android.Manifest.permission.CONTROL_DEVICE_STATE, conditional=true) public void requestState(@NonNull android.hardware.devicestate.DeviceStateRequest, @Nullable java.util.concurrent.Executor, @Nullable android.hardware.devicestate.DeviceStateRequest.Callback);
diff --git a/core/java/android/hardware/devicestate/DeviceStateManager.java b/core/java/android/hardware/devicestate/DeviceStateManager.java
index b06d076fe08e..30aa4db938da 100644
--- a/core/java/android/hardware/devicestate/DeviceStateManager.java
+++ b/core/java/android/hardware/devicestate/DeviceStateManager.java
@@ -79,9 +79,9 @@ public final class DeviceStateManager {
* <ul>
* <li>The system deems the request can no longer be honored, for example if the requested
* state becomes unsupported.
- * <li>A call to {@link #cancelRequest(DeviceStateRequest)}.
+ * <li>A call to {@link #cancelStateRequest}.
* <li>Another processes submits a request succeeding this request in which case the request
- * will be suspended until the interrupting request is canceled.
+ * will be canceled.
* </ul>
* However, this behavior can be changed by setting flags on the {@link DeviceStateRequest}.
*
@@ -100,19 +100,18 @@ public final class DeviceStateManager {
}
/**
- * Cancels a {@link DeviceStateRequest request} previously submitted with a call to
+ * Cancels the active {@link DeviceStateRequest} previously submitted with a call to
* {@link #requestState(DeviceStateRequest, Executor, DeviceStateRequest.Callback)}.
* <p>
- * This method is noop if the {@code request} has not been submitted with a call to
- * {@link #requestState(DeviceStateRequest, Executor, DeviceStateRequest.Callback)}.
+ * This method is noop if there is no request currently active.
*
* @throws SecurityException if the caller is neither the current top-focused activity nor if
* the {@link android.Manifest.permission#CONTROL_DEVICE_STATE} permission is held.
*/
@RequiresPermission(value = android.Manifest.permission.CONTROL_DEVICE_STATE,
conditional = true)
- public void cancelRequest(@NonNull DeviceStateRequest request) {
- mGlobal.cancelRequest(request);
+ public void cancelStateRequest() {
+ mGlobal.cancelStateRequest();
}
/**
diff --git a/core/java/android/hardware/devicestate/DeviceStateManagerGlobal.java b/core/java/android/hardware/devicestate/DeviceStateManagerGlobal.java
index 85e70b0fb3e9..aba538f51043 100644
--- a/core/java/android/hardware/devicestate/DeviceStateManagerGlobal.java
+++ b/core/java/android/hardware/devicestate/DeviceStateManagerGlobal.java
@@ -151,20 +151,14 @@ public final class DeviceStateManagerGlobal {
* Cancels a {@link DeviceStateRequest request} previously submitted with a call to
* {@link #requestState(DeviceStateRequest, Executor, DeviceStateRequest.Callback)}.
*
- * @see DeviceStateManager#cancelRequest(DeviceStateRequest)
+ * @see DeviceStateManager#cancelStateRequest
*/
- public void cancelRequest(@NonNull DeviceStateRequest request) {
+ public void cancelStateRequest() {
synchronized (mLock) {
registerCallbackIfNeededLocked();
- final IBinder token = findRequestTokenLocked(request);
- if (token == null) {
- // This request has not been submitted.
- return;
- }
-
try {
- mDeviceStateManager.cancelRequest(token);
+ mDeviceStateManager.cancelStateRequest();
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
@@ -299,20 +293,6 @@ public final class DeviceStateManagerGlobal {
/**
* Handles a call from the server that a request for the supplied {@code token} has become
- * suspended.
- */
- private void handleRequestSuspended(IBinder token) {
- DeviceStateRequestWrapper request;
- synchronized (mLock) {
- request = mRequests.get(token);
- }
- if (request != null) {
- request.notifyRequestSuspended();
- }
- }
-
- /**
- * Handles a call from the server that a request for the supplied {@code token} has become
* canceled.
*/
private void handleRequestCanceled(IBinder token) {
@@ -337,11 +317,6 @@ public final class DeviceStateManagerGlobal {
}
@Override
- public void onRequestSuspended(IBinder token) {
- handleRequestSuspended(token);
- }
-
- @Override
public void onRequestCanceled(IBinder token) {
handleRequestCanceled(token);
}
@@ -395,14 +370,6 @@ public final class DeviceStateManagerGlobal {
mExecutor.execute(() -> mCallback.onRequestActivated(mRequest));
}
- void notifyRequestSuspended() {
- if (mCallback == null) {
- return;
- }
-
- mExecutor.execute(() -> mCallback.onRequestSuspended(mRequest));
- }
-
void notifyRequestCanceled() {
if (mCallback == null) {
return;
diff --git a/core/java/android/hardware/devicestate/DeviceStateRequest.java b/core/java/android/hardware/devicestate/DeviceStateRequest.java
index df488d2f6df1..893d765e48da 100644
--- a/core/java/android/hardware/devicestate/DeviceStateRequest.java
+++ b/core/java/android/hardware/devicestate/DeviceStateRequest.java
@@ -32,8 +32,7 @@ import java.util.concurrent.Executor;
* DeviceStateRequest.Callback)}.
* <p>
* By default, the request is kept active until a call to
- * {@link DeviceStateManager#cancelRequest(DeviceStateRequest)} or until one of the following
- * occurs:
+ * {@link DeviceStateManager#cancelStateRequest} or until one of the following occurs:
* <ul>
* <li>Another processes submits a request succeeding this request in which case the request
* will be suspended until the interrupting request is canceled.
diff --git a/core/java/android/hardware/devicestate/IDeviceStateManager.aidl b/core/java/android/hardware/devicestate/IDeviceStateManager.aidl
index 14ed03d09fd0..e450e42497a0 100644
--- a/core/java/android/hardware/devicestate/IDeviceStateManager.aidl
+++ b/core/java/android/hardware/devicestate/IDeviceStateManager.aidl
@@ -41,8 +41,9 @@ interface IDeviceStateManager {
* previously registered with {@link #registerCallback(IDeviceStateManagerCallback)} before a
* call to this method.
*
- * @param token the request token previously registered with
- * {@link #requestState(IBinder, int, int)}
+ * @param token the request token provided
+ * @param state the state of device the request is asking for
+ * @param flags any flags that correspond to the request
*
* @throws IllegalStateException if a callback has not yet been registered for the calling
* process.
@@ -52,14 +53,11 @@ interface IDeviceStateManager {
void requestState(IBinder token, int state, int flags);
/**
- * Cancels a request previously submitted with a call to
+ * Cancels the active request previously submitted with a call to
* {@link #requestState(IBinder, int, int)}.
*
- * @param token the request token previously registered with
- * {@link #requestState(IBinder, int, int)}
- *
- * @throws IllegalStateException if the supplied {@code token} has not been previously
- * requested.
+ * @throws IllegalStateException if a callback has not yet been registered for the calling
+ * process.
*/
- void cancelRequest(IBinder token);
+ void cancelStateRequest();
}
diff --git a/core/java/android/hardware/devicestate/IDeviceStateManagerCallback.aidl b/core/java/android/hardware/devicestate/IDeviceStateManagerCallback.aidl
index efb9888fb6ba..348690f65e78 100644
--- a/core/java/android/hardware/devicestate/IDeviceStateManagerCallback.aidl
+++ b/core/java/android/hardware/devicestate/IDeviceStateManagerCallback.aidl
@@ -41,16 +41,6 @@ interface IDeviceStateManagerCallback {
oneway void onRequestActive(IBinder token);
/**
- * Called to notify the callback that a request has become suspended. Guaranteed to be called
- * before a subsequent call to {@link #onDeviceStateInfoChanged(DeviceStateInfo)} if the request
- * becoming suspended resulted in a change of device state info.
- *
- * @param token the request token previously registered with
- * {@link IDeviceStateManager#requestState(IBinder, int, int)}
- */
- oneway void onRequestSuspended(IBinder token);
-
- /**
* Called to notify the callback that a request has become canceled. No further callbacks will
* be triggered for this request. Guaranteed to be called before a subsequent call to
* {@link #onDeviceStateInfoChanged(DeviceStateInfo)} if the request becoming canceled resulted
diff --git a/core/tests/devicestatetests/src/android/hardware/devicestate/DeviceStateManagerGlobalTest.java b/core/tests/devicestatetests/src/android/hardware/devicestate/DeviceStateManagerGlobalTest.java
index db63e6e0b187..4c247427ef8f 100644
--- a/core/tests/devicestatetests/src/android/hardware/devicestate/DeviceStateManagerGlobalTest.java
+++ b/core/tests/devicestatetests/src/android/hardware/devicestate/DeviceStateManagerGlobalTest.java
@@ -38,7 +38,6 @@ import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.mockito.Mockito;
-import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
@@ -155,7 +154,7 @@ public final class DeviceStateManagerGlobalTest {
verify(callback).onStateChanged(eq(OTHER_DEVICE_STATE));
Mockito.reset(callback);
- mDeviceStateManagerGlobal.cancelRequest(request);
+ mDeviceStateManagerGlobal.cancelStateRequest();
verify(callback).onStateChanged(eq(mService.getBaseState()));
}
@@ -172,7 +171,7 @@ public final class DeviceStateManagerGlobalTest {
verify(callback).onRequestActivated(eq(request));
Mockito.reset(callback);
- mDeviceStateManagerGlobal.cancelRequest(request);
+ mDeviceStateManagerGlobal.cancelStateRequest();
verify(callback).onRequestCanceled(eq(request));
}
@@ -203,13 +202,13 @@ public final class DeviceStateManagerGlobalTest {
private int[] mSupportedStates = new int[] { DEFAULT_DEVICE_STATE, OTHER_DEVICE_STATE };
private int mBaseState = DEFAULT_DEVICE_STATE;
- private ArrayList<Request> mRequests = new ArrayList<>();
+ private Request mRequest;
private Set<IDeviceStateManagerCallback> mCallbacks = new HashSet<>();
private DeviceStateInfo getInfo() {
- final int mergedState = mRequests.isEmpty()
- ? mBaseState : mRequests.get(mRequests.size() - 1).state;
+ final int mergedState = mRequest == null
+ ? mBaseState : mRequest.state;
return new DeviceStateInfo(mSupportedStates, mBaseState, mergedState);
}
@@ -245,11 +244,10 @@ public final class DeviceStateManagerGlobalTest {
@Override
public void requestState(IBinder token, int state, int flags) {
- if (!mRequests.isEmpty()) {
- final Request topRequest = mRequests.get(mRequests.size() - 1);
+ if (mRequest != null) {
for (IDeviceStateManagerCallback callback : mCallbacks) {
try {
- callback.onRequestSuspended(topRequest.token);
+ callback.onRequestCanceled(mRequest.token);
} catch (RemoteException e) {
// Do nothing. Should never happen.
}
@@ -257,7 +255,7 @@ public final class DeviceStateManagerGlobalTest {
}
final Request request = new Request(token, state, flags);
- mRequests.add(request);
+ mRequest = request;
notifyDeviceStateInfoChanged();
for (IDeviceStateManagerCallback callback : mCallbacks) {
@@ -270,20 +268,9 @@ public final class DeviceStateManagerGlobalTest {
}
@Override
- public void cancelRequest(IBinder token) {
- int index = -1;
- for (int i = 0; i < mRequests.size(); i++) {
- if (mRequests.get(i).token.equals(token)) {
- index = i;
- break;
- }
- }
-
- if (index == -1) {
- throw new IllegalArgumentException("Unknown request: " + token);
- }
-
- mRequests.remove(index);
+ public void cancelStateRequest() {
+ IBinder token = mRequest.token;
+ mRequest = null;
for (IDeviceStateManagerCallback callback : mCallbacks) {
try {
callback.onRequestCanceled(token);
diff --git a/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java b/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
index c2ca3a502153..d0e39ccb3214 100644
--- a/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
+++ b/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
@@ -23,7 +23,6 @@ import static android.hardware.devicestate.DeviceStateManager.MINIMUM_DEVICE_STA
import static com.android.server.devicestate.DeviceState.FLAG_CANCEL_OVERRIDE_REQUESTS;
import static com.android.server.devicestate.OverrideRequestController.STATUS_ACTIVE;
import static com.android.server.devicestate.OverrideRequestController.STATUS_CANCELED;
-import static com.android.server.devicestate.OverrideRequestController.STATUS_SUSPENDED;
import android.annotation.IntDef;
import android.annotation.IntRange;
@@ -348,7 +347,7 @@ public final class DeviceStateManagerService extends SystemService {
mBaseState = Optional.of(baseState);
if (baseState.hasFlag(FLAG_CANCEL_OVERRIDE_REQUESTS)) {
- mOverrideRequestController.cancelOverrideRequests();
+ mOverrideRequestController.cancelOverrideRequest();
}
mOverrideRequestController.handleBaseStateChanged();
updatePendingStateLocked();
@@ -503,7 +502,7 @@ public final class DeviceStateManagerService extends SystemService {
@OverrideRequestController.RequestStatus int status) {
if (status == STATUS_ACTIVE) {
mActiveOverride = Optional.of(request);
- } else if (status == STATUS_SUSPENDED || status == STATUS_CANCELED) {
+ } else if (status == STATUS_CANCELED) {
if (mActiveOverride.isPresent() && mActiveOverride.get() == request) {
mActiveOverride = Optional.empty();
}
@@ -528,8 +527,6 @@ public final class DeviceStateManagerService extends SystemService {
// Schedule the notification now.
processRecord.notifyRequestActiveAsync(request.getToken());
}
- } else if (status == STATUS_SUSPENDED) {
- processRecord.notifyRequestSuspendedAsync(request.getToken());
} else {
processRecord.notifyRequestCanceledAsync(request.getToken());
}
@@ -595,15 +592,14 @@ public final class DeviceStateManagerService extends SystemService {
}
}
- private void cancelRequestInternal(int callingPid, @NonNull IBinder token) {
+ private void cancelStateRequestInternal(int callingPid) {
synchronized (mLock) {
final ProcessRecord processRecord = mProcessRecords.get(callingPid);
if (processRecord == null) {
throw new IllegalStateException("Process " + callingPid
+ " has no registered callback.");
}
-
- mOverrideRequestController.cancelRequest(token);
+ mActiveOverride.ifPresent(mOverrideRequestController::cancelRequest);
}
}
@@ -628,6 +624,23 @@ public final class DeviceStateManagerService extends SystemService {
}
}
+ /**
+ * Allow top processes to request or cancel a device state change. If the calling process ID is
+ * not the top app, then check if this process holds the CONTROL_DEVICE_STATE permission.
+ * @param callingPid
+ */
+ private void checkCanControlDeviceState(int callingPid) {
+ // Allow top processes to request a device state change
+ // If the calling process ID is not the top app, then we check if this process
+ // holds a permission to CONTROL_DEVICE_STATE
+ final WindowProcessController topApp = mActivityTaskManagerInternal.getTopApp();
+ if (topApp == null || topApp.getPid() != callingPid) {
+ getContext().enforceCallingOrSelfPermission(CONTROL_DEVICE_STATE,
+ "Permission required to request device state, "
+ + "or the call must come from the top focused app.");
+ }
+ }
+
private final class DeviceStateProviderListener implements DeviceStateProvider.Listener {
@Override
public void onSupportedDeviceStatesChanged(DeviceState[] newDeviceStates) {
@@ -716,24 +729,6 @@ public final class DeviceStateManagerService extends SystemService {
});
}
- public void notifyRequestSuspendedAsync(IBinder token) {
- @RequestStatus Integer lastStatus = mLastNotifiedStatus.get(token);
- if (lastStatus != null
- && (lastStatus == STATUS_SUSPENDED || lastStatus == STATUS_CANCELED)) {
- return;
- }
-
- mLastNotifiedStatus.put(token, STATUS_SUSPENDED);
- mHandler.post(() -> {
- try {
- mCallback.onRequestSuspended(token);
- } catch (RemoteException ex) {
- Slog.w(TAG, "Failed to notify process " + mPid + " that request state changed.",
- ex);
- }
- });
- }
-
public void notifyRequestCanceledAsync(IBinder token) {
@RequestStatus Integer lastStatus = mLastNotifiedStatus.get(token);
if (lastStatus != null && lastStatus == STATUS_CANCELED) {
@@ -782,12 +777,7 @@ public final class DeviceStateManagerService extends SystemService {
// Allow top processes to request a device state change
// If the calling process ID is not the top app, then we check if this process
// holds a permission to CONTROL_DEVICE_STATE
- final WindowProcessController topApp = mActivityTaskManagerInternal.getTopApp();
- if (topApp.getPid() != callingPid) {
- getContext().enforceCallingOrSelfPermission(CONTROL_DEVICE_STATE,
- "Permission required to request device state, "
- + "or the call must come from the top focused app.");
- }
+ checkCanControlDeviceState(callingPid);
if (token == null) {
throw new IllegalArgumentException("Request token must not be null.");
@@ -802,25 +792,16 @@ public final class DeviceStateManagerService extends SystemService {
}
@Override // Binder call
- public void cancelRequest(IBinder token) {
+ public void cancelStateRequest() {
final int callingPid = Binder.getCallingPid();
// Allow top processes to cancel a device state change
// If the calling process ID is not the top app, then we check if this process
// holds a permission to CONTROL_DEVICE_STATE
- final WindowProcessController topApp = mActivityTaskManagerInternal.getTopApp();
- if (topApp.getPid() != callingPid) {
- getContext().enforceCallingOrSelfPermission(CONTROL_DEVICE_STATE,
- "Permission required to cancel device state, "
- + "or the call must come from the top focused app.");
- }
-
- if (token == null) {
- throw new IllegalArgumentException("Request token must not be null.");
- }
+ checkCanControlDeviceState(callingPid);
final long callingIdentity = Binder.clearCallingIdentity();
try {
- cancelRequestInternal(callingPid, token);
+ cancelStateRequestInternal(callingPid);
} finally {
Binder.restoreCallingIdentity(callingIdentity);
}
diff --git a/services/core/java/com/android/server/devicestate/DeviceStateManagerShellCommand.java b/services/core/java/com/android/server/devicestate/DeviceStateManagerShellCommand.java
index eed68f8b1300..659ee75de453 100644
--- a/services/core/java/com/android/server/devicestate/DeviceStateManagerShellCommand.java
+++ b/services/core/java/com/android/server/devicestate/DeviceStateManagerShellCommand.java
@@ -97,7 +97,7 @@ public class DeviceStateManagerShellCommand extends ShellCommand {
try {
if ("reset".equals(nextArg)) {
if (sLastRequest != null) {
- mClient.cancelRequest(sLastRequest);
+ mClient.cancelStateRequest();
sLastRequest = null;
}
} else {
@@ -105,9 +105,6 @@ public class DeviceStateManagerShellCommand extends ShellCommand {
DeviceStateRequest request = DeviceStateRequest.newBuilder(requestedState).build();
mClient.requestState(request, null /* executor */, null /* callback */);
- if (sLastRequest != null) {
- mClient.cancelRequest(sLastRequest);
- }
sLastRequest = request;
}
diff --git a/services/core/java/com/android/server/devicestate/OverrideRequestController.java b/services/core/java/com/android/server/devicestate/OverrideRequestController.java
index 36cb4162accc..01f5a09323cf 100644
--- a/services/core/java/com/android/server/devicestate/OverrideRequestController.java
+++ b/services/core/java/com/android/server/devicestate/OverrideRequestController.java
@@ -18,15 +18,13 @@ package com.android.server.devicestate;
import android.annotation.IntDef;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.hardware.devicestate.DeviceStateRequest;
import android.os.IBinder;
+import android.util.Slog;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-import java.util.List;
/**
* Manages the lifecycle of override requests.
@@ -36,29 +34,26 @@ import java.util.List;
* <ul>
* <li>A new request is added with {@link #addRequest(OverrideRequest)}, in which case the
* request will become suspended.</li>
- * <li>The request is cancelled with {@link #cancelRequest(IBinder)} or as a side effect
+ * <li>The request is cancelled with {@link #cancelRequest} or as a side effect
* of other methods calls, such as {@link #handleProcessDied(int)}.</li>
* </ul>
*/
final class OverrideRequestController {
+ private static final String TAG = "OverrideRequestController";
+
static final int STATUS_UNKNOWN = 0;
/**
* The request is the top-most request.
*/
static final int STATUS_ACTIVE = 1;
/**
- * The request is still present but is being superseded by another request.
- */
- static final int STATUS_SUSPENDED = 2;
- /**
* The request is not longer valid.
*/
- static final int STATUS_CANCELED = 3;
+ static final int STATUS_CANCELED = 2;
@IntDef(prefix = {"STATUS_"}, value = {
STATUS_UNKNOWN,
STATUS_ACTIVE,
- STATUS_SUSPENDED,
STATUS_CANCELED
})
@Retention(RetentionPolicy.SOURCE)
@@ -68,8 +63,6 @@ final class OverrideRequestController {
switch (status) {
case STATUS_ACTIVE:
return "ACTIVE";
- case STATUS_SUSPENDED:
- return "SUSPENDED";
case STATUS_CANCELED:
return "CANCELED";
case STATUS_UNKNOWN:
@@ -79,15 +72,13 @@ final class OverrideRequestController {
}
private final StatusChangeListener mListener;
- private final List<OverrideRequest> mTmpRequestsToCancel = new ArrayList<>();
- // List of override requests with the most recent override request at the end.
- private final ArrayList<OverrideRequest> mRequests = new ArrayList<>();
+ // Handle to the current override request, null if none.
+ private OverrideRequest mRequest;
private boolean mStickyRequestsAllowed;
- // List of override requests that have outlived their process and will only be cancelled through
- // a call to cancelStickyRequests().
- private final ArrayList<OverrideRequest> mStickyRequests = new ArrayList<>();
+ // The current request has outlived their process.
+ private boolean mStickyRequest;
OverrideRequestController(@NonNull StatusChangeListener listener) {
mListener = listener;
@@ -97,26 +88,26 @@ final class OverrideRequestController {
* Sets sticky requests as either allowed or disallowed. When sticky requests are allowed a call
* to {@link #handleProcessDied(int)} will not result in the request being cancelled
* immediately. Instead, the request will be marked sticky and must be cancelled with a call
- * to {@link #cancelStickyRequests()}.
+ * to {@link #cancelStickyRequest()}.
*/
void setStickyRequestsAllowed(boolean stickyRequestsAllowed) {
mStickyRequestsAllowed = stickyRequestsAllowed;
if (!mStickyRequestsAllowed) {
- cancelStickyRequests();
+ cancelStickyRequest();
}
}
/**
- * Adds a request to the top of the stack and notifies the listener of all changes to request
- * status as a result of this operation.
+ * Sets the new request as active and cancels the previous override request, notifies the
+ * listener of all changes to request status as a result of this operation.
*/
void addRequest(@NonNull OverrideRequest request) {
- mRequests.add(request);
+ OverrideRequest previousRequest = mRequest;
+ mRequest = request;
mListener.onStatusChanged(request, STATUS_ACTIVE);
- if (mRequests.size() > 1) {
- OverrideRequest prevRequest = mRequests.get(mRequests.size() - 2);
- mListener.onStatusChanged(prevRequest, STATUS_SUSPENDED);
+ if (previousRequest != null) {
+ cancelRequestLocked(previousRequest);
}
}
@@ -124,42 +115,32 @@ final class OverrideRequestController {
* Cancels the request with the specified {@code token} and notifies the listener of all changes
* to request status as a result of this operation.
*/
- void cancelRequest(@NonNull IBinder token) {
- int index = getRequestIndex(token);
- if (index == -1) {
+ void cancelRequest(@NonNull OverrideRequest request) {
+ // Either don't have a current request or attempting to cancel an already cancelled request
+ if (!hasRequest(request.getToken())) {
return;
}
-
- OverrideRequest request = mRequests.remove(index);
- if (index == mRequests.size() && mRequests.size() > 0) {
- // We removed the current active request so we need to set the new active request
- // before cancelling this request.
- OverrideRequest newTop = getLast(mRequests);
- mListener.onStatusChanged(newTop, STATUS_ACTIVE);
- }
- mListener.onStatusChanged(request, STATUS_CANCELED);
+ cancelCurrentRequestLocked();
}
/**
- * Cancels all requests that are currently marked sticky and notifies the listener of all
+ * Cancels a request that is currently marked sticky and notifies the listener of all
* changes to request status as a result of this operation.
*
* @see #setStickyRequestsAllowed(boolean)
*/
- void cancelStickyRequests() {
- mTmpRequestsToCancel.clear();
- mTmpRequestsToCancel.addAll(mStickyRequests);
- cancelRequestsLocked(mTmpRequestsToCancel);
+ void cancelStickyRequest() {
+ if (mStickyRequest) {
+ cancelCurrentRequestLocked();
+ }
}
/**
- * Cancels all override requests, this could be due to the device being put
+ * Cancels the current override request, this could be due to the device being put
* into a hardware state that declares the flag "FLAG_CANCEL_OVERRIDE_REQUESTS"
*/
- void cancelOverrideRequests() {
- mTmpRequestsToCancel.clear();
- mTmpRequestsToCancel.addAll(mRequests);
- cancelRequestsLocked(mTmpRequestsToCancel);
+ void cancelOverrideRequest() {
+ cancelCurrentRequestLocked();
}
/**
@@ -167,7 +148,7 @@ final class OverrideRequestController {
* {@code token}, {@code false} otherwise.
*/
boolean hasRequest(@NonNull IBinder token) {
- return getRequestIndex(token) != -1;
+ return mRequest != null && token == mRequest.getToken();
}
/**
@@ -176,139 +157,79 @@ final class OverrideRequestController {
* operation.
*/
void handleProcessDied(int pid) {
- if (mRequests.isEmpty()) {
+ if (mRequest == null) {
return;
}
- mTmpRequestsToCancel.clear();
- OverrideRequest prevActiveRequest = getLast(mRequests);
- for (OverrideRequest request : mRequests) {
- if (request.getPid() == pid) {
- mTmpRequestsToCancel.add(request);
+ if (mRequest.getPid() == pid) {
+ if (mStickyRequestsAllowed) {
+ // Do not cancel the requests now because sticky requests are allowed. These
+ // requests will be cancelled on a call to cancelStickyRequests().
+ mStickyRequest = true;
+ return;
}
+ cancelCurrentRequestLocked();
}
-
- if (mStickyRequestsAllowed) {
- // Do not cancel the requests now because sticky requests are allowed. These
- // requests will be cancelled on a call to cancelStickyRequests().
- mStickyRequests.addAll(mTmpRequestsToCancel);
- return;
- }
-
- cancelRequestsLocked(mTmpRequestsToCancel);
}
/**
* Notifies the controller that the base state has changed. The controller will notify the
* listener of all changes to request status as a result of this change.
- *
- * @return {@code true} if calling this method has lead to a new active request, {@code false}
- * otherwise.
*/
- boolean handleBaseStateChanged() {
- if (mRequests.isEmpty()) {
- return false;
+ void handleBaseStateChanged() {
+ if (mRequest == null) {
+ return;
}
- mTmpRequestsToCancel.clear();
- OverrideRequest prevActiveRequest = getLast(mRequests);
- for (int i = 0; i < mRequests.size(); i++) {
- OverrideRequest request = mRequests.get(i);
- if ((request.getFlags() & DeviceStateRequest.FLAG_CANCEL_WHEN_BASE_CHANGES) != 0) {
- mTmpRequestsToCancel.add(request);
- }
+ if ((mRequest.getFlags()
+ & DeviceStateRequest.FLAG_CANCEL_WHEN_BASE_CHANGES) != 0) {
+ cancelCurrentRequestLocked();
}
-
- final boolean newActiveRequest = cancelRequestsLocked(mTmpRequestsToCancel);
- return newActiveRequest;
}
/**
* Notifies the controller that the set of supported states has changed. The controller will
* notify the listener of all changes to request status as a result of this change.
- *
- * @return {@code true} if calling this method has lead to a new active request, {@code false}
- * otherwise.
*/
- boolean handleNewSupportedStates(int[] newSupportedStates) {
- if (mRequests.isEmpty()) {
- return false;
+ void handleNewSupportedStates(int[] newSupportedStates) {
+ if (mRequest == null) {
+ return;
}
- mTmpRequestsToCancel.clear();
- for (int i = 0; i < mRequests.size(); i++) {
- OverrideRequest request = mRequests.get(i);
- if (!contains(newSupportedStates, request.getRequestedState())) {
- mTmpRequestsToCancel.add(request);
- }
+ if (!contains(newSupportedStates, mRequest.getRequestedState())) {
+ cancelCurrentRequestLocked();
}
-
- final boolean newActiveRequest = cancelRequestsLocked(mTmpRequestsToCancel);
- return newActiveRequest;
}
void dumpInternal(PrintWriter pw) {
- final int requestCount = mRequests.size();
+ OverrideRequest overrideRequest = mRequest;
+ final boolean requestActive = overrideRequest != null;
pw.println();
- pw.println("Override requests: size=" + requestCount);
- for (int i = 0; i < requestCount; i++) {
- OverrideRequest overrideRequest = mRequests.get(i);
- int status = (i == requestCount - 1) ? STATUS_ACTIVE : STATUS_SUSPENDED;
- pw.println(" " + i + ": mPid=" + overrideRequest.getPid()
+ pw.println("Override Request active: " + requestActive);
+ if (requestActive) {
+ pw.println("Request: mPid=" + overrideRequest.getPid()
+ ", mRequestedState=" + overrideRequest.getRequestedState()
+ ", mFlags=" + overrideRequest.getFlags()
- + ", mStatus=" + statusToString(status));
+ + ", mStatus=" + statusToString(STATUS_ACTIVE));
}
}
- /**
- * Handles cancelling a set of requests. If the set of requests to cancel will lead to a new
- * request becoming active this request will also be notified of its change in state.
- *
- * @return {@code true} if calling this method has lead to a new active request, {@code false}
- * otherwise.
- */
- private boolean cancelRequestsLocked(List<OverrideRequest> requestsToCancel) {
- if (requestsToCancel.isEmpty()) {
- return false;
- }
-
- OverrideRequest prevActiveRequest = getLast(mRequests);
- boolean causedNewRequestToBecomeActive = false;
- mRequests.removeAll(requestsToCancel);
- mStickyRequests.removeAll(requestsToCancel);
- if (!mRequests.isEmpty()) {
- OverrideRequest newActiveRequest = getLast(mRequests);
- if (newActiveRequest != prevActiveRequest) {
- mListener.onStatusChanged(newActiveRequest, STATUS_ACTIVE);
- causedNewRequestToBecomeActive = true;
- }
- }
-
- for (int i = 0; i < requestsToCancel.size(); i++) {
- mListener.onStatusChanged(requestsToCancel.get(i), STATUS_CANCELED);
- }
- return causedNewRequestToBecomeActive;
+ private void cancelRequestLocked(@NonNull OverrideRequest requestToCancel) {
+ mListener.onStatusChanged(requestToCancel, STATUS_CANCELED);
}
- private int getRequestIndex(@NonNull IBinder token) {
- final int numberOfRequests = mRequests.size();
- if (numberOfRequests == 0) {
- return -1;
- }
-
- for (int i = 0; i < numberOfRequests; i++) {
- OverrideRequest request = mRequests.get(i);
- if (request.getToken() == token) {
- return i;
- }
+ /**
+ * Handles cancelling {@code mRequest}.
+ * Notifies the listener of the canceled status as well.
+ */
+ private void cancelCurrentRequestLocked() {
+ if (mRequest == null) {
+ Slog.w(TAG, "Attempted to cancel a null OverrideRequest");
+ return;
}
- return -1;
- }
-
- @Nullable
- private static <T> T getLast(List<T> list) {
- return list.size() > 0 ? list.get(list.size() - 1) : null;
+ mStickyRequest = false;
+ mListener.onStatusChanged(mRequest, STATUS_CANCELED);
+ mRequest = null;
}
private static boolean contains(int[] array, int value) {
diff --git a/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java
index d2cff0ea1968..fe3034dc569d 100644
--- a/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java
@@ -326,7 +326,7 @@ public final class DeviceStateManagerServiceTest {
assertEquals(callback.getLastNotifiedInfo().currentState,
OTHER_DEVICE_STATE.getIdentifier());
- mService.getBinderService().cancelRequest(token);
+ mService.getBinderService().cancelStateRequest();
flushHandler();
assertEquals(callback.getLastNotifiedStatus(token),
@@ -378,9 +378,9 @@ public final class DeviceStateManagerServiceTest {
mPolicy.resumeConfigureOnce();
flushHandler();
- // First request status is now suspended as there is another pending request.
+ // First request status is now canceled as there is another pending request.
assertEquals(callback.getLastNotifiedStatus(firstRequestToken),
- TestDeviceStateManagerCallback.STATUS_SUSPENDED);
+ TestDeviceStateManagerCallback.STATUS_CANCELED);
// Second request status still unknown because the service is still awaiting policy
// callback.
assertEquals(callback.getLastNotifiedStatus(secondRequestToken),
@@ -402,19 +402,19 @@ public final class DeviceStateManagerServiceTest {
DEFAULT_DEVICE_STATE.getIdentifier());
// Now cancel the second request to make the first request active.
- mService.getBinderService().cancelRequest(secondRequestToken);
+ mService.getBinderService().cancelStateRequest();
flushHandler();
assertEquals(callback.getLastNotifiedStatus(firstRequestToken),
- TestDeviceStateManagerCallback.STATUS_ACTIVE);
+ TestDeviceStateManagerCallback.STATUS_CANCELED);
assertEquals(callback.getLastNotifiedStatus(secondRequestToken),
TestDeviceStateManagerCallback.STATUS_CANCELED);
- assertEquals(mService.getCommittedState(), Optional.of(OTHER_DEVICE_STATE));
+ assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE));
assertEquals(mService.getPendingState(), Optional.empty());
assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE));
assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
- OTHER_DEVICE_STATE.getIdentifier());
+ DEFAULT_DEVICE_STATE.getIdentifier());
}
@Test
@@ -656,11 +656,6 @@ public final class DeviceStateManagerServiceTest {
}
@Override
- public void onRequestSuspended(IBinder token) {
- mLastNotifiedStatus.put(token, STATUS_SUSPENDED);
- }
-
- @Override
public void onRequestCanceled(IBinder token) {
mLastNotifiedStatus.put(token, STATUS_CANCELED);
}
diff --git a/services/tests/servicestests/src/com/android/server/devicestate/OverrideRequestControllerTest.java b/services/tests/servicestests/src/com/android/server/devicestate/OverrideRequestControllerTest.java
index b94fc4308ce2..2297c91818c0 100644
--- a/services/tests/servicestests/src/com/android/server/devicestate/OverrideRequestControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicestate/OverrideRequestControllerTest.java
@@ -18,7 +18,6 @@ package com.android.server.devicestate;
import static com.android.server.devicestate.OverrideRequestController.STATUS_ACTIVE;
import static com.android.server.devicestate.OverrideRequestController.STATUS_CANCELED;
-import static com.android.server.devicestate.OverrideRequestController.STATUS_SUSPENDED;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNull;
@@ -66,7 +65,7 @@ public final class OverrideRequestControllerTest {
}
@Test
- public void addRequest_suspendExistingRequest() {
+ public void addRequest_cancelExistingRequestThroughNewRequest() {
OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */,
0 /* requestedState */, 0 /* flags */);
assertNull(mStatusListener.getLastStatus(firstRequest));
@@ -75,92 +74,52 @@ public final class OverrideRequestControllerTest {
assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_ACTIVE);
OverrideRequest secondRequest = new OverrideRequest(new Binder(), 0 /* pid */,
- 0 /* requestedState */, 0 /* flags */);
+ 1 /* requestedState */, 0 /* flags */);
assertNull(mStatusListener.getLastStatus(secondRequest));
mController.addRequest(secondRequest);
assertEquals(mStatusListener.getLastStatus(secondRequest).intValue(), STATUS_ACTIVE);
- assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_SUSPENDED);
+ assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_CANCELED);
}
@Test
public void addRequest_cancelActiveRequest() {
OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */,
0 /* requestedState */, 0 /* flags */);
- OverrideRequest secondRequest = new OverrideRequest(new Binder(), 0 /* pid */,
- 0 /* requestedState */, 0 /* flags */);
mController.addRequest(firstRequest);
- mController.addRequest(secondRequest);
-
- assertEquals(mStatusListener.getLastStatus(secondRequest).intValue(), STATUS_ACTIVE);
- assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_SUSPENDED);
- mController.cancelRequest(secondRequest.getToken());
-
- assertEquals(mStatusListener.getLastStatus(secondRequest).intValue(), STATUS_CANCELED);
assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_ACTIVE);
- }
- @Test
- public void addRequest_cancelSuspendedRequest() {
- OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */,
- 0 /* requestedState */, 0 /* flags */);
- OverrideRequest secondRequest = new OverrideRequest(new Binder(), 0 /* pid */,
- 0 /* requestedState */, 0 /* flags */);
+ mController.cancelOverrideRequest();
- mController.addRequest(firstRequest);
- mController.addRequest(secondRequest);
-
- assertEquals(mStatusListener.getLastStatus(secondRequest).intValue(), STATUS_ACTIVE);
- assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_SUSPENDED);
-
- mController.cancelRequest(firstRequest.getToken());
-
- assertEquals(mStatusListener.getLastStatus(secondRequest).intValue(), STATUS_ACTIVE);
assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_CANCELED);
}
@Test
public void handleBaseStateChanged() {
OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */,
- 0 /* requestedState */, 0 /* flags */);
- OverrideRequest secondRequest = new OverrideRequest(new Binder(), 0 /* pid */,
0 /* requestedState */,
DeviceStateRequest.FLAG_CANCEL_WHEN_BASE_CHANGES /* flags */);
mController.addRequest(firstRequest);
- mController.addRequest(secondRequest);
- assertEquals(mStatusListener.getLastStatus(secondRequest).intValue(), STATUS_ACTIVE);
- assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_SUSPENDED);
+ assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_ACTIVE);
mController.handleBaseStateChanged();
- assertEquals(mStatusListener.getLastStatus(secondRequest).intValue(), STATUS_CANCELED);
- assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_ACTIVE);
+ assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_CANCELED);
}
@Test
public void handleProcessDied() {
OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */,
0 /* requestedState */, 0 /* flags */);
- OverrideRequest secondRequest = new OverrideRequest(new Binder(), 1 /* pid */,
- 0 /* requestedState */, 0 /* flags */);
mController.addRequest(firstRequest);
- mController.addRequest(secondRequest);
-
- assertEquals(mStatusListener.getLastStatus(secondRequest).intValue(), STATUS_ACTIVE);
- assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_SUSPENDED);
-
- mController.handleProcessDied(1);
-
- assertEquals(mStatusListener.getLastStatus(secondRequest).intValue(), STATUS_CANCELED);
assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_ACTIVE);
mController.handleProcessDied(0);
-
assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_CANCELED);
}
@@ -170,46 +129,29 @@ public final class OverrideRequestControllerTest {
OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */,
0 /* requestedState */, 0 /* flags */);
- OverrideRequest secondRequest = new OverrideRequest(new Binder(), 1 /* pid */,
- 0 /* requestedState */, 0 /* flags */);
mController.addRequest(firstRequest);
- mController.addRequest(secondRequest);
-
- assertEquals(mStatusListener.getLastStatus(secondRequest).intValue(), STATUS_ACTIVE);
- assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_SUSPENDED);
-
- mController.handleProcessDied(1);
-
- assertEquals(mStatusListener.getLastStatus(secondRequest).intValue(), STATUS_ACTIVE);
- assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_SUSPENDED);
-
- mController.cancelStickyRequests();
+ assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_ACTIVE);
- assertEquals(mStatusListener.getLastStatus(secondRequest).intValue(), STATUS_CANCELED);
+ mController.handleProcessDied(0);
assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_ACTIVE);
+
+ mController.cancelStickyRequest();
+ assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_CANCELED);
}
@Test
public void handleNewSupportedStates() {
OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */,
1 /* requestedState */, 0 /* flags */);
- OverrideRequest secondRequest = new OverrideRequest(new Binder(), 0 /* pid */,
- 2 /* requestedState */, 0 /* flags */);
mController.addRequest(firstRequest);
- mController.addRequest(secondRequest);
-
- assertEquals(mStatusListener.getLastStatus(secondRequest).intValue(), STATUS_ACTIVE);
- assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_SUSPENDED);
+ assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_ACTIVE);
mController.handleNewSupportedStates(new int[]{ 0, 1 });
-
- assertEquals(mStatusListener.getLastStatus(secondRequest).intValue(), STATUS_CANCELED);
assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_ACTIVE);
mController.handleNewSupportedStates(new int[]{ 0 });
-
assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_CANCELED);
}
@@ -217,18 +159,11 @@ public final class OverrideRequestControllerTest {
public void cancelOverrideRequestsTest() {
OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */,
1 /* requestedState */, 0 /* flags */);
- OverrideRequest secondRequest = new OverrideRequest(new Binder(), 0 /* pid */,
- 2 /* requestedState */, 0 /* flags */);
mController.addRequest(firstRequest);
- mController.addRequest(secondRequest);
-
- assertEquals(mStatusListener.getLastStatus(secondRequest).intValue(), STATUS_ACTIVE);
- assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_SUSPENDED);
-
- mController.cancelOverrideRequests();
+ assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_ACTIVE);
- assertEquals(mStatusListener.getLastStatus(secondRequest).intValue(), STATUS_CANCELED);
+ mController.cancelOverrideRequest();
assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_CANCELED);
}