diff options
author | 2024-11-11 18:39:32 +0000 | |
---|---|---|
committer | 2024-11-11 18:39:32 +0000 | |
commit | 18eb83c20e3adb4fc3cf2a89e59780ade3b1e9ba (patch) | |
tree | 60d58fab93e4792e3eea7ff9da71f74d7b4febe1 | |
parent | fb4046d16b62c8b1fa049347c6632dc3ae58082b (diff) | |
parent | 30ac01b752230191a003d7b010c9c9e056cb04a7 (diff) |
Merge "Add DEVICE_STATE_REAR_DISPLAY_OUTER_DEFAULT" into main
5 files changed, 151 insertions, 15 deletions
diff --git a/core/java/android/hardware/devicestate/DeviceState.java b/core/java/android/hardware/devicestate/DeviceState.java index e583627c0960..8b4d0da147bc 100644 --- a/core/java/android/hardware/devicestate/DeviceState.java +++ b/core/java/android/hardware/devicestate/DeviceState.java @@ -172,6 +172,23 @@ public final class DeviceState { */ public static final int PROPERTY_FEATURE_DUAL_DISPLAY_INTERNAL_DEFAULT = 17; + /** + * Property that indicates that this state corresponds to the device state for rear display + * mode, where both the inner and outer displays are on. In this state, the outer display + * is the default display where the app is shown, and the inner display is used by the system to + * show a UI affordance for exiting the mode. + * + * Note that this value should generally not be used, and may be removed in the future (e.g. + * if or when it becomes the only type of rear display mode when + * {@link android.hardware.devicestate.feature.flags.Flags#deviceStateRdmV2} is removed). + * + * As such, clients should strongly consider relying on {@link #PROPERTY_FEATURE_REAR_DISPLAY} + * instead. + * + * @hide + */ + public static final int PROPERTY_FEATURE_REAR_DISPLAY_OUTER_DEFAULT = 1001; + /** @hide */ @IntDef(prefix = {"PROPERTY_"}, flag = false, value = { PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_CLOSED, @@ -190,7 +207,8 @@ public final class DeviceState { PROPERTY_POWER_CONFIGURATION_TRIGGER_WAKE, PROPERTY_EXTENDED_DEVICE_STATE_EXTERNAL_DISPLAY, PROPERTY_FEATURE_REAR_DISPLAY, - PROPERTY_FEATURE_DUAL_DISPLAY_INTERNAL_DEFAULT + PROPERTY_FEATURE_DUAL_DISPLAY_INTERNAL_DEFAULT, + PROPERTY_FEATURE_REAR_DISPLAY_OUTER_DEFAULT }) @Retention(RetentionPolicy.SOURCE) @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE}) diff --git a/core/java/android/hardware/devicestate/feature/flags.aconfig b/core/java/android/hardware/devicestate/feature/flags.aconfig index 98ba9192044d..6230f4dbf6f4 100644 --- a/core/java/android/hardware/devicestate/feature/flags.aconfig +++ b/core/java/android/hardware/devicestate/feature/flags.aconfig @@ -29,4 +29,13 @@ flag { metadata { purpose: PURPOSE_BUGFIX } +} + +flag { + name: "device_state_rdm_v2" + is_exported: true + namespace: "windowing_sdk" + description: "Enables Rear Display Mode V2, where the inner display shows the user a UI affordance for exiting the state" + bug: "372486634" + is_fixed_read_only: true }
\ No newline at end of file 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 4d7be39ca5a4..76eb207a31c9 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java @@ -19,6 +19,7 @@ package androidx.window.extensions.area; import static android.hardware.devicestate.DeviceState.PROPERTY_EMULATED_ONLY; import static android.hardware.devicestate.DeviceState.PROPERTY_FEATURE_DUAL_DISPLAY_INTERNAL_DEFAULT; import static android.hardware.devicestate.DeviceState.PROPERTY_FEATURE_REAR_DISPLAY; +import static android.hardware.devicestate.DeviceState.PROPERTY_FEATURE_REAR_DISPLAY_OUTER_DEFAULT; import static android.hardware.devicestate.DeviceState.PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_OUTER_PRIMARY; import static android.hardware.devicestate.DeviceStateManager.INVALID_DEVICE_STATE; import static android.hardware.devicestate.DeviceStateManager.INVALID_DEVICE_STATE_IDENTIFIER; @@ -104,6 +105,30 @@ public class WindowAreaComponentImpl implements WindowAreaComponent, @GuardedBy("mLock") private int mLastReportedRearDisplayPresentationStatus; + @VisibleForTesting + static int getRdmV1Identifier(List<DeviceState> currentSupportedDeviceStates) { + for (int i = 0; i < currentSupportedDeviceStates.size(); i++) { + DeviceState state = currentSupportedDeviceStates.get(i); + if (state.hasProperty(PROPERTY_FEATURE_REAR_DISPLAY) + && !state.hasProperty(PROPERTY_FEATURE_REAR_DISPLAY_OUTER_DEFAULT)) { + return state.getIdentifier(); + } + } + return INVALID_DEVICE_STATE_IDENTIFIER; + } + + @VisibleForTesting + static int getRdmV2Identifier(List<DeviceState> currentSupportedDeviceStates) { + for (int i = 0; i < currentSupportedDeviceStates.size(); i++) { + DeviceState state = currentSupportedDeviceStates.get(i); + if (state.hasProperties(PROPERTY_FEATURE_REAR_DISPLAY, + PROPERTY_FEATURE_REAR_DISPLAY_OUTER_DEFAULT)) { + return state.getIdentifier(); + } + } + return INVALID_DEVICE_STATE_IDENTIFIER; + } + public WindowAreaComponentImpl(@NonNull Context context) { mDeviceStateManager = context.getSystemService(DeviceStateManager.class); mDisplayManager = context.getSystemService(DisplayManager.class); @@ -112,12 +137,10 @@ public class WindowAreaComponentImpl implements WindowAreaComponent, mCurrentSupportedDeviceStates = mDeviceStateManager.getSupportedDeviceStates(); if (Flags.deviceStatePropertyMigration()) { - for (int i = 0; i < mCurrentSupportedDeviceStates.size(); i++) { - DeviceState state = mCurrentSupportedDeviceStates.get(i); - if (state.hasProperty(PROPERTY_FEATURE_REAR_DISPLAY)) { - mRearDisplayState = state.getIdentifier(); - break; - } + if (Flags.deviceStateRdmV2()) { + mRearDisplayState = getRdmV2Identifier(mCurrentSupportedDeviceStates); + } else { + mRearDisplayState = getRdmV1Identifier(mCurrentSupportedDeviceStates); } } else { mFoldedDeviceStates = context.getResources().getIntArray( diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/area/WindowAreaComponentImplTests.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/area/WindowAreaComponentImplTests.java index ccb4ebe9199e..d677fef5c22c 100644 --- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/area/WindowAreaComponentImplTests.java +++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/area/WindowAreaComponentImplTests.java @@ -16,8 +16,13 @@ package androidx.window.extensions.area; +import static android.hardware.devicestate.DeviceState.PROPERTY_FEATURE_REAR_DISPLAY; +import static android.hardware.devicestate.DeviceState.PROPERTY_FEATURE_REAR_DISPLAY_OUTER_DEFAULT; +import static android.hardware.devicestate.DeviceStateManager.INVALID_DEVICE_STATE_IDENTIFIER; + import static org.junit.Assert.assertEquals; +import android.hardware.devicestate.DeviceState; import android.platform.test.annotations.Presubmit; import android.util.DisplayMetrics; import android.view.Surface; @@ -29,11 +34,34 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + @Presubmit @SmallTest @RunWith(AndroidJUnit4.class) public class WindowAreaComponentImplTests { + private static final DeviceState REAR_DISPLAY_STATE_V1 = new DeviceState( + new DeviceState.Configuration.Builder(1, "STATE_0") + .setSystemProperties( + Set.of(PROPERTY_FEATURE_REAR_DISPLAY)) + .build()); + private static final DeviceState REAR_DISPLAY_STATE_V2 = new DeviceState( + new DeviceState.Configuration.Builder(2, "STATE_0") + .setSystemProperties( + Set.of(PROPERTY_FEATURE_REAR_DISPLAY, + PROPERTY_FEATURE_REAR_DISPLAY_OUTER_DEFAULT)) + .build()); + // The PROPERTY_FEATURE_REAR_DISPLAY_OUTER_DEFAULT state must be present together with the + // PROPERTY_FEATURE_REAR_DISPLAY state in order to be a valid state. + private static final DeviceState INVALID_REAR_DISPLAY_STATE = new DeviceState( + new DeviceState.Configuration.Builder(2, "STATE_0") + .setSystemProperties( + Set.of(PROPERTY_FEATURE_REAR_DISPLAY_OUTER_DEFAULT)) + .build()); + private final DisplayMetrics mTestDisplayMetrics = new DisplayMetrics(); @Before @@ -93,4 +121,37 @@ public class WindowAreaComponentImplTests { Surface.ROTATION_270, Surface.ROTATION_0, mTestDisplayMetrics); assertEquals(expectedMetrics, mTestDisplayMetrics); } + + @Test + public void testRdmV1Identifier() { + final List<DeviceState> supportedStates = new ArrayList<>(); + supportedStates.add(REAR_DISPLAY_STATE_V2); + assertEquals(INVALID_DEVICE_STATE_IDENTIFIER, + WindowAreaComponentImpl.getRdmV1Identifier(supportedStates)); + + supportedStates.add(REAR_DISPLAY_STATE_V1); + assertEquals(REAR_DISPLAY_STATE_V1.getIdentifier(), + WindowAreaComponentImpl.getRdmV1Identifier(supportedStates)); + } + + @Test + public void testRdmV2Identifier_whenStateIsImproperlyConfigured() { + final List<DeviceState> supportedStates = new ArrayList<>(); + supportedStates.add(INVALID_REAR_DISPLAY_STATE); + assertEquals(INVALID_DEVICE_STATE_IDENTIFIER, + WindowAreaComponentImpl.getRdmV2Identifier(supportedStates)); + } + + @Test + public void testRdmV2Identifier_whenStateIsProperlyConfigured() { + final List<DeviceState> supportedStates = new ArrayList<>(); + + supportedStates.add(REAR_DISPLAY_STATE_V1); + assertEquals(INVALID_DEVICE_STATE_IDENTIFIER, + WindowAreaComponentImpl.getRdmV2Identifier(supportedStates)); + + supportedStates.add(REAR_DISPLAY_STATE_V2); + assertEquals(REAR_DISPLAY_STATE_V2.getIdentifier(), + WindowAreaComponentImpl.getRdmV2Identifier(supportedStates)); + } } diff --git a/services/foldables/devicestateprovider/src/com/android/server/policy/BookStyleDeviceStatePolicy.java b/services/foldables/devicestateprovider/src/com/android/server/policy/BookStyleDeviceStatePolicy.java index cc5573bb01d8..f34ec72d7e27 100644 --- a/services/foldables/devicestateprovider/src/com/android/server/policy/BookStyleDeviceStatePolicy.java +++ b/services/foldables/devicestateprovider/src/com/android/server/policy/BookStyleDeviceStatePolicy.java @@ -19,6 +19,7 @@ package com.android.server.policy; import static android.hardware.devicestate.DeviceState.PROPERTY_EMULATED_ONLY; import static android.hardware.devicestate.DeviceState.PROPERTY_FEATURE_DUAL_DISPLAY_INTERNAL_DEFAULT; import static android.hardware.devicestate.DeviceState.PROPERTY_FEATURE_REAR_DISPLAY; +import static android.hardware.devicestate.DeviceState.PROPERTY_FEATURE_REAR_DISPLAY_OUTER_DEFAULT; import static android.hardware.devicestate.DeviceState.PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_INNER_PRIMARY; import static android.hardware.devicestate.DeviceState.PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_OUTER_PRIMARY; import static android.hardware.devicestate.DeviceState.PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_CLOSED; @@ -71,6 +72,7 @@ public class BookStyleDeviceStatePolicy extends DeviceStatePolicy implements private static final int DEVICE_STATE_OPENED = 2; private static final int DEVICE_STATE_REAR_DISPLAY = 3; private static final int DEVICE_STATE_CONCURRENT_INNER_DEFAULT = 4; + private static final int DEVICE_STATE_REAR_DISPLAY_OUTER_DEFAULT = 5; private static final int TENT_MODE_SWITCH_ANGLE_DEGREES = 90; private static final int TABLE_TOP_MODE_SWITCH_ANGLE_DEGREES = 125; private static final int MIN_CLOSED_ANGLE_DEGREES = 0; @@ -130,14 +132,17 @@ public class BookStyleDeviceStatePolicy extends DeviceStatePolicy implements return hingeAngle >= MAX_CLOSED_ANGLE_DEGREES && hingeAngle <= TABLE_TOP_MODE_SWITCH_ANGLE_DEGREES; }), - createConfig(getOpenedDeviceState(), /* activeStatePredicate= */ - ALLOWED), - createConfig(getRearDisplayDeviceState(), /* activeStatePredicate= */ - NOT_ALLOWED), - createConfig(getDualDisplayDeviceState(), /* activeStatePredicate= */ - NOT_ALLOWED, /* availabilityPredicate= */ - provider -> !mIsDualDisplayBlockingEnabled - || provider.hasNoConnectedExternalDisplay())}; + createConfig(getOpenedDeviceState(), + /* activeStatePredicate= */ ALLOWED), + createConfig(getRearDisplayDeviceState(), + /* activeStatePredicate= */ NOT_ALLOWED), + createConfig(getDualDisplayDeviceState(), + /* activeStatePredicate= */ NOT_ALLOWED, + /* availabilityPredicate= */ provider -> !mIsDualDisplayBlockingEnabled + || provider.hasNoConnectedExternalDisplay()), + createConfig(getRearDisplayOuterDefaultState(), + /* activeStatePredicate= */ NOT_ALLOWED) + }; } private DeviceStatePredicateWrapper createClosedConfiguration( @@ -266,4 +271,24 @@ public class BookStyleDeviceStatePolicy extends DeviceStatePolicy implements .setSystemProperties(systemProperties) .build()); } + + /** + * Returns the {link DeviceState.Configuration} that represents the new rear display state + * where the inner display is also enabled, showing a system affordance to exit the state. + */ + @NonNull + private DeviceState getRearDisplayOuterDefaultState() { + Set<@DeviceState.SystemDeviceStateProperties Integer> systemProperties = new HashSet<>( + List.of(PROPERTY_EMULATED_ONLY, + PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_OUTER_PRIMARY, + PROPERTY_POLICY_AVAILABLE_FOR_APP_REQUEST, + PROPERTY_FEATURE_REAR_DISPLAY, + PROPERTY_FEATURE_REAR_DISPLAY_OUTER_DEFAULT)); + + return new DeviceState(new DeviceState.Configuration.Builder( + DEVICE_STATE_REAR_DISPLAY_OUTER_DEFAULT, + "REAR_DISPLAY_OUTER_DEFAULT") + .setSystemProperties(systemProperties) + .build()); + } } |