Merge "Cache decor insets for display switch" into udc-dev am: 95dff23f60
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/22857217 Change-Id: Ibd3d99823f7f2f8b3174ae2a39395757064cd11f Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -2962,6 +2962,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
|
|||||||
mDisplaySwitchTransitionLauncher.requestDisplaySwitchTransitionIfNeeded(mDisplayId,
|
mDisplaySwitchTransitionLauncher.requestDisplaySwitchTransitionIfNeeded(mDisplayId,
|
||||||
mInitialDisplayWidth, mInitialDisplayHeight, newWidth, newHeight);
|
mInitialDisplayWidth, mInitialDisplayHeight, newWidth, newHeight);
|
||||||
mDisplayRotation.physicalDisplayChanged();
|
mDisplayRotation.physicalDisplayChanged();
|
||||||
|
mDisplayPolicy.physicalDisplayChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there is an override set for base values - use it, otherwise use new values.
|
// 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();
|
reconfigureDisplayLocked();
|
||||||
|
|
||||||
if (physicalDisplayChanged) {
|
if (physicalDisplayChanged) {
|
||||||
|
mDisplayPolicy.physicalDisplayUpdated();
|
||||||
mDisplaySwitchTransitionLauncher.onDisplayUpdated(currentRotation, getRotation(),
|
mDisplaySwitchTransitionLauncher.onDisplayUpdated(currentRotation, getRotation(),
|
||||||
getDisplayAreaInfo());
|
getDisplayAreaInfo());
|
||||||
}
|
}
|
||||||
@@ -3042,7 +3044,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
|
|||||||
+ mBaseDisplayHeight + " on display:" + getDisplayId());
|
+ mBaseDisplayHeight + " on display:" + getDisplayId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (mDisplayReady) {
|
if (mDisplayReady && !mDisplayPolicy.shouldKeepCurrentDecorInsets()) {
|
||||||
mDisplayPolicy.mDecorInsets.invalidate();
|
mDisplayPolicy.mDecorInsets.invalidate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -174,6 +174,10 @@ public class DisplayPolicy {
|
|||||||
|
|
||||||
private static final int INSETS_OVERRIDE_INDEX_INVALID = -1;
|
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 WindowManagerService mService;
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
private final Context mUiContext;
|
private final Context mUiContext;
|
||||||
@@ -218,6 +222,8 @@ public class DisplayPolicy {
|
|||||||
private SystemGesturesPointerEventListener mSystemGestures;
|
private SystemGesturesPointerEventListener mSystemGestures;
|
||||||
|
|
||||||
final DecorInsets mDecorInsets;
|
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 mLidState = LID_ABSENT;
|
||||||
private volatile int mDockMode = Intent.EXTRA_DOCK_STATE_UNDOCKED;
|
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.
|
* Called when the configuration has changed, and it's safe to load new values from resources.
|
||||||
*/
|
*/
|
||||||
public void onConfigurationChanged() {
|
public void onConfigurationChanged() {
|
||||||
final DisplayRotation displayRotation = mDisplayContent.getDisplayRotation();
|
|
||||||
|
|
||||||
final Resources res = getCurrentUserResources();
|
final Resources res = getCurrentUserResources();
|
||||||
final int portraitRotation = displayRotation.getPortraitRotation();
|
|
||||||
|
|
||||||
mNavBarOpacityMode = res.getInteger(R.integer.config_navBarOpacityMode);
|
mNavBarOpacityMode = res.getInteger(R.integer.config_navBarOpacityMode);
|
||||||
mLeftGestureInset = mGestureNavigationSettingsObserver.getLeftSensitivity(res);
|
mLeftGestureInset = mGestureNavigationSettingsObserver.getLeftSensitivity(res);
|
||||||
mRightGestureInset = mGestureNavigationSettingsObserver.getRightSensitivity(res);
|
mRightGestureInset = mGestureNavigationSettingsObserver.getRightSensitivity(res);
|
||||||
@@ -1882,10 +1884,11 @@ public class DisplayPolicy {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "{nonDecorInsets=" + mNonDecorInsets
|
final StringBuilder tmpSb = new StringBuilder(32);
|
||||||
+ ", configInsets=" + mConfigInsets
|
return "{nonDecorInsets=" + mNonDecorInsets.toShortString(tmpSb)
|
||||||
+ ", nonDecorFrame=" + mNonDecorFrame
|
+ ", configInsets=" + mConfigInsets.toShortString(tmpSb)
|
||||||
+ ", configFrame=" + mConfigFrame + '}';
|
+ ", nonDecorFrame=" + mNonDecorFrame.toShortString(tmpSb)
|
||||||
|
+ ", configFrame=" + mConfigFrame.toShortString(tmpSb) + '}';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1923,6 +1926,39 @@ public class DisplayPolicy {
|
|||||||
info.mNeedUpdate = true;
|
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}.
|
* call {@link DisplayContent#sendNewConfiguration()} if this method returns {@code true}.
|
||||||
*/
|
*/
|
||||||
boolean updateDecorInsetsInfo() {
|
boolean updateDecorInsetsInfo() {
|
||||||
|
if (shouldKeepCurrentDecorInsets()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
final DisplayFrames displayFrames = mDisplayContent.mDisplayFrames;
|
final DisplayFrames displayFrames = mDisplayContent.mDisplayFrames;
|
||||||
final int rotation = displayFrames.mRotation;
|
final int rotation = displayFrames.mRotation;
|
||||||
final int dw = displayFrames.mWidth;
|
final int dw = displayFrames.mWidth;
|
||||||
@@ -1940,6 +1979,10 @@ public class DisplayPolicy {
|
|||||||
if (newInfo.mConfigFrame.equals(currentInfo.mConfigFrame)) {
|
if (newInfo.mConfigFrame.equals(currentInfo.mConfigFrame)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (mCachedDecorInsets != null && !mCachedDecorInsets.canPreserve()
|
||||||
|
&& !mDisplayContent.isSleeping()) {
|
||||||
|
mCachedDecorInsets = null;
|
||||||
|
}
|
||||||
mDecorInsets.invalidate();
|
mDecorInsets.invalidate();
|
||||||
mDecorInsets.mInfoForRotation[rotation].set(newInfo);
|
mDecorInsets.mInfoForRotation[rotation].set(newInfo);
|
||||||
return true;
|
return true;
|
||||||
@@ -1949,6 +1992,71 @@ public class DisplayPolicy {
|
|||||||
return mDecorInsets.get(rotation, w, h);
|
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
|
@NavigationBarPosition
|
||||||
int navigationBarPosition(int displayRotation) {
|
int navigationBarPosition(int displayRotation) {
|
||||||
if (mNavigationBar != null) {
|
if (mNavigationBar != null) {
|
||||||
@@ -2626,9 +2734,10 @@ public class DisplayPolicy {
|
|||||||
pw.print(prefix); pw.print("mRemoteInsetsControllerControlsSystemBars=");
|
pw.print(prefix); pw.print("mRemoteInsetsControllerControlsSystemBars=");
|
||||||
pw.println(mRemoteInsetsControllerControlsSystemBars);
|
pw.println(mRemoteInsetsControllerControlsSystemBars);
|
||||||
pw.print(prefix); pw.println("mDecorInsetsInfo:");
|
pw.print(prefix); pw.println("mDecorInsetsInfo:");
|
||||||
for (int rotation = 0; rotation < mDecorInsets.mInfoForRotation.length; rotation++) {
|
mDecorInsets.dump(prefixInner, pw);
|
||||||
final DecorInsets.Info info = mDecorInsets.mInfoForRotation[rotation];
|
if (mCachedDecorInsets != null) {
|
||||||
pw.println(prefixInner + Surface.rotationToString(rotation) + "=" + info);
|
pw.print(prefix); pw.println("mCachedDecorInsets:");
|
||||||
|
mCachedDecorInsets.mDecorInsets.dump(prefixInner, pw);
|
||||||
}
|
}
|
||||||
if (!CLIENT_TRANSIENT) {
|
if (!CLIENT_TRANSIENT) {
|
||||||
mSystemGestures.dump(pw, prefix);
|
mSystemGestures.dump(pw, prefix);
|
||||||
|
|||||||
@@ -431,6 +431,19 @@ class TransitionController {
|
|||||||
return inCollectingTransition(wc) || inPlayingTransition(wc);
|
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 */
|
/** @return {@code true} if wc is in a participant subtree */
|
||||||
boolean isTransitionOnDisplay(@NonNull DisplayContent dc) {
|
boolean isTransitionOnDisplay(@NonNull DisplayContent dc) {
|
||||||
if (mCollectingTransition != null && mCollectingTransition.isOnDisplay(dc)) {
|
if (mCollectingTransition != null && mCollectingTransition.isOnDisplay(dc)) {
|
||||||
|
|||||||
@@ -300,6 +300,33 @@ public class DisplayPolicyTests extends WindowTestsBase {
|
|||||||
DisplayPolicy.isOverlappingWithNavBar(targetWin));
|
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
|
@Test
|
||||||
public void testUpdateDisplayConfigurationByDecor() {
|
public void testUpdateDisplayConfigurationByDecor() {
|
||||||
doReturn(NO_CUTOUT).when(mDisplayContent).calculateDisplayCutoutForRotation(anyInt());
|
doReturn(NO_CUTOUT).when(mDisplayContent).calculateDisplayCutoutForRotation(anyInt());
|
||||||
|
|||||||
Reference in New Issue
Block a user