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

Commit 5a6f68d8 authored by Automerger Merge Worker's avatar Automerger Merge Worker
Browse files

Merge "Prevent causing insets if the system bar is shown forcibly" into rvc-dev am: b979998e

Change-Id: I3291b59c72cb3644c60bdee6dec57dce57179aac
parents 7dff0776 b979998e
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -342,6 +342,20 @@ public class InsetsState implements Parcelable {
        }
    }

    /**
     * A shortcut for setting the visibility of the source.
     *
     * @param type The {@link InternalInsetsType} of the source to set the visibility
     * @param referenceState The {@link InsetsState} for reference
     */
    public void setSourceVisible(@InternalInsetsType int type, InsetsState referenceState) {
        InsetsSource source = mSources.get(type);
        InsetsSource referenceSource = referenceState.mSources.get(type);
        if (source != null && referenceSource != null) {
            source.setVisible(referenceSource.isVisible());
        }
    }

    public void set(InsetsState other) {
        set(other, false /* copySources */);
    }
+6 −1
Original line number Diff line number Diff line
@@ -23,7 +23,12 @@ import android.view.WindowInsets.Type.InsetsType;
 * Generalization of an object that can control insets state.
 */
interface InsetsControlTarget {
    void notifyInsetsControlChanged();

    /**
     * Notifies the control target that the insets control has changed.
     */
    default void notifyInsetsControlChanged() {
    };

    /**
     * @return {@link WindowState} of this target, if any.
+42 −44
Original line number Diff line number Diff line
@@ -57,9 +57,11 @@ class InsetsPolicy {
    private final InsetsStateController mStateController;
    private final DisplayContent mDisplayContent;
    private final DisplayPolicy mPolicy;
    private final TransientControlTarget mTransientControlTarget = new TransientControlTarget();
    private final IntArray mShowingTransientTypes = new IntArray();

    /** For resetting visibilities of insets sources. */
    private final InsetsControlTarget mDummyControlTarget = new InsetsControlTarget() { };

    private WindowState mFocusedWin;
    private BarWindow mStatusBar = new BarWindow(StatusBarManager.WINDOW_STATUS_BAR);
    private BarWindow mNavBar = new BarWindow(StatusBarManager.WINDOW_NAVIGATION_BAR);
@@ -143,12 +145,15 @@ class InsetsPolicy {
     */
    InsetsState getInsetsForDispatch(WindowState target) {
        InsetsState state = mStateController.getInsetsForDispatch(target);
        if (mShowingTransientTypes.size() == 0) {
            return state;
        }
        for (int i = mShowingTransientTypes.size() - 1; i >= 0; i--) {
            state.setSourceVisible(mShowingTransientTypes.get(i), false);
        }
        if (mFocusedWin != null && getStatusControlTarget(mFocusedWin) == mDummyControlTarget) {
            state.setSourceVisible(ITYPE_STATUS_BAR, mFocusedWin.getRequestedInsetsState());
        }
        if (mFocusedWin != null && getNavControlTarget(mFocusedWin) == mDummyControlTarget) {
            state.setSourceVisible(ITYPE_NAVIGATION_BAR, mFocusedWin.getRequestedInsetsState());
        }
        return state;
    }

@@ -194,71 +199,71 @@ class InsetsPolicy {

    private @Nullable InsetsControlTarget getFakeStatusControlTarget(
            @Nullable WindowState focused) {
        if (mShowingTransientTypes.indexOf(ITYPE_STATUS_BAR) != -1) {
            return focused;
        }
        return null;
        return getStatusControlTarget(focused) == mDummyControlTarget ? focused : null;
    }

    private @Nullable InsetsControlTarget getFakeNavControlTarget(@Nullable WindowState focused) {
        if (mShowingTransientTypes.indexOf(ITYPE_NAVIGATION_BAR) != -1) {
            return focused;
        }
        return null;
        return getNavControlTarget(focused) == mDummyControlTarget ? focused : null;
    }

    private @Nullable InsetsControlTarget getStatusControlTarget(@Nullable WindowState focusedWin) {
        if (mShowingTransientTypes.indexOf(ITYPE_STATUS_BAR) != -1) {
            return mTransientControlTarget;
            return mDummyControlTarget;
        }
        if (focusedWin == mPolicy.getNotificationShade()) {
            // Notification shade has control anyways, no reason to force anything.
            return focusedWin;
        }
        if (areSystemBarsForciblyVisible() || isKeyguardOrStatusBarForciblyVisible()) {
        if (forceShowsSystemBarsForWindowingMode()) {
            // Status bar is forcibly shown for the windowing mode which is a steady state.
            // We don't want the client to control the status bar, and we will dispatch the real
            // visibility of status bar to the client.
            return null;
        }
        if (forceShowsStatusBarTransiently()) {
            // Status bar is forcibly shown transiently, and its new visibility won't be
            // dispatched to the client so that we can keep the layout stable. We will dispatch the
            // fake control to the client, so that it can re-show the bar during this scenario.
            return mDummyControlTarget;
        }
        return focusedWin;
    }

    private @Nullable InsetsControlTarget getNavControlTarget(@Nullable WindowState focusedWin) {
        if (mShowingTransientTypes.indexOf(ITYPE_NAVIGATION_BAR) != -1) {
            return mTransientControlTarget;
            return mDummyControlTarget;
        }
        if (focusedWin == mPolicy.getNotificationShade()) {
            // Notification shade has control anyways, no reason to force anything.
            return focusedWin;
        }
        if (areSystemBarsForciblyVisible() || isNavBarForciblyVisible()) {
        if (forceShowsSystemBarsForWindowingMode()) {
            // Navigation bar is forcibly shown for the windowing mode which is a steady state.
            // We don't want the client to control the navigation bar, and we will dispatch the real
            // visibility of navigation bar to the client.
            return null;
        }
        if (forceShowsNavigationBarTransiently()) {
            // Navigation bar is forcibly shown transiently, and its new visibility won't be
            // dispatched to the client so that we can keep the layout stable. We will dispatch the
            // fake control to the client, so that it can re-show the bar during this scenario.
            return mDummyControlTarget;
        }
        return focusedWin;
    }

    private boolean isKeyguardOrStatusBarForciblyVisible() {
        final WindowState statusBar = mPolicy.getStatusBar();
        if (statusBar != null) {
            // TODO(b/118118435): Pretend to the app that it's still able to control it?
            if ((statusBar.mAttrs.privateFlags & PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR) != 0) {
                return true;
            }
        }
        return false;
    private boolean forceShowsStatusBarTransiently() {
        final WindowState win = mPolicy.getStatusBar();
        return win != null && (win.mAttrs.privateFlags & PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR) != 0;
    }

    private boolean isNavBarForciblyVisible() {
        final WindowState notificationShade = mPolicy.getNotificationShade();
        if (notificationShade == null) {
            return false;
        }
        if ((notificationShade.mAttrs.privateFlags
                & PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION) != 0) {
            return true;
        }
        return false;
    private boolean forceShowsNavigationBarTransiently() {
        final WindowState win = mPolicy.getNotificationShade();
        return win != null
                && (win.mAttrs.privateFlags & PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION) != 0;
    }

    private boolean areSystemBarsForciblyVisible() {
    private boolean forceShowsSystemBarsForWindowingMode() {
        final boolean isDockedStackVisible =
                mDisplayContent.isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
        final boolean isFreeformStackVisible =
@@ -279,7 +284,7 @@ class InsetsPolicy {
        for (int i = showingTransientTypes.size() - 1; i >= 0; i--) {
            InsetsSourceProvider provider =
                    mStateController.getSourceProvider(showingTransientTypes.get(i));
            InsetsSourceControl control = provider.getControl(mTransientControlTarget);
            InsetsSourceControl control = provider.getControl(mDummyControlTarget);
            if (control == null || control.getLeash() == null) {
                continue;
            }
@@ -412,11 +417,4 @@ class InsetsPolicy {
            }
        }
    }

    private class TransientControlTarget implements InsetsControlTarget {

        @Override
        public void notifyInsetsControlChanged() {
        }
    }
}
+1 −2
Original line number Diff line number Diff line
@@ -61,8 +61,7 @@ class InsetsStateController {
            w.notifyInsetsChanged();
        }
    };
    private final InsetsControlTarget mEmptyImeControlTarget = () -> {
    };
    private final InsetsControlTarget mEmptyImeControlTarget = new InsetsControlTarget() { };

    InsetsStateController(DisplayContent displayContent) {
        mDisplayContent = displayContent;
+4 −5
Original line number Diff line number Diff line
@@ -120,7 +120,6 @@ public class InsetsPolicyTest extends WindowTestsBase {
        assertNull(controls);
    }

    // TODO: adjust this test if we pretend to the app that it's still able to control it.
    @Test
    public void testControlsForDispatch_forceStatusBarVisible() {
        addWindow(TYPE_STATUS_BAR, "statusBar").mAttrs.privateFlags |=
@@ -129,9 +128,9 @@ public class InsetsPolicyTest extends WindowTestsBase {

        final InsetsSourceControl[] controls = addAppWindowAndGetControlsForDispatch();

        // The app must not control the status bar.
        // The focused app window can control both system bars.
        assertNotNull(controls);
        assertEquals(1, controls.length);
        assertEquals(2, controls.length);
    }

    @Test
@@ -143,9 +142,9 @@ public class InsetsPolicyTest extends WindowTestsBase {

        final InsetsSourceControl[] controls = addAppWindowAndGetControlsForDispatch();

        // The app must not control the navigation bar.
        // The focused app window can control both system bars.
        assertNotNull(controls);
        assertEquals(1, controls.length);
        assertEquals(2, controls.length);
    }

    @Test