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

Commit de92990e authored by Riddle Hsu's avatar Riddle Hsu Committed by Android (Google) Code Review
Browse files

Merge "Use cached insets for display switch" into main

parents b5e56d37 3148276a
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -50,6 +50,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"
+58 −0
Original line number Diff line number Diff line
@@ -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,23 +2235,59 @@ 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
+1 −0
Original line number Diff line number Diff line
@@ -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);
    }

+25 −1
Original line number Diff line number Diff line
@@ -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 */);