Loading core/res/AndroidManifest.xml +6 −0 Original line number Diff line number Diff line Loading @@ -5160,6 +5160,12 @@ <permission android:name="android.permission.INPUT_CONSUMER" android:protectionLevel="signature" /> <!-- @hide Allows an application to control the system's device state managed by the {@link android.service.devicestate.DeviceStateManagerService}. For example, on foldable devices this would grant access to toggle between the folded and unfolded states. --> <permission android:name="android.permission.CONTROL_DEVICE_STATE" android:protectionLevel="signature" /> <!-- Attribution for Geofencing service. --> <attribution android:tag="GeofencingService" android:label="@string/geofencing_service"/> <!-- Attribution for Country Detector. --> Loading packages/Shell/AndroidManifest.xml +3 −0 Original line number Diff line number Diff line Loading @@ -338,6 +338,9 @@ <!-- Permissions required for CTS test - NotificationManagerTest --> <uses-permission android:name="android.permission.MANAGE_NOTIFICATION_LISTENERS" /> <!-- Allows overriding the system's device state from the shell --> <uses-permission android:name="android.permission.CONTROL_DEVICE_STATE"/> <application android:label="@string/app_label" android:theme="@android:style/Theme.DeviceDefault.DayNight" android:defaultToDeviceProtectedStorage="true" Loading services/core/java/com/android/server/devicestate/DeviceStateManagerService.java +92 −14 Original line number Diff line number Diff line Loading @@ -17,10 +17,14 @@ package com.android.server.devicestate; import static android.hardware.devicestate.DeviceStateManager.INVALID_DEVICE_STATE; import static android.Manifest.permission.CONTROL_DEVICE_STATE; import android.annotation.NonNull; import android.content.Context; import android.content.pm.PackageManager; import android.hardware.devicestate.IDeviceStateManager; import android.os.ResultReceiver; import android.os.ShellCallback; import android.util.IntArray; import android.util.Slog; Loading @@ -29,6 +33,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.server.SystemService; import com.android.server.policy.DeviceStatePolicyImpl; import java.io.FileDescriptor; import java.util.Arrays; /** Loading Loading @@ -65,15 +70,20 @@ public final class DeviceStateManagerService extends SystemService { // The current committed device state. @GuardedBy("mLock") private int mCommittedState = INVALID_DEVICE_STATE; // The device state that is currently pending callback from the policy to be committed. // The device state that is currently awaiting callback from the policy to be committed. @GuardedBy("mLock") private int mPendingState = INVALID_DEVICE_STATE; // Whether or not the policy is currently waiting to be notified of the current pending state. @GuardedBy("mLock") private boolean mIsPolicyWaitingForState = false; // The device state that is currently requested and is next to be configured and committed. // Can be overwritten by an override state value if requested. @GuardedBy("mLock") private int mRequestedState = INVALID_DEVICE_STATE; // The most recently requested override state, or INVALID_DEVICE_STATE if no override is // requested. @GuardedBy("mLock") private int mRequestedOverrideState = INVALID_DEVICE_STATE; public DeviceStateManagerService(@NonNull Context context) { this(context, new DeviceStatePolicyImpl()); Loading @@ -97,7 +107,6 @@ public final class DeviceStateManagerService extends SystemService { * * @see #getPendingState() */ @VisibleForTesting int getCommittedState() { synchronized (mLock) { return mCommittedState; Loading @@ -119,13 +128,61 @@ public final class DeviceStateManagerService extends SystemService { * Returns the requested state. The service will configure the device to match the requested * state when possible. */ @VisibleForTesting int getRequestedState() { synchronized (mLock) { return mRequestedState; } } /** * Overrides the current device state with the provided state. * * @return {@code true} if the override state is valid and supported, {@code false} otherwise. */ boolean setOverrideState(int overrideState) { if (getContext().checkCallingOrSelfPermission(CONTROL_DEVICE_STATE) != PackageManager.PERMISSION_GRANTED) { throw new SecurityException("Must hold permission " + CONTROL_DEVICE_STATE); } synchronized (mLock) { if (overrideState != INVALID_DEVICE_STATE && !isSupportedStateLocked(overrideState)) { return false; } mRequestedOverrideState = overrideState; updatePendingStateLocked(); } notifyPolicyIfNeeded(); return true; } /** * Clears an override state set with {@link #setOverrideState(int)}. */ void clearOverrideState() { setOverrideState(INVALID_DEVICE_STATE); } /** * Returns the current requested override state, or {@link #INVALID_DEVICE_STATE} is no override * state is requested. */ int getOverrideState() { synchronized (mLock) { return mRequestedOverrideState; } } /** Returns the list of currently supported device states. */ int[] getSupportedStates() { synchronized (mLock) { // Copy array to prevent external modification of internal state. return Arrays.copyOf(mSupportedDeviceStates.toArray(), mSupportedDeviceStates.size()); } } private void updateSupportedStates(int[] supportedDeviceStates) { // Must ensure sorted as isSupportedStateLocked() impl uses binary search. Arrays.sort(supportedDeviceStates, 0, supportedDeviceStates.length); Loading @@ -135,11 +192,20 @@ public final class DeviceStateManagerService extends SystemService { if (mRequestedState != INVALID_DEVICE_STATE && !isSupportedStateLocked(mRequestedState)) { // The current requested state is no longer valid. We'll clear it here, though // we won't actually update the current state with a call to // updatePendingStateLocked() as doing so will not have any effect. // we won't actually update the current state until a callback comes from the // provider with the most recent state. mRequestedState = INVALID_DEVICE_STATE; } if (mRequestedOverrideState != INVALID_DEVICE_STATE && !isSupportedStateLocked(mRequestedOverrideState)) { // The current override state is no longer valid. We'll clear it here and update // the committed state if necessary. mRequestedOverrideState = INVALID_DEVICE_STATE; } updatePendingStateLocked(); } notifyPolicyIfNeeded(); } /** Loading Loading @@ -168,27 +234,34 @@ public final class DeviceStateManagerService extends SystemService { } /** * Tries to update the current configuring state with the current requested state. Must call * Tries to update the current pending state with the current requested state. Must call * {@link #notifyPolicyIfNeeded()} to actually notify the policy that the state is being * changed. */ private void updatePendingStateLocked() { if (mRequestedState == INVALID_DEVICE_STATE) { // No currently requested state. if (mPendingState != INVALID_DEVICE_STATE) { // Have pending state, can not configure a new state until the state is committed. return; } if (mPendingState != INVALID_DEVICE_STATE) { // Have pending state, can not configure a new state until the state is committed. int stateToConfigure; if (mRequestedOverrideState != INVALID_DEVICE_STATE) { stateToConfigure = mRequestedOverrideState; } else { stateToConfigure = mRequestedState; } if (stateToConfigure == INVALID_DEVICE_STATE) { // No currently requested state. return; } if (mRequestedState == mCommittedState) { // No need to notify the policy as the committed state matches the requested state. if (stateToConfigure == mCommittedState) { // The state requesting to be committed already matches the current committed state. return; } mPendingState = mRequestedState; mPendingState = stateToConfigure; mIsPolicyWaitingForState = true; } Loading Loading @@ -271,6 +344,11 @@ public final class DeviceStateManagerService extends SystemService { /** Implementation of {@link IDeviceStateManager} published as a binder service. */ private final class BinderService extends IDeviceStateManager.Stub { @Override // Binder call public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ShellCallback callback, ResultReceiver result) { new DeviceStateManagerShellCommand(DeviceStateManagerService.this) .exec(this, in, out, err, args, callback, result); } } } services/core/java/com/android/server/devicestate/DeviceStateManagerShellCommand.java 0 → 100644 +128 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.devicestate; import static android.hardware.devicestate.DeviceStateManager.INVALID_DEVICE_STATE; import android.os.ShellCommand; import java.io.PrintWriter; /** * ShellCommands for {@link DeviceStateManagerService}. * * Use with {@code adb shell cmd device_state ...}. */ public class DeviceStateManagerShellCommand extends ShellCommand { private final DeviceStateManagerService mInternal; public DeviceStateManagerShellCommand(DeviceStateManagerService service) { mInternal = service; } @Override public int onCommand(String cmd) { if (cmd == null) { return handleDefaultCommands(cmd); } final PrintWriter pw = getOutPrintWriter(); switch (cmd) { case "state": return runState(pw); case "print-states": return runPrintStates(pw); default: return handleDefaultCommands(cmd); } } private void printState(PrintWriter pw) { int committedState = mInternal.getCommittedState(); int requestedState = mInternal.getRequestedState(); int requestedOverrideState = mInternal.getOverrideState(); if (committedState == INVALID_DEVICE_STATE) { pw.println("Device state: (invalid)"); } else { pw.println("Device state: " + committedState); } if (requestedOverrideState != INVALID_DEVICE_STATE) { pw.println("----------------------"); if (requestedState == INVALID_DEVICE_STATE) { pw.println("Base state: (invalid)"); } else { pw.println("Base state: " + requestedState); } pw.println("Override state: " + committedState); } } private int runState(PrintWriter pw) { final String nextArg = getNextArg(); if (nextArg == null) { printState(pw); } else if ("reset".equals(nextArg)) { mInternal.clearOverrideState(); } else { int requestedState; try { requestedState = Integer.parseInt(nextArg); } catch (NumberFormatException e) { getErrPrintWriter().println("Error: requested state should be an integer"); return -1; } boolean success = mInternal.setOverrideState(requestedState); if (!success) { getErrPrintWriter().println("Error: failed to set override state. Run:"); getErrPrintWriter().println(""); getErrPrintWriter().println(" print-states"); getErrPrintWriter().println(""); getErrPrintWriter().println("to get the list of currently supported device states"); return -1; } } return 0; } private int runPrintStates(PrintWriter pw) { int[] states = mInternal.getSupportedStates(); pw.print("Supported states: [ "); for (int i = 0; i < states.length; i++) { pw.print(states[i]); if (i < states.length - 1) { pw.print(", "); } } pw.println(" ]"); return 0; } @Override public void onHelp() { PrintWriter pw = getOutPrintWriter(); pw.println("Device state manager (device_state) commands:"); pw.println(" help"); pw.println(" Print this help text."); pw.println(" state [reset|OVERRIDE_DEVICE_STATE]"); pw.println(" Return or override device state."); pw.println(" print-states"); pw.println(" Return list of currently supported device states."); } } services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java +41 −0 Original line number Diff line number Diff line Loading @@ -104,6 +104,30 @@ public final class DeviceStateManagerServiceTest { }); } @Test public void requestOverrideState() { mService.setOverrideState(OTHER_DEVICE_STATE); // Committed state changes as there is a requested override. assertEquals(mService.getCommittedState(), OTHER_DEVICE_STATE); assertEquals(mService.getRequestedState(), DEFAULT_DEVICE_STATE); assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(), OTHER_DEVICE_STATE); // Committed state is set back to the requested state once the override is cleared. mService.clearOverrideState(); assertEquals(mService.getCommittedState(), DEFAULT_DEVICE_STATE); assertEquals(mService.getRequestedState(), DEFAULT_DEVICE_STATE); assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(), DEFAULT_DEVICE_STATE); } @Test public void requestOverrideState_unsupportedState() { mService.setOverrideState(UNSUPPORTED_DEVICE_STATE); // Committed state remains the same as the override state is unsupported. assertEquals(mService.getCommittedState(), DEFAULT_DEVICE_STATE); assertEquals(mService.getRequestedState(), DEFAULT_DEVICE_STATE); assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(), DEFAULT_DEVICE_STATE); } @Test public void supportedStatesChanged() { assertEquals(mService.getCommittedState(), DEFAULT_DEVICE_STATE); Loading Loading @@ -146,6 +170,23 @@ public final class DeviceStateManagerServiceTest { assertEquals(mService.getRequestedState(), OTHER_DEVICE_STATE); } @Test public void supportedStatesChanged_unsupportedOverrideState() { mService.setOverrideState(OTHER_DEVICE_STATE); // Committed state changes as there is a requested override. assertEquals(mService.getCommittedState(), OTHER_DEVICE_STATE); assertEquals(mService.getRequestedState(), DEFAULT_DEVICE_STATE); assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(), OTHER_DEVICE_STATE); mProvider.notifySupportedDeviceStates(new int []{ DEFAULT_DEVICE_STATE }); // Committed state is set back to the requested state as the override state is no longer // supported. assertEquals(mService.getCommittedState(), DEFAULT_DEVICE_STATE); assertEquals(mService.getRequestedState(), DEFAULT_DEVICE_STATE); assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(), DEFAULT_DEVICE_STATE); } private static final class TestDeviceStatePolicy implements DeviceStatePolicy { private final DeviceStateProvider mProvider; private int mLastDeviceStateRequestedToConfigure = INVALID_DEVICE_STATE; Loading Loading
core/res/AndroidManifest.xml +6 −0 Original line number Diff line number Diff line Loading @@ -5160,6 +5160,12 @@ <permission android:name="android.permission.INPUT_CONSUMER" android:protectionLevel="signature" /> <!-- @hide Allows an application to control the system's device state managed by the {@link android.service.devicestate.DeviceStateManagerService}. For example, on foldable devices this would grant access to toggle between the folded and unfolded states. --> <permission android:name="android.permission.CONTROL_DEVICE_STATE" android:protectionLevel="signature" /> <!-- Attribution for Geofencing service. --> <attribution android:tag="GeofencingService" android:label="@string/geofencing_service"/> <!-- Attribution for Country Detector. --> Loading
packages/Shell/AndroidManifest.xml +3 −0 Original line number Diff line number Diff line Loading @@ -338,6 +338,9 @@ <!-- Permissions required for CTS test - NotificationManagerTest --> <uses-permission android:name="android.permission.MANAGE_NOTIFICATION_LISTENERS" /> <!-- Allows overriding the system's device state from the shell --> <uses-permission android:name="android.permission.CONTROL_DEVICE_STATE"/> <application android:label="@string/app_label" android:theme="@android:style/Theme.DeviceDefault.DayNight" android:defaultToDeviceProtectedStorage="true" Loading
services/core/java/com/android/server/devicestate/DeviceStateManagerService.java +92 −14 Original line number Diff line number Diff line Loading @@ -17,10 +17,14 @@ package com.android.server.devicestate; import static android.hardware.devicestate.DeviceStateManager.INVALID_DEVICE_STATE; import static android.Manifest.permission.CONTROL_DEVICE_STATE; import android.annotation.NonNull; import android.content.Context; import android.content.pm.PackageManager; import android.hardware.devicestate.IDeviceStateManager; import android.os.ResultReceiver; import android.os.ShellCallback; import android.util.IntArray; import android.util.Slog; Loading @@ -29,6 +33,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.server.SystemService; import com.android.server.policy.DeviceStatePolicyImpl; import java.io.FileDescriptor; import java.util.Arrays; /** Loading Loading @@ -65,15 +70,20 @@ public final class DeviceStateManagerService extends SystemService { // The current committed device state. @GuardedBy("mLock") private int mCommittedState = INVALID_DEVICE_STATE; // The device state that is currently pending callback from the policy to be committed. // The device state that is currently awaiting callback from the policy to be committed. @GuardedBy("mLock") private int mPendingState = INVALID_DEVICE_STATE; // Whether or not the policy is currently waiting to be notified of the current pending state. @GuardedBy("mLock") private boolean mIsPolicyWaitingForState = false; // The device state that is currently requested and is next to be configured and committed. // Can be overwritten by an override state value if requested. @GuardedBy("mLock") private int mRequestedState = INVALID_DEVICE_STATE; // The most recently requested override state, or INVALID_DEVICE_STATE if no override is // requested. @GuardedBy("mLock") private int mRequestedOverrideState = INVALID_DEVICE_STATE; public DeviceStateManagerService(@NonNull Context context) { this(context, new DeviceStatePolicyImpl()); Loading @@ -97,7 +107,6 @@ public final class DeviceStateManagerService extends SystemService { * * @see #getPendingState() */ @VisibleForTesting int getCommittedState() { synchronized (mLock) { return mCommittedState; Loading @@ -119,13 +128,61 @@ public final class DeviceStateManagerService extends SystemService { * Returns the requested state. The service will configure the device to match the requested * state when possible. */ @VisibleForTesting int getRequestedState() { synchronized (mLock) { return mRequestedState; } } /** * Overrides the current device state with the provided state. * * @return {@code true} if the override state is valid and supported, {@code false} otherwise. */ boolean setOverrideState(int overrideState) { if (getContext().checkCallingOrSelfPermission(CONTROL_DEVICE_STATE) != PackageManager.PERMISSION_GRANTED) { throw new SecurityException("Must hold permission " + CONTROL_DEVICE_STATE); } synchronized (mLock) { if (overrideState != INVALID_DEVICE_STATE && !isSupportedStateLocked(overrideState)) { return false; } mRequestedOverrideState = overrideState; updatePendingStateLocked(); } notifyPolicyIfNeeded(); return true; } /** * Clears an override state set with {@link #setOverrideState(int)}. */ void clearOverrideState() { setOverrideState(INVALID_DEVICE_STATE); } /** * Returns the current requested override state, or {@link #INVALID_DEVICE_STATE} is no override * state is requested. */ int getOverrideState() { synchronized (mLock) { return mRequestedOverrideState; } } /** Returns the list of currently supported device states. */ int[] getSupportedStates() { synchronized (mLock) { // Copy array to prevent external modification of internal state. return Arrays.copyOf(mSupportedDeviceStates.toArray(), mSupportedDeviceStates.size()); } } private void updateSupportedStates(int[] supportedDeviceStates) { // Must ensure sorted as isSupportedStateLocked() impl uses binary search. Arrays.sort(supportedDeviceStates, 0, supportedDeviceStates.length); Loading @@ -135,11 +192,20 @@ public final class DeviceStateManagerService extends SystemService { if (mRequestedState != INVALID_DEVICE_STATE && !isSupportedStateLocked(mRequestedState)) { // The current requested state is no longer valid. We'll clear it here, though // we won't actually update the current state with a call to // updatePendingStateLocked() as doing so will not have any effect. // we won't actually update the current state until a callback comes from the // provider with the most recent state. mRequestedState = INVALID_DEVICE_STATE; } if (mRequestedOverrideState != INVALID_DEVICE_STATE && !isSupportedStateLocked(mRequestedOverrideState)) { // The current override state is no longer valid. We'll clear it here and update // the committed state if necessary. mRequestedOverrideState = INVALID_DEVICE_STATE; } updatePendingStateLocked(); } notifyPolicyIfNeeded(); } /** Loading Loading @@ -168,27 +234,34 @@ public final class DeviceStateManagerService extends SystemService { } /** * Tries to update the current configuring state with the current requested state. Must call * Tries to update the current pending state with the current requested state. Must call * {@link #notifyPolicyIfNeeded()} to actually notify the policy that the state is being * changed. */ private void updatePendingStateLocked() { if (mRequestedState == INVALID_DEVICE_STATE) { // No currently requested state. if (mPendingState != INVALID_DEVICE_STATE) { // Have pending state, can not configure a new state until the state is committed. return; } if (mPendingState != INVALID_DEVICE_STATE) { // Have pending state, can not configure a new state until the state is committed. int stateToConfigure; if (mRequestedOverrideState != INVALID_DEVICE_STATE) { stateToConfigure = mRequestedOverrideState; } else { stateToConfigure = mRequestedState; } if (stateToConfigure == INVALID_DEVICE_STATE) { // No currently requested state. return; } if (mRequestedState == mCommittedState) { // No need to notify the policy as the committed state matches the requested state. if (stateToConfigure == mCommittedState) { // The state requesting to be committed already matches the current committed state. return; } mPendingState = mRequestedState; mPendingState = stateToConfigure; mIsPolicyWaitingForState = true; } Loading Loading @@ -271,6 +344,11 @@ public final class DeviceStateManagerService extends SystemService { /** Implementation of {@link IDeviceStateManager} published as a binder service. */ private final class BinderService extends IDeviceStateManager.Stub { @Override // Binder call public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ShellCallback callback, ResultReceiver result) { new DeviceStateManagerShellCommand(DeviceStateManagerService.this) .exec(this, in, out, err, args, callback, result); } } }
services/core/java/com/android/server/devicestate/DeviceStateManagerShellCommand.java 0 → 100644 +128 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.devicestate; import static android.hardware.devicestate.DeviceStateManager.INVALID_DEVICE_STATE; import android.os.ShellCommand; import java.io.PrintWriter; /** * ShellCommands for {@link DeviceStateManagerService}. * * Use with {@code adb shell cmd device_state ...}. */ public class DeviceStateManagerShellCommand extends ShellCommand { private final DeviceStateManagerService mInternal; public DeviceStateManagerShellCommand(DeviceStateManagerService service) { mInternal = service; } @Override public int onCommand(String cmd) { if (cmd == null) { return handleDefaultCommands(cmd); } final PrintWriter pw = getOutPrintWriter(); switch (cmd) { case "state": return runState(pw); case "print-states": return runPrintStates(pw); default: return handleDefaultCommands(cmd); } } private void printState(PrintWriter pw) { int committedState = mInternal.getCommittedState(); int requestedState = mInternal.getRequestedState(); int requestedOverrideState = mInternal.getOverrideState(); if (committedState == INVALID_DEVICE_STATE) { pw.println("Device state: (invalid)"); } else { pw.println("Device state: " + committedState); } if (requestedOverrideState != INVALID_DEVICE_STATE) { pw.println("----------------------"); if (requestedState == INVALID_DEVICE_STATE) { pw.println("Base state: (invalid)"); } else { pw.println("Base state: " + requestedState); } pw.println("Override state: " + committedState); } } private int runState(PrintWriter pw) { final String nextArg = getNextArg(); if (nextArg == null) { printState(pw); } else if ("reset".equals(nextArg)) { mInternal.clearOverrideState(); } else { int requestedState; try { requestedState = Integer.parseInt(nextArg); } catch (NumberFormatException e) { getErrPrintWriter().println("Error: requested state should be an integer"); return -1; } boolean success = mInternal.setOverrideState(requestedState); if (!success) { getErrPrintWriter().println("Error: failed to set override state. Run:"); getErrPrintWriter().println(""); getErrPrintWriter().println(" print-states"); getErrPrintWriter().println(""); getErrPrintWriter().println("to get the list of currently supported device states"); return -1; } } return 0; } private int runPrintStates(PrintWriter pw) { int[] states = mInternal.getSupportedStates(); pw.print("Supported states: [ "); for (int i = 0; i < states.length; i++) { pw.print(states[i]); if (i < states.length - 1) { pw.print(", "); } } pw.println(" ]"); return 0; } @Override public void onHelp() { PrintWriter pw = getOutPrintWriter(); pw.println("Device state manager (device_state) commands:"); pw.println(" help"); pw.println(" Print this help text."); pw.println(" state [reset|OVERRIDE_DEVICE_STATE]"); pw.println(" Return or override device state."); pw.println(" print-states"); pw.println(" Return list of currently supported device states."); } }
services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java +41 −0 Original line number Diff line number Diff line Loading @@ -104,6 +104,30 @@ public final class DeviceStateManagerServiceTest { }); } @Test public void requestOverrideState() { mService.setOverrideState(OTHER_DEVICE_STATE); // Committed state changes as there is a requested override. assertEquals(mService.getCommittedState(), OTHER_DEVICE_STATE); assertEquals(mService.getRequestedState(), DEFAULT_DEVICE_STATE); assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(), OTHER_DEVICE_STATE); // Committed state is set back to the requested state once the override is cleared. mService.clearOverrideState(); assertEquals(mService.getCommittedState(), DEFAULT_DEVICE_STATE); assertEquals(mService.getRequestedState(), DEFAULT_DEVICE_STATE); assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(), DEFAULT_DEVICE_STATE); } @Test public void requestOverrideState_unsupportedState() { mService.setOverrideState(UNSUPPORTED_DEVICE_STATE); // Committed state remains the same as the override state is unsupported. assertEquals(mService.getCommittedState(), DEFAULT_DEVICE_STATE); assertEquals(mService.getRequestedState(), DEFAULT_DEVICE_STATE); assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(), DEFAULT_DEVICE_STATE); } @Test public void supportedStatesChanged() { assertEquals(mService.getCommittedState(), DEFAULT_DEVICE_STATE); Loading Loading @@ -146,6 +170,23 @@ public final class DeviceStateManagerServiceTest { assertEquals(mService.getRequestedState(), OTHER_DEVICE_STATE); } @Test public void supportedStatesChanged_unsupportedOverrideState() { mService.setOverrideState(OTHER_DEVICE_STATE); // Committed state changes as there is a requested override. assertEquals(mService.getCommittedState(), OTHER_DEVICE_STATE); assertEquals(mService.getRequestedState(), DEFAULT_DEVICE_STATE); assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(), OTHER_DEVICE_STATE); mProvider.notifySupportedDeviceStates(new int []{ DEFAULT_DEVICE_STATE }); // Committed state is set back to the requested state as the override state is no longer // supported. assertEquals(mService.getCommittedState(), DEFAULT_DEVICE_STATE); assertEquals(mService.getRequestedState(), DEFAULT_DEVICE_STATE); assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(), DEFAULT_DEVICE_STATE); } private static final class TestDeviceStatePolicy implements DeviceStatePolicy { private final DeviceStateProvider mProvider; private int mLastDeviceStateRequestedToConfigure = INVALID_DEVICE_STATE; Loading