Loading core/java/android/hardware/devicestate/DeviceStateManagerGlobal.java +14 −19 Original line number Original line Diff line number Diff line Loading @@ -179,8 +179,6 @@ public final class DeviceStateManagerGlobal { @VisibleForTesting(visibility = Visibility.PACKAGE) @VisibleForTesting(visibility = Visibility.PACKAGE) public void registerDeviceStateCallback(@NonNull DeviceStateCallback callback, public void registerDeviceStateCallback(@NonNull DeviceStateCallback callback, @NonNull Executor executor) { @NonNull Executor executor) { DeviceStateCallbackWrapper wrapper; DeviceStateInfo currentInfo; synchronized (mLock) { synchronized (mLock) { int index = findCallbackLocked(callback); int index = findCallbackLocked(callback); if (index != -1) { if (index != -1) { Loading @@ -189,25 +187,22 @@ public final class DeviceStateManagerGlobal { } } registerCallbackIfNeededLocked(); registerCallbackIfNeededLocked(); if (mLastReceivedInfo == null) { // Initialize the last received info with the current info if this is the first // callback being registered. try { mLastReceivedInfo = mDeviceStateManager.getDeviceStateInfo(); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } } currentInfo = new DeviceStateInfo(mLastReceivedInfo); // Add the callback wrapper to the mCallbacks array after registering the callback as // the callback could be triggered immediately if the mDeviceStateManager IBinder is in wrapper = new DeviceStateCallbackWrapper(callback, executor); // the same process as this instance. DeviceStateCallbackWrapper wrapper = new DeviceStateCallbackWrapper(callback, executor); mCallbacks.add(wrapper); mCallbacks.add(wrapper); } wrapper.notifySupportedStatesChanged(currentInfo.supportedStates); if (mLastReceivedInfo != null) { wrapper.notifyBaseStateChanged(currentInfo.baseState); // Copy the array to prevent the callback from modifying the internal state. wrapper.notifyStateChanged(currentInfo.currentState); final int[] supportedStates = Arrays.copyOf(mLastReceivedInfo.supportedStates, mLastReceivedInfo.supportedStates.length); wrapper.notifySupportedStatesChanged(supportedStates); wrapper.notifyBaseStateChanged(mLastReceivedInfo.baseState); wrapper.notifyStateChanged(mLastReceivedInfo.currentState); } } } } /** /** Loading Loading @@ -267,7 +262,7 @@ public final class DeviceStateManagerGlobal { callbacks = new ArrayList<>(mCallbacks); callbacks = new ArrayList<>(mCallbacks); } } final int diff = oldInfo == null ? 1 : info.diff(oldInfo); final int diff = oldInfo == null ? ~0 : info.diff(oldInfo); if ((diff & DeviceStateInfo.CHANGED_SUPPORTED_STATES) > 0) { if ((diff & DeviceStateInfo.CHANGED_SUPPORTED_STATES) > 0) { for (int i = 0; i < callbacks.size(); i++) { for (int i = 0; i < callbacks.size(); i++) { // Copy the array to prevent callbacks from modifying the internal state. // Copy the array to prevent callbacks from modifying the internal state. Loading core/java/android/hardware/devicestate/IDeviceStateManagerCallback.aidl +2 −1 Original line number Original line Diff line number Diff line Loading @@ -21,7 +21,8 @@ import android.hardware.devicestate.DeviceStateInfo; /** @hide */ /** @hide */ interface IDeviceStateManagerCallback { interface IDeviceStateManagerCallback { /** /** * Called in response to a change in {@link DeviceStateInfo}. * Called in response to a change in {@link DeviceStateInfo}. Guaranteed to be called once * after successful registration of the callback with the initial value. * * * @param info the new device state info. * @param info the new device state info. * * Loading core/tests/devicestatetests/src/android/hardware/devicestate/DeviceStateManagerGlobalTest.java +5 −0 Original line number Original line Diff line number Diff line Loading @@ -208,6 +208,11 @@ public final class DeviceStateManagerGlobalTest { } } mCallbacks.add(callback); mCallbacks.add(callback); try { callback.onDeviceStateInfoChanged(getInfo()); } catch (RemoteException e) { // Do nothing. Should never happen. } } } @Override @Override Loading services/core/java/com/android/server/devicestate/DeviceStateManagerService.java +47 −22 Original line number Original line Diff line number Diff line Loading @@ -78,9 +78,6 @@ import java.util.Optional; public final class DeviceStateManagerService extends SystemService { public final class DeviceStateManagerService extends SystemService { private static final String TAG = "DeviceStateManagerService"; private static final String TAG = "DeviceStateManagerService"; private static final boolean DEBUG = false; private static final boolean DEBUG = false; // The device state to use as a placeholder before callback from the DeviceStateProvider occurs. private static final DeviceState UNSPECIFIED_DEVICE_STATE = new DeviceState(MINIMUM_DEVICE_STATE, "UNSPECIFIED"); private final Object mLock = new Object(); private final Object mLock = new Object(); @NonNull @NonNull Loading @@ -92,11 +89,11 @@ public final class DeviceStateManagerService extends SystemService { @GuardedBy("mLock") @GuardedBy("mLock") private SparseArray<DeviceState> mDeviceStates = new SparseArray<>(); private SparseArray<DeviceState> mDeviceStates = new SparseArray<>(); // The current committed device state. The default of UNSPECIFIED_DEVICE_STATE will be replaced // The current committed device state. Will be empty until the first device state provided by // by the current state after the initial callback from the DeviceStateProvider. // the DeviceStateProvider is committed. @GuardedBy("mLock") @GuardedBy("mLock") @NonNull @NonNull private DeviceState mCommittedState = UNSPECIFIED_DEVICE_STATE; private Optional<DeviceState> mCommittedState = Optional.empty(); // The device state that is currently awaiting callback from the policy to be committed. // The device state that is currently awaiting callback from the policy to be committed. @GuardedBy("mLock") @GuardedBy("mLock") @NonNull @NonNull Loading @@ -105,10 +102,11 @@ public final class DeviceStateManagerService extends SystemService { @GuardedBy("mLock") @GuardedBy("mLock") private boolean mIsPolicyWaitingForState = false; private boolean mIsPolicyWaitingForState = false; // The device state that is set by the device state provider. // The device state that is set by the DeviceStateProvider. Will be empty until the first // callback from the provider and then will always contain the most recent value. @GuardedBy("mLock") @GuardedBy("mLock") @NonNull @NonNull private DeviceState mBaseState = UNSPECIFIED_DEVICE_STATE; private Optional<DeviceState> mBaseState = Optional.empty(); // List of processes registered to receive notifications about changes to device state and // List of processes registered to receive notifications about changes to device state and // request status indexed by process id. // request status indexed by process id. Loading Loading @@ -142,11 +140,14 @@ public final class DeviceStateManagerService extends SystemService { /** /** * Returns the current state the system is in. Note that the system may be in the process of * Returns the current state the system is in. Note that the system may be in the process of * configuring a different state. * configuring a different state. * <p> * Note: This method will return {@link Optional#empty()} if called before the first state has * been committed, otherwise it will return the last committed state. * * * @see #getPendingState() * @see #getPendingState() */ */ @NonNull @NonNull DeviceState getCommittedState() { Optional<DeviceState> getCommittedState() { synchronized (mLock) { synchronized (mLock) { return mCommittedState; return mCommittedState; } } Loading @@ -167,11 +168,15 @@ public final class DeviceStateManagerService extends SystemService { /** /** * Returns the base state. The service will configure the device to match the base state when * Returns the base state. The service will configure the device to match the base state when * there is no active request to override the base state. * there is no active request to override the base state. * <p> * Note: This method will return {@link Optional#empty()} if called before a base state is * provided to the service by the {@link DeviceStateProvider}, otherwise it will return the * most recent provided value. * * * @see #getOverrideState() * @see #getOverrideState() */ */ @NonNull @NonNull DeviceState getBaseState() { Optional<DeviceState> getBaseState() { synchronized (mLock) { synchronized (mLock) { return mBaseState; return mBaseState; } } Loading Loading @@ -223,9 +228,14 @@ public final class DeviceStateManagerService extends SystemService { @NonNull @NonNull private DeviceStateInfo getDeviceStateInfoLocked() { private DeviceStateInfo getDeviceStateInfoLocked() { if (!mBaseState.isPresent() || !mCommittedState.isPresent()) { throw new IllegalStateException("Trying to get the current DeviceStateInfo before the" + " initial state has been committed."); } final int[] supportedStates = getSupportedStateIdentifiersLocked(); final int[] supportedStates = getSupportedStateIdentifiersLocked(); final int baseState = mBaseState.getIdentifier(); final int baseState = mBaseState.get().getIdentifier(); final int currentState = mCommittedState.getIdentifier(); final int currentState = mCommittedState.get().getIdentifier(); return new DeviceStateInfo(supportedStates, baseState, currentState); return new DeviceStateInfo(supportedStates, baseState, currentState); } } Loading @@ -237,6 +247,7 @@ public final class DeviceStateManagerService extends SystemService { private void updateSupportedStates(DeviceState[] supportedDeviceStates) { private void updateSupportedStates(DeviceState[] supportedDeviceStates) { boolean updatedPendingState; boolean updatedPendingState; boolean hasBaseState; synchronized (mLock) { synchronized (mLock) { final int[] oldStateIdentifiers = getSupportedStateIdentifiersLocked(); final int[] oldStateIdentifiers = getSupportedStateIdentifiersLocked(); Loading @@ -260,9 +271,10 @@ public final class DeviceStateManagerService extends SystemService { } } updatedPendingState = updatePendingStateLocked(); updatedPendingState = updatePendingStateLocked(); hasBaseState = mBaseState.isPresent(); } } if (!updatedPendingState) { if (hasBaseState && !updatedPendingState) { // If the change in the supported states didn't result in a change of the pending state // If the change in the supported states didn't result in a change of the pending state // commitPendingState() will never be called and the callbacks will never be notified // commitPendingState() will never be called and the callbacks will never be notified // of the change. // of the change. Loading Loading @@ -306,11 +318,11 @@ public final class DeviceStateManagerService extends SystemService { } } final DeviceState baseState = baseStateOptional.get(); final DeviceState baseState = baseStateOptional.get(); if (mBaseState.equals(baseState)) { if (mBaseState.isPresent() && mBaseState.get().equals(baseState)) { // Base state hasn't changed. Nothing to do. // Base state hasn't changed. Nothing to do. return; return; } } mBaseState = baseState; mBaseState = Optional.of(baseState); final int requestSize = mRequestRecords.size(); final int requestSize = mRequestRecords.size(); for (int i = 0; i < requestSize; i++) { for (int i = 0; i < requestSize; i++) { Loading Loading @@ -351,9 +363,10 @@ public final class DeviceStateManagerService extends SystemService { final DeviceState stateToConfigure; final DeviceState stateToConfigure; if (!mRequestRecords.isEmpty()) { if (!mRequestRecords.isEmpty()) { stateToConfigure = mRequestRecords.get(mRequestRecords.size() - 1).mRequestedState; stateToConfigure = mRequestRecords.get(mRequestRecords.size() - 1).mRequestedState; } else if (isSupportedStateLocked(mBaseState.getIdentifier())) { } else if (mBaseState.isPresent() && isSupportedStateLocked(mBaseState.get().getIdentifier())) { // Base state could have recently become unsupported after a change in supported states. // Base state could have recently become unsupported after a change in supported states. stateToConfigure = mBaseState; stateToConfigure = mBaseState.get(); } else { } else { stateToConfigure = null; stateToConfigure = null; } } Loading @@ -363,7 +376,7 @@ public final class DeviceStateManagerService extends SystemService { return false; return false; } } if (stateToConfigure.equals(mCommittedState)) { if (mCommittedState.isPresent() && stateToConfigure.equals(mCommittedState.get())) { // The state requesting to be committed already matches the current committed state. // The state requesting to be committed already matches the current committed state. return false; return false; } } Loading Loading @@ -417,15 +430,15 @@ public final class DeviceStateManagerService extends SystemService { private void commitPendingState() { private void commitPendingState() { // Update the current state. // Update the current state. synchronized (mLock) { synchronized (mLock) { final DeviceState newState = mPendingState.get(); if (DEBUG) { if (DEBUG) { Slog.d(TAG, "Committing state: " + mPendingState); Slog.d(TAG, "Committing state: " + newState); } } mCommittedState = mPendingState.get(); if (!mRequestRecords.isEmpty()) { if (!mRequestRecords.isEmpty()) { final OverrideRequestRecord topRequest = final OverrideRequestRecord topRequest = mRequestRecords.get(mRequestRecords.size() - 1); mRequestRecords.get(mRequestRecords.size() - 1); if (topRequest.mRequestedState.getIdentifier() == mCommittedState.getIdentifier()) { if (topRequest.mRequestedState.getIdentifier() == newState.getIdentifier()) { // The top request could have come in while the service was awaiting callback // The top request could have come in while the service was awaiting callback // from the policy. In that case we only set it to active if it matches the // from the policy. In that case we only set it to active if it matches the // current committed state, otherwise it will be set to active when its // current committed state, otherwise it will be set to active when its Loading @@ -434,6 +447,7 @@ public final class DeviceStateManagerService extends SystemService { } } } } mCommittedState = Optional.of(newState); mPendingState = Optional.empty(); mPendingState = Optional.empty(); updatePendingStateLocked(); updatePendingStateLocked(); } } Loading Loading @@ -503,19 +517,30 @@ public final class DeviceStateManagerService extends SystemService { } } private void registerProcess(int pid, IDeviceStateManagerCallback callback) { private void registerProcess(int pid, IDeviceStateManagerCallback callback) { DeviceStateInfo currentInfo; ProcessRecord record; // Grab the lock to register the callback and get the current state. synchronized (mLock) { synchronized (mLock) { if (mProcessRecords.contains(pid)) { if (mProcessRecords.contains(pid)) { throw new SecurityException("The calling process has already registered an" throw new SecurityException("The calling process has already registered an" + " IDeviceStateManagerCallback."); + " IDeviceStateManagerCallback."); } } ProcessRecord record = new ProcessRecord(callback, pid); record = new ProcessRecord(callback, pid); try { try { callback.asBinder().linkToDeath(record, 0); callback.asBinder().linkToDeath(record, 0); } catch (RemoteException ex) { } catch (RemoteException ex) { throw new RuntimeException(ex); throw new RuntimeException(ex); } } mProcessRecords.put(pid, record); mProcessRecords.put(pid, record); currentInfo = mCommittedState.isPresent() ? getDeviceStateInfoLocked() : null; } if (currentInfo != null) { // If there is not a committed state we'll wait to notify the process of the initial // value. record.notifyDeviceStateInfoAsync(currentInfo); } } } } Loading services/core/java/com/android/server/devicestate/DeviceStateManagerShellCommand.java +9 −4 Original line number Original line Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.server.devicestate; import static android.Manifest.permission.CONTROL_DEVICE_STATE; import static android.Manifest.permission.CONTROL_DEVICE_STATE; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.Nullable; import android.content.Context; import android.content.Context; import android.hardware.devicestate.DeviceStateManager; import android.hardware.devicestate.DeviceStateManager; Loading Loading @@ -63,14 +64,14 @@ public class DeviceStateManagerShellCommand extends ShellCommand { } } private void printState(PrintWriter pw) { private void printState(PrintWriter pw) { DeviceState committedState = mService.getCommittedState(); Optional<DeviceState> committedState = mService.getCommittedState(); DeviceState baseState = mService.getBaseState(); Optional<DeviceState> baseState = mService.getBaseState(); Optional<DeviceState> overrideState = mService.getOverrideState(); Optional<DeviceState> overrideState = mService.getOverrideState(); pw.println("Committed state: " + committedState); pw.println("Committed state: " + toString(committedState)); if (overrideState.isPresent()) { if (overrideState.isPresent()) { pw.println("----------------------"); pw.println("----------------------"); pw.println("Base state: " + baseState); pw.println("Base state: " + toString(baseState)); pw.println("Override state: " + overrideState.get()); pw.println("Override state: " + overrideState.get()); } } } } Loading Loading @@ -143,4 +144,8 @@ public class DeviceStateManagerShellCommand extends ShellCommand { pw.println(" print-states"); pw.println(" print-states"); pw.println(" Return list of currently supported device states."); pw.println(" Return list of currently supported device states."); } } private static String toString(@NonNull Optional<DeviceState> state) { return state.isPresent() ? state.get().toString() : "(none)"; } } } Loading
core/java/android/hardware/devicestate/DeviceStateManagerGlobal.java +14 −19 Original line number Original line Diff line number Diff line Loading @@ -179,8 +179,6 @@ public final class DeviceStateManagerGlobal { @VisibleForTesting(visibility = Visibility.PACKAGE) @VisibleForTesting(visibility = Visibility.PACKAGE) public void registerDeviceStateCallback(@NonNull DeviceStateCallback callback, public void registerDeviceStateCallback(@NonNull DeviceStateCallback callback, @NonNull Executor executor) { @NonNull Executor executor) { DeviceStateCallbackWrapper wrapper; DeviceStateInfo currentInfo; synchronized (mLock) { synchronized (mLock) { int index = findCallbackLocked(callback); int index = findCallbackLocked(callback); if (index != -1) { if (index != -1) { Loading @@ -189,25 +187,22 @@ public final class DeviceStateManagerGlobal { } } registerCallbackIfNeededLocked(); registerCallbackIfNeededLocked(); if (mLastReceivedInfo == null) { // Initialize the last received info with the current info if this is the first // callback being registered. try { mLastReceivedInfo = mDeviceStateManager.getDeviceStateInfo(); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } } currentInfo = new DeviceStateInfo(mLastReceivedInfo); // Add the callback wrapper to the mCallbacks array after registering the callback as // the callback could be triggered immediately if the mDeviceStateManager IBinder is in wrapper = new DeviceStateCallbackWrapper(callback, executor); // the same process as this instance. DeviceStateCallbackWrapper wrapper = new DeviceStateCallbackWrapper(callback, executor); mCallbacks.add(wrapper); mCallbacks.add(wrapper); } wrapper.notifySupportedStatesChanged(currentInfo.supportedStates); if (mLastReceivedInfo != null) { wrapper.notifyBaseStateChanged(currentInfo.baseState); // Copy the array to prevent the callback from modifying the internal state. wrapper.notifyStateChanged(currentInfo.currentState); final int[] supportedStates = Arrays.copyOf(mLastReceivedInfo.supportedStates, mLastReceivedInfo.supportedStates.length); wrapper.notifySupportedStatesChanged(supportedStates); wrapper.notifyBaseStateChanged(mLastReceivedInfo.baseState); wrapper.notifyStateChanged(mLastReceivedInfo.currentState); } } } } /** /** Loading Loading @@ -267,7 +262,7 @@ public final class DeviceStateManagerGlobal { callbacks = new ArrayList<>(mCallbacks); callbacks = new ArrayList<>(mCallbacks); } } final int diff = oldInfo == null ? 1 : info.diff(oldInfo); final int diff = oldInfo == null ? ~0 : info.diff(oldInfo); if ((diff & DeviceStateInfo.CHANGED_SUPPORTED_STATES) > 0) { if ((diff & DeviceStateInfo.CHANGED_SUPPORTED_STATES) > 0) { for (int i = 0; i < callbacks.size(); i++) { for (int i = 0; i < callbacks.size(); i++) { // Copy the array to prevent callbacks from modifying the internal state. // Copy the array to prevent callbacks from modifying the internal state. Loading
core/java/android/hardware/devicestate/IDeviceStateManagerCallback.aidl +2 −1 Original line number Original line Diff line number Diff line Loading @@ -21,7 +21,8 @@ import android.hardware.devicestate.DeviceStateInfo; /** @hide */ /** @hide */ interface IDeviceStateManagerCallback { interface IDeviceStateManagerCallback { /** /** * Called in response to a change in {@link DeviceStateInfo}. * Called in response to a change in {@link DeviceStateInfo}. Guaranteed to be called once * after successful registration of the callback with the initial value. * * * @param info the new device state info. * @param info the new device state info. * * Loading
core/tests/devicestatetests/src/android/hardware/devicestate/DeviceStateManagerGlobalTest.java +5 −0 Original line number Original line Diff line number Diff line Loading @@ -208,6 +208,11 @@ public final class DeviceStateManagerGlobalTest { } } mCallbacks.add(callback); mCallbacks.add(callback); try { callback.onDeviceStateInfoChanged(getInfo()); } catch (RemoteException e) { // Do nothing. Should never happen. } } } @Override @Override Loading
services/core/java/com/android/server/devicestate/DeviceStateManagerService.java +47 −22 Original line number Original line Diff line number Diff line Loading @@ -78,9 +78,6 @@ import java.util.Optional; public final class DeviceStateManagerService extends SystemService { public final class DeviceStateManagerService extends SystemService { private static final String TAG = "DeviceStateManagerService"; private static final String TAG = "DeviceStateManagerService"; private static final boolean DEBUG = false; private static final boolean DEBUG = false; // The device state to use as a placeholder before callback from the DeviceStateProvider occurs. private static final DeviceState UNSPECIFIED_DEVICE_STATE = new DeviceState(MINIMUM_DEVICE_STATE, "UNSPECIFIED"); private final Object mLock = new Object(); private final Object mLock = new Object(); @NonNull @NonNull Loading @@ -92,11 +89,11 @@ public final class DeviceStateManagerService extends SystemService { @GuardedBy("mLock") @GuardedBy("mLock") private SparseArray<DeviceState> mDeviceStates = new SparseArray<>(); private SparseArray<DeviceState> mDeviceStates = new SparseArray<>(); // The current committed device state. The default of UNSPECIFIED_DEVICE_STATE will be replaced // The current committed device state. Will be empty until the first device state provided by // by the current state after the initial callback from the DeviceStateProvider. // the DeviceStateProvider is committed. @GuardedBy("mLock") @GuardedBy("mLock") @NonNull @NonNull private DeviceState mCommittedState = UNSPECIFIED_DEVICE_STATE; private Optional<DeviceState> mCommittedState = Optional.empty(); // The device state that is currently awaiting callback from the policy to be committed. // The device state that is currently awaiting callback from the policy to be committed. @GuardedBy("mLock") @GuardedBy("mLock") @NonNull @NonNull Loading @@ -105,10 +102,11 @@ public final class DeviceStateManagerService extends SystemService { @GuardedBy("mLock") @GuardedBy("mLock") private boolean mIsPolicyWaitingForState = false; private boolean mIsPolicyWaitingForState = false; // The device state that is set by the device state provider. // The device state that is set by the DeviceStateProvider. Will be empty until the first // callback from the provider and then will always contain the most recent value. @GuardedBy("mLock") @GuardedBy("mLock") @NonNull @NonNull private DeviceState mBaseState = UNSPECIFIED_DEVICE_STATE; private Optional<DeviceState> mBaseState = Optional.empty(); // List of processes registered to receive notifications about changes to device state and // List of processes registered to receive notifications about changes to device state and // request status indexed by process id. // request status indexed by process id. Loading Loading @@ -142,11 +140,14 @@ public final class DeviceStateManagerService extends SystemService { /** /** * Returns the current state the system is in. Note that the system may be in the process of * Returns the current state the system is in. Note that the system may be in the process of * configuring a different state. * configuring a different state. * <p> * Note: This method will return {@link Optional#empty()} if called before the first state has * been committed, otherwise it will return the last committed state. * * * @see #getPendingState() * @see #getPendingState() */ */ @NonNull @NonNull DeviceState getCommittedState() { Optional<DeviceState> getCommittedState() { synchronized (mLock) { synchronized (mLock) { return mCommittedState; return mCommittedState; } } Loading @@ -167,11 +168,15 @@ public final class DeviceStateManagerService extends SystemService { /** /** * Returns the base state. The service will configure the device to match the base state when * Returns the base state. The service will configure the device to match the base state when * there is no active request to override the base state. * there is no active request to override the base state. * <p> * Note: This method will return {@link Optional#empty()} if called before a base state is * provided to the service by the {@link DeviceStateProvider}, otherwise it will return the * most recent provided value. * * * @see #getOverrideState() * @see #getOverrideState() */ */ @NonNull @NonNull DeviceState getBaseState() { Optional<DeviceState> getBaseState() { synchronized (mLock) { synchronized (mLock) { return mBaseState; return mBaseState; } } Loading Loading @@ -223,9 +228,14 @@ public final class DeviceStateManagerService extends SystemService { @NonNull @NonNull private DeviceStateInfo getDeviceStateInfoLocked() { private DeviceStateInfo getDeviceStateInfoLocked() { if (!mBaseState.isPresent() || !mCommittedState.isPresent()) { throw new IllegalStateException("Trying to get the current DeviceStateInfo before the" + " initial state has been committed."); } final int[] supportedStates = getSupportedStateIdentifiersLocked(); final int[] supportedStates = getSupportedStateIdentifiersLocked(); final int baseState = mBaseState.getIdentifier(); final int baseState = mBaseState.get().getIdentifier(); final int currentState = mCommittedState.getIdentifier(); final int currentState = mCommittedState.get().getIdentifier(); return new DeviceStateInfo(supportedStates, baseState, currentState); return new DeviceStateInfo(supportedStates, baseState, currentState); } } Loading @@ -237,6 +247,7 @@ public final class DeviceStateManagerService extends SystemService { private void updateSupportedStates(DeviceState[] supportedDeviceStates) { private void updateSupportedStates(DeviceState[] supportedDeviceStates) { boolean updatedPendingState; boolean updatedPendingState; boolean hasBaseState; synchronized (mLock) { synchronized (mLock) { final int[] oldStateIdentifiers = getSupportedStateIdentifiersLocked(); final int[] oldStateIdentifiers = getSupportedStateIdentifiersLocked(); Loading @@ -260,9 +271,10 @@ public final class DeviceStateManagerService extends SystemService { } } updatedPendingState = updatePendingStateLocked(); updatedPendingState = updatePendingStateLocked(); hasBaseState = mBaseState.isPresent(); } } if (!updatedPendingState) { if (hasBaseState && !updatedPendingState) { // If the change in the supported states didn't result in a change of the pending state // If the change in the supported states didn't result in a change of the pending state // commitPendingState() will never be called and the callbacks will never be notified // commitPendingState() will never be called and the callbacks will never be notified // of the change. // of the change. Loading Loading @@ -306,11 +318,11 @@ public final class DeviceStateManagerService extends SystemService { } } final DeviceState baseState = baseStateOptional.get(); final DeviceState baseState = baseStateOptional.get(); if (mBaseState.equals(baseState)) { if (mBaseState.isPresent() && mBaseState.get().equals(baseState)) { // Base state hasn't changed. Nothing to do. // Base state hasn't changed. Nothing to do. return; return; } } mBaseState = baseState; mBaseState = Optional.of(baseState); final int requestSize = mRequestRecords.size(); final int requestSize = mRequestRecords.size(); for (int i = 0; i < requestSize; i++) { for (int i = 0; i < requestSize; i++) { Loading Loading @@ -351,9 +363,10 @@ public final class DeviceStateManagerService extends SystemService { final DeviceState stateToConfigure; final DeviceState stateToConfigure; if (!mRequestRecords.isEmpty()) { if (!mRequestRecords.isEmpty()) { stateToConfigure = mRequestRecords.get(mRequestRecords.size() - 1).mRequestedState; stateToConfigure = mRequestRecords.get(mRequestRecords.size() - 1).mRequestedState; } else if (isSupportedStateLocked(mBaseState.getIdentifier())) { } else if (mBaseState.isPresent() && isSupportedStateLocked(mBaseState.get().getIdentifier())) { // Base state could have recently become unsupported after a change in supported states. // Base state could have recently become unsupported after a change in supported states. stateToConfigure = mBaseState; stateToConfigure = mBaseState.get(); } else { } else { stateToConfigure = null; stateToConfigure = null; } } Loading @@ -363,7 +376,7 @@ public final class DeviceStateManagerService extends SystemService { return false; return false; } } if (stateToConfigure.equals(mCommittedState)) { if (mCommittedState.isPresent() && stateToConfigure.equals(mCommittedState.get())) { // The state requesting to be committed already matches the current committed state. // The state requesting to be committed already matches the current committed state. return false; return false; } } Loading Loading @@ -417,15 +430,15 @@ public final class DeviceStateManagerService extends SystemService { private void commitPendingState() { private void commitPendingState() { // Update the current state. // Update the current state. synchronized (mLock) { synchronized (mLock) { final DeviceState newState = mPendingState.get(); if (DEBUG) { if (DEBUG) { Slog.d(TAG, "Committing state: " + mPendingState); Slog.d(TAG, "Committing state: " + newState); } } mCommittedState = mPendingState.get(); if (!mRequestRecords.isEmpty()) { if (!mRequestRecords.isEmpty()) { final OverrideRequestRecord topRequest = final OverrideRequestRecord topRequest = mRequestRecords.get(mRequestRecords.size() - 1); mRequestRecords.get(mRequestRecords.size() - 1); if (topRequest.mRequestedState.getIdentifier() == mCommittedState.getIdentifier()) { if (topRequest.mRequestedState.getIdentifier() == newState.getIdentifier()) { // The top request could have come in while the service was awaiting callback // The top request could have come in while the service was awaiting callback // from the policy. In that case we only set it to active if it matches the // from the policy. In that case we only set it to active if it matches the // current committed state, otherwise it will be set to active when its // current committed state, otherwise it will be set to active when its Loading @@ -434,6 +447,7 @@ public final class DeviceStateManagerService extends SystemService { } } } } mCommittedState = Optional.of(newState); mPendingState = Optional.empty(); mPendingState = Optional.empty(); updatePendingStateLocked(); updatePendingStateLocked(); } } Loading Loading @@ -503,19 +517,30 @@ public final class DeviceStateManagerService extends SystemService { } } private void registerProcess(int pid, IDeviceStateManagerCallback callback) { private void registerProcess(int pid, IDeviceStateManagerCallback callback) { DeviceStateInfo currentInfo; ProcessRecord record; // Grab the lock to register the callback and get the current state. synchronized (mLock) { synchronized (mLock) { if (mProcessRecords.contains(pid)) { if (mProcessRecords.contains(pid)) { throw new SecurityException("The calling process has already registered an" throw new SecurityException("The calling process has already registered an" + " IDeviceStateManagerCallback."); + " IDeviceStateManagerCallback."); } } ProcessRecord record = new ProcessRecord(callback, pid); record = new ProcessRecord(callback, pid); try { try { callback.asBinder().linkToDeath(record, 0); callback.asBinder().linkToDeath(record, 0); } catch (RemoteException ex) { } catch (RemoteException ex) { throw new RuntimeException(ex); throw new RuntimeException(ex); } } mProcessRecords.put(pid, record); mProcessRecords.put(pid, record); currentInfo = mCommittedState.isPresent() ? getDeviceStateInfoLocked() : null; } if (currentInfo != null) { // If there is not a committed state we'll wait to notify the process of the initial // value. record.notifyDeviceStateInfoAsync(currentInfo); } } } } Loading
services/core/java/com/android/server/devicestate/DeviceStateManagerShellCommand.java +9 −4 Original line number Original line Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.server.devicestate; import static android.Manifest.permission.CONTROL_DEVICE_STATE; import static android.Manifest.permission.CONTROL_DEVICE_STATE; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.Nullable; import android.content.Context; import android.content.Context; import android.hardware.devicestate.DeviceStateManager; import android.hardware.devicestate.DeviceStateManager; Loading Loading @@ -63,14 +64,14 @@ public class DeviceStateManagerShellCommand extends ShellCommand { } } private void printState(PrintWriter pw) { private void printState(PrintWriter pw) { DeviceState committedState = mService.getCommittedState(); Optional<DeviceState> committedState = mService.getCommittedState(); DeviceState baseState = mService.getBaseState(); Optional<DeviceState> baseState = mService.getBaseState(); Optional<DeviceState> overrideState = mService.getOverrideState(); Optional<DeviceState> overrideState = mService.getOverrideState(); pw.println("Committed state: " + committedState); pw.println("Committed state: " + toString(committedState)); if (overrideState.isPresent()) { if (overrideState.isPresent()) { pw.println("----------------------"); pw.println("----------------------"); pw.println("Base state: " + baseState); pw.println("Base state: " + toString(baseState)); pw.println("Override state: " + overrideState.get()); pw.println("Override state: " + overrideState.get()); } } } } Loading Loading @@ -143,4 +144,8 @@ public class DeviceStateManagerShellCommand extends ShellCommand { pw.println(" print-states"); pw.println(" print-states"); pw.println(" Return list of currently supported device states."); pw.println(" Return list of currently supported device states."); } } private static String toString(@NonNull Optional<DeviceState> state) { return state.isPresent() ? state.get().toString() : "(none)"; } } }