Merge "Add DEVICE_STATE_REAR_DISPLAY_OUTER_DEFAULT" into main
diff --git a/core/java/android/hardware/devicestate/DeviceState.java b/core/java/android/hardware/devicestate/DeviceState.java
index e583627..8b4d0da 100644
--- a/core/java/android/hardware/devicestate/DeviceState.java
+++ b/core/java/android/hardware/devicestate/DeviceState.java
@@ -172,6 +172,23 @@
*/
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 @@
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 98ba9192..6230f4d 100644
--- a/core/java/android/hardware/devicestate/feature/flags.aconfig
+++ b/core/java/android/hardware/devicestate/feature/flags.aconfig
@@ -29,4 +29,13 @@
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 4d7be39..76eb207 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 @@
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 @@
@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 @@
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 ccb4ebe..d677fef 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.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 @@
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 cc5573b..f34ec72 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 @@
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 @@
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 @@
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 @@
.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());
+ }
}