Merge "Cache decor insets for display switch" into udc-dev
This commit is contained in:
@@ -2962,6 +2962,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
|
||||
mDisplaySwitchTransitionLauncher.requestDisplaySwitchTransitionIfNeeded(mDisplayId,
|
||||
mInitialDisplayWidth, mInitialDisplayHeight, newWidth, newHeight);
|
||||
mDisplayRotation.physicalDisplayChanged();
|
||||
mDisplayPolicy.physicalDisplayChanged();
|
||||
}
|
||||
|
||||
// If there is an override set for base values - use it, otherwise use new values.
|
||||
@@ -2993,6 +2994,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
|
||||
reconfigureDisplayLocked();
|
||||
|
||||
if (physicalDisplayChanged) {
|
||||
mDisplayPolicy.physicalDisplayUpdated();
|
||||
mDisplaySwitchTransitionLauncher.onDisplayUpdated(currentRotation, getRotation(),
|
||||
getDisplayAreaInfo());
|
||||
}
|
||||
@@ -3042,7 +3044,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
|
||||
+ mBaseDisplayHeight + " on display:" + getDisplayId());
|
||||
}
|
||||
}
|
||||
if (mDisplayReady) {
|
||||
if (mDisplayReady && !mDisplayPolicy.shouldKeepCurrentDecorInsets()) {
|
||||
mDisplayPolicy.mDecorInsets.invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,6 +174,10 @@ public class DisplayPolicy {
|
||||
|
||||
private static final int INSETS_OVERRIDE_INDEX_INVALID = -1;
|
||||
|
||||
// TODO(b/266197298): Remove this by a more general protocol from the insets providers.
|
||||
private static final boolean USE_CACHED_INSETS_FOR_DISPLAY_SWITCH =
|
||||
SystemProperties.getBoolean("persist.wm.debug.cached_insets_switch", false);
|
||||
|
||||
private final WindowManagerService mService;
|
||||
private final Context mContext;
|
||||
private final Context mUiContext;
|
||||
@@ -218,6 +222,8 @@ public class DisplayPolicy {
|
||||
private SystemGesturesPointerEventListener mSystemGestures;
|
||||
|
||||
final DecorInsets mDecorInsets;
|
||||
/** Currently it can only be non-null when physical display switch happens. */
|
||||
private DecorInsets.Cache mCachedDecorInsets;
|
||||
|
||||
private volatile int mLidState = LID_ABSENT;
|
||||
private volatile int mDockMode = Intent.EXTRA_DOCK_STATE_UNDOCKED;
|
||||
@@ -1707,11 +1713,7 @@ public class DisplayPolicy {
|
||||
* Called when the configuration has changed, and it's safe to load new values from resources.
|
||||
*/
|
||||
public void onConfigurationChanged() {
|
||||
final DisplayRotation displayRotation = mDisplayContent.getDisplayRotation();
|
||||
|
||||
final Resources res = getCurrentUserResources();
|
||||
final int portraitRotation = displayRotation.getPortraitRotation();
|
||||
|
||||
mNavBarOpacityMode = res.getInteger(R.integer.config_navBarOpacityMode);
|
||||
mLeftGestureInset = mGestureNavigationSettingsObserver.getLeftSensitivity(res);
|
||||
mRightGestureInset = mGestureNavigationSettingsObserver.getRightSensitivity(res);
|
||||
@@ -1882,10 +1884,11 @@ public class DisplayPolicy {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "{nonDecorInsets=" + mNonDecorInsets
|
||||
+ ", configInsets=" + mConfigInsets
|
||||
+ ", nonDecorFrame=" + mNonDecorFrame
|
||||
+ ", configFrame=" + mConfigFrame + '}';
|
||||
final StringBuilder tmpSb = new StringBuilder(32);
|
||||
return "{nonDecorInsets=" + mNonDecorInsets.toShortString(tmpSb)
|
||||
+ ", configInsets=" + mConfigInsets.toShortString(tmpSb)
|
||||
+ ", nonDecorFrame=" + mNonDecorFrame.toShortString(tmpSb)
|
||||
+ ", configFrame=" + mConfigFrame.toShortString(tmpSb) + '}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1923,6 +1926,39 @@ public class DisplayPolicy {
|
||||
info.mNeedUpdate = true;
|
||||
}
|
||||
}
|
||||
|
||||
void setTo(DecorInsets src) {
|
||||
for (int i = mInfoForRotation.length - 1; i >= 0; i--) {
|
||||
mInfoForRotation[i].set(src.mInfoForRotation[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void dump(String prefix, PrintWriter pw) {
|
||||
for (int rotation = 0; rotation < mInfoForRotation.length; rotation++) {
|
||||
final DecorInsets.Info info = mInfoForRotation[rotation];
|
||||
pw.println(prefix + Surface.rotationToString(rotation) + "=" + info);
|
||||
}
|
||||
}
|
||||
|
||||
private static class Cache {
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
static final int ID_UPDATING_CONFIG = -1;
|
||||
final DecorInsets mDecorInsets;
|
||||
int mPreserveId;
|
||||
boolean mActive;
|
||||
|
||||
Cache(DisplayContent dc) {
|
||||
mDecorInsets = new DecorInsets(dc);
|
||||
}
|
||||
|
||||
boolean canPreserve() {
|
||||
return mPreserveId == ID_UPDATING_CONFIG || mDecorInsets.mDisplayContent
|
||||
.mTransitionController.inTransition(mPreserveId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1930,6 +1966,9 @@ public class DisplayPolicy {
|
||||
* call {@link DisplayContent#sendNewConfiguration()} if this method returns {@code true}.
|
||||
*/
|
||||
boolean updateDecorInsetsInfo() {
|
||||
if (shouldKeepCurrentDecorInsets()) {
|
||||
return false;
|
||||
}
|
||||
final DisplayFrames displayFrames = mDisplayContent.mDisplayFrames;
|
||||
final int rotation = displayFrames.mRotation;
|
||||
final int dw = displayFrames.mWidth;
|
||||
@@ -1940,6 +1979,10 @@ public class DisplayPolicy {
|
||||
if (newInfo.mConfigFrame.equals(currentInfo.mConfigFrame)) {
|
||||
return false;
|
||||
}
|
||||
if (mCachedDecorInsets != null && !mCachedDecorInsets.canPreserve()
|
||||
&& !mDisplayContent.isSleeping()) {
|
||||
mCachedDecorInsets = null;
|
||||
}
|
||||
mDecorInsets.invalidate();
|
||||
mDecorInsets.mInfoForRotation[rotation].set(newInfo);
|
||||
return true;
|
||||
@@ -1949,6 +1992,71 @@ public class DisplayPolicy {
|
||||
return mDecorInsets.get(rotation, w, h);
|
||||
}
|
||||
|
||||
/** Returns {@code true} to trust that {@link #mDecorInsets} already has the expected state. */
|
||||
boolean shouldKeepCurrentDecorInsets() {
|
||||
return mCachedDecorInsets != null && mCachedDecorInsets.mActive
|
||||
&& mCachedDecorInsets.canPreserve();
|
||||
}
|
||||
|
||||
void physicalDisplayChanged() {
|
||||
if (USE_CACHED_INSETS_FOR_DISPLAY_SWITCH) {
|
||||
updateCachedDecorInsets();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Caches the current insets and switches current insets to previous cached insets. This is to
|
||||
* reduce multiple display configuration changes if there are multiple insets provider windows
|
||||
* which may trigger {@link #updateDecorInsetsInfo()} individually.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
void updateCachedDecorInsets() {
|
||||
DecorInsets prevCache = null;
|
||||
if (mCachedDecorInsets == null) {
|
||||
mCachedDecorInsets = new DecorInsets.Cache(mDisplayContent);
|
||||
} else {
|
||||
prevCache = new DecorInsets(mDisplayContent);
|
||||
prevCache.setTo(mCachedDecorInsets.mDecorInsets);
|
||||
}
|
||||
// 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);
|
||||
// Switch current to previous cache.
|
||||
if (prevCache != null) {
|
||||
mDecorInsets.setTo(prevCache);
|
||||
mCachedDecorInsets.mActive = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
void physicalDisplayUpdated() {
|
||||
if (mCachedDecorInsets == null) {
|
||||
return;
|
||||
}
|
||||
if (!mDisplayContent.mTransitionController.isCollecting()) {
|
||||
// Unable to know when the display switch is finished.
|
||||
mCachedDecorInsets = null;
|
||||
return;
|
||||
}
|
||||
mCachedDecorInsets.mPreserveId =
|
||||
mDisplayContent.mTransitionController.getCollectingTransitionId();
|
||||
// The validator will run after the transition is finished. So if the insets are changed
|
||||
// during the transition, it can update to the latest state.
|
||||
mDisplayContent.mTransitionController.mStateValidators.add(() -> {
|
||||
// The insets provider client may defer to change its window until screen is on. So
|
||||
// only validate when awake to avoid the cache being always dropped.
|
||||
if (!mDisplayContent.isSleeping() && updateDecorInsetsInfo()) {
|
||||
Slog.d(TAG, "Insets changed after display switch transition");
|
||||
mDisplayContent.sendNewConfiguration();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@NavigationBarPosition
|
||||
int navigationBarPosition(int displayRotation) {
|
||||
if (mNavigationBar != null) {
|
||||
@@ -2626,9 +2734,10 @@ public class DisplayPolicy {
|
||||
pw.print(prefix); pw.print("mRemoteInsetsControllerControlsSystemBars=");
|
||||
pw.println(mRemoteInsetsControllerControlsSystemBars);
|
||||
pw.print(prefix); pw.println("mDecorInsetsInfo:");
|
||||
for (int rotation = 0; rotation < mDecorInsets.mInfoForRotation.length; rotation++) {
|
||||
final DecorInsets.Info info = mDecorInsets.mInfoForRotation[rotation];
|
||||
pw.println(prefixInner + Surface.rotationToString(rotation) + "=" + info);
|
||||
mDecorInsets.dump(prefixInner, pw);
|
||||
if (mCachedDecorInsets != null) {
|
||||
pw.print(prefix); pw.println("mCachedDecorInsets:");
|
||||
mCachedDecorInsets.mDecorInsets.dump(prefixInner, pw);
|
||||
}
|
||||
if (!CLIENT_TRANSIENT) {
|
||||
mSystemGestures.dump(pw, prefix);
|
||||
|
||||
@@ -431,6 +431,19 @@ class TransitionController {
|
||||
return inCollectingTransition(wc) || inPlayingTransition(wc);
|
||||
}
|
||||
|
||||
/** Returns {@code true} if the id matches a collecting or playing transition. */
|
||||
boolean inTransition(int syncId) {
|
||||
if (mCollectingTransition != null && mCollectingTransition.getSyncId() == syncId) {
|
||||
return true;
|
||||
}
|
||||
for (int i = mPlayingTransitions.size() - 1; i >= 0; --i) {
|
||||
if (mPlayingTransitions.get(i).getSyncId() == syncId) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** @return {@code true} if wc is in a participant subtree */
|
||||
boolean isTransitionOnDisplay(@NonNull DisplayContent dc) {
|
||||
if (mCollectingTransition != null && mCollectingTransition.isOnDisplay(dc)) {
|
||||
|
||||
@@ -300,6 +300,33 @@ public class DisplayPolicyTests extends WindowTestsBase {
|
||||
DisplayPolicy.isOverlappingWithNavBar(targetWin));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSwitchDecorInsets() {
|
||||
createNavBarWithProvidedInsets(mDisplayContent);
|
||||
final DisplayPolicy displayPolicy = mDisplayContent.getDisplayPolicy();
|
||||
final DisplayInfo info = mDisplayContent.getDisplayInfo();
|
||||
final int w = info.logicalWidth;
|
||||
final int h = info.logicalHeight;
|
||||
displayPolicy.updateDecorInsetsInfo();
|
||||
final Rect prevConfigFrame = new Rect(displayPolicy.getDecorInsetsInfo(info.rotation,
|
||||
info.logicalWidth, info.logicalHeight).mConfigFrame);
|
||||
|
||||
displayPolicy.updateCachedDecorInsets();
|
||||
mDisplayContent.updateBaseDisplayMetrics(w / 2, h / 2,
|
||||
info.logicalDensityDpi, info.physicalXDpi, info.physicalYDpi);
|
||||
// There is no previous cache. But the current state will be cached.
|
||||
assertFalse(displayPolicy.shouldKeepCurrentDecorInsets());
|
||||
|
||||
// Switch to original state.
|
||||
displayPolicy.updateCachedDecorInsets();
|
||||
mDisplayContent.updateBaseDisplayMetrics(w, h,
|
||||
info.logicalDensityDpi, info.physicalXDpi, info.physicalYDpi);
|
||||
assertTrue(displayPolicy.shouldKeepCurrentDecorInsets());
|
||||
// The current insets are restored from cache directly.
|
||||
assertEquals(prevConfigFrame, displayPolicy.getDecorInsetsInfo(info.rotation,
|
||||
info.logicalWidth, info.logicalHeight).mConfigFrame);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateDisplayConfigurationByDecor() {
|
||||
doReturn(NO_CUTOUT).when(mDisplayContent).calculateDisplayCutoutForRotation(anyInt());
|
||||
|
||||
Reference in New Issue
Block a user