summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Kevin Chyn <kchyn@google.com> 2024-09-20 18:50:35 +0000
committer Kevin Chyn <kchyn@google.com> 2024-11-08 21:01:19 +0000
commit30ac01b752230191a003d7b010c9c9e056cb04a7 (patch)
tree46e67bdcf05c1a3ead5ac8dc43643075a95babbd
parent73cdce538e2bad650737bf1727e8edfe21500bad (diff)
Add DEVICE_STATE_REAR_DISPLAY_OUTER_DEFAULT
Adds this new state which is the same as DEVICE_STATE_REAR_DISPLAY, except with the additional property PROPERTY_FEATURE_REAR_DISPLAY_OUTER_DEFAULT. Note that this change/topic can be enabled even without the System-UI-side change that actually displays a new dialog on the inner display while in this mode. To the user, it will still be exactly like the existing Rear Display Mode. For the changes in this CL to take effect (regardless of the SystemUI side), the corresponding changes must be done in the device-specific overlays. Namely: A) Add a new display layout that maps to the new device state (state 5) defined in BookStyleDeviceStatePolicy B) Update the config_deviceStatesToReverseDefaultDisplayRotationAroundZAxis overlays to include state 5 C) Update the config_rearDisplayDeviceStates overlay to include state 5 D) Update the config_device_state_postures overlay to include state 5 E) Enable the flag Bug: 371095273 Flag: android.hardware.devicestate.feature.flags.device_state_rdm_v2 Test: demo app Test: atest WindowAreaComponentImplTests Test: atest ExtensionRearDisplayTest BYPASS_LARGE_CHANGE_WARNING Change-Id: I4a4559649df6c37dc183514a38010dcab698b14d
-rw-r--r--core/java/android/hardware/devicestate/DeviceState.java20
-rw-r--r--core/java/android/hardware/devicestate/feature/flags.aconfig9
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java35
-rw-r--r--libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/area/WindowAreaComponentImplTests.java61
-rw-r--r--services/foldables/devicestateprovider/src/com/android/server/policy/BookStyleDeviceStatePolicy.java41
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());
+ }
}