Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e694f2f9 authored by Riddle Hsu's avatar Riddle Hsu Committed by Automerger Merge Worker
Browse files

Merge "Cache decor insets for display switch" into udc-dev am: 95dff23f

parents 76a1b10a 95dff23f
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -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();
        }
    }
+120 −11
Original line number Diff line number Diff line
@@ -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);
+13 −0
Original line number Diff line number Diff line
@@ -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)) {
+27 −0
Original line number Diff line number Diff line
@@ -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());