diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java index a09b30f41f498..af556a26e3af3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java @@ -79,6 +79,8 @@ public class PhoneStatusBarView extends PanelBar { private int mStatusBarHeight; @Nullable private List mExpansionChangedListeners; + @Nullable + private PanelExpansionStateChangedListener mPanelExpansionStateChangedListener; private PanelEnabledProvider mPanelEnabledProvider; @@ -102,6 +104,10 @@ public class PhoneStatusBarView extends PanelBar { mExpansionChangedListeners = listeners; } + void setPanelExpansionStateChangedListener(PanelExpansionStateChangedListener listener) { + mPanelExpansionStateChangedListener = listener; + } + public void setScrimController(ScrimController scrimController) { mScrimController = scrimController; } @@ -289,11 +295,10 @@ public class PhoneStatusBarView extends PanelBar { super.panelExpansionChanged(frac, expanded); updateScrimFraction(); if ((frac == 0 || frac == 1)) { - if (mBar.getNavigationBarView() != null) { - mBar.getNavigationBarView().onStatusBarPanelStateChanged(); - } - if (mBar.getNotificationPanelViewController() != null) { - mBar.getNotificationPanelViewController().updateSystemUiStateFlags(); + if (mPanelExpansionStateChangedListener != null) { + mPanelExpansionStateChangedListener.onPanelExpansionStateChanged(); + } else { + Log.w(TAG, "No PanelExpansionStateChangedListener provided."); } } @@ -412,4 +417,10 @@ public class PhoneStatusBarView extends PanelBar { /** Returns true if the panel is enabled and false otherwise. */ boolean panelEnabled(); } + + /** A listener that will be notified when a panel's expansion state may have changed. */ + public interface PanelExpansionStateChangedListener { + /** Called when a panel's expansion state may have changed. */ + void onPanelExpansionStateChanged(); + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt index 9799533a568d2..28040fd8d8a10 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt @@ -27,7 +27,8 @@ import com.android.systemui.util.ViewController class PhoneStatusBarViewController( view: PhoneStatusBarView, commandQueue: CommandQueue, - statusBarMoveFromCenterAnimationController: StatusBarMoveFromCenterAnimationController? + statusBarMoveFromCenterAnimationController: StatusBarMoveFromCenterAnimationController?, + panelExpansionStateChangedListener: PhoneStatusBarView.PanelExpansionStateChangedListener, ) : ViewController(view) { override fun onViewAttached() {} @@ -37,6 +38,7 @@ class PhoneStatusBarViewController( mView.setPanelEnabledProvider { commandQueue.panelsEnabled() } + mView.setPanelExpansionStateChangedListener(panelExpansionStateChangedListener) statusBarMoveFromCenterAnimationController?.let { animationController -> val statusBarLeftSide: View = mView.findViewById(R.id.status_bar_left_side) 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 4220a6876478b..50db1362cc906 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -1152,8 +1152,11 @@ public class StatusBar extends SystemUI implements moveFromCenterAnimation = mMoveFromCenterAnimation.get(); } mPhoneStatusBarViewController = - new PhoneStatusBarViewController(mStatusBarView, mCommandQueue, - moveFromCenterAnimation); + new PhoneStatusBarViewController( + mStatusBarView, + mCommandQueue, + moveFromCenterAnimation, + this::onPanelExpansionStateChanged); mPhoneStatusBarViewController.init(); mBatteryMeterViewController = new BatteryMeterViewController( @@ -1424,6 +1427,15 @@ public class StatusBar extends SystemUI implements } } + private void onPanelExpansionStateChanged() { + if (getNavigationBarView() != null) { + getNavigationBarView().onStatusBarPanelStateChanged(); + } + if (getNotificationPanelViewController() != null) { + getNotificationPanelViewController().updateSystemUiStateFlags(); + } + } + @NonNull @Override public Lifecycle getLifecycle() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt index c7d4794bd962e..52a5e064f984e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt @@ -17,11 +17,14 @@ package com.android.systemui.statusbar.phone import android.view.LayoutInflater +import android.view.ViewGroup import android.widget.FrameLayout import androidx.test.filters.SmallTest import androidx.test.platform.app.InstrumentationRegistry +import com.android.systemui.R import com.android.systemui.SysuiTestCase import com.android.systemui.statusbar.CommandQueue +import com.android.systemui.util.mockito.any import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Test @@ -29,14 +32,20 @@ import org.mockito.Mock import org.mockito.Mockito.`when` import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations -import com.android.systemui.R -import com.android.systemui.util.mockito.any @SmallTest class PhoneStatusBarViewControllerTest : SysuiTestCase() { + private val stateChangeListener = TestStateChangedListener() + @Mock private lateinit var commandQueue: CommandQueue + @Mock + private lateinit var panelViewController: PanelViewController + @Mock + private lateinit var panelView: ViewGroup + @Mock + private lateinit var scrimController: ScrimController @Mock private lateinit var moveFromCenterAnimation: StatusBarMoveFromCenterAnimationController @@ -47,13 +56,23 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() { @Before fun setUp() { MockitoAnnotations.initMocks(this) + `when`(panelViewController.view).thenReturn(panelView) + // create the view on main thread as it requires main looper InstrumentationRegistry.getInstrumentation().runOnMainSync { val parent = FrameLayout(mContext) // add parent to keep layout params view = LayoutInflater.from(mContext) .inflate(R.layout.status_bar, parent, false) as PhoneStatusBarView + view.setPanel(panelViewController) + view.setScrimController(scrimController) } - controller = PhoneStatusBarViewController(view, commandQueue, null) + + controller = PhoneStatusBarViewController( + view, + commandQueue, + null, + stateChangeListener + ) } @Test @@ -73,8 +92,29 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() { @Test fun constructor_moveFromCenterAnimationIsNotNull_moveFromCenterAnimationInitialized() { - controller = PhoneStatusBarViewController(view, commandQueue, moveFromCenterAnimation) + controller = PhoneStatusBarViewController( + view, commandQueue, moveFromCenterAnimation, stateChangeListener + ) verify(moveFromCenterAnimation).init(any(), any()) } + + @Test + fun constructor_setsExpansionStateChangedListenerOnView() { + assertThat(stateChangeListener.stateChangeCalled).isFalse() + + // If the constructor correctly set the listener, then it should be used when + // [PhoneStatusBarView.panelExpansionChanged] is called. + view.panelExpansionChanged(0f, false) + + assertThat(stateChangeListener.stateChangeCalled).isTrue() + } + + private class TestStateChangedListener : PhoneStatusBarView.PanelExpansionStateChangedListener { + var stateChangeCalled: Boolean = false + + override fun onPanelExpansionStateChanged() { + stateChangeCalled = true + } + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewTest.kt index 49ab6ebbde93e..aee9f12c3844a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewTest.kt @@ -16,20 +16,38 @@ package com.android.systemui.statusbar.phone +import android.view.ViewGroup import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Test +import org.mockito.Mock +import org.mockito.Mockito.`when` +import org.mockito.MockitoAnnotations @SmallTest class PhoneStatusBarViewTest : SysuiTestCase() { + @Mock + private lateinit var panelViewController: PanelViewController + @Mock + private lateinit var panelView: ViewGroup + @Mock + private lateinit var scrimController: ScrimController + private lateinit var view: PhoneStatusBarView @Before fun setUp() { + MockitoAnnotations.initMocks(this) + // TODO(b/197137564): Setting up a panel view and its controller feels unnecessary when + // testing just [PhoneStatusBarView]. + `when`(panelViewController.view).thenReturn(panelView) + view = PhoneStatusBarView(mContext, null) + view.setPanel(panelViewController) + view.setScrimController(scrimController) } @Test @@ -51,4 +69,48 @@ class PhoneStatusBarViewTest : SysuiTestCase() { view.panelEnabled() // No assert needed, just testing no crash } + + @Test + fun panelExpansionChanged_fracZero_stateChangeListenerNotified() { + val listener = TestStateChangedListener() + view.setPanelExpansionStateChangedListener(listener) + + view.panelExpansionChanged(0f, false) + + assertThat(listener.stateChangeCalled).isTrue() + } + + @Test + fun panelExpansionChanged_fracOne_stateChangeListenerNotified() { + val listener = TestStateChangedListener() + view.setPanelExpansionStateChangedListener(listener) + + view.panelExpansionChanged(1f, false) + + assertThat(listener.stateChangeCalled).isTrue() + } + + @Test + fun panelExpansionChanged_fracHalf_stateChangeListenerNotNotified() { + val listener = TestStateChangedListener() + view.setPanelExpansionStateChangedListener(listener) + + view.panelExpansionChanged(0.5f, false) + + assertThat(listener.stateChangeCalled).isFalse() + } + + @Test + fun panelExpansionChanged_noStateChangeListener_noCrash() { + view.panelExpansionChanged(1f, false) + // No assert needed, just testing no crash + } + + private class TestStateChangedListener : PhoneStatusBarView.PanelExpansionStateChangedListener { + var stateChangeCalled: Boolean = false + + override fun onPanelExpansionStateChanged() { + stateChangeCalled = true + } + } }