diff options
24 files changed, 408 insertions, 198 deletions
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java index d2e4a614202f..b43a900bec80 100644 --- a/core/java/android/hardware/camera2/CameraManager.java +++ b/core/java/android/hardware/camera2/CameraManager.java @@ -47,6 +47,7 @@ import android.hardware.camera2.params.StreamConfiguration; import android.hardware.camera2.utils.CameraIdAndSessionConfiguration; import android.hardware.camera2.utils.ConcurrentCameraIdCombination; import android.hardware.camera2.utils.ExceptionUtils; +import android.hardware.devicestate.DeviceState; import android.hardware.devicestate.DeviceStateManager; import android.hardware.display.DisplayManager; import android.os.Binder; @@ -204,14 +205,12 @@ public final class CameraManager { mDeviceStateListeners.add(new WeakReference<>(listener)); } + @SuppressWarnings("FlaggedApi") @Override - public final void onBaseStateChanged(int state) { - handleStateChange(state); - } - - @Override - public final void onStateChanged(int state) { - handleStateChange(state); + public void onDeviceStateChanged(DeviceState state) { + // Suppressing the FlaggedAPI warning as this specific API isn't new, just moved to + // system API which requires it to be flagged. + handleStateChange(state.getIdentifier()); } } diff --git a/core/java/android/hardware/devicestate/DeviceStateRequest.java b/core/java/android/hardware/devicestate/DeviceStateRequest.java index 893d765e48da..7665e2f173b9 100644 --- a/core/java/android/hardware/devicestate/DeviceStateRequest.java +++ b/core/java/android/hardware/devicestate/DeviceStateRequest.java @@ -115,8 +115,8 @@ public final class DeviceStateRequest { * requested state. * <p> * Guaranteed to be called after a call to - * {@link DeviceStateManager.DeviceStateCallback#onStateChanged(int)} with a state - * matching the requested state. + * {@link DeviceStateManager.DeviceStateCallback#onDeviceStateChanged(DeviceState)} with a + * state matching the requested state. */ default void onRequestActivated(@NonNull DeviceStateRequest request) {} @@ -124,7 +124,7 @@ public final class DeviceStateRequest { * Called to indicate the request has been temporarily suspended. * <p> * Guaranteed to be called before a call to - * {@link DeviceStateManager.DeviceStateCallback#onStateChanged(int)}. + * {@link DeviceStateManager.DeviceStateCallback#onDeviceStateChanged(DeviceState)}. */ default void onRequestSuspended(@NonNull DeviceStateRequest request) {} @@ -134,7 +134,7 @@ public final class DeviceStateRequest { * DeviceStateRequest.Callback)}. * <p> * Guaranteed to be called before a call to - * {@link DeviceStateManager.DeviceStateCallback#onStateChanged(int)}. + * {@link DeviceStateManager.DeviceStateCallback#onDeviceStateChanged(DeviceState)}. * <p> * Note: A call to {@link #onRequestSuspended(DeviceStateRequest)} is not guaranteed to * occur before this method. diff --git a/core/java/android/hardware/devicestate/DeviceStateUtil.java b/core/java/android/hardware/devicestate/DeviceStateUtil.java new file mode 100644 index 000000000000..627e740f4a5c --- /dev/null +++ b/core/java/android/hardware/devicestate/DeviceStateUtil.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2024 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 android.hardware.devicestate; + +import static android.hardware.devicestate.DeviceStateManager.INVALID_DEVICE_STATE_IDENTIFIER; + +import android.annotation.NonNull; + +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +/** + * Utilities for {@link DeviceStateManager}. + * @hide + */ +public class DeviceStateUtil { + private DeviceStateUtil() { } + + /** + * Returns the state identifier of the {@link DeviceState} that matches the + * {@code currentState}s physical properties. This will return the identifier of the + * {@link DeviceState} that matches the devices physical configuration. + * + * Returns {@link INVALID_DEVICE_STATE_IDENTIFIER} if there is no {@link DeviceState} in the + * provided list of {@code supportedStates} that matches. + * @hide + */ + public static int calculateBaseStateIdentifier(@NonNull DeviceState currentState, + @NonNull List<DeviceState> supportedStates) { + DeviceState.Configuration stateConfiguration = currentState.getConfiguration(); + for (int i = 0; i < supportedStates.size(); i++) { + DeviceState stateToCompare = supportedStates.get(i); + if (stateToCompare.getConfiguration().getPhysicalProperties().isEmpty()) { + continue; + } + if (isDeviceStateMatchingPhysicalProperties(stateConfiguration.getPhysicalProperties(), + supportedStates.get(i))) { + return supportedStates.get(i).getIdentifier(); + } + } + return INVALID_DEVICE_STATE_IDENTIFIER; + } + + /** + * Returns if the physical properties provided, matches the same physical properties on the + * provided {@link DeviceState}. + */ + private static boolean isDeviceStateMatchingPhysicalProperties( + Set<@DeviceState.PhysicalDeviceStateProperties Integer> physicalProperties, + DeviceState state) { + Iterator<@DeviceState.PhysicalDeviceStateProperties Integer> iterator = + physicalProperties.iterator(); + while (iterator.hasNext()) { + if (!state.hasProperty(iterator.next())) { + return false; + } + } + return true; + } + +} diff --git a/libs/WindowManager/Jetpack/src/androidx/window/common/DeviceStateManagerFoldingFeatureProducer.java b/libs/WindowManager/Jetpack/src/androidx/window/common/DeviceStateManagerFoldingFeatureProducer.java index fa35b632a6b3..98935e95deaf 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/common/DeviceStateManagerFoldingFeatureProducer.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/common/DeviceStateManagerFoldingFeatureProducer.java @@ -19,13 +19,14 @@ package androidx.window.common; import static android.hardware.devicestate.DeviceStateManager.INVALID_DEVICE_STATE_IDENTIFIER; import static androidx.window.common.CommonFoldingFeature.COMMON_STATE_UNKNOWN; -import static androidx.window.common.CommonFoldingFeature.COMMON_STATE_USE_BASE_STATE; import static androidx.window.common.CommonFoldingFeature.parseListFromString; import android.annotation.NonNull; import android.content.Context; +import android.hardware.devicestate.DeviceState; import android.hardware.devicestate.DeviceStateManager; import android.hardware.devicestate.DeviceStateManager.DeviceStateCallback; +import android.hardware.devicestate.DeviceStateUtil; import android.text.TextUtils; import android.util.Log; import android.util.SparseIntArray; @@ -54,29 +55,27 @@ public final class DeviceStateManagerFoldingFeatureProducer private static final boolean DEBUG = false; /** - * Emulated device state {@link DeviceStateManager.DeviceStateCallback#onStateChanged(int)} to + * Emulated device state + * {@link DeviceStateManager.DeviceStateCallback#onDeviceStateChanged(DeviceState)} to * {@link CommonFoldingFeature.State} map. */ private final SparseIntArray mDeviceStateToPostureMap = new SparseIntArray(); /** - * Emulated device state received via - * {@link DeviceStateManager.DeviceStateCallback#onStateChanged(int)}. - * "Emulated" states differ from "base" state in the sense that they may not correspond 1:1 with - * physical device states. They represent the state of the device when various software - * features and APIs are applied. The emulated states generally consist of all "base" states, - * but may have additional states such as "concurrent" or "rear display". Concurrent mode for - * example is activated via public API and can be active in both the "open" and "half folded" - * device states. + * Device state received via + * {@link DeviceStateManager.DeviceStateCallback#onDeviceStateChanged(DeviceState)}. + * The identifier returned through {@link DeviceState#getIdentifier()} may not correspond 1:1 + * with the physical state of the device. This could correspond to the system state of the + * device when various software features or overrides are applied. The emulated states generally + * consist of all "base" states, but may have additional states such as "concurrent" or + * "rear display". Concurrent mode for example is activated via public API and can be active in + * both the "open" and "half folded" device states. */ - private int mCurrentDeviceState = INVALID_DEVICE_STATE_IDENTIFIER; + private DeviceState mCurrentDeviceState = new DeviceState( + new DeviceState.Configuration.Builder(INVALID_DEVICE_STATE_IDENTIFIER, + "INVALID").build()); - /** - * Base device state received via - * {@link DeviceStateManager.DeviceStateCallback#onBaseStateChanged(int)}. - * "Base" in this context means the "physical" state of the device. - */ - private int mCurrentBaseDeviceState = INVALID_DEVICE_STATE_IDENTIFIER; + private List<DeviceState> mSupportedStates; @NonNull private final RawFoldingFeatureProducer mRawFoldSupplier; @@ -85,22 +84,11 @@ public final class DeviceStateManagerFoldingFeatureProducer private final DeviceStateCallback mDeviceStateCallback = new DeviceStateCallback() { @Override - public void onStateChanged(int state) { + public void onDeviceStateChanged(@NonNull DeviceState state) { mCurrentDeviceState = state; mRawFoldSupplier.getData(DeviceStateManagerFoldingFeatureProducer .this::notifyFoldingFeatureChange); } - - @Override - public void onBaseStateChanged(int state) { - mCurrentBaseDeviceState = state; - - if (mDeviceStateToPostureMap.get(mCurrentDeviceState) - == COMMON_STATE_USE_BASE_STATE) { - mRawFoldSupplier.getData(DeviceStateManagerFoldingFeatureProducer - .this::notifyFoldingFeatureChange); - } - } }; public DeviceStateManagerFoldingFeatureProducer(@NonNull Context context, @@ -109,6 +97,7 @@ public final class DeviceStateManagerFoldingFeatureProducer mRawFoldSupplier = rawFoldSupplier; String[] deviceStatePosturePairs = context.getResources() .getStringArray(R.array.config_device_state_postures); + mSupportedStates = deviceStateManager.getSupportedDeviceStates(); boolean isHalfOpenedSupported = false; for (String deviceStatePosturePair : deviceStatePosturePairs) { String[] deviceStatePostureMapping = deviceStatePosturePair.split(":"); @@ -168,7 +157,7 @@ public final class DeviceStateManagerFoldingFeatureProducer */ private boolean isCurrentStateValid() { // If the device state is not found in the map, indexOfKey returns a negative number. - return mDeviceStateToPostureMap.indexOfKey(mCurrentDeviceState) >= 0; + return mDeviceStateToPostureMap.indexOfKey(mCurrentDeviceState.getIdentifier()) >= 0; } @Override @@ -177,7 +166,9 @@ public final class DeviceStateManagerFoldingFeatureProducer if (hasListeners()) { mRawFoldSupplier.addDataChangedCallback(this::notifyFoldingFeatureChange); } else { - mCurrentDeviceState = INVALID_DEVICE_STATE_IDENTIFIER; + mCurrentDeviceState = new DeviceState( + new DeviceState.Configuration.Builder(INVALID_DEVICE_STATE_IDENTIFIER, + "INVALID").build()); mRawFoldSupplier.removeDataChangedCallback(this::notifyFoldingFeatureChange); } } @@ -251,10 +242,13 @@ public final class DeviceStateManagerFoldingFeatureProducer @CommonFoldingFeature.State private int currentHingeState() { @CommonFoldingFeature.State - int posture = mDeviceStateToPostureMap.get(mCurrentDeviceState, COMMON_STATE_UNKNOWN); + int posture = mDeviceStateToPostureMap.get(mCurrentDeviceState.getIdentifier(), + COMMON_STATE_UNKNOWN); if (posture == CommonFoldingFeature.COMMON_STATE_USE_BASE_STATE) { - posture = mDeviceStateToPostureMap.get(mCurrentBaseDeviceState, COMMON_STATE_UNKNOWN); + posture = mDeviceStateToPostureMap.get( + DeviceStateUtil.calculateBaseStateIdentifier(mCurrentDeviceState, + mSupportedStates), COMMON_STATE_UNKNOWN); } return posture; diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java index d31bf2a662a3..a3d2d7f4dcdf 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java @@ -20,6 +20,7 @@ import static android.hardware.devicestate.DeviceStateManager.INVALID_DEVICE_STA import android.app.Activity; import android.content.Context; +import android.hardware.devicestate.DeviceState; import android.hardware.devicestate.DeviceStateManager; import android.hardware.devicestate.DeviceStateRequest; import android.hardware.display.DisplayManager; @@ -40,6 +41,7 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; +import java.util.List; import java.util.Objects; import java.util.concurrent.Executor; @@ -101,7 +103,9 @@ public class WindowAreaComponentImpl implements WindowAreaComponent, mDisplayManager = context.getSystemService(DisplayManager.class); mExecutor = context.getMainExecutor(); - mCurrentSupportedDeviceStates = mDeviceStateManager.getSupportedStates(); + // TODO(b/329436166): Update the usage of device state manager API's + mCurrentSupportedDeviceStates = getSupportedStateIdentifiers( + mDeviceStateManager.getSupportedDeviceStates()); mFoldedDeviceStates = context.getResources().getIntArray( R.array.config_foldedDeviceStates); @@ -446,9 +450,10 @@ public class WindowAreaComponentImpl implements WindowAreaComponent, } @Override - public void onSupportedStatesChanged(int[] supportedStates) { + public void onSupportedStatesChanged(@NonNull List<DeviceState> supportedStates) { synchronized (mLock) { - mCurrentSupportedDeviceStates = supportedStates; + // TODO(b/329436166): Update the usage of device state manager API's + mCurrentSupportedDeviceStates = getSupportedStateIdentifiers(supportedStates); updateRearDisplayStatusListeners(getCurrentRearDisplayModeStatus()); updateRearDisplayPresentationStatusListeners( getCurrentRearDisplayPresentationModeStatus()); @@ -456,9 +461,10 @@ public class WindowAreaComponentImpl implements WindowAreaComponent, } @Override - public void onStateChanged(int state) { + public void onDeviceStateChanged(@NonNull DeviceState state) { synchronized (mLock) { - mCurrentDeviceState = state; + // TODO(b/329436166): Update the usage of device state manager API's + mCurrentDeviceState = state.getIdentifier(); updateRearDisplayStatusListeners(getCurrentRearDisplayModeStatus()); updateRearDisplayPresentationStatusListeners( getCurrentRearDisplayPresentationModeStatus()); @@ -482,6 +488,15 @@ public class WindowAreaComponentImpl implements WindowAreaComponent, return WindowAreaComponent.STATUS_AVAILABLE; } + // TODO(b/329436166): Remove and update the usage of device state manager API's + private int[] getSupportedStateIdentifiers(@NonNull List<DeviceState> states) { + int[] identifiers = new int[states.size()]; + for (int i = 0; i < states.size(); i++) { + identifiers[i] = states.get(i).getIdentifier(); + } + return identifiers; + } + /** * Helper method to determine if a rear display session is currently active by checking * if the current device state is that which corresponds to {@code mRearDisplayState}. diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DevicePostureController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DevicePostureController.java index 8b4ac1a8dc79..d17e8620ff12 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DevicePostureController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DevicePostureController.java @@ -107,7 +107,7 @@ public class DevicePostureController { DeviceStateManager.class); if (deviceStateManager != null) { deviceStateManager.registerCallback(mMainExecutor, state -> onDevicePostureChanged( - mDeviceStateToPostureMap.get(state, DEVICE_POSTURE_UNKNOWN))); + mDeviceStateToPostureMap.get(state.getIdentifier(), DEVICE_POSTURE_UNKNOWN))); } } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java b/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java index 0bb5c174444f..fb331b62369e 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java @@ -15,8 +15,10 @@ */ package com.android.keyguard; +import android.annotation.NonNull; import android.app.Presentation; import android.content.Context; +import android.hardware.devicestate.DeviceState; import android.hardware.devicestate.DeviceStateManager; import android.hardware.display.DisplayManager; import android.media.MediaRouter; @@ -315,11 +317,11 @@ public class KeyguardDisplayManager { } @Override - public void onStateChanged(int state) { + public void onDeviceStateChanged(@NonNull DeviceState state) { // When concurrent state ends, the display also turns off. This is enforced in various // ExtensionRearDisplayPresentationTest CTS tests. So, we don't need to invoke // hide() since that will happen through the onDisplayRemoved callback. - mIsInConcurrentDisplayState = state == mConcurrentState; + mIsInConcurrentDisplayState = state.getIdentifier() == mConcurrentState; } boolean isConcurrentDisplayActive(Display display) { diff --git a/packages/SystemUI/src/com/android/systemui/display/data/repository/DeviceStateRepository.kt b/packages/SystemUI/src/com/android/systemui/display/data/repository/DeviceStateRepository.kt index 83337f760c33..fa7603ff777c 100644 --- a/packages/SystemUI/src/com/android/systemui/display/data/repository/DeviceStateRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/display/data/repository/DeviceStateRepository.kt @@ -62,7 +62,7 @@ constructor( conflatedCallbackFlow { val callback = DeviceStateManager.DeviceStateCallback { state -> - trySend(deviceStateToPosture(state)) + trySend(deviceStateToPosture(state.identifier)) } deviceStateManager.registerCallback(executor, callback) awaitClose { deviceStateManager.unregisterCallback(callback) } diff --git a/packages/SystemUI/src/com/android/systemui/reardisplay/RearDisplayDialogController.java b/packages/SystemUI/src/com/android/systemui/reardisplay/RearDisplayDialogController.java index 9076182def70..f02b871b196d 100644 --- a/packages/SystemUI/src/com/android/systemui/reardisplay/RearDisplayDialogController.java +++ b/packages/SystemUI/src/com/android/systemui/reardisplay/RearDisplayDialogController.java @@ -16,12 +16,14 @@ package com.android.systemui.reardisplay; +import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SuppressLint; import android.annotation.TestApi; import android.content.Context; import android.content.res.Configuration; import android.content.res.Resources; +import android.hardware.devicestate.DeviceState; import android.hardware.devicestate.DeviceStateManager; import android.hardware.devicestate.DeviceStateManagerGlobal; import android.view.LayoutInflater; @@ -29,7 +31,6 @@ import android.view.View; import android.view.ViewGroup.LayoutParams; import android.widget.LinearLayout; -import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.CoreStartable; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; @@ -179,6 +180,7 @@ public class RearDisplayDialogController implements */ private void initializeValues(int startingBaseState) { mRearDisplayEducationDialog = mSystemUIDialogFactory.create(); + // TODO(b/329170810): Refactor and remove with updated DeviceStateManager values. if (mFoldedStates == null) { mFoldedStates = mResources.getIntArray( com.android.internal.R.array.config_foldedDeviceStates); @@ -228,21 +230,19 @@ public class RearDisplayDialogController implements private class DeviceStateManagerCallback implements DeviceStateManager.DeviceStateCallback { @Override - public void onBaseStateChanged(int state) { - if (mStartedFolded && !isFoldedState(state)) { + public void onDeviceStateChanged(@NonNull DeviceState state) { + if (mStartedFolded && !state.hasProperty( + DeviceState.PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_CLOSED)) { // We've opened the device, we can close the overlay mRearDisplayEducationDialog.dismiss(); closeOverlayAndNotifyService(false); - } else if (!mStartedFolded && isFoldedState(state)) { + } else if (!mStartedFolded && state.hasProperty( + DeviceState.PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_CLOSED)) { // We've closed the device, finish activity mRearDisplayEducationDialog.dismiss(); closeOverlayAndNotifyService(true); } } - - // We only care about physical device changes in this scenario - @Override - public void onStateChanged(int state) {} } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FoldStateListener.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FoldStateListener.kt index 56b0d598a512..db237e89a683 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FoldStateListener.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FoldStateListener.kt @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.phone import android.content.Context +import android.hardware.devicestate.DeviceState import android.hardware.devicestate.DeviceStateManager.DeviceStateCallback import com.android.internal.R @@ -45,13 +46,13 @@ internal class FoldStateListener( private var wasFolded: Boolean? = null - override fun onStateChanged(state: Int) { - val isFolded = foldedDeviceStates.contains(state) + override fun onDeviceStateChanged(state: DeviceState) { + val isFolded = foldedDeviceStates.contains(state.identifier) if (wasFolded == isFolded) { return } wasFolded = isFolded - val willGoToSleep = goToSleepDeviceStates.contains(state) + val willGoToSleep = goToSleepDeviceStates.contains(state.identifier) listener.onFoldStateChanged(isFolded, willGoToSleep) } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DevicePostureControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DevicePostureControllerImpl.java index 422aa4d4aa60..de0eb493c83d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DevicePostureControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DevicePostureControllerImpl.java @@ -16,12 +16,13 @@ package com.android.systemui.statusbar.policy; +import android.annotation.NonNull; import android.content.Context; +import android.hardware.devicestate.DeviceState; import android.hardware.devicestate.DeviceStateManager; +import android.hardware.devicestate.DeviceStateUtil; import android.util.SparseIntArray; -import androidx.annotation.NonNull; - import com.android.app.tracing.ListenersTracing; import com.android.internal.R; import com.android.systemui.dagger.SysUISingleton; @@ -42,8 +43,9 @@ public class DevicePostureControllerImpl implements DevicePostureController { /** From androidx.window.common.COMMON_STATE_USE_BASE_STATE */ private static final int COMMON_STATE_USE_BASE_STATE = 1000; private final List<Callback> mListeners = new ArrayList<>(); + private final List<DeviceState> mSupportedStates; + private DeviceState mCurrentDeviceState; private int mCurrentDevicePosture = DEVICE_POSTURE_UNKNOWN; - private int mCurrentBasePosture = DEVICE_POSTURE_UNKNOWN; private final SparseIntArray mDeviceStateToPostureMap = new SparseIntArray(); @@ -76,21 +78,17 @@ public class DevicePostureControllerImpl implements DevicePostureController { mDeviceStateToPostureMap.put(deviceState, posture); } + mSupportedStates = deviceStateManager.getSupportedDeviceStates(); deviceStateManager.registerCallback(executor, new DeviceStateManager.DeviceStateCallback() { @Override - public void onStateChanged(int state) { - Assert.isMainThread(); - mCurrentDevicePosture = - mDeviceStateToPostureMap.get(state, DEVICE_POSTURE_UNKNOWN); - sendUpdatePosture(); - } - - @Override - public void onBaseStateChanged(int state) { + public void onDeviceStateChanged(@NonNull DeviceState state) { + mCurrentDeviceState = state; Assert.isMainThread(); - mCurrentBasePosture = mDeviceStateToPostureMap.get(state, DEVICE_POSTURE_UNKNOWN); - - if (useBaseState()) { + int newDevicePosture = + mDeviceStateToPostureMap.get(state.getIdentifier(), DEVICE_POSTURE_UNKNOWN); + if (newDevicePosture != mCurrentDevicePosture + || newDevicePosture == COMMON_STATE_USE_BASE_STATE) { + mCurrentDevicePosture = newDevicePosture; sendUpdatePosture(); } } @@ -120,7 +118,8 @@ public class DevicePostureControllerImpl implements DevicePostureController { @Override public int getDevicePosture() { if (useBaseState()) { - return mCurrentBasePosture; + return DeviceStateUtil.calculateBaseStateIdentifier(mCurrentDeviceState, + mSupportedStates); } else { return mCurrentDevicePosture; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingController.java index 3008c866d207..88cf46a0ca07 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingController.java @@ -20,6 +20,7 @@ import static android.provider.Settings.Secure.DEVICE_STATE_ROTATION_LOCK_IGNORE import static android.provider.Settings.Secure.DEVICE_STATE_ROTATION_LOCK_LOCKED; import android.annotation.Nullable; +import android.hardware.devicestate.DeviceState; import android.hardware.devicestate.DeviceStateManager; import android.os.Trace; import android.util.IndentingPrintWriter; @@ -120,18 +121,18 @@ public final class DeviceStateRotationLockSettingController mDeviceStateRotationLockSettingsManager.updateSetting(deviceState, isRotationLocked); } - private void updateDeviceState(int state) { - mLogger.logUpdateDeviceState(mDeviceState, state); - if (Trace.isEnabled()) { - Trace.traceBegin( - Trace.TRACE_TAG_APP, "updateDeviceState [state=" + state + "]"); - } + private void updateDeviceState(@NonNull DeviceState state) { + mLogger.logUpdateDeviceState(mDeviceState, state.getIdentifier()); try { - if (mDeviceState == state) { + if (Trace.isEnabled()) { + Trace.traceBegin(Trace.TRACE_TAG_APP, + "updateDeviceState [state=" + state.getIdentifier() + "]"); + } + if (mDeviceState == state.getIdentifier()) { return; } - readPersistedSetting("updateDeviceState", state); + readPersistedSetting("updateDeviceState", state.getIdentifier()); } finally { Trace.endSection(); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/display/data/repository/DeviceStateRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/display/data/repository/DeviceStateRepositoryTest.kt index 21b8aca363ca..c79cbab87576 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/display/data/repository/DeviceStateRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/display/data/repository/DeviceStateRepositoryTest.kt @@ -85,7 +85,9 @@ class DeviceStateRepositoryTest : SysuiTestCase() { testScope.runTest { val state = displayState() - deviceStateManagerListener.value.onStateChanged(TEST_FOLDED) + deviceStateManagerListener.value.onDeviceStateChanged( + getDeviceStateForIdentifier(TEST_FOLDED) + ) assertThat(state()).isEqualTo(DeviceState.FOLDED) } @@ -95,7 +97,9 @@ class DeviceStateRepositoryTest : SysuiTestCase() { testScope.runTest { val state = displayState() - deviceStateManagerListener.value.onStateChanged(TEST_HALF_FOLDED) + deviceStateManagerListener.value.onDeviceStateChanged( + getDeviceStateForIdentifier(TEST_HALF_FOLDED) + ) assertThat(state()).isEqualTo(DeviceState.HALF_FOLDED) } @@ -105,7 +109,9 @@ class DeviceStateRepositoryTest : SysuiTestCase() { testScope.runTest { val state = displayState() - deviceStateManagerListener.value.onStateChanged(TEST_UNFOLDED) + deviceStateManagerListener.value.onDeviceStateChanged( + getDeviceStateForIdentifier(TEST_UNFOLDED) + ) assertThat(state()).isEqualTo(DeviceState.UNFOLDED) } @@ -115,7 +121,9 @@ class DeviceStateRepositoryTest : SysuiTestCase() { testScope.runTest { val state = displayState() - deviceStateManagerListener.value.onStateChanged(TEST_REAR_DISPLAY) + deviceStateManagerListener.value.onDeviceStateChanged( + getDeviceStateForIdentifier(TEST_REAR_DISPLAY) + ) assertThat(state()).isEqualTo(DeviceState.REAR_DISPLAY) } @@ -125,7 +133,9 @@ class DeviceStateRepositoryTest : SysuiTestCase() { testScope.runTest { val state = displayState() - deviceStateManagerListener.value.onStateChanged(TEST_CONCURRENT_DISPLAY) + deviceStateManagerListener.value.onDeviceStateChanged( + getDeviceStateForIdentifier(TEST_CONCURRENT_DISPLAY) + ) assertThat(state()).isEqualTo(DeviceState.CONCURRENT_DISPLAY) } @@ -135,7 +145,9 @@ class DeviceStateRepositoryTest : SysuiTestCase() { testScope.runTest { val state = displayState() - deviceStateManagerListener.value.onStateChanged(123456) + deviceStateManagerListener.value.onDeviceStateChanged( + getDeviceStateForIdentifier(123456) + ) assertThat(state()).isEqualTo(DeviceState.UNKNOWN) } @@ -152,6 +164,13 @@ class DeviceStateRepositoryTest : SysuiTestCase() { private fun Int.toIntArray() = listOf(this).toIntArray() + private fun getDeviceStateForIdentifier(id: Int): android.hardware.devicestate.DeviceState { + return android.hardware.devicestate.DeviceState( + android.hardware.devicestate.DeviceState.Configuration.Builder(id, /* name= */ "") + .build() + ) + } + private companion object { // Used to fake the ids in the test. Note that there is no guarantees different devices will // have the same ids (that's why the ones in this test start from 41) diff --git a/packages/SystemUI/tests/src/com/android/systemui/reardisplay/RearDisplayDialogControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/reardisplay/RearDisplayDialogControllerTest.java index dc211303e52c..f88a5a0d9f41 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/reardisplay/RearDisplayDialogControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/reardisplay/RearDisplayDialogControllerTest.java @@ -19,7 +19,6 @@ package com.android.systemui.reardisplay; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertNotSame; -import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.reset; @@ -28,6 +27,7 @@ import static org.mockito.Mockito.when; import android.content.res.Configuration; import android.content.res.Resources; +import android.hardware.devicestate.DeviceState; import android.hardware.devicestate.DeviceStateManager; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; @@ -38,9 +38,7 @@ import android.widget.TextView; import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; -import com.android.systemui.res.R; import com.android.systemui.flags.FakeFeatureFlags; -import com.android.systemui.flags.Flags; import com.android.systemui.model.SysUiState; import com.android.systemui.res.R; import com.android.systemui.statusbar.CommandQueue; @@ -176,6 +174,6 @@ public class RearDisplayDialogControllerTest extends SysuiTestCase { DeviceStateManager.DeviceStateCallback { @Override - public void onStateChanged(int state) { } + public void onDeviceStateChanged(DeviceState state) { } } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java index c8c54dbd4ac2..611cf91813ab 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java @@ -49,6 +49,7 @@ import android.app.WallpaperManager; import android.app.trust.TrustManager; import android.content.BroadcastReceiver; import android.content.IntentFilter; +import android.hardware.devicestate.DeviceState; import android.hardware.devicestate.DeviceStateManager; import android.hardware.display.AmbientDisplayConfiguration; import android.hardware.fingerprint.FingerprintManager; @@ -1113,10 +1114,12 @@ public class CentralSurfacesImplTest extends SysuiTestCase { } private void setDeviceState(int state) { + DeviceState deviceState = new DeviceState( + new DeviceState.Configuration.Builder(state, "TEST").build()); ArgumentCaptor<DeviceStateManager.DeviceStateCallback> callbackCaptor = ArgumentCaptor.forClass(DeviceStateManager.DeviceStateCallback.class); verify(mDeviceStateManager).registerCallback(any(), callbackCaptor.capture()); - callbackCaptor.getValue().onStateChanged(state); + callbackCaptor.getValue().onDeviceStateChanged(deviceState); } private void setGoToSleepStates(int... states) { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/FoldStateListenerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/FoldStateListenerTest.kt index 649dc235f398..5d42d5167c27 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/FoldStateListenerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/FoldStateListenerTest.kt @@ -15,6 +15,7 @@ */ package com.android.systemui.statusbar.phone +import android.hardware.devicestate.DeviceState import android.testing.AndroidTestingRunner import androidx.test.filters.SmallTest import com.android.internal.R @@ -40,52 +41,52 @@ class FoldStateListenerTest : SysuiTestCase() { @Before fun setUp() { initMocks(this) - setFoldedStates(DEVICE_STATE_FOLDED) - setGoToSleepStates(DEVICE_STATE_FOLDED) + setFoldedStates(DEVICE_STATE_FOLDED.identifier) + setGoToSleepStates(DEVICE_STATE_FOLDED.identifier) sut = FoldStateListener(mContext, listener) } @Test fun onStateChanged_stateFolded_notifiesWithFoldedAndGoingToSleep() { - sut.onStateChanged(DEVICE_STATE_FOLDED) + sut.onDeviceStateChanged(DEVICE_STATE_FOLDED) verify(listener).onFoldStateChanged(FOLDED, WILL_GO_TO_SLEEP) } @Test fun onStateChanged_stateHalfFolded_notifiesWithNotFoldedAndNotGoingToSleep() { - sut.onStateChanged(DEVICE_STATE_HALF_FOLDED) + sut.onDeviceStateChanged(DEVICE_STATE_HALF_FOLDED) verify(listener).onFoldStateChanged(NOT_FOLDED, WILL_NOT_SLEEP) } @Test fun onStateChanged_stateUnfolded_notifiesWithNotFoldedAndNotGoingToSleep() { - sut.onStateChanged(DEVICE_STATE_UNFOLDED) + sut.onDeviceStateChanged(DEVICE_STATE_UNFOLDED) verify(listener).onFoldStateChanged(NOT_FOLDED, WILL_NOT_SLEEP) } @Test fun onStateChanged_stateUnfoldedThenHalfFolded_notifiesOnce() { - sut.onStateChanged(DEVICE_STATE_UNFOLDED) - sut.onStateChanged(DEVICE_STATE_HALF_FOLDED) + sut.onDeviceStateChanged(DEVICE_STATE_UNFOLDED) + sut.onDeviceStateChanged(DEVICE_STATE_HALF_FOLDED) verify(listener, times(1)).onFoldStateChanged(NOT_FOLDED, WILL_NOT_SLEEP) } @Test fun onStateChanged_stateHalfFoldedThenUnfolded_notifiesOnce() { - sut.onStateChanged(DEVICE_STATE_HALF_FOLDED) - sut.onStateChanged(DEVICE_STATE_UNFOLDED) + sut.onDeviceStateChanged(DEVICE_STATE_HALF_FOLDED) + sut.onDeviceStateChanged(DEVICE_STATE_UNFOLDED) verify(listener, times(1)).onFoldStateChanged(NOT_FOLDED, WILL_NOT_SLEEP) } @Test fun onStateChanged_stateHalfFoldedThenFolded_notifiesTwice() { - sut.onStateChanged(DEVICE_STATE_HALF_FOLDED) - sut.onStateChanged(DEVICE_STATE_FOLDED) + sut.onDeviceStateChanged(DEVICE_STATE_HALF_FOLDED) + sut.onDeviceStateChanged(DEVICE_STATE_FOLDED) val inOrder = Mockito.inOrder(listener) inOrder.verify(listener).onFoldStateChanged(NOT_FOLDED, WILL_NOT_SLEEP) @@ -94,8 +95,8 @@ class FoldStateListenerTest : SysuiTestCase() { @Test fun onStateChanged_stateFoldedThenHalfFolded_notifiesTwice() { - sut.onStateChanged(DEVICE_STATE_FOLDED) - sut.onStateChanged(DEVICE_STATE_HALF_FOLDED) + sut.onDeviceStateChanged(DEVICE_STATE_FOLDED) + sut.onDeviceStateChanged(DEVICE_STATE_HALF_FOLDED) val inOrder = Mockito.inOrder(listener) inOrder.verify(listener).onFoldStateChanged(FOLDED, WILL_GO_TO_SLEEP) @@ -117,9 +118,18 @@ class FoldStateListenerTest : SysuiTestCase() { } companion object { - private const val DEVICE_STATE_FOLDED = 123 - private const val DEVICE_STATE_HALF_FOLDED = 456 - private const val DEVICE_STATE_UNFOLDED = 789 + private val DEVICE_STATE_FOLDED = DeviceState( + DeviceState.Configuration.Builder(123 /* id */, "FOLDED" /* name */) + .build() + ) + private val DEVICE_STATE_HALF_FOLDED = DeviceState( + DeviceState.Configuration.Builder(456 /* id */, "HALF_FOLDED" /* name */) + .build() + ) + private val DEVICE_STATE_UNFOLDED = DeviceState( + DeviceState.Configuration.Builder(789 /* id */, "UNFOLDED" /* name */) + .build() + ) private const val FOLDED = true private const val NOT_FOLDED = false diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DevicePostureControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DevicePostureControllerImplTest.kt index ce471705ed85..c606511456fe 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DevicePostureControllerImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DevicePostureControllerImplTest.kt @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.policy +import android.hardware.devicestate.DeviceState import android.hardware.devicestate.DeviceStateManager import android.testing.AndroidTestingRunner import android.testing.TestableLooper @@ -30,6 +31,7 @@ import com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POST import com.android.systemui.statusbar.policy.DevicePostureController.SUPPORTED_POSTURES_SIZE import com.android.systemui.util.concurrency.FakeExecutor import com.android.systemui.util.mockito.eq +import com.android.systemui.util.mockito.whenever import com.android.systemui.util.time.FakeSystemClock import com.google.common.truth.Truth.assertThat import org.junit.Before @@ -72,6 +74,18 @@ class DevicePostureControllerImplTest : SysuiTestCase() { com.android.internal.R.array.config_device_state_postures, deviceStateToPostureMapping ) + whenever(deviceStateManager.supportedDeviceStates) + .thenReturn( + listOf( + DEVICE_STATE_CLOSED, + DEVICE_STATE_HALF_FOLDED, + DEVICE_STATE_OPENED, + DEVICE_STATE_FLIPPED, + DEVICE_STATE_UNKNOWN, + DEVICE_STATE_USE_BASE_STATE + ) + ) + underTest = DevicePostureControllerImpl( context, @@ -86,20 +100,20 @@ class DevicePostureControllerImplTest : SysuiTestCase() { var posture = -1 underTest.addCallback { posture = it } - deviceStateCallback.value.onStateChanged(DEVICE_POSTURE_UNKNOWN) - assertThat(posture).isEqualTo(DEVICE_POSTURE_UNKNOWN) - - deviceStateCallback.value.onStateChanged(DEVICE_POSTURE_CLOSED) + deviceStateCallback.value.onDeviceStateChanged(DEVICE_STATE_CLOSED) assertThat(posture).isEqualTo(DEVICE_POSTURE_CLOSED) - deviceStateCallback.value.onStateChanged(DEVICE_POSTURE_HALF_OPENED) + deviceStateCallback.value.onDeviceStateChanged(DEVICE_STATE_HALF_FOLDED) assertThat(posture).isEqualTo(DEVICE_POSTURE_HALF_OPENED) - deviceStateCallback.value.onStateChanged(DEVICE_POSTURE_OPENED) + deviceStateCallback.value.onDeviceStateChanged(DEVICE_STATE_OPENED) assertThat(posture).isEqualTo(DEVICE_POSTURE_OPENED) - deviceStateCallback.value.onStateChanged(DEVICE_POSTURE_FLIPPED) + deviceStateCallback.value.onDeviceStateChanged(DEVICE_STATE_FLIPPED) assertThat(posture).isEqualTo(DEVICE_POSTURE_FLIPPED) + + deviceStateCallback.value.onDeviceStateChanged(DEVICE_STATE_UNKNOWN) + assertThat(posture).isEqualTo(DEVICE_POSTURE_UNKNOWN) } @Test @@ -107,15 +121,26 @@ class DevicePostureControllerImplTest : SysuiTestCase() { var posture = -1 underTest.addCallback { posture = it } - deviceStateCallback.value.onStateChanged(DEVICE_POSTURE_HALF_OPENED) + deviceStateCallback.value.onDeviceStateChanged(DEVICE_STATE_HALF_FOLDED) assertThat(posture).isEqualTo(DEVICE_POSTURE_HALF_OPENED) - // base state change doesn't change the posture - deviceStateCallback.value.onBaseStateChanged(DEVICE_POSTURE_CLOSED) + val physicalProperties = + setOf(DeviceState.PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_CLOSED) + val updatedState = + DeviceState( + DeviceState.Configuration.Builder( + DEVICE_STATE_HALF_FOLDED.identifier, + DEVICE_STATE_HALF_FOLDED.name + ) + .setPhysicalProperties(physicalProperties) + .build() + ) + // state change with updated physical properties shouldn't cause a posture change + deviceStateCallback.value.onDeviceStateChanged(updatedState) assertThat(posture).isEqualTo(DEVICE_POSTURE_HALF_OPENED) - // WHEN the display state maps to using the base state, then posture updates - deviceStateCallback.value.onStateChanged(useBaseStateDeviceState) + // WHEN the display state maps to the physical state, then posture updates + deviceStateCallback.value.onDeviceStateChanged(DEVICE_STATE_USE_BASE_STATE) assertThat(posture).isEqualTo(DEVICE_POSTURE_CLOSED) } @@ -124,20 +149,97 @@ class DevicePostureControllerImplTest : SysuiTestCase() { var numPostureChanges = 0 underTest.addCallback { numPostureChanges++ } - deviceStateCallback.value.onStateChanged(DEVICE_POSTURE_HALF_OPENED) + deviceStateCallback.value.onDeviceStateChanged(DEVICE_STATE_HALF_FOLDED) assertThat(numPostureChanges).isEqualTo(1) - // base state changes doesn't send another posture update since the device state isn't - // useBaseStateDeviceState - deviceStateCallback.value.onBaseStateChanged(DEVICE_POSTURE_CLOSED) - deviceStateCallback.value.onBaseStateChanged(DEVICE_POSTURE_HALF_OPENED) - deviceStateCallback.value.onBaseStateChanged(DEVICE_POSTURE_FLIPPED) - deviceStateCallback.value.onBaseStateChanged(DEVICE_POSTURE_OPENED) - deviceStateCallback.value.onBaseStateChanged(DEVICE_POSTURE_UNKNOWN) + // update to physical properties doesn't send another posture update since the device state + // isn't useBaseStateDeviceState + deviceStateCallback.value.onDeviceStateChanged( + getStateUpdatedPhysicalProperties(DEVICE_STATE_HALF_FOLDED, DEVICE_STATE_CLOSED) + ) + deviceStateCallback.value.onDeviceStateChanged( + getStateUpdatedPhysicalProperties(DEVICE_STATE_HALF_FOLDED, DEVICE_STATE_HALF_FOLDED) + ) + deviceStateCallback.value.onDeviceStateChanged( + getStateUpdatedPhysicalProperties(DEVICE_STATE_HALF_FOLDED, DEVICE_STATE_OPENED) + ) + deviceStateCallback.value.onDeviceStateChanged( + getStateUpdatedPhysicalProperties(DEVICE_STATE_HALF_FOLDED, DEVICE_STATE_UNKNOWN) + ) assertThat(numPostureChanges).isEqualTo(1) } private fun verifyRegistersForDeviceStateCallback() { verify(deviceStateManager).registerCallback(eq(mainExecutor), deviceStateCallback.capture()) } + + private fun getStateUpdatedPhysicalProperties( + currentState: DeviceState, + physicalState: DeviceState + ): DeviceState { + return DeviceState( + DeviceState.Configuration.Builder(currentState.identifier, currentState.name) + .setSystemProperties(currentState.configuration.systemProperties) + .setPhysicalProperties(physicalState.configuration.physicalProperties) + .build() + ) + } + + companion object { + val DEVICE_STATE_CLOSED = + DeviceState( + DeviceState.Configuration.Builder( + DEVICE_POSTURE_CLOSED /* id */, + "CLOSED" /* name */ + ) + .setPhysicalProperties( + setOf(DeviceState.PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_CLOSED) + ) + .build() + ) + val DEVICE_STATE_HALF_FOLDED = + DeviceState( + DeviceState.Configuration.Builder( + DEVICE_POSTURE_HALF_OPENED /* id */, + "HALF_FOLDED" /* name */ + ) + .setPhysicalProperties( + setOf( + DeviceState.PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_HALF_OPEN + ) + ) + .build() + ) + val DEVICE_STATE_OPENED = + DeviceState( + DeviceState.Configuration.Builder( + DEVICE_POSTURE_OPENED /* id */, + "OPENED" /* name */ + ) + .setPhysicalProperties( + setOf(DeviceState.PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_OPEN) + ) + .build() + ) + val DEVICE_STATE_FLIPPED = + DeviceState( + DeviceState.Configuration.Builder( + DEVICE_POSTURE_FLIPPED /* id */, + "FLIPPED" /* name */ + ) + .build() + ) + val DEVICE_STATE_UNKNOWN = + DeviceState( + DeviceState.Configuration.Builder( + DEVICE_POSTURE_UNKNOWN /* id */, + "UNKNOWN" /* name */ + ) + .build() + ) + val DEVICE_STATE_USE_BASE_STATE = + DeviceState( + DeviceState.Configuration.Builder(SUPPORTED_POSTURES_SIZE, "USE_BASE_STATE").build() + ) + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingControllerTest.java index 4ccbd1b739f3..2955162f80c2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingControllerTest.java @@ -25,6 +25,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.verify; +import android.hardware.devicestate.DeviceState; import android.hardware.devicestate.DeviceStateManager; import android.os.UserHandle; import android.provider.Settings; @@ -119,11 +120,11 @@ public class DeviceStateRotationLockSettingControllerTest extends SysuiTestCase 0, DEVICE_STATE_ROTATION_LOCK_UNLOCKED, 1, DEVICE_STATE_ROTATION_LOCK_UNLOCKED); mFakeRotationPolicy.setRotationLock(true); - mDeviceStateCallback.onStateChanged(1); + mDeviceStateCallback.onDeviceStateChanged(createDeviceStateForIdentifier(1)); assertThat(mFakeRotationPolicy.isRotationLocked()).isFalse(); // Settings only exist for state 0 and 1 - mDeviceStateCallback.onStateChanged(2); + mDeviceStateCallback.onDeviceStateChanged(createDeviceStateForIdentifier(2)); assertThat(mFakeRotationPolicy.isRotationLocked()).isFalse(); } @@ -134,10 +135,10 @@ public class DeviceStateRotationLockSettingControllerTest extends SysuiTestCase 0, DEVICE_STATE_ROTATION_LOCK_UNLOCKED, 1, DEVICE_STATE_ROTATION_LOCK_LOCKED); mFakeRotationPolicy.setRotationLock(true); - mDeviceStateCallback.onStateChanged(0); + mDeviceStateCallback.onDeviceStateChanged(createDeviceStateForIdentifier(0)); assertThat(mFakeRotationPolicy.isRotationLocked()).isFalse(); - mDeviceStateCallback.onStateChanged(1); + mDeviceStateCallback.onDeviceStateChanged(createDeviceStateForIdentifier(1)); assertThat(mFakeRotationPolicy.isRotationLocked()).isTrue(); } @@ -147,7 +148,7 @@ public class DeviceStateRotationLockSettingControllerTest extends SysuiTestCase mFakeRotationPolicy.setRotationLock(true); // State 2 -> Ignored -> Fall back to state 1 which is unlocked - mDeviceStateCallback.onStateChanged(2); + mDeviceStateCallback.onDeviceStateChanged(createDeviceStateForIdentifier(2)); assertThat(mFakeRotationPolicy.isRotationLocked()).isFalse(); } @@ -161,7 +162,7 @@ public class DeviceStateRotationLockSettingControllerTest extends SysuiTestCase mFakeRotationPolicy.setRotationLock(false); // State 2 -> Ignored -> Fall back to state 1 which is locked - mDeviceStateCallback.onStateChanged(2); + mDeviceStateCallback.onDeviceStateChanged(createDeviceStateForIdentifier(2)); assertThat(mFakeRotationPolicy.isRotationLocked()).isTrue(); } @@ -173,7 +174,7 @@ public class DeviceStateRotationLockSettingControllerTest extends SysuiTestCase mSettingsManager.onPersistedSettingsChanged(); mFakeRotationPolicy.setRotationLock(true); - mDeviceStateCallback.onStateChanged(0); + mDeviceStateCallback.onDeviceStateChanged(createDeviceStateForIdentifier(0)); assertThat(mFakeRotationPolicy.isRotationLocked()).isTrue(); mDeviceStateRotationLockSettingController.onRotationLockStateChanged( @@ -189,10 +190,10 @@ public class DeviceStateRotationLockSettingControllerTest extends SysuiTestCase @Test public void whenDeviceStateSwitchedToIgnoredState_useFallbackSetting() { - mDeviceStateCallback.onStateChanged(0); + mDeviceStateCallback.onDeviceStateChanged(createDeviceStateForIdentifier(0)); assertThat(mFakeRotationPolicy.isRotationLocked()).isTrue(); - mDeviceStateCallback.onStateChanged(2); + mDeviceStateCallback.onDeviceStateChanged(createDeviceStateForIdentifier(2)); assertThat(mFakeRotationPolicy.isRotationLocked()).isFalse(); } @@ -202,10 +203,10 @@ public class DeviceStateRotationLockSettingControllerTest extends SysuiTestCase 8, DEVICE_STATE_ROTATION_LOCK_IGNORED, 1, DEVICE_STATE_ROTATION_LOCK_UNLOCKED); mFakeRotationPolicy.setRotationLock(true); - mDeviceStateCallback.onStateChanged(1); + mDeviceStateCallback.onDeviceStateChanged(createDeviceStateForIdentifier(1)); assertThat(mFakeRotationPolicy.isRotationLocked()).isFalse(); - mDeviceStateCallback.onStateChanged(8); + mDeviceStateCallback.onDeviceStateChanged(createDeviceStateForIdentifier(8)); assertThat(mFakeRotationPolicy.isRotationLocked()).isFalse(); mDeviceStateRotationLockSettingController.onRotationLockStateChanged( @@ -225,7 +226,7 @@ public class DeviceStateRotationLockSettingControllerTest extends SysuiTestCase 0, DEVICE_STATE_ROTATION_LOCK_UNLOCKED, 1, DEVICE_STATE_ROTATION_LOCK_UNLOCKED); mFakeRotationPolicy.setRotationLock(false); - mDeviceStateCallback.onStateChanged(0); + mDeviceStateCallback.onDeviceStateChanged(createDeviceStateForIdentifier(0)); assertThat(mFakeRotationPolicy.isRotationLocked()).isFalse(); @@ -241,7 +242,7 @@ public class DeviceStateRotationLockSettingControllerTest extends SysuiTestCase initializeSettingsWith( 0, DEVICE_STATE_ROTATION_LOCK_LOCKED, 1, DEVICE_STATE_ROTATION_LOCK_UNLOCKED); - mDeviceStateCallback.onStateChanged(0); + mDeviceStateCallback.onDeviceStateChanged(createDeviceStateForIdentifier(0)); mDeviceStateRotationLockSettingController.onRotationLockStateChanged( /* rotationLocked= */ false, @@ -262,7 +263,7 @@ public class DeviceStateRotationLockSettingControllerTest extends SysuiTestCase 0, DEVICE_STATE_ROTATION_LOCK_LOCKED, 1, DEVICE_STATE_ROTATION_LOCK_UNLOCKED, 2, DEVICE_STATE_ROTATION_LOCK_IGNORED); - mDeviceStateCallback.onStateChanged(2); + mDeviceStateCallback.onDeviceStateChanged(createDeviceStateForIdentifier(2)); mDeviceStateRotationLockSettingController.onRotationLockStateChanged( /* rotationLocked= */ true, @@ -283,8 +284,8 @@ public class DeviceStateRotationLockSettingControllerTest extends SysuiTestCase 0, DEVICE_STATE_ROTATION_LOCK_LOCKED, 1, DEVICE_STATE_ROTATION_LOCK_UNLOCKED, 8, DEVICE_STATE_ROTATION_LOCK_IGNORED); - mDeviceStateCallback.onStateChanged(1); - mDeviceStateCallback.onStateChanged(8); + mDeviceStateCallback.onDeviceStateChanged(createDeviceStateForIdentifier(1)); + mDeviceStateCallback.onDeviceStateChanged(createDeviceStateForIdentifier(8)); mDeviceStateRotationLockSettingController.onRotationLockStateChanged( /* rotationLocked= */ true, @@ -320,6 +321,10 @@ public class DeviceStateRotationLockSettingControllerTest extends SysuiTestCase mSettingsManager.onPersistedSettingsChanged(); } + private DeviceState createDeviceStateForIdentifier(int id) { + return new DeviceState(new DeviceState.Configuration.Builder(id, "" /* name */).build()); + } + private static class FakeRotationPolicy implements RotationPolicyWrapper { private boolean mRotationLock; diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java index ce7c22438d54..29e0586b9ac4 100644 --- a/services/core/java/com/android/server/display/DisplayManagerService.java +++ b/services/core/java/com/android/server/display/DisplayManagerService.java @@ -75,6 +75,7 @@ import android.graphics.Point; import android.hardware.OverlayProperties; import android.hardware.Sensor; import android.hardware.SensorManager; +import android.hardware.devicestate.DeviceState; import android.hardware.devicestate.DeviceStateManager; import android.hardware.devicestate.DeviceStateManagerInternal; import android.hardware.display.AmbientBrightnessDayStats; @@ -5034,30 +5035,22 @@ public final class DisplayManagerService extends SystemService { * Listens to changes in device state and reports the state to LogicalDisplayMapper. */ class DeviceStateListener implements DeviceStateManager.DeviceStateCallback { - // Base state corresponds to the physical state of the device - private int mBaseState = DeviceStateManager.INVALID_DEVICE_STATE_IDENTIFIER; @Override - public void onStateChanged(int deviceState) { - boolean isDeviceStateOverrideActive = deviceState != mBaseState; + public void onDeviceStateChanged(DeviceState deviceState) { synchronized (mSyncRoot) { // Notify WindowManager that we are about to handle new device state, this should // be sent before any work related to the device state in DisplayManager, so // WindowManager could do implement that depends on the device state and display // changes (serializes device state update and display change events) Message msg = mHandler.obtainMessage(MSG_RECEIVED_DEVICE_STATE); - msg.arg1 = deviceState; + msg.arg1 = deviceState.getIdentifier(); mHandler.sendMessage(msg); mLogicalDisplayMapper - .setDeviceStateLocked(deviceState, isDeviceStateOverrideActive); + .setDeviceStateLocked(deviceState.getIdentifier()); } } - - @Override - public void onBaseStateChanged(int state) { - mBaseState = state; - } }; private class BrightnessPair { diff --git a/services/core/java/com/android/server/display/LogicalDisplayMapper.java b/services/core/java/com/android/server/display/LogicalDisplayMapper.java index e092fdae7cc7..b6c92199a571 100644 --- a/services/core/java/com/android/server/display/LogicalDisplayMapper.java +++ b/services/core/java/com/android/server/display/LogicalDisplayMapper.java @@ -441,7 +441,7 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener { mVirtualDeviceDisplayMapping.put(displayDevice.getUniqueId(), virtualDeviceUniqueId); } - void setDeviceStateLocked(int state, boolean isOverrideActive) { + void setDeviceStateLocked(int state) { if (!mBootCompleted) { // The boot animation might still be in progress, we do not want to switch states now // as the boot animation would end up with an incorrect size. @@ -465,7 +465,7 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener { final boolean wakeDevice = shouldDeviceBeWoken(mPendingDeviceState, mDeviceState, mInteractive, mBootCompleted); final boolean sleepDevice = shouldDeviceBePutToSleep(mPendingDeviceState, mDeviceState, - isOverrideActive, mInteractive, mBootCompleted); + mInteractive, mBootCompleted); // If all displays are off already, we can just transition here, unless we are trying to // wake or sleep the device as part of this transition. In that case defer the final @@ -513,8 +513,7 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener { mBootCompleted = true; if (mDeviceStateToBeAppliedAfterBoot != DeviceStateManager.INVALID_DEVICE_STATE_IDENTIFIER) { - setDeviceStateLocked(mDeviceStateToBeAppliedAfterBoot, - /* isOverrideActive= */ false); + setDeviceStateLocked(mDeviceStateToBeAppliedAfterBoot); } } } @@ -560,7 +559,6 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener { * * @param pendingState device state we are moving to * @param currentState device state we are currently in - * @param isOverrideActive if a device state override is currently active or not * @param isInteractive if the device is in an interactive state * @param isBootCompleted is the device fully booted * @@ -568,13 +566,13 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener { * @see #setDeviceStateLocked */ @VisibleForTesting - boolean shouldDeviceBePutToSleep(int pendingState, int currentState, boolean isOverrideActive, - boolean isInteractive, boolean isBootCompleted) { + boolean shouldDeviceBePutToSleep(int pendingState, int currentState, boolean isInteractive, + boolean isBootCompleted) { return currentState != DeviceStateManager.INVALID_DEVICE_STATE_IDENTIFIER && mDeviceStatesOnWhichToSleep.get(pendingState) && !mDeviceStatesOnWhichToSleep.get(currentState) - && !isOverrideActive - && isInteractive && isBootCompleted + && isInteractive + && isBootCompleted && !mFoldSettingProvider.shouldStayAwakeOnFold(); } diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index b50e2bf317b5..6ff8cf3cc2c8 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -56,6 +56,7 @@ import android.content.res.Resources; import android.database.ContentObserver; import android.hardware.SensorManager; import android.hardware.SystemSensorManager; +import android.hardware.devicestate.DeviceState; import android.hardware.devicestate.DeviceStateManager; import android.hardware.display.AmbientDisplayConfiguration; import android.hardware.display.DisplayManagerInternal; @@ -7152,9 +7153,10 @@ public final class PowerManagerService extends SystemService private int mDeviceState = DeviceStateManager.INVALID_DEVICE_STATE_IDENTIFIER; @Override - public void onStateChanged(int deviceState) { - if (mDeviceState != deviceState) { - mDeviceState = deviceState; + public void onDeviceStateChanged(@NonNull DeviceState deviceState) { + int stateIdentifier = deviceState.getIdentifier(); + if (mDeviceState != stateIdentifier) { + mDeviceState = stateIdentifier; // Device-state interactions are applied to the default display so that they // are reflected only with the default power group. userActivityInternal(Display.DEFAULT_DISPLAY, mClock.uptimeMillis(), diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java index 18f03113c01c..e4619a47103e 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java @@ -78,6 +78,7 @@ import android.graphics.Insets; import android.graphics.Rect; import android.hardware.Sensor; import android.hardware.SensorManager; +import android.hardware.devicestate.DeviceState; import android.hardware.display.BrightnessConfiguration; import android.hardware.display.BrightnessInfo; import android.hardware.display.Curve; @@ -714,7 +715,9 @@ public class DisplayManagerServiceTest { IDisplayManagerCallback displayChangesCallback = registerDisplayChangeCallback( displayManager); - listener.onStateChanged(123); + listener.onDeviceStateChanged(new DeviceState( + new DeviceState.Configuration.Builder(123 /* identifier */, + "TEST" /* name */).build())); waitForIdleHandler(handler); InOrder inOrder = inOrder(mMockWindowManagerInternal, displayChangesCallback); diff --git a/services/tests/displayservicetests/src/com/android/server/display/LogicalDisplayMapperTest.java b/services/tests/displayservicetests/src/com/android/server/display/LogicalDisplayMapperTest.java index 2939192d3d2e..d0c7077f29c0 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/LogicalDisplayMapperTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/LogicalDisplayMapperTest.java @@ -650,7 +650,6 @@ public class LogicalDisplayMapperTest { public void testDeviceShouldBePutToSleep() { assertTrue(mLogicalDisplayMapper.shouldDeviceBePutToSleep(DEVICE_STATE_CLOSED, DEVICE_STATE_OPEN, - /* isOverrideActive= */false, /* isInteractive= */true, /* isBootCompleted= */true)); } @@ -661,7 +660,6 @@ public class LogicalDisplayMapperTest { assertFalse(mLogicalDisplayMapper.shouldDeviceBePutToSleep(DEVICE_STATE_CLOSED, DEVICE_STATE_OPEN, - /* isOverrideActive= */false, /* isInteractive= */true, /* isBootCompleted= */true)); } @@ -670,21 +668,10 @@ public class LogicalDisplayMapperTest { public void testDeviceShouldNotBePutToSleep() { assertFalse(mLogicalDisplayMapper.shouldDeviceBePutToSleep(DEVICE_STATE_OPEN, DEVICE_STATE_CLOSED, - /* isOverrideActive= */false, /* isInteractive= */true, /* isBootCompleted= */true)); assertFalse(mLogicalDisplayMapper.shouldDeviceBePutToSleep(DEVICE_STATE_CLOSED, INVALID_DEVICE_STATE_IDENTIFIER, - /* isOverrideActive= */false, - /* isInteractive= */true, - /* isBootCompleted= */true)); - } - - @Test - public void testDeviceShouldNotBePutToSleepDifferentBaseState() { - assertFalse(mLogicalDisplayMapper.shouldDeviceBePutToSleep(DEVICE_STATE_CLOSED, - DEVICE_STATE_OPEN, - /* isOverrideActive= */true, /* isInteractive= */true, /* isBootCompleted= */true)); } @@ -750,7 +737,7 @@ public class LogicalDisplayMapperTest { // We can only have one default display assertEquals(DEFAULT_DISPLAY, id(display1)); - mLogicalDisplayMapper.setDeviceStateLocked(0, false); + mLogicalDisplayMapper.setDeviceStateLocked(0); advanceTime(1000); // The new state is not applied until the boot is completed assertTrue(mLogicalDisplayMapper.getDisplayLocked(device1).isEnabledLocked()); @@ -771,7 +758,7 @@ public class LogicalDisplayMapperTest { assertEquals("concurrent", mLogicalDisplayMapper.getDisplayLocked(device2) .getDisplayInfoLocked().thermalBrightnessThrottlingDataId); - mLogicalDisplayMapper.setDeviceStateLocked(1, false); + mLogicalDisplayMapper.setDeviceStateLocked(1); advanceTime(1000); assertFalse(mLogicalDisplayMapper.getDisplayLocked(device1).isEnabledLocked()); assertTrue(mLogicalDisplayMapper.getDisplayLocked(device2).isEnabledLocked()); @@ -784,7 +771,7 @@ public class LogicalDisplayMapperTest { mLogicalDisplayMapper.getDisplayLocked(device2) .getDisplayInfoLocked().thermalBrightnessThrottlingDataId); - mLogicalDisplayMapper.setDeviceStateLocked(2, false); + mLogicalDisplayMapper.setDeviceStateLocked(2); advanceTime(1000); assertFalse(mLogicalDisplayMapper.getDisplayLocked(device1).isEnabledLocked()); assertTrue(mLogicalDisplayMapper.getDisplayLocked(device2).isEnabledLocked()); @@ -861,7 +848,7 @@ public class LogicalDisplayMapperTest { // 3) Send DISPLAY_DEVICE_EVENT_CHANGE to inform the mapper of the new display state // 4) Dispatch handler events. mLogicalDisplayMapper.onBootCompleted(); - mLogicalDisplayMapper.setDeviceStateLocked(0, false); + mLogicalDisplayMapper.setDeviceStateLocked(0); mDisplayDeviceRepo.onDisplayDeviceEvent(device3, DISPLAY_DEVICE_EVENT_CHANGED); advanceTime(1000); final int[] allDisplayIds = mLogicalDisplayMapper.getDisplayIdsLocked( @@ -891,7 +878,7 @@ public class LogicalDisplayMapperTest { /* includeDisabled= */ false)); // Now do it again to go back to state 1 - mLogicalDisplayMapper.setDeviceStateLocked(1, false); + mLogicalDisplayMapper.setDeviceStateLocked(1); mDisplayDeviceRepo.onDisplayDeviceEvent(device3, DISPLAY_DEVICE_EVENT_CHANGED); advanceTime(1000); final int[] threeDisplaysEnabled = mLogicalDisplayMapper.getDisplayIdsLocked( @@ -945,7 +932,7 @@ public class LogicalDisplayMapperTest { // We can only have one default display assertEquals(DEFAULT_DISPLAY, id(display1)); - mLogicalDisplayMapper.setDeviceStateLocked(0, false); + mLogicalDisplayMapper.setDeviceStateLocked(0); advanceTime(1000); mLogicalDisplayMapper.onBootCompleted(); advanceTime(1000); @@ -964,11 +951,11 @@ public class LogicalDisplayMapperTest { ///////////////// private void finishBootAndFoldDevice() { - mLogicalDisplayMapper.setDeviceStateLocked(DEVICE_STATE_OPEN, false); + mLogicalDisplayMapper.setDeviceStateLocked(DEVICE_STATE_OPEN); advanceTime(1000); mLogicalDisplayMapper.onBootCompleted(); advanceTime(1000); - mLogicalDisplayMapper.setDeviceStateLocked(DEVICE_STATE_CLOSED, false); + mLogicalDisplayMapper.setDeviceStateLocked(DEVICE_STATE_CLOSED); advanceTime(1000); } diff --git a/services/tests/powerservicetests/src/com/android/server/power/PowerManagerServiceTest.java b/services/tests/powerservicetests/src/com/android/server/power/PowerManagerServiceTest.java index aec896f383c4..f86ff14218ba 100644 --- a/services/tests/powerservicetests/src/com/android/server/power/PowerManagerServiceTest.java +++ b/services/tests/powerservicetests/src/com/android/server/power/PowerManagerServiceTest.java @@ -64,6 +64,7 @@ import android.content.IntentFilter; import android.content.PermissionChecker; import android.content.res.Resources; import android.hardware.SensorManager; +import android.hardware.devicestate.DeviceState; import android.hardware.devicestate.DeviceStateManager; import android.hardware.devicestate.DeviceStateManager.DeviceStateCallback; import android.hardware.display.AmbientDisplayConfiguration; @@ -154,6 +155,8 @@ public class PowerManagerServiceTest { private static final float BRIGHTNESS_FACTOR = 0.7f; private static final boolean BATTERY_SAVER_ENABLED = true; + private static final DeviceState DEVICE_STATE_1 = new DeviceState( + new DeviceState.Configuration.Builder(1 /* identifier */, "" /* name */).build()); @Mock private BatterySaverController mBatterySaverControllerMock; @Mock private BatterySaverPolicy mBatterySaverPolicyMock; @@ -2839,7 +2842,7 @@ public class PowerManagerServiceTest { // Send a display state change event and advance the clock 10. final DeviceStateCallback deviceStateCallback = deviceStateCallbackCaptor.getValue(); - deviceStateCallback.onStateChanged(1); + deviceStateCallback.onDeviceStateChanged(DEVICE_STATE_1); final long timeToAdvance = 10; advanceTime(timeToAdvance); @@ -2849,7 +2852,7 @@ public class PowerManagerServiceTest { assertThat(mService.wasDeviceIdleForInternal(timeToAdvance)).isFalse(); // Send the same state and ensure that does not trigger an update. - deviceStateCallback.onStateChanged(1); + deviceStateCallback.onDeviceStateChanged(DEVICE_STATE_1); advanceTime(timeToAdvance); final long newTime = timeToAdvance * 2; |