From 2f9bd04d63c4302ee72c59ef40f7fd9ad001e476 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Go=CC=88llner?= Date: Thu, 9 Mar 2023 15:50:06 +0100 Subject: [PATCH] Fix lockscreen shortcuts not showing on split shade The issue was that qsVisible was wrongly being set to `true` when on split shade, even when it was not visible. Lockscreen shortcuts only show when QS are not visible. To check whether QS (or QQS) was visible, we were checking: 1 - qsExpansionFraction > 0 1.1 Split shade: true when full QS showing 1.2 Single shade: true when full QS showing 2 - qsPanelBottomY > 0 2.1 Split Shade: ALWAYS true. Even if QS not showing 2.2 Single shade: true when on QQS or QS Since on split shade we can always rely on qsExpansionFraction, because there is no QQS, we changed the condition to ignore qsPanelBottomY when on split shade. Fixes: 272448562 Test: Manually on-device: 1 - Enabled teamfood flag 2 - Homescreen -> Wallpaper & Style 3 - Lockscreen -> Pick 2 non-none shortcuts 4 - Lock the screen 5 - Verify shortcuts are visible both in single and split shade Test: QuickSettingsControllerTest.java Change-Id: I9adc0c4625aadcc729b484c453c6ef7d17013fc9 --- .../shade/QuickSettingsController.java | 8 +- .../shade/QuickSettingsControllerTest.java | 112 ++++++++++++++++-- 2 files changed, 110 insertions(+), 10 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java index 099ad94736734..50e6c719e6464 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java +++ b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java @@ -1035,7 +1035,11 @@ public class QuickSettingsController { private void setClippingBounds() { float qsExpansionFraction = computeExpansionFraction(); final int qsPanelBottomY = calculateBottomPosition(qsExpansionFraction); - final boolean qsVisible = (qsExpansionFraction > 0 || qsPanelBottomY > 0); + // Split shade has no QQS + final boolean qqsVisible = + !mSplitShadeEnabled && qsExpansionFraction == 0 && qsPanelBottomY > 0; + final boolean qsVisible = qsExpansionFraction > 0; + final boolean qsOrQqsVisible = qqsVisible || qsVisible; checkCorrectScrimVisibility(qsExpansionFraction); int top = calculateTopClippingBound(qsPanelBottomY); @@ -1044,7 +1048,7 @@ public class QuickSettingsController { int right = calculateRightClippingBound(); // top should never be lower than bottom, otherwise it will be invisible. top = Math.min(top, bottom); - applyClippingBounds(left, top, right, bottom, qsVisible); + applyClippingBounds(left, top, right, bottom, qsOrQqsVisible); } /** diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerTest.java index e3a3678fd91e9..15b84238dd19e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerTest.java @@ -32,6 +32,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyFloat; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; @@ -77,7 +78,6 @@ import com.android.systemui.statusbar.StatusBarStateControllerImpl; import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.notification.stack.AmbientState; import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController; -import com.android.systemui.statusbar.phone.HeadsUpManagerPhone; import com.android.systemui.statusbar.phone.KeyguardBottomAreaView; import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.phone.KeyguardStatusBarView; @@ -91,9 +91,12 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import java.util.List; + import dagger.Lazy; @SmallTest @@ -101,12 +104,14 @@ import dagger.Lazy; @TestableLooper.RunWithLooper(setAsMainLooper = true) public class QuickSettingsControllerTest extends SysuiTestCase { - private static final int SPLIT_SHADE_FULL_TRANSITION_DISTANCE = 400; private static final float QS_FRAME_START_X = 0f; private static final int QS_FRAME_WIDTH = 1000; private static final int QS_FRAME_TOP = 0; private static final int QS_FRAME_BOTTOM = 1000; - + private static final int DEFAULT_HEIGHT = 1000; + // In split shade min = max + private static final int DEFAULT_MIN_HEIGHT_SPLIT_SHADE = DEFAULT_HEIGHT; + private static final int DEFAULT_MIN_HEIGHT = 300; private QuickSettingsController mQsController; @@ -115,7 +120,6 @@ public class QuickSettingsControllerTest extends SysuiTestCase { @Mock private KeyguardStatusBarView mKeyguardStatusBar; @Mock private QS mQs; @Mock private QSFragment mQSFragment; - @Mock private Lazy mPanelViewControllerLazy; @Mock private NotificationPanelViewController mNotificationPanelViewController; @Mock private NotificationPanelView mPanelView; @@ -147,10 +151,7 @@ public class QuickSettingsControllerTest extends SysuiTestCase { @Mock private FeatureFlags mFeatureFlags; @Mock private InteractionJankMonitor mInteractionJankMonitor; @Mock private ShadeLogger mShadeLogger; - @Mock private DumpManager mDumpManager; - - @Mock private HeadsUpManagerPhone mHeadsUpManager; @Mock private UiEventLogger mUiEventLogger; private SysuiStatusBarStateController mStatusBarStateController; @@ -173,6 +174,8 @@ public class QuickSettingsControllerTest extends SysuiTestCase { KeyguardStatusView keyguardStatusView = new KeyguardStatusView(mContext); keyguardStatusView.setId(R.id.keyguard_status_view); + when(mResources.getDimensionPixelSize( + R.dimen.lockscreen_shade_qs_transition_distance)).thenReturn(DEFAULT_HEIGHT); when(mPanelView.getResources()).thenReturn(mResources); when(mPanelView.getContext()).thenReturn(getContext()); when(mPanelView.findViewById(R.id.keyguard_header)).thenReturn(mKeyguardStatusBar); @@ -529,6 +532,88 @@ public class QuickSettingsControllerTest extends SysuiTestCase { assertThat(mQsController.isOpenQsEvent(event)).isTrue(); } + @Test + public void shadeClosed_onLockscreen_inSplitShade_setsQsNotVisible() { + mQsController.setQs(mQs); + enableSplitShade(true); + lockScreen(); + + closeLockedQS(); + + assertQsVisible(false); + } + + @Test + public void shadeOpened_onLockscreen_inSplitShade_setsQsVisible() { + mQsController.setQs(mQs); + enableSplitShade(true); + lockScreen(); + + openLockedQS(); + + assertQsVisible(true); + } + + @Test + public void shadeClosed_onLockscreen_inSingleShade_setsQsNotVisible() { + mQsController.setQs(mQs); + enableSplitShade(false); + lockScreen(); + + closeLockedQS(); + + verify(mQs).setQsVisible(false); + } + + @Test + public void shadeOpened_onLockscreen_inSingleShade_setsQsVisible() { + mQsController.setQs(mQs); + enableSplitShade(false); + lockScreen(); + + openLockedQS(); + + verify(mQs).setQsVisible(true); + } + + private void lockScreen() { + mQsController.setBarState(KEYGUARD); + } + + private void openLockedQS() { + when(mLockscreenShadeTransitionController.getQSDragProgress()) + .thenReturn((float) DEFAULT_HEIGHT); + mLockscreenShadeTransitionCallback.setTransitionToFullShadeAmount( + /* pxAmount= */ DEFAULT_HEIGHT, + /* animate=*/ false, + /* delay= */ 0 + ); + } + + private void closeLockedQS() { + when(mLockscreenShadeTransitionController.getQSDragProgress()).thenReturn(0f); + mLockscreenShadeTransitionCallback.setTransitionToFullShadeAmount( + /* pxAmount= */ 0, + /* animate=*/ false, + /* delay= */ 0 + ); + } + + private void setSplitShadeHeightProperties() { + // In split shade, min = max + when(mQs.getQsMinExpansionHeight()).thenReturn(DEFAULT_MIN_HEIGHT_SPLIT_SHADE); + when(mQs.getDesiredHeight()).thenReturn(DEFAULT_HEIGHT); + mQsController.updateMinHeight(); + mQsController.onHeightChanged(); + } + + private void setDefaultHeightProperties() { + when(mQs.getQsMinExpansionHeight()).thenReturn(DEFAULT_MIN_HEIGHT); + when(mQs.getDesiredHeight()).thenReturn(DEFAULT_HEIGHT); + mQsController.updateMinHeight(); + mQsController.onHeightChanged(); + } + private static MotionEvent createMotionEvent(int x, int y, int action) { return MotionEvent.obtain(0, 0, action, x, y, 0); } @@ -549,6 +634,11 @@ public class QuickSettingsControllerTest extends SysuiTestCase { private void enableSplitShade(boolean enabled) { when(mResources.getBoolean(R.bool.config_use_split_notification_shade)).thenReturn(enabled); mQsController.updateResources(); + if (enabled) { + setSplitShadeHeightProperties(); + } else { + setDefaultHeightProperties(); + } } private void setIsFullWidth(boolean fullWidth) { @@ -561,5 +651,11 @@ public class QuickSettingsControllerTest extends SysuiTestCase { mQsController.handleShadeLayoutChanged(oldMaxHeight); } - + private void assertQsVisible(boolean visible) { + ArgumentCaptor visibilityCaptor = ArgumentCaptor.forClass(Boolean.class); + verify(mQs, atLeastOnce()).setQsVisible(visibilityCaptor.capture()); + List allVisibilities = visibilityCaptor.getAllValues(); + boolean lastVisibility = allVisibilities.get(allVisibilities.size() - 1); + assertThat(lastVisibility).isEqualTo(visible); + } }