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

Commit c8d60387 authored by Jorim Jaggi's avatar Jorim Jaggi
Browse files

A brave new world for window insets (4/n)

Rework how new window insets are dispatched: Send it to the
controller, controller applies the local visibility overrides and
then dispatch it without doing a full layout.

Bug: 118118435
Change-Id: I0d3070d2c46c3af6236e98b858bed5b463da6053
parent f3867a70
Loading
Loading
Loading
Loading
+24 −2
Original line number Diff line number Diff line
@@ -38,9 +38,14 @@ public class InsetsController implements WindowInsetsController {
    private final InsetsState mState = new InsetsState();
    private final Rect mFrame = new Rect();
    private final SparseArray<InsetsSourceConsumer> mSourceConsumers = new SparseArray<>();
    private final ViewRootImpl mViewRoot;

    private final SparseArray<InsetsSourceControl> mTmpControlArray = new SparseArray<>();

    public InsetsController(ViewRootImpl viewRoot) {
        mViewRoot = viewRoot;
    }

    void onFrameChanged(Rect frame) {
        mFrame.set(frame);
    }
@@ -49,8 +54,14 @@ public class InsetsController implements WindowInsetsController {
        return mState;
    }

    public void setState(InsetsState state) {
    boolean onStateChanged(InsetsState state) {
        if (mState.equals(state)) {
            return false;
        }
        mState.set(state);
        applyLocalVisibilityOverride();
        mViewRoot.notifyInsetsChanged();
        return true;
    }

    /**
@@ -105,17 +116,28 @@ public class InsetsController implements WindowInsetsController {
        }
    }

    private void applyLocalVisibilityOverride() {
        for (int i = mSourceConsumers.size() - 1; i >= 0; i--) {
            final InsetsSourceConsumer controller = mSourceConsumers.valueAt(i);
            controller.applyLocalVisibilityOverride();
        }
    }

    @VisibleForTesting
    public @NonNull InsetsSourceConsumer getSourceConsumer(@InternalInsetType int type) {
        InsetsSourceConsumer controller = mSourceConsumers.get(type);
        if (controller != null) {
            return controller;
        }
        controller = new InsetsSourceConsumer(type, mState, Transaction::new);
        controller = new InsetsSourceConsumer(type, mState, Transaction::new, this);
        mSourceConsumers.put(type, controller);
        return controller;
    }

    void notifyVisibilityChanged() {
        mViewRoot.notifyInsetsChanged();
    }

    void dump(String prefix, PrintWriter pw) {
        pw.println(prefix); pw.println("InsetsController:");
        mState.dump(prefix + "  ", pw);
+23 −8
Original line number Diff line number Diff line
@@ -33,27 +33,31 @@ public class InsetsSourceConsumer {
    private final Supplier<Transaction> mTransactionSupplier;
    private final @InternalInsetType int mType;
    private final InsetsState mState;
    private @Nullable InsetsSourceControl mControl;
    private final InsetsController mController;
    private @Nullable InsetsSourceControl mSourceControl;
    private boolean mHidden;

    public InsetsSourceConsumer(@InternalInsetType int type, InsetsState state,
            Supplier<Transaction> transactionSupplier) {
            Supplier<Transaction> transactionSupplier, InsetsController controller) {
        mType = type;
        mState = state;
        mTransactionSupplier = transactionSupplier;
        mController = controller;
    }

    public void setControl(@Nullable InsetsSourceControl control) {
        if (mControl == control) {
        if (mSourceControl == control) {
            return;
        }
        mControl = control;
        mSourceControl = control;
        applyHiddenToControl();
        applyLocalVisibilityOverride();
        mController.notifyVisibilityChanged();
    }

    @VisibleForTesting
    public InsetsSourceControl getControl() {
        return mControl;
        return mSourceControl;
    }

    int getType() {
@@ -70,25 +74,36 @@ public class InsetsSourceConsumer {
        setHidden(true);
    }

    void applyLocalVisibilityOverride() {

        // If we don't have control, we are not able to change the visibility.
        if (mSourceControl == null) {
            return;
        }
        mState.getSource(mType).setVisible(!mHidden);
    }

    private void setHidden(boolean hidden) {
        if (mHidden == hidden) {
            return;
        }
        mHidden = hidden;
        applyHiddenToControl();
        applyLocalVisibilityOverride();
        mController.notifyVisibilityChanged();
    }

    private void applyHiddenToControl() {
        if (mControl == null) {
        if (mSourceControl == null) {
            return;
        }

        // TODO: Animation
        final Transaction t = mTransactionSupplier.get();
        if (mHidden) {
            t.hide(mControl.getLeash());
            t.hide(mSourceControl.getLeash());
        } else {
            t.show(mControl.getLeash());
            t.show(mSourceControl.getLeash());
        }
        t.apply();
    }
+21 −27
Original line number Diff line number Diff line
@@ -464,7 +464,7 @@ public final class ViewRootImpl implements ViewParent,
    final DisplayCutout.ParcelableWrapper mPendingDisplayCutout =
            new DisplayCutout.ParcelableWrapper(DisplayCutout.NO_CUTOUT);
    boolean mPendingAlwaysConsumeNavBar;
    private InsetsState mPendingInsets = new InsetsState();
    private InsetsState mTempInsets = new InsetsState();
    final ViewTreeObserver.InternalInsetsInfo mLastGivenInsets
            = new ViewTreeObserver.InternalInsetsInfo();

@@ -552,7 +552,7 @@ public final class ViewRootImpl implements ViewParent,
            InputEventConsistencyVerifier.isInstrumentationEnabled() ?
                    new InputEventConsistencyVerifier(this, 0) : null;

    private final InsetsController mInsetsController = new InsetsController();
    private final InsetsController mInsetsController = new InsetsController(this);

    static final class SystemUiVisibilityInfo {
        int seq;
@@ -823,7 +823,7 @@ public final class ViewRootImpl implements ViewParent,
                            getHostVisibility(), mDisplay.getDisplayId(), mTmpFrame,
                            mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
                            mAttachInfo.mOutsets, mAttachInfo.mDisplayCutout, mInputChannel,
                            mInsetsController.getState());
                            mTempInsets);
                    setFrame(mTmpFrame);
                } catch (RemoteException e) {
                    mAdded = false;
@@ -851,7 +851,7 @@ public final class ViewRootImpl implements ViewParent,
                mAttachInfo.mAlwaysConsumeNavBar =
                        (res & WindowManagerGlobal.ADD_FLAG_ALWAYS_CONSUME_NAV_BAR) != 0;
                mPendingAlwaysConsumeNavBar = mAttachInfo.mAlwaysConsumeNavBar;
                mPendingInsets = mInsetsController.getState();
                mInsetsController.onStateChanged(mTempInsets);
                if (DEBUG_LAYOUT) Log.v(mTag, "Added window " + mWindow);
                if (res < WindowManagerGlobal.ADD_OKAY) {
                    mAttachInfo.mRootView = null;
@@ -1342,6 +1342,19 @@ public final class ViewRootImpl implements ViewParent,
        scheduleTraversals();
    }

    void notifyInsetsChanged() {
        if (!USE_NEW_INSETS) {
            return;
        }
        mApplyInsetsRequested = true;

        // If this changes during traversal, no need to schedule another one as it will dispatch it
        // during the current traversal.
        if (!mIsInTraversal) {
            scheduleTraversals();
        }
    }

    @Override
    public void requestLayout() {
        if (!mHandlingLayoutInLayoutRequest) {
@@ -2027,9 +2040,6 @@ public final class ViewRootImpl implements ViewParent,
                if (mPendingAlwaysConsumeNavBar != mAttachInfo.mAlwaysConsumeNavBar) {
                    insetsChanged = true;
                }
                if (!mPendingInsets.equals(mInsetsController.getState())) {
                    insetsChanged = true;
                }
                if (lp.width == ViewGroup.LayoutParams.WRAP_CONTENT
                        || lp.height == ViewGroup.LayoutParams.WRAP_CONTENT) {
                    windowSizeMayChange = true;
@@ -2223,8 +2233,6 @@ public final class ViewRootImpl implements ViewParent,
                        mAttachInfo.mStableInsets);
                final boolean cutoutChanged = !mPendingDisplayCutout.equals(
                        mAttachInfo.mDisplayCutout);
                final boolean insetsStateChanged = !mPendingInsets.equals(
                        mInsetsController.getState());
                final boolean outsetsChanged = !mPendingOutsets.equals(mAttachInfo.mOutsets);
                final boolean surfaceSizeChanged = (relayoutResult
                        & WindowManagerGlobal.RELAYOUT_RES_SURFACE_RESIZED) != 0;
@@ -2262,10 +2270,6 @@ public final class ViewRootImpl implements ViewParent,
                    mAttachInfo.mAlwaysConsumeNavBar = mPendingAlwaysConsumeNavBar;
                    contentInsetsChanged = true;
                }
                if (insetsStateChanged) {
                    mInsetsController.setState(mPendingInsets);
                    contentInsetsChanged = true;
                }
                if (contentInsetsChanged || mLastSystemUiVisibility !=
                        mAttachInfo.mSystemUiVisibility || mApplyInsetsRequested
                        || mLastOverscanRequested != mAttachInfo.mOverscanRequested
@@ -4378,22 +4382,12 @@ public final class ViewRootImpl implements ViewParent,
                    }
                    break;
                case MSG_INSETS_CHANGED:
                    mPendingInsets = (InsetsState) msg.obj;

                    // TODO: Full traversal not needed here.
                    if (USE_NEW_INSETS) {
                        requestLayout();
                    }
                    mInsetsController.onStateChanged((InsetsState) msg.obj);
                    break;
                case MSG_INSETS_CONTROL_CHANGED: {
                    SomeArgs args = (SomeArgs) msg.obj;
                    mPendingInsets = (InsetsState) args.arg1;
                    mInsetsController.onControlsChanged((InsetsSourceControl[]) args.arg2);

                    // TODO: Full traversal not necessarily needed here.
                    if (USE_NEW_INSETS) {
                        requestLayout();
                    }
                    mInsetsController.onStateChanged((InsetsState) args.arg1);
                    break;
                }
                case MSG_WINDOW_MOVED:
@@ -6794,7 +6788,7 @@ public final class ViewRootImpl implements ViewParent,
                insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0, frameNumber,
                mTmpFrame, mPendingOverscanInsets, mPendingContentInsets, mPendingVisibleInsets,
                mPendingStableInsets, mPendingOutsets, mPendingBackDropFrame, mPendingDisplayCutout,
                mPendingMergedConfiguration, mSurface, mPendingInsets);
                mPendingMergedConfiguration, mSurface, mTempInsets);

        mPendingAlwaysConsumeNavBar =
                (relayoutResult & WindowManagerGlobal.RELAYOUT_RES_CONSUME_ALWAYS_NAV_BAR) != 0;
@@ -6811,7 +6805,7 @@ public final class ViewRootImpl implements ViewParent,
            mTranslator.translateRectInScreenToAppWindow(mPendingStableInsets);
        }
        setFrame(mTmpFrame);

        mInsetsController.onStateChanged(mTempInsets);
        return relayoutResult;
    }

+2 −1
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package android.view;
import static android.view.InsetsState.TYPE_TOP_BAR;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNull;
import static org.mockito.Mockito.mock;

import android.platform.test.annotations.Presubmit;
import android.support.test.filters.FlakyTest;
@@ -33,7 +34,7 @@ import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
public class InsetsControllerTest {

    private InsetsController mController = new InsetsController();
    private InsetsController mController = new InsetsController(mock(ViewRootImpl.class));

    private SurfaceSession mSession = new SurfaceSession();
    private SurfaceControl mLeash;
+1 −1
Original line number Diff line number Diff line
@@ -53,7 +53,7 @@ public class InsetsSourceConsumerTest {
                .setName("testSurface")
                .build();
        mConsumer = new InsetsSourceConsumer(TYPE_TOP_BAR, new InsetsState(),
                () -> mMockTransaction);
                () -> mMockTransaction, mMockController);
        mConsumer.setControl(new InsetsSourceControl(TYPE_TOP_BAR, mLeash));
    }