summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/window/flags/windowing_frontend.aconfig11
-rw-r--r--services/core/java/com/android/server/wm/DisplayPolicy.java58
-rw-r--r--services/core/java/com/android/server/wm/InsetsPolicy.java1
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java26
4 files changed, 95 insertions, 1 deletions
diff --git a/core/java/android/window/flags/windowing_frontend.aconfig b/core/java/android/window/flags/windowing_frontend.aconfig
index f2ba16cf43d6..b4fec416bd5f 100644
--- a/core/java/android/window/flags/windowing_frontend.aconfig
+++ b/core/java/android/window/flags/windowing_frontend.aconfig
@@ -51,6 +51,17 @@ flag {
}
flag {
+ name: "use_cached_insets_for_display_switch"
+ namespace: "windowing_frontend"
+ description: "Reduce intermediate insets changes for display switch"
+ bug: "266197298"
+ is_fixed_read_only: true
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
name: "edge_to_edge_by_default"
namespace: "windowing_frontend"
description: "Make app go edge-to-edge by default when targeting SDK 35 or greater"
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index ec5b503fbb9b..c27aefa0b1bc 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -107,6 +107,7 @@ import android.view.InsetsFlags;
import android.view.InsetsFrameProvider;
import android.view.InsetsSource;
import android.view.InsetsState;
+import android.view.PrivacyIndicatorBounds;
import android.view.Surface;
import android.view.View;
import android.view.ViewDebug;
@@ -2121,6 +2122,8 @@ public class DisplayPolicy {
}
private static class Cache {
+ static final int TYPE_REGULAR_BARS = WindowInsets.Type.statusBars()
+ | WindowInsets.Type.navigationBars();
/**
* If {@link #mPreserveId} is this value, it is in the middle of updating display
* configuration before a transition is started. Then the active cache should be used.
@@ -2130,6 +2133,14 @@ public class DisplayPolicy {
int mPreserveId;
boolean mActive;
+ /**
+ * When display switches, mRegularBarsInsets will assign to mPreservedInsets, and the
+ * insets sources of previous device state will copy to mRegularBarsInsets.
+ */
+ ArrayList<InsetsSource> mPreservedInsets;
+ ArrayList<InsetsSource> mRegularBarsInsets;
+ PrivacyIndicatorBounds mPrivacyIndicatorBounds;
+
Cache(DisplayContent dc) {
mDecorInsets = new DecorInsets(dc);
}
@@ -2138,6 +2149,17 @@ public class DisplayPolicy {
return mPreserveId == ID_UPDATING_CONFIG || mDecorInsets.mDisplayContent
.mTransitionController.inTransition(mPreserveId);
}
+
+ static ArrayList<InsetsSource> copyRegularBarInsets(InsetsState srcState) {
+ final ArrayList<InsetsSource> state = new ArrayList<>();
+ for (int i = srcState.sourceSize() - 1; i >= 0; i--) {
+ final InsetsSource source = srcState.sourceAt(i);
+ if ((source.getType() & TYPE_REGULAR_BARS) != 0) {
+ state.add(new InsetsSource(source));
+ }
+ }
+ return state;
+ }
}
}
@@ -2213,24 +2235,60 @@ public class DisplayPolicy {
@VisibleForTesting
void updateCachedDecorInsets() {
DecorInsets prevCache = null;
+ PrivacyIndicatorBounds privacyIndicatorBounds = null;
if (mCachedDecorInsets == null) {
mCachedDecorInsets = new DecorInsets.Cache(mDisplayContent);
} else {
prevCache = new DecorInsets(mDisplayContent);
prevCache.setTo(mCachedDecorInsets.mDecorInsets);
+ privacyIndicatorBounds = mCachedDecorInsets.mPrivacyIndicatorBounds;
+ mCachedDecorInsets.mPreservedInsets = mCachedDecorInsets.mRegularBarsInsets;
}
// Set a special id to preserve it before a real id is available from transition.
mCachedDecorInsets.mPreserveId = DecorInsets.Cache.ID_UPDATING_CONFIG;
// Cache the current insets.
mCachedDecorInsets.mDecorInsets.setTo(mDecorInsets);
+ if (com.android.window.flags.Flags.useCachedInsetsForDisplaySwitch()) {
+ mCachedDecorInsets.mRegularBarsInsets = DecorInsets.Cache.copyRegularBarInsets(
+ mDisplayContent.mDisplayFrames.mInsetsState);
+ mCachedDecorInsets.mPrivacyIndicatorBounds =
+ mDisplayContent.mCurrentPrivacyIndicatorBounds;
+ } else {
+ mCachedDecorInsets.mRegularBarsInsets = null;
+ mCachedDecorInsets.mPrivacyIndicatorBounds = null;
+ }
// Switch current to previous cache.
if (prevCache != null) {
mDecorInsets.setTo(prevCache);
+ if (privacyIndicatorBounds != null) {
+ mDisplayContent.mCurrentPrivacyIndicatorBounds = privacyIndicatorBounds;
+ }
mCachedDecorInsets.mActive = true;
}
}
/**
+ * This returns a new InsetsState with replacing the insets in target device state when the
+ * display is switching (e.g. fold/unfold). Otherwise, it returns the original state. This is
+ * to avoid dispatching old insets source before the insets providers update new insets.
+ */
+ InsetsState replaceInsetsSourcesIfNeeded(InsetsState originalState, boolean copyState) {
+ if (mCachedDecorInsets == null || mCachedDecorInsets.mPreservedInsets == null
+ || !shouldKeepCurrentDecorInsets()) {
+ return originalState;
+ }
+ final ArrayList<InsetsSource> preservedSources = mCachedDecorInsets.mPreservedInsets;
+ final InsetsState state = copyState ? new InsetsState(originalState) : originalState;
+ for (int i = preservedSources.size() - 1; i >= 0; i--) {
+ final InsetsSource cacheSource = preservedSources.get(i);
+ if (state.peekSource(cacheSource.getId()) != null) {
+ state.addSource(new InsetsSource(cacheSource));
+ }
+ }
+ return state;
+ }
+
+ /**
* Called after the display configuration is updated according to the physical change. Suppose
* there should be a display change transition, so associate the cached decor insets with the
* transition to limit the lifetime of using the cache.
diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java
index 28722141dcd3..06754c4517ab 100644
--- a/services/core/java/com/android/server/wm/InsetsPolicy.java
+++ b/services/core/java/com/android/server/wm/InsetsPolicy.java
@@ -229,6 +229,7 @@ class InsetsPolicy {
state = originalState;
}
state = adjustVisibilityForIme(target, state, state == originalState);
+ state = mPolicy.replaceInsetsSourcesIfNeeded(state, state == originalState);
return adjustInsetsForRoundedCorners(target.mToken, state, state == originalState);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
index 4854f0d948b4..862158e8a0a1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
@@ -362,7 +362,19 @@ public class DisplayPolicyTests extends WindowTestsBase {
@Test
public void testSwitchDecorInsets() {
- createNavBarWithProvidedInsets(mDisplayContent);
+ final WindowState win = createApplicationWindow();
+ final WindowState bar = createNavBarWithProvidedInsets(mDisplayContent);
+ bar.getFrame().set(0, mDisplayContent.mDisplayFrames.mHeight - NAV_BAR_HEIGHT,
+ mDisplayContent.mDisplayFrames.mWidth, mDisplayContent.mDisplayFrames.mHeight);
+ final int insetsId = bar.mAttrs.providedInsets[0].getId();
+ final InsetsSourceProvider provider = mDisplayContent.getInsetsStateController()
+ .getOrCreateSourceProvider(insetsId, bar.mAttrs.providedInsets[0].getType());
+ provider.setServerVisible(true);
+ provider.updateSourceFrame(bar.getFrame());
+
+ final InsetsState prevInsetsState = new InsetsState();
+ prevInsetsState.addSource(new InsetsSource(provider.getSource()));
+
final DisplayPolicy displayPolicy = mDisplayContent.getDisplayPolicy();
final DisplayInfo info = mDisplayContent.getDisplayInfo();
final int w = info.logicalWidth;
@@ -385,6 +397,18 @@ public class DisplayPolicyTests extends WindowTestsBase {
// The current insets are restored from cache directly.
assertEquals(prevConfigFrame, displayPolicy.getDecorInsetsInfo(info.rotation,
info.logicalWidth, info.logicalHeight).mConfigFrame);
+ // Assume that the InsetsSource in current InsetsState is not updated yet. And it will be
+ // replaced by the one in cache.
+ InsetsState currentInsetsState = new InsetsState();
+ final InsetsSource prevSource = new InsetsSource(provider.getSource());
+ prevSource.getFrame().scale(0.5f);
+ currentInsetsState.addSource(prevSource);
+ currentInsetsState = mDisplayContent.getInsetsPolicy().adjustInsetsForWindow(
+ win, currentInsetsState);
+ if (com.android.window.flags.Flags.useCachedInsetsForDisplaySwitch()) {
+ assertEquals(prevInsetsState.peekSource(insetsId),
+ currentInsetsState.peekSource(insetsId));
+ }
// If screen is not fully turned on, then the cache should be preserved.
displayPolicy.screenTurnedOff(false /* acquireSleepToken */);