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

Commit cfebf43a authored by Tiger's avatar Tiger
Browse files

Describe requested visibilities in public types (1/n: client side)

We have been using InsetsVisibilities to store the requested visibility
of each internal type. But since the public caller cannot access the
internal insets types, we don’t need to store individual requested
visibilities of the internal types. We can just use an integer to
describe the requested visibilities of all public types. This is a step
of removing the internal insets types.

This CL is one of the many to achieve the task, which:

- defines "@InsetsType int mRequestedVisibleTypes" in InsetsController,
  (It will replace "InsetsVisibilities mRequestedVisibilities".)

- refactors the logic of updating/dispatching system UI visibility, and

- removes ITYPEs from DecorView.

Bug: 253420890
Bug: 234093736
Test: atest WindowInsetsControllerTests
Change-Id: Ib3d0eeb40db0943d150eec45b9c5a6df496da5d2
parent 9157854c
Loading
Loading
Loading
Loading
+60 −10
Original line number Diff line number Diff line
@@ -102,10 +102,16 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
        void applySurfaceParams(final SyncRtSurfaceTransactionApplier.SurfaceParams... params);

        /**
         * @see ViewRootImpl#updateCompatSysUiVisibility(int, boolean, boolean)
         * TODO (b/253420890): Remove this after removing all the implementations.
         */
        void updateCompatSysUiVisibility(@InternalInsetsType int type, boolean visible,
                boolean hasControl);
        default void updateCompatSysUiVisibility(@InternalInsetsType int type, boolean visible,
                boolean hasControl) { }

        /**
         * @see ViewRootImpl#updateCompatSysUiVisibility(int, int, int)
         */
        default void updateCompatSysUiVisibility(@InsetsType int visibleTypes,
                @InsetsType int requestedVisibleTypes, @InsetsType int controllableTypes) { }

        /**
         * Called when the requested visibilities of insets have been modified by the client.
@@ -593,6 +599,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
    private boolean mStartingAnimation;
    private int mCaptionInsetsHeight = 0;
    private boolean mAnimationsDisabled;
    private boolean mCompatSysUiVisibilityStaled;

    private final Runnable mPendingControlTimeout = this::abortPendingImeControlRequest;
    private final ArrayList<OnControllableInsetsChangedListener> mControllableInsetsChangedListeners
@@ -604,6 +611,15 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
    /** Set of inset types which cannot be controlled by the user animation */
    private @InsetsType int mDisabledUserAnimationInsetsTypes;

    /** Set of inset types which are visible */
    private @InsetsType int mVisibleTypes = WindowInsets.Type.defaultVisible();

    /** Set of inset types which are requested visible */
    private @InsetsType int mRequestedVisibleTypes = WindowInsets.Type.defaultVisible();

    /** Set of inset types that we have controls of */
    private @InsetsType int mControllableTypes;

    private final Runnable mInvokeControllableInsetsChangedListeners =
            this::invokeControllableInsetsChangedListeners;

@@ -687,8 +703,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
    }

    @Override
    public boolean isRequestedVisible(int type) {
        return getSourceConsumer(type).isRequestedVisible();
    public @InsetsType int getRequestedVisibleTypes() {
        return mRequestedVisibleTypes;
    }

    public InsetsState getLastDispatchedState() {
@@ -715,6 +731,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
        final InsetsState lastState = new InsetsState(mState, true /* copySources */);
        updateState(state);
        applyLocalVisibilityOverride();
        updateCompatSysUiVisibility();

        if (!mState.equals(lastState, false /* excludingCaptionInsets */,
                true /* excludeInvisibleIme */)) {
@@ -727,14 +744,15 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation

    private void updateState(InsetsState newState) {
        mState.set(newState, 0 /* types */);
        @InsetsType int visibleTypes = 0;
        @InsetsType int disabledUserAnimationTypes = 0;
        @InsetsType int[] cancelledUserAnimationTypes = {0};
        for (@InternalInsetsType int type = 0; type < InsetsState.SIZE; type++) {
            InsetsSource source = newState.peekSource(type);
            if (source == null) continue;
            @AnimationType int animationType = getAnimationType(type);
            if (!source.isUserControllable()) {
            @InsetsType int insetsType = toPublicType(type);
            if (!source.isUserControllable()) {
                // The user animation is not allowed when visible frame is empty.
                disabledUserAnimationTypes |= insetsType;
                if (animationType == ANIMATION_TYPE_USER) {
@@ -744,6 +762,15 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
                }
            }
            getSourceConsumer(type).updateSource(source, animationType);
            if (source.isVisible()) {
                visibleTypes |= insetsType;
            }
        }
        if (mVisibleTypes != visibleTypes) {
            if (WindowInsets.Type.hasCompatSystemBars(mVisibleTypes ^ visibleTypes)) {
                mCompatSysUiVisibilityStaled = true;
            }
            mVisibleTypes = visibleTypes;
        }
        for (@InternalInsetsType int type = 0; type < InsetsState.SIZE; type++) {
            // Only update the server side insets here.
@@ -868,6 +895,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
            }
        }

        @InsetsType int controllableTypes = 0;
        boolean requestedVisibilityStale = false;
        final int[] showTypes = new int[1];
        final int[] hideTypes = new int[1];
@@ -888,6 +916,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
            final @InternalInsetsType int type = control.getType();
            final InsetsSourceConsumer consumer = getSourceConsumer(type);
            consumer.setControl(control, showTypes, hideTypes);
            controllableTypes |= InsetsState.toPublicType(type);

            if (!requestedVisibilityStale) {
                final boolean requestedVisible = consumer.isRequestedVisible();
@@ -927,6 +956,13 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
            applyAnimation(hideTypes[0], false /* show */, false /* fromIme */);
        }

        if (mControllableTypes != controllableTypes) {
            if (WindowInsets.Type.hasCompatSystemBars(mControllableTypes ^ controllableTypes)) {
                mCompatSysUiVisibilityStaled = true;
            }
            mControllableTypes = controllableTypes;
        }

        // InsetsSourceConsumer#setControl might change the requested visibility.
        updateRequestedVisibilities();
    }
@@ -1386,11 +1422,14 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
    }

    /**
     * @see ViewRootImpl#updateCompatSysUiVisibility(int, boolean, boolean)
     * @see ViewRootImpl#updateCompatSysUiVisibility(int, int, int)
     */
    public void updateCompatSysUiVisibility(@InternalInsetsType int type, boolean visible,
            boolean hasControl) {
        mHost.updateCompatSysUiVisibility(type, visible, hasControl);
    public void updateCompatSysUiVisibility() {
        if (mCompatSysUiVisibilityStaled) {
            mCompatSysUiVisibilityStaled = false;
            mHost.updateCompatSysUiVisibility(
                    mVisibleTypes, mRequestedVisibleTypes, mControllableTypes);
        }
    }

    /**
@@ -1421,12 +1460,23 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
    @VisibleForTesting
    public void onRequestedVisibilityChanged(InsetsSourceConsumer consumer) {
        mRequestedVisibilityChanged.add(consumer);
        final @InsetsType int type = InsetsState.toPublicType(consumer.getType());
        final int requestedVisibleTypes = consumer.isRequestedVisible()
                ? mRequestedVisibleTypes | type
                : mRequestedVisibleTypes & ~type;
        if (mRequestedVisibleTypes != requestedVisibleTypes) {
            mRequestedVisibleTypes = requestedVisibleTypes;
            if (WindowInsets.Type.hasCompatSystemBars(type)) {
                mCompatSysUiVisibilityStaled = true;
            }
        }
    }

    /**
     * Sends the requested visibilities to window manager if any of them is changed.
     */
    private void updateRequestedVisibilities() {
        updateCompatSysUiVisibility();
        boolean changed = false;
        for (int i = mRequestedVisibilityChanged.size() - 1; i >= 0; i--) {
            final InsetsSourceConsumer consumer = mRequestedVisibilityChanged.valueAt(i);
+0 −36
Original line number Diff line number Diff line
@@ -34,7 +34,6 @@ import static com.android.internal.annotations.VisibleForTesting.Visibility.PACK
import android.annotation.IntDef;
import android.annotation.Nullable;
import android.graphics.Rect;
import android.util.ArraySet;
import android.util.Log;
import android.util.proto.ProtoOutputStream;
import android.view.InsetsState.InternalInsetsType;
@@ -149,9 +148,6 @@ public class InsetsSourceConsumer {
                source.setVisible(serverVisibility);
                mController.notifyVisibilityChanged();
            }

            // For updateCompatSysUiVisibility
            applyLocalVisibilityOverride();
        } else {
            final boolean requestedVisible = isRequestedVisibleAwaitingControl();
            final SurfaceControl oldLeash = lastControl != null ? lastControl.getLeash() : null;
@@ -259,8 +255,6 @@ public class InsetsSourceConsumer {
                    mController.getHost().getInputMethodManager(), null /* icProto */);
        }

        updateCompatSysUiVisibility(hasControl, source, isVisible);

        // If we don't have control, we are not able to change the visibility.
        if (!hasControl) {
            if (DEBUG) Log.d(TAG, "applyLocalVisibilityOverride: No control in "
@@ -277,36 +271,6 @@ public class InsetsSourceConsumer {
        return true;
    }

    private void updateCompatSysUiVisibility(boolean hasControl, InsetsSource source,
            boolean visible) {
        final @InsetsType int publicType = InsetsState.toPublicType(mType);
        if (publicType != WindowInsets.Type.statusBars()
                && publicType != WindowInsets.Type.navigationBars()) {
            // System UI visibility only controls status bars and navigation bars.
            return;
        }
        final boolean compatVisible;
        if (hasControl) {
            compatVisible = mRequestedVisible;
        } else if (source != null && !source.getFrame().isEmpty()) {
            compatVisible = visible;
        } else {
            final ArraySet<Integer> types = InsetsState.toInternalType(publicType);
            for (int i = types.size() - 1; i >= 0; i--) {
                final InsetsSource s = mState.peekSource(types.valueAt(i));
                if (s != null && !s.getFrame().isEmpty()) {
                    // The compat system UI visibility would be updated by another consumer which
                    // handles the same public insets type.
                    return;
                }
            }
            // No one provides the public type. Use the requested visibility for making the callback
            // behavior compatible.
            compatVisible = mRequestedVisible;
        }
        mController.updateCompatSysUiVisibility(mType, compatVisible, hasControl);
    }

    @VisibleForTesting
    public boolean isRequestedVisible() {
        return mRequestedVisible;
+16 −0
Original line number Diff line number Diff line
@@ -517,6 +517,22 @@ public class InsetsState implements Parcelable {
        return mSources[type];
    }

    /**
     * FIXME (b/253420890): This can be removed once the requested visibilities are migrated to
     *                      public types.
     */
    public boolean hasVisibleSource(@InsetsType int types) {
        for (InsetsSource source : mSources) {
            if (source == null) {
                continue;
            }
            if (source.isVisible() && (toPublicType(source.getType()) & types) != 0) {
                return true;
            }
        }
        return false;
    }

    /**
     * Returns the source visibility or the default visibility if the source doesn't exist. This is
     * useful if when treating this object as a request.
+9 −5
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ public class PendingInsetsController implements WindowInsetsController {
            = new ArrayList<>();
    private int mCaptionInsetsHeight = 0;
    private WindowInsetsAnimationControlListener mLoggingListener;
    private @InsetsType int mRequestedVisibleTypes = WindowInsets.Type.defaultVisible();

    @Override
    public void show(int types) {
@@ -52,6 +53,7 @@ public class PendingInsetsController implements WindowInsetsController {
            mReplayedInsetsController.show(types);
        } else {
            mRequests.add(new ShowRequest(types));
            mRequestedVisibleTypes |= types;
        }
    }

@@ -61,6 +63,7 @@ public class PendingInsetsController implements WindowInsetsController {
            mReplayedInsetsController.hide(types);
        } else {
            mRequests.add(new HideRequest(types));
            mRequestedVisibleTypes &= ~types;
        }
    }

@@ -122,11 +125,11 @@ public class PendingInsetsController implements WindowInsetsController {
    }

    @Override
    public boolean isRequestedVisible(int type) {

        // Method is only used once real insets controller is attached, so no need to traverse
        // requests here.
        return InsetsState.getDefaultVisibility(type);
    public @InsetsType int getRequestedVisibleTypes() {
        if (mReplayedInsetsController != null) {
            return mReplayedInsetsController.getRequestedVisibleTypes();
        }
        return mRequestedVisibleTypes;
    }

    @Override
@@ -189,6 +192,7 @@ public class PendingInsetsController implements WindowInsetsController {
        mAppearanceMask = 0;
        mAnimationsDisabled = false;
        mLoggingListener = null;
        mRequestedVisibleTypes = WindowInsets.Type.defaultVisible();
        // After replaying, we forward everything directly to the replayed instance.
        mReplayedInsetsController = controller;
    }
+36 −30
Original line number Diff line number Diff line
@@ -162,7 +162,6 @@ import android.util.TimeUtils;
import android.util.TypedValue;
import android.util.proto.ProtoOutputStream;
import android.view.InputDevice.InputSourceClass;
import android.view.InsetsState.InternalInsetsType;
import android.view.Surface.OutOfResourcesException;
import android.view.SurfaceControl.Transaction;
import android.view.View.AttachInfo;
@@ -2382,7 +2381,7 @@ public final class ViewRootImpl implements ViewParent,
            mCompatibleVisibilityInfo.globalVisibility =
                    (mCompatibleVisibilityInfo.globalVisibility & ~View.SYSTEM_UI_FLAG_LOW_PROFILE)
                            | (mAttachInfo.mSystemUiVisibility & View.SYSTEM_UI_FLAG_LOW_PROFILE);
            dispatchDispatchSystemUiVisibilityChanged(mCompatibleVisibilityInfo);
            dispatchDispatchSystemUiVisibilityChanged();
            if (mAttachInfo.mKeepScreenOn != oldScreenOn
                    || mAttachInfo.mSystemUiVisibility != params.subtreeSystemUiVisibility
                    || mAttachInfo.mHasSystemUiListeners != params.hasSystemUiListeners) {
@@ -2410,24 +2409,29 @@ public final class ViewRootImpl implements ViewParent,

    /**
     * Update the compatible system UI visibility for dispatching it to the legacy app.
     *
     * @param type Indicates which type of the insets source we are handling.
     * @param visible True if the insets source is visible.
     * @param hasControl True if we can control the insets source.
     */
    void updateCompatSysUiVisibility(@InternalInsetsType int type, boolean visible,
            boolean hasControl) {
        @InsetsType final int publicType = InsetsState.toPublicType(type);
        if (publicType != Type.statusBars() && publicType != Type.navigationBars()) {
            return;
     */
    void updateCompatSysUiVisibility(@InsetsType int visibleTypes,
            @InsetsType int requestedVisibleTypes, @InsetsType int controllableTypes) {
        // If a type is controllable, the visibility is overridden by the requested visibility.
        visibleTypes =
                (requestedVisibleTypes & controllableTypes) | (visibleTypes & ~controllableTypes);

        updateCompatSystemUiVisibilityInfo(SYSTEM_UI_FLAG_FULLSCREEN, Type.statusBars(),
                visibleTypes, controllableTypes);
        updateCompatSystemUiVisibilityInfo(SYSTEM_UI_FLAG_HIDE_NAVIGATION, Type.navigationBars(),
                visibleTypes, controllableTypes);
        dispatchDispatchSystemUiVisibilityChanged();
    }

    private void updateCompatSystemUiVisibilityInfo(int systemUiFlag, @InsetsType int insetsType,
            @InsetsType int visibleTypes, @InsetsType int controllableTypes) {
        final SystemUiVisibilityInfo info = mCompatibleVisibilityInfo;
        final int systemUiFlag = publicType == Type.statusBars()
                ? View.SYSTEM_UI_FLAG_FULLSCREEN
                : View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
        if (visible) {
        final boolean willBeVisible = (visibleTypes & insetsType) != 0;
        final boolean hasControl = (controllableTypes & insetsType) != 0;
        final boolean wasInvisible = (mAttachInfo.mSystemUiVisibility & systemUiFlag) != 0;
        if (willBeVisible) {
            info.globalVisibility &= ~systemUiFlag;
            if (hasControl && (mAttachInfo.mSystemUiVisibility & systemUiFlag) != 0) {
            if (hasControl && wasInvisible) {
                // The local system UI visibility can only be cleared while we have the control.
                info.localChanges |= systemUiFlag;
            }
@@ -2435,7 +2439,6 @@ public final class ViewRootImpl implements ViewParent,
            info.globalVisibility |= systemUiFlag;
            info.localChanges &= ~systemUiFlag;
        }
        dispatchDispatchSystemUiVisibilityChanged(info);
    }

    /**
@@ -2451,25 +2454,28 @@ public final class ViewRootImpl implements ViewParent,
                && (info.globalVisibility & SYSTEM_UI_FLAG_LOW_PROFILE) != 0) {
            info.globalVisibility &= ~SYSTEM_UI_FLAG_LOW_PROFILE;
            info.localChanges |= SYSTEM_UI_FLAG_LOW_PROFILE;
            dispatchDispatchSystemUiVisibilityChanged(info);
            dispatchDispatchSystemUiVisibilityChanged();
        }
    }

    private void dispatchDispatchSystemUiVisibilityChanged(SystemUiVisibilityInfo args) {
        if (mDispatchedSystemUiVisibility != args.globalVisibility) {
    private void dispatchDispatchSystemUiVisibilityChanged() {
        if (mDispatchedSystemUiVisibility != mCompatibleVisibilityInfo.globalVisibility) {
            mHandler.removeMessages(MSG_DISPATCH_SYSTEM_UI_VISIBILITY);
            mHandler.sendMessage(mHandler.obtainMessage(MSG_DISPATCH_SYSTEM_UI_VISIBILITY, args));
            mHandler.sendMessage(mHandler.obtainMessage(MSG_DISPATCH_SYSTEM_UI_VISIBILITY));
        }
    }

    private void handleDispatchSystemUiVisibilityChanged(SystemUiVisibilityInfo args) {
        if (mView == null) return;
        if (args.localChanges != 0) {
            mView.updateLocalSystemUiVisibility(args.localValue, args.localChanges);
            args.localChanges = 0;
    private void handleDispatchSystemUiVisibilityChanged() {
        if (mView == null) {
            return;
        }
        final SystemUiVisibilityInfo info = mCompatibleVisibilityInfo;
        if (info.localChanges != 0) {
            mView.updateLocalSystemUiVisibility(info.localValue, info.localChanges);
            info.localChanges = 0;
        }

        final int visibility = args.globalVisibility & View.SYSTEM_UI_CLEARABLE_FLAGS;
        final int visibility = info.globalVisibility & View.SYSTEM_UI_CLEARABLE_FLAGS;
        if (mDispatchedSystemUiVisibility != visibility) {
            mDispatchedSystemUiVisibility = visibility;
            mView.dispatchSystemUiVisibilityChanged(visibility);
@@ -5734,7 +5740,7 @@ public final class ViewRootImpl implements ViewParent,
                    handleDragEvent(event);
                } break;
                case MSG_DISPATCH_SYSTEM_UI_VISIBILITY: {
                    handleDispatchSystemUiVisibilityChanged((SystemUiVisibilityInfo) msg.obj);
                    handleDispatchSystemUiVisibilityChanged();
                } break;
                case MSG_UPDATE_CONFIGURATION: {
                    Configuration config = (Configuration) msg.obj;
Loading