Adds requestBaseStateOverride method on DeviceStateManagerService
Server side changes to accompany the addition of the DeviceStateManager#requestBaseStateOverride test API Bug: 234336979 Test: OverrideRequestControllerTest && DeviceStateManagerServiceTest Change-Id: Ib915b245acd260be1e0d5016d765af5598ea390c
This commit is contained in:
@@ -41,6 +41,10 @@ interface IDeviceStateManager {
|
||||
* previously registered with {@link #registerCallback(IDeviceStateManagerCallback)} before a
|
||||
* call to this method.
|
||||
*
|
||||
* Requesting a state does not cancel a base state override made through
|
||||
* {@link #requestBaseStateOverride}, but will still attempt to put the device into the
|
||||
* supplied {@code state}.
|
||||
*
|
||||
* @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
|
||||
@@ -50,14 +54,53 @@ interface IDeviceStateManager {
|
||||
* @throws IllegalStateException if the supplied {@code token} has already been registered.
|
||||
* @throws IllegalArgumentException if the supplied {@code state} is not supported.
|
||||
*/
|
||||
@JavaPassthrough(annotation=
|
||||
"@android.annotation.RequiresPermission(value=android.Manifest.permission.CONTROL_DEVICE_STATE, conditional=true)")
|
||||
void requestState(IBinder token, int state, int flags);
|
||||
|
||||
/**
|
||||
* Cancels the active request previously submitted with a call to
|
||||
* {@link #requestState(IBinder, int, int)}.
|
||||
* {@link #requestState(IBinder, int, int)}. Will have no effect on any base state override that
|
||||
* was previously requested with {@link #requestBaseStateOverride}.
|
||||
*
|
||||
* @throws IllegalStateException if a callback has not yet been registered for the calling
|
||||
* process.
|
||||
*/
|
||||
@JavaPassthrough(annotation=
|
||||
"@android.annotation.RequiresPermission(value=android.Manifest.permission.CONTROL_DEVICE_STATE, conditional=true)")
|
||||
void cancelStateRequest();
|
||||
|
||||
/**
|
||||
* Requests that the device's base state be overridden to the supplied {@code state}. A callback
|
||||
* <b>MUST</b> have been previously registered with
|
||||
* {@link #registerCallback(IDeviceStateManagerCallback)} before a call to this method.
|
||||
*
|
||||
* This method should only be used for testing, when you want to simulate the device physically
|
||||
* changing states. If you are looking to change device state for a feature, where the system
|
||||
* should still be aware that the physical state is different than the emulated state, use
|
||||
* {@link #requestState}.
|
||||
*
|
||||
* @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.
|
||||
* @throws IllegalStateException if the supplied {@code token} has already been registered.
|
||||
* @throws IllegalArgumentException if the supplied {@code state} is not supported.
|
||||
*/
|
||||
@JavaPassthrough(annotation=
|
||||
"@android.annotation.RequiresPermission(android.Manifest.permission.CONTROL_DEVICE_STATE)")
|
||||
void requestBaseStateOverride(IBinder token, int state, int flags);
|
||||
|
||||
/**
|
||||
* Cancels the active base state request previously submitted with a call to
|
||||
* {@link #overrideBaseState(IBinder, int, int)}.
|
||||
*
|
||||
* @throws IllegalStateException if a callback has not yet been registered for the calling
|
||||
* process.
|
||||
*/
|
||||
@JavaPassthrough(annotation=
|
||||
"@android.annotation.RequiresPermission(android.Manifest.permission.CONTROL_DEVICE_STATE)")
|
||||
void cancelBaseStateOverride();
|
||||
}
|
||||
|
||||
@@ -21,8 +21,11 @@ import static android.hardware.devicestate.DeviceStateManager.MAXIMUM_DEVICE_STA
|
||||
import static android.hardware.devicestate.DeviceStateManager.MINIMUM_DEVICE_STATE;
|
||||
|
||||
import static com.android.server.devicestate.DeviceState.FLAG_CANCEL_OVERRIDE_REQUESTS;
|
||||
import static com.android.server.devicestate.OverrideRequest.OVERRIDE_REQUEST_TYPE_BASE_STATE;
|
||||
import static com.android.server.devicestate.OverrideRequest.OVERRIDE_REQUEST_TYPE_EMULATED_STATE;
|
||||
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_UNKNOWN;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.IntRange;
|
||||
@@ -106,6 +109,8 @@ public final class DeviceStateManagerService extends SystemService {
|
||||
private final BinderService mBinderService;
|
||||
@NonNull
|
||||
private final OverrideRequestController mOverrideRequestController;
|
||||
@NonNull
|
||||
private final DeviceStateProviderListener mDeviceStateProviderListener;
|
||||
@VisibleForTesting
|
||||
@NonNull
|
||||
public ActivityTaskManagerInternal mActivityTaskManagerInternal;
|
||||
@@ -139,6 +144,12 @@ public final class DeviceStateManagerService extends SystemService {
|
||||
@NonNull
|
||||
private Optional<OverrideRequest> mActiveOverride = Optional.empty();
|
||||
|
||||
// The current active base state override request. When set the device state specified here will
|
||||
// replace the value in mBaseState.
|
||||
@GuardedBy("mLock")
|
||||
@NonNull
|
||||
private Optional<OverrideRequest> mActiveBaseStateOverride = Optional.empty();
|
||||
|
||||
// List of processes registered to receive notifications about changes to device state and
|
||||
// request status indexed by process id.
|
||||
@GuardedBy("mLock")
|
||||
@@ -177,7 +188,8 @@ public final class DeviceStateManagerService extends SystemService {
|
||||
mOverrideRequestController = new OverrideRequestController(
|
||||
this::onOverrideRequestStatusChangedLocked);
|
||||
mDeviceStatePolicy = policy;
|
||||
mDeviceStatePolicy.getDeviceStateProvider().setListener(new DeviceStateProviderListener());
|
||||
mDeviceStateProviderListener = new DeviceStateProviderListener();
|
||||
mDeviceStatePolicy.getDeviceStateProvider().setListener(mDeviceStateProviderListener);
|
||||
mBinderService = new BinderService();
|
||||
mActivityTaskManagerInternal = LocalServices.getService(ActivityTaskManagerInternal.class);
|
||||
}
|
||||
@@ -257,6 +269,21 @@ public final class DeviceStateManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current override base state, or {@link Optional#empty()} if no override state is
|
||||
* requested. If an override base state is present, the returned state will be the same as
|
||||
* the base state returned from {@link #getBaseState()}.
|
||||
*/
|
||||
@NonNull
|
||||
Optional<DeviceState> getOverrideBaseState() {
|
||||
synchronized (mLock) {
|
||||
if (mActiveBaseStateOverride.isPresent()) {
|
||||
return getStateLocked(mActiveBaseStateOverride.get().getRequestedState());
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns the list of currently supported device states. */
|
||||
DeviceState[] getSupportedStates() {
|
||||
synchronized (mLock) {
|
||||
@@ -366,6 +393,7 @@ public final class DeviceStateManagerService extends SystemService {
|
||||
}
|
||||
|
||||
final DeviceState baseState = baseStateOptional.get();
|
||||
|
||||
if (mBaseState.isPresent() && mBaseState.get().equals(baseState)) {
|
||||
// Base state hasn't changed. Nothing to do.
|
||||
return;
|
||||
@@ -375,7 +403,7 @@ public final class DeviceStateManagerService extends SystemService {
|
||||
if (baseState.hasFlag(FLAG_CANCEL_OVERRIDE_REQUESTS)) {
|
||||
mOverrideRequestController.cancelOverrideRequest();
|
||||
}
|
||||
mOverrideRequestController.handleBaseStateChanged();
|
||||
mOverrideRequestController.handleBaseStateChanged(identifier);
|
||||
updatePendingStateLocked();
|
||||
|
||||
if (!mPendingState.isPresent()) {
|
||||
@@ -528,16 +556,41 @@ public final class DeviceStateManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
@GuardedBy("mLock")
|
||||
private void onOverrideRequestStatusChangedLocked(@NonNull OverrideRequest request,
|
||||
@OverrideRequestController.RequestStatus int status) {
|
||||
if (status == STATUS_ACTIVE) {
|
||||
mActiveOverride = Optional.of(request);
|
||||
} else if (status == STATUS_CANCELED) {
|
||||
if (mActiveOverride.isPresent() && mActiveOverride.get() == request) {
|
||||
mActiveOverride = Optional.empty();
|
||||
if (request.getRequestType() == OVERRIDE_REQUEST_TYPE_BASE_STATE) {
|
||||
switch (status) {
|
||||
case STATUS_ACTIVE:
|
||||
enableBaseStateRequestLocked(request);
|
||||
return;
|
||||
case STATUS_CANCELED:
|
||||
if (mActiveBaseStateOverride.isPresent()
|
||||
&& mActiveBaseStateOverride.get() == request) {
|
||||
mActiveBaseStateOverride = Optional.empty();
|
||||
}
|
||||
break;
|
||||
case STATUS_UNKNOWN: // same as default
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown request status: " + status);
|
||||
}
|
||||
} else if (request.getRequestType() == OVERRIDE_REQUEST_TYPE_EMULATED_STATE) {
|
||||
switch (status) {
|
||||
case STATUS_ACTIVE:
|
||||
mActiveOverride = Optional.of(request);
|
||||
break;
|
||||
case STATUS_CANCELED:
|
||||
if (mActiveOverride.isPresent() && mActiveOverride.get() == request) {
|
||||
mActiveOverride = Optional.empty();
|
||||
}
|
||||
break;
|
||||
case STATUS_UNKNOWN: // same as default
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown request status: " + status);
|
||||
}
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unknown request status: " + status);
|
||||
throw new IllegalArgumentException(
|
||||
"Unknown OverrideRest type: " + request.getRequestType());
|
||||
}
|
||||
|
||||
boolean updatedPendingState = updatePendingStateLocked();
|
||||
@@ -564,6 +617,18 @@ public final class DeviceStateManagerService extends SystemService {
|
||||
mHandler.post(this::notifyPolicyIfNeeded);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the new base state of the device and notifies the process that made the base state
|
||||
* override request that the request is now active.
|
||||
*/
|
||||
@GuardedBy("mLock")
|
||||
private void enableBaseStateRequestLocked(OverrideRequest request) {
|
||||
setBaseState(request.getRequestedState());
|
||||
mActiveBaseStateOverride = Optional.of(request);
|
||||
ProcessRecord processRecord = mProcessRecords.get(request.getPid());
|
||||
processRecord.notifyRequestActiveAsync(request.getToken());
|
||||
}
|
||||
|
||||
private void registerProcess(int pid, IDeviceStateManagerCallback callback) {
|
||||
synchronized (mLock) {
|
||||
if (mProcessRecords.contains(pid)) {
|
||||
@@ -606,7 +671,8 @@ public final class DeviceStateManagerService extends SystemService {
|
||||
+ " has no registered callback.");
|
||||
}
|
||||
|
||||
if (mOverrideRequestController.hasRequest(token)) {
|
||||
if (mOverrideRequestController.hasRequest(token,
|
||||
OVERRIDE_REQUEST_TYPE_EMULATED_STATE)) {
|
||||
throw new IllegalStateException("Request has already been made for the supplied"
|
||||
+ " token: " + token);
|
||||
}
|
||||
@@ -618,7 +684,7 @@ public final class DeviceStateManagerService extends SystemService {
|
||||
}
|
||||
|
||||
OverrideRequest request = new OverrideRequest(token, callingPid, state, flags,
|
||||
OverrideRequest.OVERRIDE_REQUEST_TYPE_EMULATED_STATE);
|
||||
OVERRIDE_REQUEST_TYPE_EMULATED_STATE);
|
||||
mOverrideRequestController.addRequest(request);
|
||||
}
|
||||
}
|
||||
@@ -634,6 +700,44 @@ public final class DeviceStateManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
private void requestBaseStateOverrideInternal(int state, int flags, int callingPid,
|
||||
@NonNull IBinder token) {
|
||||
synchronized (mLock) {
|
||||
final Optional<DeviceState> deviceState = getStateLocked(state);
|
||||
if (!deviceState.isPresent()) {
|
||||
throw new IllegalArgumentException("Requested state: " + state
|
||||
+ " is not supported.");
|
||||
}
|
||||
|
||||
final ProcessRecord processRecord = mProcessRecords.get(callingPid);
|
||||
if (processRecord == null) {
|
||||
throw new IllegalStateException("Process " + callingPid
|
||||
+ " has no registered callback.");
|
||||
}
|
||||
|
||||
if (mOverrideRequestController.hasRequest(token,
|
||||
OVERRIDE_REQUEST_TYPE_BASE_STATE)) {
|
||||
throw new IllegalStateException("Request has already been made for the supplied"
|
||||
+ " token: " + token);
|
||||
}
|
||||
|
||||
OverrideRequest request = new OverrideRequest(token, callingPid, state, flags,
|
||||
OVERRIDE_REQUEST_TYPE_BASE_STATE);
|
||||
mOverrideRequestController.addBaseStateRequest(request);
|
||||
}
|
||||
}
|
||||
|
||||
private void cancelBaseStateOverrideInternal(int callingPid) {
|
||||
synchronized (mLock) {
|
||||
final ProcessRecord processRecord = mProcessRecords.get(callingPid);
|
||||
if (processRecord == null) {
|
||||
throw new IllegalStateException("Process " + callingPid
|
||||
+ " has no registered callback.");
|
||||
}
|
||||
setBaseState(mDeviceStateProviderListener.mCurrentBaseState);
|
||||
}
|
||||
}
|
||||
|
||||
private void dumpInternal(PrintWriter pw) {
|
||||
pw.println("DEVICE STATE MANAGER (dumpsys device_state)");
|
||||
|
||||
@@ -730,6 +834,8 @@ public final class DeviceStateManagerService extends SystemService {
|
||||
}
|
||||
|
||||
private final class DeviceStateProviderListener implements DeviceStateProvider.Listener {
|
||||
@IntRange(from = MINIMUM_DEVICE_STATE, to = MAXIMUM_DEVICE_STATE) int mCurrentBaseState;
|
||||
|
||||
@Override
|
||||
public void onSupportedDeviceStatesChanged(DeviceState[] newDeviceStates) {
|
||||
if (newDeviceStates.length == 0) {
|
||||
@@ -744,7 +850,7 @@ public final class DeviceStateManagerService extends SystemService {
|
||||
if (identifier < MINIMUM_DEVICE_STATE || identifier > MAXIMUM_DEVICE_STATE) {
|
||||
throw new IllegalArgumentException("Invalid identifier: " + identifier);
|
||||
}
|
||||
|
||||
mCurrentBaseState = identifier;
|
||||
setBaseState(identifier);
|
||||
}
|
||||
}
|
||||
@@ -895,6 +1001,38 @@ public final class DeviceStateManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
public void requestBaseStateOverride(IBinder token, int state, int flags) {
|
||||
final int callingPid = Binder.getCallingPid();
|
||||
getContext().enforceCallingOrSelfPermission(CONTROL_DEVICE_STATE,
|
||||
"Permission required to control base state of device.");
|
||||
|
||||
if (token == null) {
|
||||
throw new IllegalArgumentException("Request token must not be null.");
|
||||
}
|
||||
|
||||
final long callingIdentity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
requestBaseStateOverrideInternal(state, flags, callingPid, token);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(callingIdentity);
|
||||
}
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
public void cancelBaseStateOverride() {
|
||||
final int callingPid = Binder.getCallingPid();
|
||||
getContext().enforceCallingOrSelfPermission(CONTROL_DEVICE_STATE,
|
||||
"Permission required to control base state of device.");
|
||||
|
||||
final long callingIdentity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
cancelBaseStateOverrideInternal(callingPid);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(callingIdentity);
|
||||
}
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
|
||||
String[] args, ShellCallback callback, ResultReceiver result) {
|
||||
|
||||
@@ -16,11 +16,8 @@
|
||||
|
||||
package com.android.server.devicestate;
|
||||
|
||||
import static android.Manifest.permission.CONTROL_DEVICE_STATE;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.Context;
|
||||
import android.hardware.devicestate.DeviceStateManager;
|
||||
import android.hardware.devicestate.DeviceStateRequest;
|
||||
import android.os.Binder;
|
||||
@@ -39,6 +36,8 @@ import java.util.stream.Collectors;
|
||||
public class DeviceStateManagerShellCommand extends ShellCommand {
|
||||
@Nullable
|
||||
private static DeviceStateRequest sLastRequest;
|
||||
@Nullable
|
||||
private static DeviceStateRequest sLastBaseStateRequest;
|
||||
|
||||
private final DeviceStateManagerService mService;
|
||||
private final DeviceStateManager mClient;
|
||||
@@ -58,6 +57,8 @@ public class DeviceStateManagerShellCommand extends ShellCommand {
|
||||
switch (cmd) {
|
||||
case "state":
|
||||
return runState(pw);
|
||||
case "base-state":
|
||||
return runBaseState(pw);
|
||||
case "print-state":
|
||||
return runPrintState(pw);
|
||||
case "print-states":
|
||||
@@ -89,10 +90,6 @@ public class DeviceStateManagerShellCommand extends ShellCommand {
|
||||
return 0;
|
||||
}
|
||||
|
||||
final Context context = mService.getContext();
|
||||
context.enforceCallingOrSelfPermission(
|
||||
CONTROL_DEVICE_STATE,
|
||||
"Permission required to request device state.");
|
||||
final long callingIdentity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
if ("reset".equals(nextArg)) {
|
||||
@@ -127,6 +124,47 @@ public class DeviceStateManagerShellCommand extends ShellCommand {
|
||||
return 0;
|
||||
}
|
||||
|
||||
private int runBaseState(PrintWriter pw) {
|
||||
final String nextArg = getNextArg();
|
||||
if (nextArg == null) {
|
||||
printAllStates(pw);
|
||||
return 0;
|
||||
}
|
||||
|
||||
final long callingIdentity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
if ("reset".equals(nextArg)) {
|
||||
if (sLastBaseStateRequest != null) {
|
||||
mClient.cancelBaseStateOverride();
|
||||
sLastBaseStateRequest = null;
|
||||
}
|
||||
} else {
|
||||
int requestedState = Integer.parseInt(nextArg);
|
||||
DeviceStateRequest request = DeviceStateRequest.newBuilder(requestedState).build();
|
||||
|
||||
mClient.requestBaseStateOverride(request, null, null);
|
||||
|
||||
sLastBaseStateRequest = request;
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
getErrPrintWriter().println("Error: requested state should be an integer");
|
||||
return -1;
|
||||
} catch (IllegalArgumentException e) {
|
||||
getErrPrintWriter().println("Error: " + e.getMessage());
|
||||
getErrPrintWriter().println("-------------------");
|
||||
getErrPrintWriter().println("Run:");
|
||||
getErrPrintWriter().println("");
|
||||
getErrPrintWriter().println(" print-states");
|
||||
getErrPrintWriter().println("");
|
||||
getErrPrintWriter().println("to get the list of currently supported device states");
|
||||
return -1;
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(callingIdentity);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private int runPrintState(PrintWriter pw) {
|
||||
Optional<DeviceState> deviceState = mService.getCommittedState();
|
||||
if (deviceState.isPresent()) {
|
||||
|
||||
@@ -75,6 +75,8 @@ final class OverrideRequestController {
|
||||
|
||||
// Handle to the current override request, null if none.
|
||||
private OverrideRequest mRequest;
|
||||
// Handle to the current base state override request, null if none.
|
||||
private OverrideRequest mBaseStateRequest;
|
||||
|
||||
private boolean mStickyRequestsAllowed;
|
||||
// The current request has outlived their process.
|
||||
@@ -111,13 +113,23 @@ final class OverrideRequestController {
|
||||
}
|
||||
}
|
||||
|
||||
void addBaseStateRequest(@NonNull OverrideRequest request) {
|
||||
OverrideRequest previousRequest = mBaseStateRequest;
|
||||
mBaseStateRequest = request;
|
||||
mListener.onStatusChanged(request, STATUS_ACTIVE);
|
||||
|
||||
if (previousRequest != null) {
|
||||
cancelRequestLocked(previousRequest);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 OverrideRequest request) {
|
||||
// Either don't have a current request or attempting to cancel an already cancelled request
|
||||
if (!hasRequest(request.getToken())) {
|
||||
if (!hasRequest(request.getToken(), request.getRequestType())) {
|
||||
return;
|
||||
}
|
||||
cancelCurrentRequestLocked();
|
||||
@@ -143,12 +155,25 @@ final class OverrideRequestController {
|
||||
cancelCurrentRequestLocked();
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels the current base state override request, this could be due to the physical
|
||||
* configuration of the device changing.
|
||||
*/
|
||||
void cancelBaseStateOverrideRequest() {
|
||||
cancelCurrentBaseStateRequestLocked();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if this controller is current managing a request with the specified
|
||||
* {@code token}, {@code false} otherwise.
|
||||
*/
|
||||
boolean hasRequest(@NonNull IBinder token) {
|
||||
return mRequest != null && token == mRequest.getToken();
|
||||
boolean hasRequest(@NonNull IBinder token,
|
||||
@OverrideRequest.OverrideRequestType int requestType) {
|
||||
if (requestType == OverrideRequest.OVERRIDE_REQUEST_TYPE_BASE_STATE) {
|
||||
return mBaseStateRequest != null && token == mBaseStateRequest.getToken();
|
||||
} else {
|
||||
return mRequest != null && token == mRequest.getToken();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -157,11 +182,11 @@ final class OverrideRequestController {
|
||||
* operation.
|
||||
*/
|
||||
void handleProcessDied(int pid) {
|
||||
if (mRequest == null) {
|
||||
return;
|
||||
if (mBaseStateRequest != null && mBaseStateRequest.getPid() == pid) {
|
||||
cancelCurrentBaseStateRequestLocked();
|
||||
}
|
||||
|
||||
if (mRequest.getPid() == pid) {
|
||||
if (mRequest != null && 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().
|
||||
@@ -176,7 +201,10 @@ final class OverrideRequestController {
|
||||
* 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.
|
||||
*/
|
||||
void handleBaseStateChanged() {
|
||||
void handleBaseStateChanged(int state) {
|
||||
if (mBaseStateRequest != null && state != mBaseStateRequest.getRequestedState()) {
|
||||
cancelBaseStateOverrideRequest();
|
||||
}
|
||||
if (mRequest == null) {
|
||||
return;
|
||||
}
|
||||
@@ -192,11 +220,12 @@ final class OverrideRequestController {
|
||||
* notify the listener of all changes to request status as a result of this change.
|
||||
*/
|
||||
void handleNewSupportedStates(int[] newSupportedStates) {
|
||||
if (mRequest == null) {
|
||||
return;
|
||||
if (mBaseStateRequest != null && !contains(newSupportedStates,
|
||||
mBaseStateRequest.getRequestedState())) {
|
||||
cancelCurrentBaseStateRequestLocked();
|
||||
}
|
||||
|
||||
if (!contains(newSupportedStates, mRequest.getRequestedState())) {
|
||||
if (mRequest != null && !contains(newSupportedStates, mRequest.getRequestedState())) {
|
||||
cancelCurrentRequestLocked();
|
||||
}
|
||||
}
|
||||
@@ -228,10 +257,23 @@ final class OverrideRequestController {
|
||||
return;
|
||||
}
|
||||
mStickyRequest = false;
|
||||
mListener.onStatusChanged(mRequest, STATUS_CANCELED);
|
||||
cancelRequestLocked(mRequest);
|
||||
mRequest = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles cancelling {@code mBaseStateRequest}.
|
||||
* Notifies the listener of the canceled status as well.
|
||||
*/
|
||||
private void cancelCurrentBaseStateRequestLocked() {
|
||||
if (mBaseStateRequest == null) {
|
||||
Slog.w(TAG, "Attempted to cancel a null OverrideRequest");
|
||||
return;
|
||||
}
|
||||
cancelRequestLocked(mBaseStateRequest);
|
||||
mBaseStateRequest = null;
|
||||
}
|
||||
|
||||
private static boolean contains(int[] array, int value) {
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
if (array[i] == value) {
|
||||
|
||||
@@ -587,6 +587,157 @@ public final class DeviceStateManagerServiceTest {
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestBaseStateOverride() throws RemoteException {
|
||||
TestDeviceStateManagerCallback callback = new TestDeviceStateManagerCallback();
|
||||
mService.getBinderService().registerCallback(callback);
|
||||
flushHandler();
|
||||
|
||||
final IBinder token = new Binder();
|
||||
assertEquals(callback.getLastNotifiedStatus(token),
|
||||
TestDeviceStateManagerCallback.STATUS_UNKNOWN);
|
||||
|
||||
mService.getBinderService().requestBaseStateOverride(token,
|
||||
OTHER_DEVICE_STATE.getIdentifier(),
|
||||
0 /* flags */);
|
||||
// Flush the handler twice. The first flush ensures the request is added and the policy is
|
||||
// notified, while the second flush ensures the callback is notified once the change is
|
||||
// committed.
|
||||
flushHandler(2 /* count */);
|
||||
|
||||
assertEquals(callback.getLastNotifiedStatus(token),
|
||||
TestDeviceStateManagerCallback.STATUS_ACTIVE);
|
||||
// Committed state changes as there is a requested override.
|
||||
assertEquals(mService.getCommittedState(), Optional.of(OTHER_DEVICE_STATE));
|
||||
assertEquals(mSysPropSetter.getValue(),
|
||||
OTHER_DEVICE_STATE.getIdentifier() + ":" + OTHER_DEVICE_STATE.getName());
|
||||
assertEquals(mService.getBaseState(), Optional.of(OTHER_DEVICE_STATE));
|
||||
assertEquals(mService.getOverrideBaseState().get(), OTHER_DEVICE_STATE);
|
||||
assertFalse(mService.getOverrideState().isPresent());
|
||||
assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
|
||||
OTHER_DEVICE_STATE.getIdentifier());
|
||||
|
||||
assertNotNull(callback.getLastNotifiedInfo());
|
||||
assertEquals(callback.getLastNotifiedInfo().baseState,
|
||||
OTHER_DEVICE_STATE.getIdentifier());
|
||||
assertEquals(callback.getLastNotifiedInfo().currentState,
|
||||
OTHER_DEVICE_STATE.getIdentifier());
|
||||
|
||||
mService.getBinderService().cancelBaseStateOverride();
|
||||
flushHandler();
|
||||
|
||||
assertEquals(callback.getLastNotifiedStatus(token),
|
||||
TestDeviceStateManagerCallback.STATUS_CANCELED);
|
||||
// Committed state is set back to the requested state once the override is cleared.
|
||||
assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE));
|
||||
assertEquals(mSysPropSetter.getValue(),
|
||||
DEFAULT_DEVICE_STATE.getIdentifier() + ":" + DEFAULT_DEVICE_STATE.getName());
|
||||
assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE));
|
||||
assertFalse(mService.getOverrideBaseState().isPresent());
|
||||
assertFalse(mService.getOverrideState().isPresent());
|
||||
assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
|
||||
DEFAULT_DEVICE_STATE.getIdentifier());
|
||||
|
||||
assertEquals(callback.getLastNotifiedInfo().baseState,
|
||||
DEFAULT_DEVICE_STATE.getIdentifier());
|
||||
assertEquals(callback.getLastNotifiedInfo().currentState,
|
||||
DEFAULT_DEVICE_STATE.getIdentifier());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestBaseStateOverride_cancelledByBaseStateUpdate() throws RemoteException {
|
||||
final DeviceState testDeviceState = new DeviceState(2, "TEST", 0);
|
||||
TestDeviceStateManagerCallback callback = new TestDeviceStateManagerCallback();
|
||||
mService.getBinderService().registerCallback(callback);
|
||||
mProvider.notifySupportedDeviceStates(
|
||||
new DeviceState[]{DEFAULT_DEVICE_STATE, OTHER_DEVICE_STATE, testDeviceState });
|
||||
flushHandler();
|
||||
|
||||
final IBinder token = new Binder();
|
||||
assertEquals(callback.getLastNotifiedStatus(token),
|
||||
TestDeviceStateManagerCallback.STATUS_UNKNOWN);
|
||||
|
||||
mService.getBinderService().requestBaseStateOverride(token,
|
||||
OTHER_DEVICE_STATE.getIdentifier(),
|
||||
0 /* flags */);
|
||||
// Flush the handler twice. The first flush ensures the request is added and the policy is
|
||||
// notified, while the second flush ensures the callback is notified once the change is
|
||||
// committed.
|
||||
flushHandler(2 /* count */);
|
||||
|
||||
assertEquals(callback.getLastNotifiedStatus(token),
|
||||
TestDeviceStateManagerCallback.STATUS_ACTIVE);
|
||||
// Committed state changes as there is a requested override.
|
||||
assertEquals(mService.getCommittedState(), Optional.of(OTHER_DEVICE_STATE));
|
||||
assertEquals(mSysPropSetter.getValue(),
|
||||
OTHER_DEVICE_STATE.getIdentifier() + ":" + OTHER_DEVICE_STATE.getName());
|
||||
assertEquals(mService.getBaseState(), Optional.of(OTHER_DEVICE_STATE));
|
||||
assertEquals(mService.getOverrideBaseState().get(), OTHER_DEVICE_STATE);
|
||||
assertFalse(mService.getOverrideState().isPresent());
|
||||
assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
|
||||
OTHER_DEVICE_STATE.getIdentifier());
|
||||
|
||||
assertNotNull(callback.getLastNotifiedInfo());
|
||||
assertEquals(callback.getLastNotifiedInfo().baseState,
|
||||
OTHER_DEVICE_STATE.getIdentifier());
|
||||
assertEquals(callback.getLastNotifiedInfo().currentState,
|
||||
OTHER_DEVICE_STATE.getIdentifier());
|
||||
|
||||
mProvider.setState(testDeviceState.getIdentifier());
|
||||
flushHandler();
|
||||
|
||||
assertEquals(callback.getLastNotifiedStatus(token),
|
||||
TestDeviceStateManagerCallback.STATUS_CANCELED);
|
||||
// Committed state is set to the new base state once the override is cleared.
|
||||
assertEquals(mService.getCommittedState(), Optional.of(testDeviceState));
|
||||
assertEquals(mSysPropSetter.getValue(),
|
||||
testDeviceState.getIdentifier() + ":" + testDeviceState.getName());
|
||||
assertEquals(mService.getBaseState(), Optional.of(testDeviceState));
|
||||
assertFalse(mService.getOverrideBaseState().isPresent());
|
||||
assertFalse(mService.getOverrideState().isPresent());
|
||||
assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
|
||||
testDeviceState.getIdentifier());
|
||||
|
||||
assertEquals(callback.getLastNotifiedInfo().baseState,
|
||||
testDeviceState.getIdentifier());
|
||||
assertEquals(callback.getLastNotifiedInfo().currentState,
|
||||
testDeviceState.getIdentifier());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestBaseState_unsupportedState() throws RemoteException {
|
||||
TestDeviceStateManagerCallback callback = new TestDeviceStateManagerCallback();
|
||||
mService.getBinderService().registerCallback(callback);
|
||||
|
||||
assertThrows(IllegalArgumentException.class, () -> {
|
||||
final IBinder token = new Binder();
|
||||
mService.getBinderService().requestBaseStateOverride(token,
|
||||
UNSUPPORTED_DEVICE_STATE.getIdentifier(), 0 /* flags */);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestBaseState_invalidState() throws RemoteException {
|
||||
TestDeviceStateManagerCallback callback = new TestDeviceStateManagerCallback();
|
||||
mService.getBinderService().registerCallback(callback);
|
||||
|
||||
assertThrows(IllegalArgumentException.class, () -> {
|
||||
final IBinder token = new Binder();
|
||||
mService.getBinderService().requestBaseStateOverride(token, INVALID_DEVICE_STATE,
|
||||
0 /* flags */);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestBaseState_beforeRegisteringCallback() {
|
||||
assertThrows(IllegalStateException.class, () -> {
|
||||
final IBinder token = new Binder();
|
||||
mService.getBinderService().requestBaseStateOverride(token,
|
||||
DEFAULT_DEVICE_STATE.getIdentifier(),
|
||||
0 /* flags */);
|
||||
});
|
||||
}
|
||||
|
||||
private static void assertArrayEquals(int[] expected, int[] actual) {
|
||||
Assert.assertTrue(Arrays.equals(expected, actual));
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.server.devicestate;
|
||||
|
||||
import static com.android.server.devicestate.OverrideRequest.OVERRIDE_REQUEST_TYPE_BASE_STATE;
|
||||
import static com.android.server.devicestate.OverrideRequest.OVERRIDE_REQUEST_TYPE_EMULATED_STATE;
|
||||
import static com.android.server.devicestate.OverrideRequestController.STATUS_ACTIVE;
|
||||
import static com.android.server.devicestate.OverrideRequestController.STATUS_CANCELED;
|
||||
@@ -97,6 +98,48 @@ public final class OverrideRequestControllerTest {
|
||||
assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_CANCELED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addBaseStateRequest() {
|
||||
OverrideRequest request = new OverrideRequest(new Binder(), 0 /* pid */,
|
||||
0 /* requestedState */, 0 /* flags */, OVERRIDE_REQUEST_TYPE_BASE_STATE);
|
||||
assertNull(mStatusListener.getLastStatus(request));
|
||||
|
||||
mController.addBaseStateRequest(request);
|
||||
assertEquals(mStatusListener.getLastStatus(request).intValue(), STATUS_ACTIVE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addBaseStateRequest_cancelExistingBaseStateRequestThroughNewRequest() {
|
||||
OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */,
|
||||
0 /* requestedState */, 0 /* flags */, OVERRIDE_REQUEST_TYPE_BASE_STATE);
|
||||
assertNull(mStatusListener.getLastStatus(firstRequest));
|
||||
|
||||
mController.addBaseStateRequest(firstRequest);
|
||||
assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_ACTIVE);
|
||||
|
||||
OverrideRequest secondRequest = new OverrideRequest(new Binder(), 0 /* pid */,
|
||||
1 /* requestedState */, 0 /* flags */, OVERRIDE_REQUEST_TYPE_BASE_STATE);
|
||||
assertNull(mStatusListener.getLastStatus(secondRequest));
|
||||
|
||||
mController.addBaseStateRequest(secondRequest);
|
||||
assertEquals(mStatusListener.getLastStatus(secondRequest).intValue(), STATUS_ACTIVE);
|
||||
assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_CANCELED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addBaseStateRequest_cancelActiveBaseStateRequest() {
|
||||
OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */,
|
||||
0 /* requestedState */, 0 /* flags */, OVERRIDE_REQUEST_TYPE_BASE_STATE);
|
||||
|
||||
mController.addBaseStateRequest(firstRequest);
|
||||
|
||||
assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_ACTIVE);
|
||||
|
||||
mController.cancelBaseStateOverrideRequest();
|
||||
|
||||
assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_CANCELED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handleBaseStateChanged() {
|
||||
OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */,
|
||||
@@ -104,13 +147,22 @@ public final class OverrideRequestControllerTest {
|
||||
DeviceStateRequest.FLAG_CANCEL_WHEN_BASE_CHANGES /* flags */,
|
||||
OVERRIDE_REQUEST_TYPE_EMULATED_STATE);
|
||||
|
||||
OverrideRequest baseStateRequest = new OverrideRequest(new Binder(), 0 /* pid */,
|
||||
0 /* requestedState */,
|
||||
0 /* flags */, OVERRIDE_REQUEST_TYPE_BASE_STATE);
|
||||
|
||||
mController.addRequest(firstRequest);
|
||||
|
||||
assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_ACTIVE);
|
||||
|
||||
mController.handleBaseStateChanged();
|
||||
mController.addBaseStateRequest(baseStateRequest);
|
||||
|
||||
assertEquals(mStatusListener.getLastStatus(baseStateRequest).intValue(), STATUS_ACTIVE);
|
||||
|
||||
mController.handleBaseStateChanged(1);
|
||||
|
||||
assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_CANCELED);
|
||||
assertEquals(mStatusListener.getLastStatus(baseStateRequest).intValue(), STATUS_CANCELED);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -118,11 +170,19 @@ public final class OverrideRequestControllerTest {
|
||||
OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */,
|
||||
0 /* requestedState */, 0 /* flags */, OVERRIDE_REQUEST_TYPE_EMULATED_STATE);
|
||||
|
||||
OverrideRequest baseStateRequest = new OverrideRequest(new Binder(), 0 /* pid */,
|
||||
1 /* requestedState */,
|
||||
0 /* flags */, OVERRIDE_REQUEST_TYPE_BASE_STATE);
|
||||
|
||||
mController.addRequest(firstRequest);
|
||||
assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_ACTIVE);
|
||||
|
||||
mController.addBaseStateRequest(baseStateRequest);
|
||||
assertEquals(mStatusListener.getLastStatus(baseStateRequest).intValue(), STATUS_ACTIVE);
|
||||
|
||||
mController.handleProcessDied(0);
|
||||
assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_CANCELED);
|
||||
assertEquals(mStatusListener.getLastStatus(baseStateRequest).intValue(), STATUS_CANCELED);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -132,11 +192,18 @@ public final class OverrideRequestControllerTest {
|
||||
OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */,
|
||||
0 /* requestedState */, 0 /* flags */, OVERRIDE_REQUEST_TYPE_EMULATED_STATE);
|
||||
|
||||
OverrideRequest baseStateRequest = new OverrideRequest(new Binder(), 0 /* pid */,
|
||||
1 /* requestedState */, 0 /* flags */, OVERRIDE_REQUEST_TYPE_BASE_STATE);
|
||||
|
||||
mController.addRequest(firstRequest);
|
||||
assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_ACTIVE);
|
||||
|
||||
mController.addBaseStateRequest(baseStateRequest);
|
||||
assertEquals(mStatusListener.getLastStatus(baseStateRequest).intValue(), STATUS_ACTIVE);
|
||||
|
||||
mController.handleProcessDied(0);
|
||||
assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_ACTIVE);
|
||||
assertEquals(mStatusListener.getLastStatus(baseStateRequest).intValue(), STATUS_CANCELED);
|
||||
|
||||
mController.cancelStickyRequest();
|
||||
assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_CANCELED);
|
||||
@@ -147,14 +214,23 @@ public final class OverrideRequestControllerTest {
|
||||
OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */,
|
||||
1 /* requestedState */, 0 /* flags */, OVERRIDE_REQUEST_TYPE_EMULATED_STATE);
|
||||
|
||||
OverrideRequest baseStateRequest = new OverrideRequest(new Binder(), 0 /* pid */,
|
||||
1 /* requestedState */,
|
||||
0 /* flags */, OVERRIDE_REQUEST_TYPE_BASE_STATE);
|
||||
|
||||
mController.addRequest(firstRequest);
|
||||
assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_ACTIVE);
|
||||
|
||||
mController.handleNewSupportedStates(new int[]{ 0, 1 });
|
||||
assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_ACTIVE);
|
||||
mController.addBaseStateRequest(baseStateRequest);
|
||||
assertEquals(mStatusListener.getLastStatus(baseStateRequest).intValue(), STATUS_ACTIVE);
|
||||
|
||||
mController.handleNewSupportedStates(new int[]{ 0 });
|
||||
mController.handleNewSupportedStates(new int[]{0, 1});
|
||||
assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_ACTIVE);
|
||||
assertEquals(mStatusListener.getLastStatus(baseStateRequest).intValue(), STATUS_ACTIVE);
|
||||
|
||||
mController.handleNewSupportedStates(new int[]{0});
|
||||
assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_CANCELED);
|
||||
assertEquals(mStatusListener.getLastStatus(baseStateRequest).intValue(), STATUS_CANCELED);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user