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

Commit 521ba43e authored by Tiger Huang's avatar Tiger Huang
Browse files

Only update the compat system UI visibility if the source is valid

If two insets source consumers handle the same public type (like
navigation bar and taskbar both provide Type.navigationBars()), one has
a valid source but the other one doesn't, we should only let the one
with the valid source update the compat system UI visibility.

Bug: 232327949
Test: atest WindowInsetsControllerTests\
      #testSystemUiVisibilityCallbackCausedByInsets
Change-Id: I07b35f488c5af273cafaf4a8a41f0a51365038a0
parent 811e3c9d
Loading
Loading
Loading
Loading
+32 −5
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ import android.annotation.IntDef;
import android.annotation.Nullable;
import android.graphics.Insets;
import android.graphics.Rect;
import android.util.ArraySet;
import android.util.Log;
import android.util.proto.ProtoOutputStream;
import android.view.InsetsState.InternalInsetsType;
@@ -272,11 +273,7 @@ public class InsetsSourceConsumer {
                    mController.getHost().getInputMethodManager(), null /* icProto */);
        }

        // We still need to let the legacy app know the visibility change even if we don't have the
        // control. If we don't have the source, we don't change the requested visibility for making
        // the callback behavior compatible.
        mController.updateCompatSysUiVisibility(
                mType, (hasControl || source == null) ? mRequestedVisible : isVisible, hasControl);
        updateCompatSysUiVisibility(hasControl, source, isVisible);

        // If we don't have control, we are not able to change the visibility.
        if (!hasControl) {
@@ -294,6 +291,36 @@ 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;