[Status Bar Refactor] Move status bar window state tracking into a
centralized class and add some listeners for it.
Bug: 212424936
Test: manual (verified callbacks trigger)
Test: new StatusBarWindowStateControllerTest
Change-Id: Ib75206c05551ddf6512dd608295b9043dabd7c88
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
index 434671c..08b5cf5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.phone;
+import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
import static android.view.View.GONE;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
@@ -197,6 +198,7 @@
import com.android.systemui.statusbar.policy.KeyguardUserSwitcherController;
import com.android.systemui.statusbar.policy.KeyguardUserSwitcherView;
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
+import com.android.systemui.statusbar.window.StatusBarWindowStateController;
import com.android.systemui.unfold.SysUIUnfoldComponent;
import com.android.systemui.util.Utils;
import com.android.systemui.util.settings.SecureSettings;
@@ -732,7 +734,9 @@
NotificationEntryManager notificationEntryManager,
CommunalStateController communalStateController,
KeyguardStateController keyguardStateController,
- StatusBarStateController statusBarStateController, DozeLog dozeLog,
+ StatusBarStateController statusBarStateController,
+ StatusBarWindowStateController statusBarWindowStateController,
+ DozeLog dozeLog,
DozeParameters dozeParameters, CommandQueue commandQueue, VibratorHelper vibratorHelper,
LatencyTracker latencyTracker, PowerManager powerManager,
AccessibilityManager accessibilityManager, @DisplayId int displayId,
@@ -862,6 +866,7 @@
mQs.animateHeaderSlidingOut();
}
});
+ statusBarWindowStateController.addListener(this::onStatusBarWindowStateChanged);
mThemeResId = mView.getContext().getThemeResId();
mKeyguardBypassController = bypassController;
mUpdateMonitor = keyguardUpdateMonitor;
@@ -5006,4 +5011,14 @@
public PhoneStatusBarView.TouchEventHandler getStatusBarTouchEventHandler() {
return mStatusBarViewTouchEventHandler;
}
+
+ private void onStatusBarWindowStateChanged(@StatusBarManager.WindowVisibleState int state) {
+ if (state != WINDOW_STATE_SHOWING
+ && mStatusBarStateController.getState() == StatusBarState.SHADE) {
+ collapsePanel(
+ false /* animate */,
+ false /* delayed */,
+ 1.0f /* speedUpFactor */);
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 8fe03e4..4ecbb7c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -232,6 +232,7 @@
import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.statusbar.window.StatusBarWindowController;
+import com.android.systemui.statusbar.window.StatusBarWindowStateController;
import com.android.systemui.util.DumpUtilsKt;
import com.android.systemui.util.WallpaperController;
import com.android.systemui.util.concurrency.DelayableExecutor;
@@ -337,9 +338,11 @@
private final LockscreenShadeTransitionController mLockscreenShadeTransitionController;
private StatusBarCommandQueueCallbacks mCommandQueueCallbacks;
- void setWindowState(int state) {
- mStatusBarWindowState = state;
+ void onStatusBarWindowStateChanged(@WindowVisibleState int state) {
+ updateBubblesVisibility();
+ mStatusBarWindowState = state;
mStatusBarWindowHidden = state == WINDOW_STATE_HIDDEN;
+ // TODO(b/212424936): Have this icon manager just implement its own listener.
mStatusBarHideIconsForBouncerManager.setStatusBarWindowHidden(mStatusBarWindowHidden);
if (mStatusBarView != null) {
// Should #updateHideIconsForBouncer always be called, regardless of whether we have a
@@ -464,7 +467,7 @@
private PhoneStatusBarViewController mPhoneStatusBarViewController;
private PhoneStatusBarTransitions mStatusBarTransitions;
private AuthRippleController mAuthRippleController;
- private int mStatusBarWindowState = WINDOW_STATE_SHOWING;
+ @WindowVisibleState private int mStatusBarWindowState = WINDOW_STATE_SHOWING;
protected NotificationShadeWindowController mNotificationShadeWindowController;
private final StatusBarWindowController mStatusBarWindowController;
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
@@ -692,6 +695,7 @@
LightBarController lightBarController,
AutoHideController autoHideController,
StatusBarWindowController statusBarWindowController,
+ StatusBarWindowStateController statusBarWindowStateController,
KeyguardUpdateMonitor keyguardUpdateMonitor,
StatusBarSignalPolicy statusBarSignalPolicy,
PulseExpansionHandler pulseExpansionHandler,
@@ -872,6 +876,7 @@
mStartingSurfaceOptional = startingSurfaceOptional;
mNotifPipelineFlags = notifPipelineFlags;
lockscreenShadeTransitionController.setStatusbar(this);
+ statusBarWindowStateController.addListener(this::onStatusBarWindowStateChanged);
mScreenOffAnimationController = screenOffAnimationController;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarCommandQueueCallbacks.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarCommandQueueCallbacks.java
index b391de3..51f2e67 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarCommandQueueCallbacks.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarCommandQueueCallbacks.java
@@ -16,8 +16,6 @@
package com.android.systemui.statusbar.phone;
-import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
-import static android.app.StatusBarManager.windowStateToString;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
import static android.view.InsetsState.containsType;
@@ -58,7 +56,6 @@
import com.android.systemui.qs.QSPanelController;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.DisableFlagsLogger;
-import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
@@ -515,30 +512,6 @@
}
@Override
- public void setWindowState(
- int displayId, @StatusBarManager.WindowType int window,
- @StatusBarManager.WindowVisibleState int state) {
- if (displayId != mDisplayId) {
- return;
- }
- boolean showing = state == WINDOW_STATE_SHOWING;
- if (mNotificationShadeWindowView != null
- && window == StatusBarManager.WINDOW_STATUS_BAR
- && !mStatusBar.isSameStatusBarState(state)) {
- mStatusBar.setWindowState(state);
- if (StatusBar.DEBUG_WINDOW_STATE) {
- Log.d(StatusBar.TAG, "Status bar " + windowStateToString(state));
- }
- if (!showing && mStatusBarStateController.getState() == StatusBarState.SHADE) {
- mNotificationPanelViewController.collapsePanel(
- false /* animate */, false /* delayed */, 1.0f /* speedUpFactor */);
- }
- }
-
- mStatusBar.updateBubblesVisibility();
- }
-
- @Override
public void showAssistDisclosure() {
mAssistManager.showDisclosure();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
index f93a8dc..4830b37 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
@@ -105,6 +105,7 @@
import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.statusbar.window.StatusBarWindowController;
+import com.android.systemui.statusbar.window.StatusBarWindowStateController;
import com.android.systemui.util.WallpaperController;
import com.android.systemui.util.concurrency.DelayableExecutor;
import com.android.systemui.util.concurrency.MessageRouter;
@@ -140,6 +141,7 @@
LightBarController lightBarController,
AutoHideController autoHideController,
StatusBarWindowController statusBarWindowController,
+ StatusBarWindowStateController statusBarWindowStateController,
KeyguardUpdateMonitor keyguardUpdateMonitor,
StatusBarSignalPolicy statusBarSignalPolicy,
PulseExpansionHandler pulseExpansionHandler,
@@ -235,6 +237,7 @@
lightBarController,
autoHideController,
statusBarWindowController,
+ statusBarWindowStateController,
keyguardUpdateMonitor,
statusBarSignalPolicy,
pulseExpansionHandler,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowStateController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowStateController.kt
new file mode 100644
index 0000000..facbe8a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowStateController.kt
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.window
+
+import android.app.StatusBarManager
+import android.app.StatusBarManager.WindowVisibleState
+import android.app.StatusBarManager.WINDOW_STATE_SHOWING
+import android.app.StatusBarManager.WINDOW_STATUS_BAR
+import android.app.StatusBarManager.windowStateToString
+import android.util.Log
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.DisplayId
+import com.android.systemui.statusbar.CommandQueue
+import com.android.systemui.statusbar.phone.StatusBar
+import javax.inject.Inject
+
+/**
+ * A centralized class maintaining the state of the status bar window.
+ *
+ * Classes that want to get updates about the status bar window state should subscribe to this class
+ * via [addListener] and should NOT add their own callback on [CommandQueue].
+ */
+@SysUISingleton
+class StatusBarWindowStateController @Inject constructor(
+ @DisplayId private val thisDisplayId: Int,
+ commandQueue: CommandQueue
+) {
+ private val commandQueueCallback = object : CommandQueue.Callbacks {
+ override fun setWindowState(
+ displayId: Int,
+ @StatusBarManager.WindowType window: Int,
+ @WindowVisibleState state: Int
+ ) {
+ this@StatusBarWindowStateController.setWindowState(displayId, window, state)
+ }
+ }
+ private val listeners: MutableSet<StatusBarWindowStateListener> = HashSet()
+
+ @WindowVisibleState private var windowState: Int = WINDOW_STATE_SHOWING
+
+ init {
+ commandQueue.addCallback(commandQueueCallback)
+ }
+
+ /** Adds a listener. */
+ fun addListener(listener: StatusBarWindowStateListener) {
+ listeners.add(listener)
+ }
+
+ private fun setWindowState(
+ displayId: Int,
+ @StatusBarManager.WindowType window: Int,
+ @WindowVisibleState state: Int
+ ) {
+ if (displayId != thisDisplayId) {
+ return
+ }
+ if (window != WINDOW_STATUS_BAR) {
+ return
+ }
+ if (windowState == state) {
+ return
+ }
+
+ windowState = state
+ if (StatusBar.DEBUG_WINDOW_STATE) {
+ Log.d(StatusBar.TAG, "Status bar " + windowStateToString(state))
+ }
+ listeners.forEach { it.onStatusBarWindowStateChanged(state) }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowStateListener.kt b/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowStateListener.kt
new file mode 100644
index 0000000..5586c1b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowStateListener.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.window
+
+import android.app.StatusBarManager
+
+/** Listener interface for changes in the status bar window state. */
+interface StatusBarWindowStateListener {
+ fun onStatusBarWindowStateChanged(@StatusBarManager.WindowVisibleState state: Int)
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java
index 1cd9b9e..df11bf6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java
@@ -141,6 +141,7 @@
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.KeyguardUserSwitcherController;
import com.android.systemui.statusbar.policy.KeyguardUserSwitcherView;
+import com.android.systemui.statusbar.window.StatusBarWindowStateController;
import com.android.systemui.unfold.SysUIUnfoldComponent;
import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.settings.SecureSettings;
@@ -358,6 +359,8 @@
private NotificationsQSContainerController mNotificationsQSContainerController;
@Mock
private QsFrameTranslateController mQsFrameTranslateController;
+ @Mock
+ private StatusBarWindowStateController mStatusBarWindowStateController;
private Optional<SysUIUnfoldComponent> mSysUIUnfoldComponent = Optional.empty();
private SysuiStatusBarStateController mStatusBarStateController;
private NotificationPanelViewController mNotificationPanelViewController;
@@ -491,7 +494,9 @@
coordinator, expansionHandler, mDynamicPrivacyController, mKeyguardBypassController,
mFalsingManager, new FalsingCollectorFake(),
mNotificationLockscreenUserManager, mNotificationEntryManager,
- mCommunalStateController, mKeyguardStateController, mStatusBarStateController,
+ mCommunalStateController, mKeyguardStateController,
+ mStatusBarStateController,
+ mStatusBarWindowStateController,
mDozeLog, mDozeParameters, mCommandQueue, mVibratorHelper,
mLatencyTracker, mPowerManager, mAccessibilityManager, 0, mUpdateMonitor,
mCommunalSourceMonitor, mMetricsLogger, mActivityManager, mConfigurationController,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index 9d5b17e..a4b6480 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -147,6 +147,7 @@
import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.statusbar.window.StatusBarWindowController;
+import com.android.systemui.statusbar.window.StatusBarWindowStateController;
import com.android.systemui.util.WallpaperController;
import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.concurrency.MessageRouterImpl;
@@ -228,6 +229,7 @@
@Mock private DynamicPrivacyController mDynamicPrivacyController;
@Mock private AutoHideController mAutoHideController;
@Mock private StatusBarWindowController mStatusBarWindowController;
+ @Mock private StatusBarWindowStateController mStatusBarWindowStateController;
@Mock private NotificationViewHierarchyManager mNotificationViewHierarchyManager;
@Mock private UserSwitcherController mUserSwitcherController;
@Mock private NetworkController mNetworkController;
@@ -374,6 +376,7 @@
mLightBarController,
mAutoHideController,
mStatusBarWindowController,
+ mStatusBarWindowStateController,
mKeyguardUpdateMonitor,
mStatusBarSignalPolicy,
mPulseExpansionHandler,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/window/StatusBarWindowStateControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/window/StatusBarWindowStateControllerTest.kt
new file mode 100644
index 0000000..8576d4f
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/window/StatusBarWindowStateControllerTest.kt
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.window
+
+import android.app.StatusBarManager.WindowVisibleState
+import android.app.StatusBarManager.WINDOW_NAVIGATION_BAR
+import android.app.StatusBarManager.WINDOW_STATE_HIDDEN
+import android.app.StatusBarManager.WINDOW_STATE_SHOWING
+import android.app.StatusBarManager.WINDOW_STATUS_BAR
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.statusbar.CommandQueue
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.mockito.ArgumentCaptor
+import org.mockito.Mock
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+class StatusBarWindowStateControllerTest : SysuiTestCase() {
+ private lateinit var controller: StatusBarWindowStateController
+ private lateinit var callback: CommandQueue.Callbacks
+
+ @Mock
+ private lateinit var commandQueue: CommandQueue
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ controller = StatusBarWindowStateController(DISPLAY_ID, commandQueue)
+
+ val callbackCaptor = ArgumentCaptor.forClass(CommandQueue.Callbacks::class.java)
+ verify(commandQueue).addCallback(callbackCaptor.capture())
+ callback = callbackCaptor.value!!
+ }
+
+ @Test
+ fun setWindowState_notSameDisplayId_listenersNotNotified() {
+ val listener = TestListener()
+ controller.addListener(listener)
+
+ callback.setWindowState(DISPLAY_ID + 1, WINDOW_STATUS_BAR, WINDOW_STATE_HIDDEN)
+
+ assertThat(listener.state).isNull()
+ }
+
+ @Test
+ fun setWindowState_notStatusBarWindow_listenersNotNotified() {
+ val listener = TestListener()
+ controller.addListener(listener)
+
+ callback.setWindowState(DISPLAY_ID, WINDOW_NAVIGATION_BAR, WINDOW_STATE_HIDDEN)
+
+ assertThat(listener.state).isNull()
+ }
+
+ @Test
+ fun setWindowState_sameState_listenersNotNotified() {
+ val listener = TestListener()
+ controller.addListener(listener)
+
+ callback.setWindowState(DISPLAY_ID, WINDOW_STATUS_BAR, WINDOW_STATE_SHOWING)
+
+ assertThat(listener.state).isNull()
+ }
+
+ @Test
+ fun setWindowState_newState_listenersNotified() {
+ val listener = TestListener()
+ controller.addListener(listener)
+ val newState = WINDOW_STATE_HIDDEN
+
+ callback.setWindowState(DISPLAY_ID, WINDOW_STATUS_BAR, newState)
+
+ assertThat(listener.state).isEqualTo(newState)
+ }
+
+ private class TestListener : StatusBarWindowStateListener {
+ @WindowVisibleState var state: Int? = null
+ override fun onStatusBarWindowStateChanged(@WindowVisibleState state: Int) {
+ this.state = state
+ }
+ }
+}
+
+private const val DISPLAY_ID = 10