Introduce opt-out options to stable configuration
To avoid incremental breakages, re-use the e2e enforcement opt-out flag
to let the app developers opt-out the stable configuration change.
Besides, the change also updates the Display.getSize() API doc to
reflect the stable configuration change. And updated the API doc of
LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES flag to reflect the movable
display cutout change.
Bug: 332750049
Test: DisplayTests
Test: Set the flag and observe the behavior
Change-Id: I66f3dc52af822a4c9b4e49eafd118e9c078fcac2
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index 885f4c5..982224b 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -806,7 +806,7 @@
*
* <aside class="note"><b>Note:</b> If the app targets
* {@link android.os.Build.VERSION_CODES#VANILLA_ICE_CREAM}
- * or after, The width measurement reflects the window size without excluding insets.
+ * or after, the width measurement reflects the window size without excluding insets.
* Otherwise, the measurement excludes window insets even when the app is displayed edge to edge
* using {@link android.view.Window#setDecorFitsSystemWindows(boolean)
* Window#setDecorFitsSystemWindows(boolean)}.</aside>
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 4475418..6464239 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -916,6 +916,12 @@
* {@code getWindowManager()} or {@code getSystemService(Context.WINDOW_SERVICE)}), the
* size of the current app window is returned. As a result, in multi-window mode, the
* returned size can be smaller than the size of the device screen.
+ * The returned window size can vary depending on API level:
+ * <ul>
+ * <li>API level 35 and above, the window size will be returned.
+ * <li>API level 34 and below, the window size minus system decoration areas and
+ * display cutout is returned.
+ * </ul>
* <li>If size is requested from a non-activity context (for example, the application
* context, where the WindowManager is accessed by
* {@code getApplicationContext().getSystemService(Context.WINDOW_SERVICE)}), the
@@ -924,9 +930,10 @@
* <li>API level 29 and below — The size of the entire display (based on
* current rotation) minus system decoration areas is returned.
* <li>API level 30 and above — The size of the top running activity in the
- * current process is returned. If the current process has no running
- * activities, the size of the device default display, including system
- * decoration areas, is returned.
+ * current process is returned, system decoration areas exclusion follows the
+ * behavior defined above, based on the caller's API level. If the current
+ * process has no running activities, the size of the device default display,
+ * including system decoration areas, is returned.
* </ul>
* </ul>
*
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index f22e8f5..0f54940b 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -781,7 +781,7 @@
* <p>
* The metrics describe the size of the area the window would occupy with
* {@link LayoutParams#MATCH_PARENT MATCH_PARENT} width and height, and the {@link WindowInsets}
- * such a window would have.
+ * such a window would have. The {@link WindowInsets} are not deducted from the bounds.
* <p>
* The value of this is based on the <b>current</b> windowing state of the system.
*
@@ -811,7 +811,7 @@
* <p>
* The metrics describe the size of the largest potential area the window might occupy with
* {@link LayoutParams#MATCH_PARENT MATCH_PARENT} width and height, and the {@link WindowInsets}
- * such a window would have.
+ * such a window would have. The {@link WindowInsets} are not deducted from the bounds.
* <p>
* Note that this might still be smaller than the size of the physical display if certain areas
* of the display are not available to windows created in this {@link Context}.
@@ -4264,11 +4264,9 @@
* no letterbox is applied."/>
*
* <p>
- * A cutout in the corner is considered to be on the short edge: <br/>
- * <img src="{@docRoot}reference/android/images/display_cutout/short_edge/fullscreen_corner_no_letterbox.png"
- * height="720"
- * alt="Screenshot of a fullscreen activity on a display with a cutout in the corner in
- * portrait, no letterbox is applied."/>
+ * A cutout in the corner can be considered to be on different edge in different device
+ * rotations. This behavior may vary from device to device. Use this flag is possible to
+ * letterbox your app if the display cutout is at corner.
*
* <p>
* On the other hand, should the cutout be on the long edge of the display, a letterbox will
diff --git a/core/java/android/view/WindowMetrics.java b/core/java/android/view/WindowMetrics.java
index 26298bc..8bcc9de 100644
--- a/core/java/android/view/WindowMetrics.java
+++ b/core/java/android/view/WindowMetrics.java
@@ -101,9 +101,13 @@
* Returns the bounds of the area associated with this window or {@code UiContext}.
* <p>
* <b>Note that the size of the reported bounds can have different size than
- * {@link Display#getSize(Point)}.</b> This method reports the window size including all system
- * bar areas, while {@link Display#getSize(Point)} reports the area excluding navigation bars
- * and display cutout areas. The value reported by {@link Display#getSize(Point)} can be
+ * {@link Display#getSize(Point)} based on your target API level and calling context.</b>
+ * This method reports the window size including all system
+ * bar areas, while {@link Display#getSize(Point)} can report the area excluding navigation bars
+ * and display cutout areas depending on the calling context and target SDK level. Please refer
+ * to {@link Display#getSize(Point)} for details.
+ * <p>
+ * The value reported by {@link Display#getSize(Point)} excluding system decoration areas can be
* obtained by using:
* <pre class="prettyprint">
* final WindowMetrics metrics = windowManager.getCurrentWindowMetrics();
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 5fa13ba..405324b 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2589,6 +2589,8 @@
<li>The framework will set {@link android.R.attr#statusBarColor},
{@link android.R.attr#navigationBarColor}, and
{@link android.R.attr#navigationBarDividerColor} to transparent.
+ <li>The frameworks will send Configuration no longer considering system insets.
+ The Configuration will be stable regardless of the system insets change.
</ul>
<p>If this is true, the edge-to-edge enforcement won't be applied. However, this
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 0066269..655a6c2 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -660,6 +660,8 @@
private final TaskFragment.ConfigOverrideHint mResolveConfigHint;
+ private final boolean mOptOutEdgeToEdge;
+
private static ConstrainDisplayApisConfig sConstrainDisplayApisConfig;
boolean pendingVoiceInteractionStart; // Waiting for activity-invoked voice session
@@ -2163,9 +2165,12 @@
|| ent.array.getBoolean(R.styleable.Window_windowShowWallpaper, false);
mStyleFillsParent = mOccludesParent;
noDisplay = ent.array.getBoolean(R.styleable.Window_windowNoDisplay, false);
+ mOptOutEdgeToEdge = ent.array.getBoolean(
+ R.styleable.Window_windowOptOutEdgeToEdgeEnforcement, false);
} else {
mStyleFillsParent = mOccludesParent = true;
noDisplay = false;
+ mOptOutEdgeToEdge = false;
}
if (options != null) {
@@ -8694,9 +8699,9 @@
if (rotation == ROTATION_UNDEFINED && !isFixedRotationTransforming()) {
rotation = mDisplayContent.getRotation();
}
- if (!mResolveConfigHint.mUseOverrideInsetsForConfig
- || getCompatDisplayInsets() != null || shouldCreateCompatDisplayInsets()
- || isFloating(parentWindowingMode) || rotation == ROTATION_UNDEFINED) {
+ if (!mOptOutEdgeToEdge && (!mResolveConfigHint.mUseOverrideInsetsForConfig
+ || getCompatDisplayInsets() != null || isFloating(parentWindowingMode)
+ || rotation == ROTATION_UNDEFINED)) {
// If the insets configuration decoupled logic is not enabled for the app, or the app
// already has a compat override, or the context doesn't contain enough info to
// calculate the override, skip the override.