From 521ba43e12fe38f5178ceab6fc843cfa393f875f Mon Sep 17 00:00:00 2001 From: Tiger Huang Date: Wed, 25 May 2022 00:55:26 +0800 Subject: [PATCH] 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 --- .../android/view/InsetsSourceConsumer.java | 37 ++++++++++++++++--- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/core/java/android/view/InsetsSourceConsumer.java b/core/java/android/view/InsetsSourceConsumer.java index d6b75b94b19aa..b17e19998a9d4 100644 --- a/core/java/android/view/InsetsSourceConsumer.java +++ b/core/java/android/view/InsetsSourceConsumer.java @@ -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 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;