From cff14c062341dc2cacbb43906ba4dc5e1515591d Mon Sep 17 00:00:00 2001 From: Tiger Date: Tue, 10 Jan 2023 19:54:07 +0800 Subject: [PATCH] Send public types while showing or aborting transient bars The sources with the same pulic type should be controlled together. So we can just use public types to indicate which types of transient bars are shown or aborted. This CL also fixes bugs related to transient bars: - Incorrect window layout after aborting transient bar. The transient state affects the window layout, but we didn't relayout after aborting it. - Hiding taskbar won't trigger immersive mode confirmation. We only checked the visibility change of ITYPE_NAVIGATION_BAR before this CL, instead of all the sources with WindowInsets.Type#navigationbars(). - Transient taskbar won't show after performing the panic gesture. The reason is the same as the second bug above. Fix: 265396491 Fix: 265394635 Fix: 265394625 Bug: 234093736 Test: atest CommandQueueTest InsetsPolicyTest InsetsStateControllerTest RegisterStatusBarResultTest Change-Id: Ib150826402d281de1aedf98336d05010496842c0 --- core/java/android/view/InsetsState.java | 13 -- .../internal/statusbar/IStatusBar.aidl | 8 +- .../statusbar/RegisterStatusBarResult.java | 10 +- .../RegisterStatusBarResultTest.java | 2 +- .../systemui/navigationbar/NavigationBar.java | 12 +- .../navigationbar/TaskbarDelegate.java | 13 +- .../systemui/statusbar/CommandQueue.java | 43 ++-- .../CentralSurfacesCommandQueueCallbacks.java | 14 +- .../statusbar/phone/CentralSurfacesImpl.java | 5 +- .../systemui/statusbar/CommandQueueTest.java | 10 +- .../statusbar/StatusBarManagerInternal.java | 6 +- .../statusbar/StatusBarManagerService.java | 26 +-- .../com/android/server/wm/DisplayPolicy.java | 53 ++--- .../com/android/server/wm/InsetsPolicy.java | 193 +++++++++--------- .../server/wm/InsetsSourceProvider.java | 21 +- .../server/wm/InsetsStateController.java | 169 +++++++-------- .../android/server/wm/InsetsPolicyTest.java | 17 +- .../server/wm/InsetsStateControllerTest.java | 4 +- ...ndowContainerInsetsSourceProviderTest.java | 4 +- 19 files changed, 295 insertions(+), 328 deletions(-) diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java index 70a7739949269..ba7d823750a3f 100644 --- a/core/java/android/view/InsetsState.java +++ b/core/java/android/view/InsetsState.java @@ -781,19 +781,6 @@ public class InsetsState implements Parcelable { } } - public static boolean containsType(@InternalInsetsType int[] types, - @InternalInsetsType int type) { - if (types == null) { - return false; - } - for (int t : types) { - if (t == type) { - return true; - } - } - return false; - } - public void dump(String prefix, PrintWriter pw) { final String newPrefix = prefix + " "; pw.println(prefix + "InsetsState"); diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl index 1c85ca2bb2697..b529a10164641 100644 --- a/core/java/com/android/internal/statusbar/IStatusBar.aidl +++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl @@ -214,11 +214,11 @@ oneway interface IStatusBar * bar and navigation bar which are temporarily visible to the user. * * @param displayId the ID of the display to notify. - * @param types the internal insets types of the bars are about to show transiently. + * @param types the insets types of the bars are about to show transiently. * @param isGestureOnSystemBar whether the gesture to show the transient bar was a gesture on * one of the bars itself. */ - void showTransient(int displayId, in int[] types, boolean isGestureOnSystemBar); + void showTransient(int displayId, int types, boolean isGestureOnSystemBar); /** * Notifies System UI to abort the transient state of system bars, which prevents the bars being @@ -226,9 +226,9 @@ oneway interface IStatusBar * bars again. * * @param displayId the ID of the display to notify. - * @param types the internal insets types of the bars are about to abort the transient state. + * @param types the insets types of the bars are about to abort the transient state. */ - void abortTransient(int displayId, in int[] types); + void abortTransient(int displayId, int types); /** * Show a warning that the device is about to go to sleep due to user inactivity. diff --git a/core/java/com/android/internal/statusbar/RegisterStatusBarResult.java b/core/java/com/android/internal/statusbar/RegisterStatusBarResult.java index 54221ce92dc4a..4f827cda6afaf 100644 --- a/core/java/com/android/internal/statusbar/RegisterStatusBarResult.java +++ b/core/java/com/android/internal/statusbar/RegisterStatusBarResult.java @@ -16,7 +16,6 @@ package com.android.internal.statusbar; -import android.annotation.NonNull; import android.os.IBinder; import android.os.Parcel; import android.os.Parcelable; @@ -41,15 +40,14 @@ public final class RegisterStatusBarResult implements Parcelable { public final int mBehavior; public final int mRequestedVisibleTypes; public final String mPackageName; - public final int[] mTransientBarTypes; + public final int mTransientBarTypes; public final LetterboxDetails[] mLetterboxDetails; public RegisterStatusBarResult(ArrayMap icons, int disabledFlags1, int appearance, AppearanceRegion[] appearanceRegions, int imeWindowVis, int imeBackDisposition, boolean showImeSwitcher, int disabledFlags2, IBinder imeToken, boolean navbarColorManagedByIme, int behavior, int requestedVisibleTypes, - String packageName, @NonNull int[] transientBarTypes, - LetterboxDetails[] letterboxDetails) { + String packageName, int transientBarTypes, LetterboxDetails[] letterboxDetails) { mIcons = new ArrayMap<>(icons); mDisabledFlags1 = disabledFlags1; mAppearance = appearance; @@ -87,7 +85,7 @@ public final class RegisterStatusBarResult implements Parcelable { dest.writeInt(mBehavior); dest.writeInt(mRequestedVisibleTypes); dest.writeString(mPackageName); - dest.writeIntArray(mTransientBarTypes); + dest.writeInt(mTransientBarTypes); dest.writeParcelableArray(mLetterboxDetails, flags); } @@ -113,7 +111,7 @@ public final class RegisterStatusBarResult implements Parcelable { final int behavior = source.readInt(); final int requestedVisibleTypes = source.readInt(); final String packageName = source.readString(); - final int[] transientBarTypes = source.createIntArray(); + final int transientBarTypes = source.readInt(); final LetterboxDetails[] letterboxDetails = source.readParcelableArray(null, LetterboxDetails.class); return new RegisterStatusBarResult(icons, disabledFlags1, appearance, diff --git a/core/tests/coretests/src/com/android/internal/statusbar/RegisterStatusBarResultTest.java b/core/tests/coretests/src/com/android/internal/statusbar/RegisterStatusBarResultTest.java index 048c48bc45fae..f79ba28d946f5 100644 --- a/core/tests/coretests/src/com/android/internal/statusbar/RegisterStatusBarResultTest.java +++ b/core/tests/coretests/src/com/android/internal/statusbar/RegisterStatusBarResultTest.java @@ -67,7 +67,7 @@ public class RegisterStatusBarResultTest { BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE, WindowInsets.Type.defaultVisible(), "test" /* packageName */, - new int[0] /* transientBarTypes */, + 0 /* transientBarTypes */, new LetterboxDetails[] {letterboxDetails}); final RegisterStatusBarResult copy = clone(original); diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java index 79b4b3a4ab28b..f2c422986e5b1 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java @@ -30,7 +30,6 @@ import static android.view.InsetsState.ITYPE_BOTTOM_TAPPABLE_ELEMENT; import static android.view.InsetsState.ITYPE_LEFT_GESTURES; import static android.view.InsetsState.ITYPE_NAVIGATION_BAR; import static android.view.InsetsState.ITYPE_RIGHT_GESTURES; -import static android.view.InsetsState.containsType; import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE; import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION; @@ -85,7 +84,6 @@ import android.view.DisplayCutout; import android.view.Gravity; import android.view.HapticFeedbackConstants; import android.view.InsetsFrameProvider; -import android.view.InsetsState.InternalInsetsType; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.Surface; @@ -97,6 +95,7 @@ import android.view.ViewRootImpl.SurfaceChangedCallback; import android.view.ViewTreeObserver; import android.view.ViewTreeObserver.InternalInsetsInfo; import android.view.ViewTreeObserver.OnComputeInternalInsetsListener; +import android.view.WindowInsets; import android.view.WindowInsets.Type.InsetsType; import android.view.WindowInsetsController.Appearance; import android.view.WindowInsetsController.Behavior; @@ -1150,12 +1149,11 @@ public class NavigationBar extends ViewController implements } @Override - public void showTransient(int displayId, @InternalInsetsType int[] types, - boolean isGestureOnSystemBar) { + public void showTransient(int displayId, @InsetsType int types, boolean isGestureOnSystemBar) { if (displayId != mDisplayId) { return; } - if (!containsType(types, ITYPE_NAVIGATION_BAR)) { + if ((types & WindowInsets.Type.navigationBars()) == 0) { return; } if (!mTransientShown) { @@ -1166,11 +1164,11 @@ public class NavigationBar extends ViewController implements } @Override - public void abortTransient(int displayId, @InternalInsetsType int[] types) { + public void abortTransient(int displayId, @InsetsType int types) { if (displayId != mDisplayId) { return; } - if (!containsType(types, ITYPE_NAVIGATION_BAR)) { + if ((types & WindowInsets.Type.navigationBars()) == 0) { return; } clearTransient(); diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java index f3712e66e330b..c3d736917b5df 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java @@ -20,8 +20,6 @@ import static android.app.ActivityManager.LOCK_TASK_MODE_PINNED; import static android.app.StatusBarManager.NAVIGATION_HINT_BACK_ALT; import static android.app.StatusBarManager.NAVIGATION_HINT_IME_SWITCHER_SHOWN; import static android.app.StatusBarManager.WINDOW_STATE_SHOWING; -import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR; -import static android.view.InsetsState.containsType; import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; @@ -41,7 +39,6 @@ import static com.android.systemui.statusbar.phone.BarTransitions.TransitionMode import android.app.StatusBarManager; import android.app.StatusBarManager.WindowVisibleState; -import android.content.ComponentName; import android.content.Context; import android.content.res.Configuration; import android.graphics.Rect; @@ -52,6 +49,7 @@ import android.os.RemoteException; import android.util.Log; import android.view.Display; import android.view.View; +import android.view.WindowInsets; import android.view.WindowInsets.Type.InsetsType; import android.view.WindowInsetsController.Appearance; import android.view.WindowInsetsController.Behavior; @@ -68,7 +66,6 @@ import com.android.systemui.model.SysUiState; import com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler; import com.android.systemui.recents.OverviewProxyService; import com.android.systemui.shared.recents.utilities.Utilities; -import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.QuickStepContract; import com.android.systemui.shared.system.TaskStackChangeListener; import com.android.systemui.shared.system.TaskStackChangeListeners; @@ -401,11 +398,11 @@ public class TaskbarDelegate implements CommandQueue.Callbacks, } @Override - public void showTransient(int displayId, int[] types, boolean isGestureOnSystemBar) { + public void showTransient(int displayId, @InsetsType int types, boolean isGestureOnSystemBar) { if (displayId != mDisplayId) { return; } - if (!containsType(types, ITYPE_EXTRA_NAVIGATION_BAR)) { + if ((types & WindowInsets.Type.navigationBars()) == 0) { return; } if (!mTaskbarTransientShowing) { @@ -415,11 +412,11 @@ public class TaskbarDelegate implements CommandQueue.Callbacks, } @Override - public void abortTransient(int displayId, int[] types) { + public void abortTransient(int displayId, @InsetsType int types) { if (displayId != mDisplayId) { return; } - if (!containsType(types, ITYPE_EXTRA_NAVIGATION_BAR)) { + if ((types & WindowInsets.Type.navigationBars()) == 0) { return; } clearTransient(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java index 3aaad87b8eab8..2cf1f53b4499b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java @@ -53,7 +53,6 @@ import android.os.Process; import android.os.RemoteException; import android.util.Pair; import android.util.SparseArray; -import android.view.InsetsState.InternalInsetsType; import android.view.WindowInsets.Type.InsetsType; import android.view.WindowInsetsController.Appearance; import android.view.WindowInsetsController.Behavior; @@ -371,22 +370,22 @@ public class CommandQueue extends IStatusBar.Stub implements String packageName, LetterboxDetails[] letterboxDetails) { } /** - * @see IStatusBar#showTransient(int, int[], boolean). + * @see IStatusBar#showTransient(int, int, boolean). */ - default void showTransient(int displayId, @InternalInsetsType int[] types) { } + default void showTransient(int displayId, @InsetsType int types) { } /** - * @see IStatusBar#showTransient(int, int[], boolean). + * @see IStatusBar#showTransient(int, int, boolean). */ - default void showTransient(int displayId, @InternalInsetsType int[] types, + default void showTransient(int displayId, @InsetsType int types, boolean isGestureOnSystemBar) { showTransient(displayId, types); } /** - * @see IStatusBar#abortTransient(int, int[]). + * @see IStatusBar#abortTransient(int, int). */ - default void abortTransient(int displayId, @InternalInsetsType int[] types) { } + default void abortTransient(int displayId, @InsetsType int types) { } /** * Called to notify System UI that a warning about the device going to sleep @@ -1131,17 +1130,23 @@ public class CommandQueue extends IStatusBar.Stub implements } @Override - public void showTransient(int displayId, int[] types, boolean isGestureOnSystemBar) { + public void showTransient(int displayId, int types, boolean isGestureOnSystemBar) { synchronized (mLock) { - mHandler.obtainMessage(MSG_SHOW_TRANSIENT, displayId, isGestureOnSystemBar ? 1 : 0, - types).sendToTarget(); + SomeArgs args = SomeArgs.obtain(); + args.argi1 = displayId; + args.argi2 = types; + args.argi3 = isGestureOnSystemBar ? 1 : 0; + mHandler.obtainMessage(MSG_SHOW_TRANSIENT, args).sendToTarget(); } } @Override - public void abortTransient(int displayId, int[] types) { + public void abortTransient(int displayId, int types) { synchronized (mLock) { - mHandler.obtainMessage(MSG_ABORT_TRANSIENT, displayId, 0, types).sendToTarget(); + SomeArgs args = SomeArgs.obtain(); + args.argi1 = displayId; + args.argi2 = types; + mHandler.obtainMessage(MSG_ABORT_TRANSIENT, args).sendToTarget(); } } @@ -1644,17 +1649,21 @@ public class CommandQueue extends IStatusBar.Stub implements args.recycle(); break; case MSG_SHOW_TRANSIENT: { - final int displayId = msg.arg1; - final int[] types = (int[]) msg.obj; - final boolean isGestureOnSystemBar = msg.arg2 != 0; + args = (SomeArgs) msg.obj; + final int displayId = args.argi1; + final int types = args.argi2; + final boolean isGestureOnSystemBar = args.argi3 != 0; + args.recycle(); for (int i = 0; i < mCallbacks.size(); i++) { mCallbacks.get(i).showTransient(displayId, types, isGestureOnSystemBar); } break; } case MSG_ABORT_TRANSIENT: { - final int displayId = msg.arg1; - final int[] types = (int[]) msg.obj; + args = (SomeArgs) msg.obj; + final int displayId = args.argi1; + final int types = args.argi2; + args.recycle(); for (int i = 0; i < mCallbacks.size(); i++) { mCallbacks.get(i).abortTransient(displayId, types); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java index 856d7dedb4eb0..fecaa3a0caf5a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java @@ -16,9 +16,6 @@ package com.android.systemui.statusbar.phone; -import static android.view.InsetsState.ITYPE_STATUS_BAR; -import static android.view.InsetsState.containsType; - import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_AWAKE; import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_WAKING; @@ -36,8 +33,8 @@ import android.os.VibrationEffect; import android.os.Vibrator; import android.util.Log; import android.util.Slog; -import android.view.InsetsState.InternalInsetsType; import android.view.KeyEvent; +import android.view.WindowInsets; import android.view.WindowInsets.Type.InsetsType; import android.view.WindowInsetsController.Appearance; import android.view.WindowInsetsController.Behavior; @@ -168,11 +165,11 @@ public class CentralSurfacesCommandQueueCallbacks implements CommandQueue.Callba } @Override - public void abortTransient(int displayId, @InternalInsetsType int[] types) { + public void abortTransient(int displayId, @InsetsType int types) { if (displayId != mDisplayId) { return; } - if (!containsType(types, ITYPE_STATUS_BAR)) { + if ((types & WindowInsets.Type.statusBars()) == 0) { return; } mCentralSurfaces.clearTransient(); @@ -489,12 +486,11 @@ public class CentralSurfacesCommandQueueCallbacks implements CommandQueue.Callba } @Override - public void showTransient(int displayId, @InternalInsetsType int[] types, - boolean isGestureOnSystemBar) { + public void showTransient(int displayId, @InsetsType int types, boolean isGestureOnSystemBar) { if (displayId != mDisplayId) { return; } - if (!containsType(types, ITYPE_STATUS_BAR)) { + if ((types & WindowInsets.Type.statusBars()) == 0) { return; } mCentralSurfaces.showTransientUnchecked(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java index e595ddf46a89b..1966a6657acbe 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java @@ -21,8 +21,6 @@ import static android.app.StatusBarManager.WINDOW_STATE_HIDDEN; import static android.app.StatusBarManager.WINDOW_STATE_SHOWING; import static android.app.StatusBarManager.WindowVisibleState; import static android.app.StatusBarManager.windowStateToString; -import static android.view.InsetsState.ITYPE_STATUS_BAR; -import static android.view.InsetsState.containsType; import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS; import static android.view.WindowInsetsController.APPEARANCE_OPAQUE_STATUS_BARS; import static android.view.WindowInsetsController.APPEARANCE_SEMI_TRANSPARENT_STATUS_BARS; @@ -100,6 +98,7 @@ import android.view.ThreadedRenderer; import android.view.View; import android.view.ViewGroup; import android.view.ViewRootImpl; +import android.view.WindowInsets; import android.view.WindowInsetsController.Appearance; import android.view.WindowManager; import android.view.WindowManagerGlobal; @@ -943,7 +942,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { // Set up the initial notification state. This needs to happen before CommandQueue.disable() setUpPresenter(); - if (containsType(result.mTransientBarTypes, ITYPE_STATUS_BAR)) { + if ((result.mTransientBarTypes & WindowInsets.Type.statusBars()) != 0) { showTransientUnchecked(); } mCommandQueueCallbacks.onSystemBarAttributesChanged(mDisplayId, result.mAppearance, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java index b1ca1c02f6daf..f581154f66c02 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java @@ -18,8 +18,6 @@ import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE; import static android.inputmethodservice.InputMethodService.BACK_DISPOSITION_DEFAULT; import static android.inputmethodservice.InputMethodService.IME_INVISIBLE; import static android.view.Display.DEFAULT_DISPLAY; -import static android.view.InsetsState.ITYPE_NAVIGATION_BAR; -import static android.view.InsetsState.ITYPE_STATUS_BAR; import static android.view.WindowInsetsController.BEHAVIOR_DEFAULT; import static org.mockito.ArgumentMatchers.anyInt; @@ -158,7 +156,7 @@ public class CommandQueueTest extends SysuiTestCase { @Test public void testShowTransient() { - int[] types = new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR}; + int types = WindowInsets.Type.statusBars() | WindowInsets.Type.navigationBars(); mCommandQueue.showTransient(DEFAULT_DISPLAY, types, true /* isGestureOnSystemBar */); waitForIdleSync(); verify(mCallbacks).showTransient(eq(DEFAULT_DISPLAY), eq(types), eq(true)); @@ -166,7 +164,7 @@ public class CommandQueueTest extends SysuiTestCase { @Test public void testShowTransientForSecondaryDisplay() { - int[] types = new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR}; + int types = WindowInsets.Type.statusBars() | WindowInsets.Type.navigationBars(); mCommandQueue.showTransient(SECONDARY_DISPLAY, types, true /* isGestureOnSystemBar */); waitForIdleSync(); verify(mCallbacks).showTransient(eq(SECONDARY_DISPLAY), eq(types), eq(true)); @@ -174,7 +172,7 @@ public class CommandQueueTest extends SysuiTestCase { @Test public void testAbortTransient() { - int[] types = new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR}; + int types = WindowInsets.Type.statusBars() | WindowInsets.Type.navigationBars(); mCommandQueue.abortTransient(DEFAULT_DISPLAY, types); waitForIdleSync(); verify(mCallbacks).abortTransient(eq(DEFAULT_DISPLAY), eq(types)); @@ -182,7 +180,7 @@ public class CommandQueueTest extends SysuiTestCase { @Test public void testAbortTransientForSecondaryDisplay() { - int[] types = new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR}; + int types = WindowInsets.Type.statusBars() | WindowInsets.Type.navigationBars(); mCommandQueue.abortTransient(SECONDARY_DISPLAY, types); waitForIdleSync(); verify(mCallbacks).abortTransient(eq(SECONDARY_DISPLAY), eq(types)); diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java index 5521384bb1693..ec052ecd20f29 100644 --- a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java +++ b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java @@ -21,7 +21,6 @@ import android.app.ITransientNotificationCallback; import android.hardware.fingerprint.IUdfpsRefreshRateRequestCallback; import android.os.Bundle; import android.os.IBinder; -import android.view.InsetsState.InternalInsetsType; import android.view.WindowInsets.Type.InsetsType; import android.view.WindowInsetsController.Appearance; import android.view.WindowInsetsController.Behavior; @@ -162,11 +161,10 @@ public interface StatusBarManagerInternal { LetterboxDetails[] letterboxDetails); /** @see com.android.internal.statusbar.IStatusBar#showTransient */ - void showTransient(int displayId, @InternalInsetsType int[] types, - boolean isGestureOnSystemBar); + void showTransient(int displayId, @InsetsType int types, boolean isGestureOnSystemBar); /** @see com.android.internal.statusbar.IStatusBar#abortTransient */ - void abortTransient(int displayId, @InternalInsetsType int[] types); + void abortTransient(int displayId, @InsetsType int types); /** * @see com.android.internal.statusbar.IStatusBar#showToast(String, IBinder, CharSequence, diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java index 83f4805aca58a..4489ba94235ce 100644 --- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java +++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java @@ -79,12 +79,10 @@ import android.service.notification.NotificationStats; import android.service.quicksettings.TileService; import android.text.TextUtils; import android.util.ArrayMap; -import android.util.ArraySet; import android.util.IndentingPrintWriter; import android.util.Pair; import android.util.Slog; import android.util.SparseArray; -import android.view.InsetsState.InternalInsetsType; import android.view.WindowInsets; import android.view.WindowInsets.Type.InsetsType; import android.view.WindowInsetsController.Appearance; @@ -645,7 +643,7 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D } @Override - public void showTransient(int displayId, @InternalInsetsType int[] types, + public void showTransient(int displayId, @InsetsType int types, boolean isGestureOnSystemBar) { getUiState(displayId).showTransient(types); if (mBar != null) { @@ -656,7 +654,7 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D } @Override - public void abortTransient(int displayId, @InternalInsetsType int[] types) { + public void abortTransient(int displayId, @InsetsType int types) { getUiState(displayId).clearTransient(types); if (mBar != null) { try { @@ -1258,7 +1256,7 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D private static class UiState { private @Appearance int mAppearance = 0; private AppearanceRegion[] mAppearanceRegions = new AppearanceRegion[0]; - private final ArraySet mTransientBarTypes = new ArraySet<>(); + private @InsetsType int mTransientBarTypes; private boolean mNavbarColorManagedByIme = false; private @Behavior int mBehavior; private @InsetsType int mRequestedVisibleTypes = WindowInsets.Type.defaultVisible(); @@ -1285,16 +1283,12 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D mLetterboxDetails = letterboxDetails; } - private void showTransient(@InternalInsetsType int[] types) { - for (int type : types) { - mTransientBarTypes.add(type); - } + private void showTransient(@InsetsType int types) { + mTransientBarTypes |= types; } - private void clearTransient(@InternalInsetsType int[] types) { - for (int type : types) { - mTransientBarTypes.remove(type); - } + private void clearTransient(@InsetsType int types) { + mTransientBarTypes &= ~types; } private int getDisabled1() { @@ -1410,16 +1404,12 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D // TODO(b/118592525): Currently, status bar only works on the default display. // Make it aware of multi-display if needed. final UiState state = mDisplayUiState.get(DEFAULT_DISPLAY); - final int[] transientBarTypes = new int[state.mTransientBarTypes.size()]; - for (int i = 0; i < transientBarTypes.length; i++) { - transientBarTypes[i] = state.mTransientBarTypes.valueAt(i); - } return new RegisterStatusBarResult(icons, gatherDisableActionsLocked(mCurrentUserId, 1), state.mAppearance, state.mAppearanceRegions, state.mImeWindowVis, state.mImeBackDisposition, state.mShowImeSwitcher, gatherDisableActionsLocked(mCurrentUserId, 2), state.mImeToken, state.mNavbarColorManagedByIme, state.mBehavior, state.mRequestedVisibleTypes, - state.mPackageName, transientBarTypes, state.mLetterboxDetails); + state.mPackageName, state.mTransientBarTypes, state.mLetterboxDetails); } } diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index e87680ac5a16f..7c12dbc7964b4 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -171,9 +171,8 @@ public class DisplayPolicy { /** Use the transit animation in style resource (see {@link #selectAnimation}). */ static final int ANIMATION_STYLEABLE = 0; - private static final int[] SHOW_TYPES_FOR_SWIPE = {ITYPE_NAVIGATION_BAR, ITYPE_STATUS_BAR, - ITYPE_CLIMATE_BAR, ITYPE_EXTRA_NAVIGATION_BAR}; - private static final int[] SHOW_TYPES_FOR_PANIC = {ITYPE_NAVIGATION_BAR}; + private static final int SHOW_TYPES_FOR_SWIPE = Type.statusBars() | Type.navigationBars(); + private static final int SHOW_TYPES_FOR_PANIC = Type.navigationBars(); private final WindowManagerService mService; private final Context mContext; @@ -251,7 +250,7 @@ public class DisplayPolicy { private boolean mIsFreeformWindowOverlappingWithNavBar; - private boolean mLastImmersiveMode; + private boolean mIsImmersiveMode; // The windows we were told about in focusChanged. private WindowState mFocusedWindow; @@ -2171,14 +2170,27 @@ public class DisplayPolicy { appearance = configureNavBarOpacity(appearance, multiWindowTaskVisible, freeformRootTaskVisible); + // Show immersive mode confirmation if needed. + final boolean wasImmersiveMode = mIsImmersiveMode; + final boolean isImmersiveMode = isImmersiveMode(win); + if (wasImmersiveMode != isImmersiveMode) { + mIsImmersiveMode = isImmersiveMode; + // The immersive confirmation window should be attached to the immersive window root. + final RootDisplayArea root = win.getRootDisplayArea(); + final int rootDisplayAreaId = root == null ? FEATURE_UNDEFINED : root.mFeatureId; + mImmersiveModeConfirmation.immersiveModeChangedLw(rootDisplayAreaId, isImmersiveMode, + mService.mPolicy.isUserSetupComplete(), + isNavBarEmpty(disableFlags)); + } + + // Show transient bars for panic if needed. final boolean requestHideNavBar = !win.isRequestedVisible(Type.navigationBars()); final long now = SystemClock.uptimeMillis(); final boolean pendingPanic = mPendingPanicGestureUptime != 0 && now - mPendingPanicGestureUptime <= PANIC_GESTURE_EXPIRATION; final DisplayPolicy defaultDisplayPolicy = mService.getDefaultDisplayContentLocked().getDisplayPolicy(); - if (pendingPanic && requestHideNavBar && win != mNotificationShade - && getInsetsPolicy().isHidden(ITYPE_NAVIGATION_BAR) + if (pendingPanic && requestHideNavBar && isImmersiveMode // TODO (b/111955725): Show keyguard presentation on all external displays && defaultDisplayPolicy.isKeyguardDrawComplete()) { // The user performed the panic gesture recently, we're about to hide the bars, @@ -2190,19 +2202,6 @@ public class DisplayPolicy { } } - // update navigation bar - boolean oldImmersiveMode = mLastImmersiveMode; - boolean newImmersiveMode = isImmersiveMode(win); - if (oldImmersiveMode != newImmersiveMode) { - mLastImmersiveMode = newImmersiveMode; - // The immersive confirmation window should be attached to the immersive window root. - final RootDisplayArea root = win.getRootDisplayArea(); - final int rootDisplayAreaId = root == null ? FEATURE_UNDEFINED : root.mFeatureId; - mImmersiveModeConfirmation.immersiveModeChangedLw(rootDisplayAreaId, newImmersiveMode, - mService.mPolicy.isUserSetupComplete(), - isNavBarEmpty(disableFlags)); - } - return appearance; } @@ -2324,18 +2323,10 @@ public class DisplayPolicy { if (win == null) { return false; } - return getNavigationBar() != null - && canHideNavigationBar() - && getInsetsPolicy().isHidden(ITYPE_NAVIGATION_BAR) - && win != getNotificationShade() - && !win.isActivityTypeDream(); - } - - /** - * @return whether the navigation bar can be hidden, e.g. the device has a navigation bar - */ - private boolean canHideNavigationBar() { - return hasNavigationBar(); + if (win == getNotificationShade() || win.isActivityTypeDream()) { + return false; + } + return getInsetsPolicy().hasHiddenSources(Type.navigationBars()); } private static boolean isNavBarEmpty(int systemUiFlags) { diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java index bd821134f9b73..f5d29ed54921f 100644 --- a/services/core/java/com/android/server/wm/InsetsPolicy.java +++ b/services/core/java/com/android/server/wm/InsetsPolicy.java @@ -26,8 +26,6 @@ import static android.view.InsetsController.ANIMATION_TYPE_SHOW; import static android.view.InsetsController.LAYOUT_INSETS_DURING_ANIMATION_HIDDEN; import static android.view.InsetsController.LAYOUT_INSETS_DURING_ANIMATION_SHOWN; import static android.view.InsetsSource.ID_IME; -import static android.view.InsetsState.ITYPE_NAVIGATION_BAR; -import static android.view.InsetsState.ITYPE_STATUS_BAR; import static android.view.SyncRtSurfaceTransactionApplier.applyParams; import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR; @@ -42,7 +40,6 @@ import android.app.WindowConfiguration; import android.content.ComponentName; import android.content.res.Resources; import android.util.ArrayMap; -import android.util.IntArray; import android.util.SparseArray; import android.view.InsetsAnimationControlCallbacks; import android.view.InsetsAnimationControlImpl; @@ -52,7 +49,6 @@ import android.view.InsetsFrameProvider; import android.view.InsetsSource; import android.view.InsetsSourceControl; import android.view.InsetsState; -import android.view.InsetsState.InternalInsetsType; import android.view.InternalInsetsAnimationController; import android.view.SurfaceControl; import android.view.SyncRtSurfaceTransactionApplier; @@ -81,7 +77,6 @@ class InsetsPolicy { private final InsetsStateController mStateController; private final DisplayContent mDisplayContent; private final DisplayPolicy mPolicy; - private final IntArray mShowingTransientTypes = new IntArray(); /** For resetting visibilities of insets sources. */ private final InsetsControlTarget mDummyControlTarget = new InsetsControlTarget() { @@ -95,7 +90,7 @@ class InsetsPolicy { return; } for (InsetsSourceControl control : controls) { - if (mShowingTransientTypes.indexOf(control.getId()) != -1) { + if (isTransient(control.getType())) { // The visibilities of transient bars will be handled with animations. continue; } @@ -117,13 +112,16 @@ class InsetsPolicy { }; private WindowState mFocusedWin; - private BarWindow mStatusBar = new BarWindow(StatusBarManager.WINDOW_STATUS_BAR); - private BarWindow mNavBar = new BarWindow(StatusBarManager.WINDOW_NAVIGATION_BAR); + private final BarWindow mStatusBar = new BarWindow(StatusBarManager.WINDOW_STATUS_BAR); + private final BarWindow mNavBar = new BarWindow(StatusBarManager.WINDOW_NAVIGATION_BAR); + private @InsetsType int mShowingTransientTypes; private boolean mAnimatingShown; + /** * Let remote insets controller control system bars regardless of other settings. */ private boolean mRemoteInsetsControllerControlsSystemBars; + private final boolean mHideNavBarForKeyboard; private final float[] mTmpFloat9 = new float[9]; @@ -178,37 +176,46 @@ class InsetsPolicy { mNavBar.updateVisibility(navControlTarget, Type.navigationBars()); } - boolean isHidden(@InternalInsetsType int type) { - final WindowContainerInsetsSourceProvider provider = mStateController - .peekSourceProvider(type); - return provider != null && provider.hasWindowContainer() - && !provider.getSource().isVisible(); + boolean hasHiddenSources(@InsetsType int types) { + final InsetsState state = mStateController.getRawInsetsState(); + for (int i = state.sourceSize() - 1; i >= 0; i--) { + final InsetsSource source = state.sourceAt(i); + if ((source.getType() & types) == 0) { + continue; + } + if (!source.getFrame().isEmpty() && !source.isVisible()) { + return true; + } + } + return false; } - void showTransient(@InternalInsetsType int[] types, boolean isGestureOnSystemBar) { - boolean changed = false; - for (int i = types.length - 1; i >= 0; i--) { - final @InternalInsetsType int type = types[i]; - if (!isHidden(type)) { + void showTransient(@InsetsType int types, boolean isGestureOnSystemBar) { + @InsetsType int showingTransientTypes = mShowingTransientTypes; + final InsetsState rawState = mStateController.getRawInsetsState(); + for (int i = rawState.sourceSize() - 1; i >= 0; i--) { + final InsetsSource source = rawState.sourceAt(i); + if (source.isVisible()) { continue; } - if (mShowingTransientTypes.indexOf(type) != -1) { + final @InsetsType int type = source.getType(); + if ((source.getType() & types) == 0) { continue; } - mShowingTransientTypes.add(type); - changed = true; + showingTransientTypes |= type; } - if (changed) { + if (mShowingTransientTypes != showingTransientTypes) { + mShowingTransientTypes = showingTransientTypes; StatusBarManagerInternal statusBarManagerInternal = mPolicy.getStatusBarManagerInternal(); if (statusBarManagerInternal != null) { statusBarManagerInternal.showTransient(mDisplayContent.getDisplayId(), - mShowingTransientTypes.toArray(), isGestureOnSystemBar); + showingTransientTypes, isGestureOnSystemBar); } updateBarControlTarget(mFocusedWin); dispatchTransientSystemBarsVisibilityChanged( mFocusedWin, - isTransient(ITYPE_STATUS_BAR) || isTransient(ITYPE_NAVIGATION_BAR), + (showingTransientTypes & (Type.statusBars() | Type.navigationBars())) != 0, isGestureOnSystemBar); // The leashes can be created while updating bar control target. The surface transaction @@ -224,7 +231,7 @@ class InsetsPolicy { } void hideTransient() { - if (mShowingTransientTypes.size() == 0) { + if (mShowingTransientTypes == 0) { return; } @@ -235,20 +242,25 @@ class InsetsPolicy { startAnimation(false /* show */, () -> { synchronized (mDisplayContent.mWmService.mGlobalLock) { - for (int i = mShowingTransientTypes.size() - 1; i >= 0; i--) { + final ArrayMap providers = + mStateController.getSourceProviders(); + for (int i = providers.size() - 1; i >= 0; i--) { + final WindowContainerInsetsSourceProvider provider = providers.valueAt(i); + if (!isTransient(provider.getSource().getType())) { + continue; + } // We are about to clear mShowingTransientTypes, we don't want the transient bar // can cause insets on the client. Restore the client visibility. - final @InternalInsetsType int type = mShowingTransientTypes.get(i); - mStateController.getSourceProvider(type).setClientVisible(false); + provider.setClientVisible(false); } - mShowingTransientTypes.clear(); + mShowingTransientTypes = 0; updateBarControlTarget(mFocusedWin); } }); } - boolean isTransient(@InternalInsetsType int type) { - return mShowingTransientTypes.indexOf(type) != -1; + boolean isTransient(@InsetsType int type) { + return (mShowingTransientTypes & type) != 0; } /** @@ -280,9 +292,9 @@ class InsetsPolicy { ? token.getFixedRotationTransformInsetsState() : mStateController.getRawInsetsState(); outInsetsState.set(srcState, true /* copySources */); - for (int i = mShowingTransientTypes.size() - 1; i >= 0; i--) { - final InsetsSource source = outInsetsState.peekSource(mShowingTransientTypes.get(i)); - if (source != null) { + for (int i = outInsetsState.sourceSize() - 1; i >= 0; i--) { + final InsetsSource source = outInsetsState.sourceAt(i); + if (isTransient(source.getType())) { source.setVisible(false); } } @@ -365,18 +377,17 @@ class InsetsPolicy { private InsetsState adjustVisibilityForTransientTypes(InsetsState originalState) { InsetsState state = originalState; - for (int i = mShowingTransientTypes.size() - 1; i >= 0; i--) { - final @InternalInsetsType int type = mShowingTransientTypes.get(i); - final InsetsSource originalSource = state.peekSource(type); - if (originalSource != null && originalSource.isVisible()) { + for (int i = state.sourceSize() - 1; i >= 0; i--) { + final InsetsSource source = state.sourceAt(i); + if (isTransient(source.getType()) && source.isVisible()) { if (state == originalState) { // The source will be modified, create a non-deep copy to store the new one. state = new InsetsState(originalState); } // Replace the source with a copy in invisible state. - final InsetsSource source = new InsetsSource(originalSource); - source.setVisible(false); - state.addSource(source); + final InsetsSource outSource = new InsetsSource(source); + outSource.setVisible(false); + state.addSource(outSource); } } return state; @@ -385,18 +396,23 @@ class InsetsPolicy { private InsetsState adjustVisibilityForIme(WindowState w, InsetsState originalState, boolean copyState) { if (w.mIsImWindow) { + InsetsState state = originalState; // If navigation bar is not hidden by IME, IME should always receive visible // navigation bar insets. final boolean navVisible = !mHideNavBarForKeyboard; - final InsetsSource originalNavSource = originalState.peekSource(ITYPE_NAVIGATION_BAR); - if (originalNavSource != null && originalNavSource.isVisible() != navVisible) { - final InsetsState state = copyState ? new InsetsState(originalState) - : originalState; - final InsetsSource navSource = new InsetsSource(originalNavSource); + for (int i = originalState.sourceSize() - 1; i >= 0; i--) { + final InsetsSource source = originalState.sourceAt(i); + if (source.getType() != Type.navigationBars() || source.isVisible() == navVisible) { + continue; + } + if (state == originalState && copyState) { + state = new InsetsState(originalState); + } + final InsetsSource navSource = new InsetsSource(source); navSource.setVisible(navVisible); state.addSource(navSource); - return state; } + return state; } else if (w.mActivityRecord != null && w.mActivityRecord.mImeInsetsFrozenUntilStartInput) { // During switching tasks with gestural navigation, before the next IME input target // starts the input, we should adjust and freeze the last IME visibility of the window @@ -447,23 +463,22 @@ class InsetsPolicy { * @param caller who changed the insets state. */ private void checkAbortTransient(InsetsControlTarget caller) { - if (mShowingTransientTypes.size() != 0) { - final IntArray abortTypes = new IntArray(); - final boolean imeRequestedVisible = caller.isRequestedVisible(Type.ime()); - for (int i = mShowingTransientTypes.size() - 1; i >= 0; i--) { - final @InternalInsetsType int type = mShowingTransientTypes.get(i); - if ((mStateController.isFakeTarget(type, caller) - && caller.isRequestedVisible(InsetsState.toPublicType(type))) - || (type == ITYPE_NAVIGATION_BAR && imeRequestedVisible)) { - mShowingTransientTypes.remove(i); - abortTypes.add(type); - } - } - StatusBarManagerInternal statusBarManagerInternal = - mPolicy.getStatusBarManagerInternal(); - if (abortTypes.size() > 0 && statusBarManagerInternal != null) { - statusBarManagerInternal.abortTransient( - mDisplayContent.getDisplayId(), abortTypes.toArray()); + if (mShowingTransientTypes == 0) { + return; + } + final boolean isImeVisible = mStateController.getImeSourceProvider().isClientVisible(); + final @InsetsType int fakeControllingTypes = + mStateController.getFakeControllingTypes(caller); + final @InsetsType int abortTypes = + (fakeControllingTypes & caller.getRequestedVisibleTypes()) + | (isImeVisible ? Type.navigationBars() : 0); + mShowingTransientTypes &= ~abortTypes; + if (abortTypes != 0) { + mDisplayContent.setLayoutNeeded(); + mDisplayContent.mWmService.requestTraversal(); + final StatusBarManagerInternal statusBarManager = mPolicy.getStatusBarManagerInternal(); + if (statusBarManager != null) { + statusBarManager.abortTransient(mDisplayContent.getDisplayId(), abortTypes); } } } @@ -473,12 +488,16 @@ class InsetsPolicy { * updateBarControlTarget(mFocusedWin) after this invocation. */ private void abortTransient() { - StatusBarManagerInternal statusBarManagerInternal = mPolicy.getStatusBarManagerInternal(); - if (statusBarManagerInternal != null) { - statusBarManagerInternal.abortTransient( - mDisplayContent.getDisplayId(), mShowingTransientTypes.toArray()); + if (mShowingTransientTypes == 0) { + return; } - mShowingTransientTypes.clear(); + final StatusBarManagerInternal statusBarManager = mPolicy.getStatusBarManagerInternal(); + if (statusBarManager != null) { + statusBarManager.abortTransient(mDisplayContent.getDisplayId(), mShowingTransientTypes); + } + mShowingTransientTypes = 0; + mDisplayContent.setLayoutNeeded(); + mDisplayContent.mWmService.requestTraversal(); dispatchTransientSystemBarsVisibilityChanged( mFocusedWin, @@ -488,7 +507,7 @@ class InsetsPolicy { private @Nullable InsetsControlTarget getStatusControlTarget(@Nullable WindowState focusedWin, boolean fake) { - if (!fake && isShowingTransientTypes(Type.statusBars())) { + if (!fake && isTransient(Type.statusBars())) { return mDummyControlTarget; } final WindowState notificationShade = mPolicy.getNotificationShade(); @@ -541,7 +560,7 @@ class InsetsPolicy { // configured to be hidden by the IME. return null; } - if (!fake && isShowingTransientTypes(Type.navigationBars())) { + if (!fake && isTransient(Type.navigationBars())) { return mDummyControlTarget; } if (focusedWin == mPolicy.getNotificationShade()) { @@ -577,16 +596,6 @@ class InsetsPolicy { return focusedWin; } - private boolean isShowingTransientTypes(@InsetsType int types) { - final IntArray showingTransientTypes = mShowingTransientTypes; - for (int i = showingTransientTypes.size() - 1; i >= 0; i--) { - if ((InsetsState.toPublicType(showingTransientTypes.get(i)) & types) != 0) { - return true; - } - } - return false; - } - /** * Determines whether the remote insets controller should take control of system bars for all * windows. @@ -622,21 +631,17 @@ class InsetsPolicy { @VisibleForTesting void startAnimation(boolean show, Runnable callback) { - int typesReady = 0; - final SparseArray controls = new SparseArray<>(); - final IntArray showingTransientTypes = mShowingTransientTypes; - for (int i = showingTransientTypes.size() - 1; i >= 0; i--) { - final int sourceId = showingTransientTypes.get(i); - final WindowContainerInsetsSourceProvider provider = - mStateController.getSourceProvider(sourceId); - final InsetsSourceControl control = provider.getControl(mDummyControlTarget); - if (control == null || control.getLeash() == null) { - continue; + @InsetsType int typesReady = 0; + final SparseArray controlsReady = new SparseArray<>(); + final InsetsSourceControl[] controls = + mStateController.getControlsForDispatch(mDummyControlTarget); + for (InsetsSourceControl control : controls) { + if (isTransient(control.getType()) && control.getLeash() != null) { + typesReady |= control.getType(); + controlsReady.put(control.getId(), new InsetsSourceControl(control)); } - typesReady |= control.getType(); - controls.put(sourceId, new InsetsSourceControl(control)); } - controlAnimationUnchecked(typesReady, controls, show, callback); + controlAnimationUnchecked(typesReady, controlsReady, show, callback); } private void controlAnimationUnchecked(int typesReady, diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java index f5af2929c2bda..3ff37060ae925 100644 --- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java +++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java @@ -191,13 +191,6 @@ abstract class InsetsSourceProvider { } } - /** - * @return Whether there is a window container which backs this source. - */ - boolean hasWindowContainer() { - return mWindowContainer != null; - } - /** * The source frame can affect the layout of other windows, so this should be called once the * window container gets laid out. @@ -363,9 +356,9 @@ abstract class InsetsSourceProvider { } /** - * @see InsetsStateController#onControlFakeTargetChanged(int, InsetsControlTarget) + * @see InsetsStateController#onControlTargetChanged */ - void updateControlForFakeTarget(@Nullable InsetsControlTarget fakeTarget) { + void updateFakeControlTarget(@Nullable InsetsControlTarget fakeTarget) { if (fakeTarget == mFakeControlTarget) { return; } @@ -570,6 +563,10 @@ abstract class InsetsSourceProvider { return mControlTarget; } + InsetsControlTarget getFakeControlTarget() { + return mFakeControlTarget; + } + boolean isClientVisible() { return mClientVisible; } @@ -609,15 +606,15 @@ abstract class InsetsSourceProvider { } if (mControlTarget != null) { pw.print(prefix + "mControlTarget="); - pw.println(mControlTarget.getWindow()); + pw.println(mControlTarget); } if (mPendingControlTarget != null) { pw.print(prefix + "mPendingControlTarget="); - pw.println(mPendingControlTarget.getWindow()); + pw.println(mPendingControlTarget); } if (mFakeControlTarget != null) { pw.print(prefix + "mFakeControlTarget="); - pw.println(mFakeControlTarget.getWindow()); + pw.println(mFakeControlTarget); } } diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java index a3f62b2c5693b..d377a3347d464 100644 --- a/services/core/java/com/android/server/wm/InsetsStateController.java +++ b/services/core/java/com/android/server/wm/InsetsStateController.java @@ -18,10 +18,6 @@ package com.android.server.wm; import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; import static android.view.InsetsSource.ID_IME; -import static android.view.InsetsState.ITYPE_CLIMATE_BAR; -import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR; -import static android.view.InsetsState.ITYPE_NAVIGATION_BAR; -import static android.view.InsetsState.ITYPE_STATUS_BAR; import static android.view.WindowInsets.Type.displayCutout; import static android.view.WindowInsets.Type.ime; import static android.view.WindowInsets.Type.mandatorySystemGestures; @@ -42,6 +38,7 @@ import android.view.InsetsSourceControl; import android.view.InsetsState; import android.view.InsetsState.InternalInsetsType; import android.view.WindowInsets; +import android.view.WindowInsets.Type.InsetsType; import com.android.internal.protolog.common.ProtoLog; import com.android.server.inputmethod.InputMethodManagerInternal; @@ -62,12 +59,10 @@ class InsetsStateController { private final ArrayMap mProviders = new ArrayMap<>(); - private final ArrayMap> mControlTargetTypeMap = - new ArrayMap<>(); - private final SparseArray mTypeControlTargetMap = new SparseArray<>(); - - /** @see #onControlFakeTargetChanged */ - private final SparseArray mTypeFakeControlTargetMap = new SparseArray<>(); + private final ArrayMap> + mControlTargetProvidersMap = new ArrayMap<>(); + private final SparseArray mIdControlTargetMap = new SparseArray<>(); + private final SparseArray mIdFakeControlTargetMap = new SparseArray<>(); private final ArraySet mPendingControlChanged = new ArraySet<>(); @@ -108,14 +103,14 @@ class InsetsStateController { } @Nullable InsetsSourceControl[] getControlsForDispatch(InsetsControlTarget target) { - ArrayList controlled = mControlTargetTypeMap.get(target); + final ArrayList controlled = mControlTargetProvidersMap.get(target); if (controlled == null) { return null; } final int size = controlled.size(); final InsetsSourceControl[] result = new InsetsSourceControl[size]; for (int i = 0; i < size; i++) { - result[i] = mProviders.get(controlled.get(i)).getControl(target); + result[i] = controlled.get(i).getControl(target); } return result; } @@ -208,8 +203,16 @@ class InsetsStateController { } } - boolean isFakeTarget(@InternalInsetsType int type, InsetsControlTarget target) { - return mTypeFakeControlTargetMap.get(type) == target; + @InsetsType int getFakeControllingTypes(InsetsControlTarget target) { + @InsetsType int types = 0; + for (int i = mProviders.size() - 1; i >= 0; i--) { + final InsetsSourceProvider provider = mProviders.valueAt(i); + final InsetsControlTarget fakeControlTarget = provider.getFakeControlTarget(); + if (target == fakeControlTarget) { + types |= provider.getSource().getType(); + } + } + return types; } void onImeControlTargetChanged(@Nullable InsetsControlTarget imeTarget) { @@ -217,7 +220,7 @@ class InsetsStateController { // Make sure that we always have a control target for the IME, even if the IME target is // null. Otherwise there is no leash that will hide it and IME becomes "randomly" visible. InsetsControlTarget target = imeTarget != null ? imeTarget : mEmptyImeControlTarget; - onControlChanged(ID_IME, target); + onControlTargetChanged(getImeSourceProvider(), target, false /* fake */); ProtoLog.d(WM_DEBUG_IME, "onImeControlTargetChanged %s", target != null ? target.getWindow() : "null"); notifyPendingInsetsControlChanged(); @@ -235,101 +238,88 @@ class InsetsStateController { @Nullable InsetsControlTarget fakeStatusControlling, @Nullable InsetsControlTarget navControlling, @Nullable InsetsControlTarget fakeNavControlling) { - onControlChanged(ITYPE_STATUS_BAR, statusControlling); - onControlChanged(ITYPE_NAVIGATION_BAR, navControlling); - onControlChanged(ITYPE_CLIMATE_BAR, statusControlling); - onControlChanged(ITYPE_EXTRA_NAVIGATION_BAR, navControlling); - onControlFakeTargetChanged(ITYPE_STATUS_BAR, fakeStatusControlling); - onControlFakeTargetChanged(ITYPE_NAVIGATION_BAR, fakeNavControlling); - onControlFakeTargetChanged(ITYPE_CLIMATE_BAR, fakeStatusControlling); - onControlFakeTargetChanged(ITYPE_EXTRA_NAVIGATION_BAR, fakeNavControlling); + for (int i = mProviders.size() - 1; i >= 0; i--) { + final InsetsSourceProvider provider = mProviders.valueAt(i); + final @InsetsType int type = provider.getSource().getType(); + if (type == WindowInsets.Type.statusBars()) { + onControlTargetChanged(provider, statusControlling, false /* fake */); + onControlTargetChanged(provider, fakeStatusControlling, true /* fake */); + } else if (type == WindowInsets.Type.navigationBars()) { + onControlTargetChanged(provider, navControlling, false /* fake */); + onControlTargetChanged(provider, fakeNavControlling, true /* fake */); + } + } notifyPendingInsetsControlChanged(); } void notifyControlRevoked(@NonNull InsetsControlTarget previousControlTarget, InsetsSourceProvider provider) { - removeFromControlMaps(previousControlTarget, provider.getSource().getId(), - false /* fake */); + removeFromControlMaps(previousControlTarget, provider, false /* fake */); } - private void onControlChanged(@InternalInsetsType int type, - @Nullable InsetsControlTarget target) { - final InsetsControlTarget previous = mTypeControlTargetMap.get(type); - if (target == previous) { - return; - } - final WindowContainerInsetsSourceProvider provider = mProviders.get(type); - if (provider == null) { + private void onControlTargetChanged(InsetsSourceProvider provider, + @Nullable InsetsControlTarget target, boolean fake) { + final InsetsControlTarget lastTarget = fake + ? mIdFakeControlTargetMap.get(provider.getSource().getId()) + : mIdControlTargetMap.get(provider.getSource().getId()); + if (target == lastTarget) { return; } if (!provider.isControllable()) { return; } - provider.updateControlForTarget(target, false /* force */); - target = provider.getControlTarget(); - if (previous != null) { - removeFromControlMaps(previous, type, false /* fake */); - mPendingControlChanged.add(previous); + if (fake) { + // The fake target updated here will be used to pretend to the app that it's still under + // control of the bars while it's not really, but we still need to find out the apps + // intentions around showing/hiding. For example, when the transient bars are showing, + // and the fake target requests to show system bars, the transient state will be + // aborted. + provider.updateFakeControlTarget(target); + } else { + provider.updateControlForTarget(target, false /* force */); + + // Get control target again in case the provider didn't accept the one we passed to it. + target = provider.getControlTarget(); + if (target == lastTarget) { + return; + } + } + if (lastTarget != null) { + removeFromControlMaps(lastTarget, provider, fake); + mPendingControlChanged.add(lastTarget); } if (target != null) { - addToControlMaps(target, type, false /* fake */); + addToControlMaps(target, provider, fake); mPendingControlChanged.add(target); } } - /** - * The fake target saved here will be used to pretend to the app that it's still under control - * of the bars while it's not really, but we still need to find out the apps intentions around - * showing/hiding. For example, when the transient bars are showing, and the fake target - * requests to show system bars, the transient state will be aborted. - */ - void onControlFakeTargetChanged(@InternalInsetsType int type, - @Nullable InsetsControlTarget fakeTarget) { - final InsetsControlTarget previous = mTypeFakeControlTargetMap.get(type); - if (fakeTarget == previous) { - return; - } - final WindowContainerInsetsSourceProvider provider = mProviders.get(type); - if (provider == null) { - return; - } - provider.updateControlForFakeTarget(fakeTarget); - if (previous != null) { - removeFromControlMaps(previous, type, true /* fake */); - mPendingControlChanged.add(previous); - } - if (fakeTarget != null) { - addToControlMaps(fakeTarget, type, true /* fake */); - mPendingControlChanged.add(fakeTarget); - } - } - private void removeFromControlMaps(@NonNull InsetsControlTarget target, - @InternalInsetsType int type, boolean fake) { - final ArrayList array = mControlTargetTypeMap.get(target); + InsetsSourceProvider provider, boolean fake) { + final ArrayList array = mControlTargetProvidersMap.get(target); if (array == null) { return; } - array.remove((Integer) type); + array.remove(provider); if (array.isEmpty()) { - mControlTargetTypeMap.remove(target); + mControlTargetProvidersMap.remove(target); } if (fake) { - mTypeFakeControlTargetMap.remove(type); + mIdFakeControlTargetMap.remove(provider.getSource().getId()); } else { - mTypeControlTargetMap.remove(type); + mIdControlTargetMap.remove(provider.getSource().getId()); } } private void addToControlMaps(@NonNull InsetsControlTarget target, - @InternalInsetsType int type, boolean fake) { - final ArrayList array = mControlTargetTypeMap.computeIfAbsent(target, - key -> new ArrayList<>()); - array.add(type); + InsetsSourceProvider provider, boolean fake) { + final ArrayList array = mControlTargetProvidersMap.computeIfAbsent( + target, key -> new ArrayList<>()); + array.add(provider); if (fake) { - mTypeFakeControlTargetMap.put(type, target); + mIdFakeControlTargetMap.put(provider.getSource().getId(), target); } else { - mTypeControlTargetMap.put(type, target); + mIdControlTargetMap.put(provider.getSource().getId(), target); } } @@ -351,7 +341,7 @@ class InsetsStateController { for (int i = mPendingControlChanged.size() - 1; i >= 0; i--) { final InsetsControlTarget controlTarget = mPendingControlChanged.valueAt(i); controlTarget.notifyInsetsControlChanged(); - if (mControlTargetTypeMap.containsKey(controlTarget)) { + if (mControlTargetProvidersMap.containsKey(controlTarget)) { // We only collect targets who get controls, not lose controls. newControlTargets.add(controlTarget); } @@ -377,10 +367,25 @@ class InsetsStateController { prefix = prefix + " "; mState.dump(prefix, pw); pw.println(prefix + "Control map:"); - for (int i = mTypeControlTargetMap.size() - 1; i >= 0; i--) { + for (int i = mControlTargetProvidersMap.size() - 1; i >= 0; i--) { + final InsetsControlTarget controlTarget = mControlTargetProvidersMap.keyAt(i); pw.print(prefix + " "); - pw.println(InsetsState.typeToString(mTypeControlTargetMap.keyAt(i)) + " -> " - + mTypeControlTargetMap.valueAt(i)); + pw.print(controlTarget); + pw.println(":"); + final ArrayList providers = mControlTargetProvidersMap.valueAt(i); + for (int j = providers.size() - 1; j >= 0; j--) { + final InsetsSourceProvider provider = providers.get(j); + if (provider != null) { + pw.print(prefix + " "); + if (controlTarget == provider.getFakeControlTarget()) { + pw.print("(fake) "); + } + pw.println(provider.getControl(controlTarget)); + } + } + } + if (mControlTargetProvidersMap.isEmpty()) { + pw.print(prefix + " none"); } pw.println(prefix + "InsetsSourceProviders:"); for (int i = mProviders.size() - 1; i >= 0; i--) { diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java index dba299566f84d..1a126cfa5c2c4 100644 --- a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java @@ -280,8 +280,7 @@ public class InsetsPolicyTest extends WindowTestsBase { assertFalse(mDisplayContent.getInsetsStateController().getRawInsetsState() .isSourceOrDefaultVisible(ITYPE_NAVIGATION_BAR, navigationBars())); - policy.showTransient(new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR}, - true /* isGestureOnSystemBar */); + policy.showTransient(navigationBars() | statusBars(), true /* isGestureOnSystemBar */); waitUntilWindowAnimatorIdle(); final InsetsSourceControl[] controls = mDisplayContent.getInsetsStateController().getControlsForDispatch(mAppWindow); @@ -308,11 +307,11 @@ public class InsetsPolicyTest extends WindowTestsBase { spyOn(policy); doNothing().when(policy).startAnimation(anyBoolean(), any()); policy.updateBarControlTarget(mAppWindow); - policy.showTransient(new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR}, + policy.showTransient(navigationBars() | statusBars(), true /* isGestureOnSystemBar */); waitUntilWindowAnimatorIdle(); - assertTrue(policy.isTransient(ITYPE_STATUS_BAR)); - assertFalse(policy.isTransient(ITYPE_NAVIGATION_BAR)); + assertTrue(policy.isTransient(statusBars())); + assertFalse(policy.isTransient(navigationBars())); final InsetsSourceControl[] controls = mDisplayContent.getInsetsStateController().getControlsForDispatch(mAppWindow); @@ -344,7 +343,7 @@ public class InsetsPolicyTest extends WindowTestsBase { spyOn(policy); doNothing().when(policy).startAnimation(anyBoolean(), any()); policy.updateBarControlTarget(mAppWindow); - policy.showTransient(new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR}, + policy.showTransient(navigationBars() | statusBars(), true /* isGestureOnSystemBar */); waitUntilWindowAnimatorIdle(); InsetsSourceControl[] controls = @@ -393,13 +392,13 @@ public class InsetsPolicyTest extends WindowTestsBase { spyOn(policy); doNothing().when(policy).startAnimation(anyBoolean(), any()); policy.updateBarControlTarget(app); - policy.showTransient(new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR}, + policy.showTransient(navigationBars() | statusBars(), true /* isGestureOnSystemBar */); final InsetsSourceControl[] controls = mDisplayContent.getInsetsStateController().getControlsForDispatch(app); policy.updateBarControlTarget(app2); - assertFalse(policy.isTransient(ITYPE_STATUS_BAR)); - assertFalse(policy.isTransient(ITYPE_NAVIGATION_BAR)); + assertFalse(policy.isTransient(statusBars())); + assertFalse(policy.isTransient(navigationBars())); } private WindowState addNavigationBar() { diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java index 88ecd3fe2ceaf..5df8421d3aea4 100644 --- a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java @@ -351,10 +351,10 @@ public class InsetsStateControllerTest extends WindowTestsBase { assertTrue(rotatedState.isSourceOrDefaultVisible(ITYPE_STATUS_BAR, statusBars())); provider.getSource().setVisible(false); - mDisplayContent.getInsetsPolicy().showTransient(new int[] { ITYPE_STATUS_BAR }, + mDisplayContent.getInsetsPolicy().showTransient(statusBars(), true /* isGestureOnSystemBar */); - assertTrue(mDisplayContent.getInsetsPolicy().isTransient(ITYPE_STATUS_BAR)); + assertTrue(mDisplayContent.getInsetsPolicy().isTransient(statusBars())); assertFalse(app.getInsetsState().isSourceOrDefaultVisible(ITYPE_STATUS_BAR, statusBars())); } diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContainerInsetsSourceProviderTest.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerInsetsSourceProviderTest.java index 1e5ec4c4e48cc..7d13de84642ea 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerInsetsSourceProviderTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerInsetsSourceProviderTest.java @@ -170,10 +170,10 @@ public class WindowContainerInsetsSourceProviderTest extends WindowTestsBase { final WindowState target = createWindow(null, TYPE_APPLICATION, "target"); statusBar.getFrame().set(0, 0, 500, 100); mProvider.setWindowContainer(statusBar, null, null); - mProvider.updateControlForFakeTarget(target); + mProvider.updateFakeControlTarget(target); assertNotNull(mProvider.getControl(target)); assertNull(mProvider.getControl(target).getLeash()); - mProvider.updateControlForFakeTarget(null); + mProvider.updateFakeControlTarget(null); assertNull(mProvider.getControl(target)); }