[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
This commit is contained in:
Caitlin Cassidy
2021-12-28 18:55:09 +00:00
parent bb7dc5afcb
commit 06a2da0b98
9 changed files with 247 additions and 32 deletions

View File

@@ -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.KeyguardStateController;
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 @@ public class NotificationPanelViewController extends PanelViewController {
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 @@ public class NotificationPanelViewController extends PanelViewController {
mQs.animateHeaderSlidingOut();
}
});
statusBarWindowStateController.addListener(this::onStatusBarWindowStateChanged);
mThemeResId = mView.getContext().getThemeResId();
mKeyguardBypassController = bypassController;
mUpdateMonitor = keyguardUpdateMonitor;
@@ -5006,4 +5011,14 @@ public class NotificationPanelViewController extends PanelViewController {
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 */);
}
}
}

View File

@@ -232,6 +232,7 @@ import com.android.systemui.statusbar.policy.KeyguardStateController;
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 @@ public class StatusBar extends CoreStartable implements
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 @@ public class StatusBar extends CoreStartable implements
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 @@ public class StatusBar extends CoreStartable implements
LightBarController lightBarController,
AutoHideController autoHideController,
StatusBarWindowController statusBarWindowController,
StatusBarWindowStateController statusBarWindowStateController,
KeyguardUpdateMonitor keyguardUpdateMonitor,
StatusBarSignalPolicy statusBarSignalPolicy,
PulseExpansionHandler pulseExpansionHandler,
@@ -872,6 +876,7 @@ public class StatusBar extends CoreStartable implements
mStartingSurfaceOptional = startingSurfaceOptional;
mNotifPipelineFlags = notifPipelineFlags;
lockscreenShadeTransitionController.setStatusbar(this);
statusBarWindowStateController.addListener(this::onStatusBarWindowStateChanged);
mScreenOffAnimationController = screenOffAnimationController;

View File

@@ -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.keyguard.WakefulnessLifecycle;
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;
@@ -514,30 +511,6 @@ public class StatusBarCommandQueueCallbacks implements CommandQueue.Callbacks {
.setTopAppHidesStatusBarAndTriggerUpdate(topAppHidesStatusBar);
}
@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();

View File

@@ -105,6 +105,7 @@ import com.android.systemui.statusbar.policy.KeyguardStateController;
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 @@ public interface StatusBarPhoneModule {
LightBarController lightBarController,
AutoHideController autoHideController,
StatusBarWindowController statusBarWindowController,
StatusBarWindowStateController statusBarWindowStateController,
KeyguardUpdateMonitor keyguardUpdateMonitor,
StatusBarSignalPolicy statusBarSignalPolicy,
PulseExpansionHandler pulseExpansionHandler,
@@ -235,6 +237,7 @@ public interface StatusBarPhoneModule {
lightBarController,
autoHideController,
statusBarWindowController,
statusBarWindowStateController,
keyguardUpdateMonitor,
statusBarSignalPolicy,
pulseExpansionHandler,

View File

@@ -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) }
}
}

View File

@@ -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)
}

View File

@@ -141,6 +141,7 @@ import com.android.systemui.statusbar.policy.KeyguardQsUserSwitchController;
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 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
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 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
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,

View File

@@ -147,6 +147,7 @@ import com.android.systemui.statusbar.policy.KeyguardStateController;
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 @@ public class StatusBarTest extends SysuiTestCase {
@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 @@ public class StatusBarTest extends SysuiTestCase {
mLightBarController,
mAutoHideController,
mStatusBarWindowController,
mStatusBarWindowStateController,
mKeyguardUpdateMonitor,
mStatusBarSignalPolicy,
mPulseExpansionHandler,

View File

@@ -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