diff options
5 files changed, 241 insertions, 198 deletions
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 22a47aad4e2f..510334c2292e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java @@ -18,13 +18,9 @@ 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; -import static androidx.constraintlayout.widget.ConstraintSet.BOTTOM; import static androidx.constraintlayout.widget.ConstraintSet.END; import static androidx.constraintlayout.widget.ConstraintSet.PARENT_ID; -import static androidx.constraintlayout.widget.ConstraintSet.START; -import static androidx.constraintlayout.widget.ConstraintSet.TOP; import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE; import static com.android.keyguard.KeyguardClockSwitch.LARGE; @@ -1070,14 +1066,10 @@ public class NotificationPanelViewController extends PanelViewController { public void updateResources() { mQuickQsOffsetHeight = SystemBarUtils.getQuickQsOffsetHeight(mView.getContext()); - mSplitShadeStatusBarHeight = Utils.getSplitShadeStatusBarHeight(mView.getContext()); mSplitShadeNotificationsScrimMarginBottom = mResources.getDimensionPixelSize( R.dimen.split_shade_notifications_scrim_margin_bottom); - int panelMarginHorizontal = mResources.getDimensionPixelSize( - R.dimen.notification_panel_margin_horizontal); - final boolean newShouldUseSplitNotificationShade = Utils.shouldUseSplitNotificationShade(mResources); final boolean splitNotificationShadeChanged = @@ -1087,49 +1079,12 @@ public class NotificationPanelViewController extends PanelViewController { if (mQs != null) { mQs.setInSplitShade(mShouldUseSplitNotificationShade); } - - int notificationsBottomMargin = mResources.getDimensionPixelSize( - R.dimen.notification_panel_margin_bottom); + mSplitShadeStatusBarHeight = Utils.getSplitShadeStatusBarHeight(mView.getContext()); int topMargin = mShouldUseSplitNotificationShade ? mSplitShadeStatusBarHeight : mResources.getDimensionPixelSize(R.dimen.notification_panel_margin_top); mSplitShadeHeaderController.setSplitShadeMode(mShouldUseSplitNotificationShade); - - // To change the constraints at runtime, all children of the ConstraintLayout must have ids - ensureAllViewsHaveIds(mNotificationContainerParent); - ConstraintSet constraintSet = new ConstraintSet(); - constraintSet.clone(mNotificationContainerParent); - int statusViewMarginHorizontal = mResources.getDimensionPixelSize( - R.dimen.status_view_margin_horizontal); - constraintSet.setMargin(R.id.keyguard_status_view, START, statusViewMarginHorizontal); - constraintSet.setMargin(R.id.keyguard_status_view, END, statusViewMarginHorizontal); - if (mShouldUseSplitNotificationShade) { - // width = 0 to take up all available space within constraints - constraintSet.connect(R.id.qs_frame, END, R.id.qs_edge_guideline, END); - constraintSet.connect( - R.id.notification_stack_scroller, START, - R.id.qs_edge_guideline, START); - constraintSet.constrainHeight(R.id.split_shade_status_bar, mSplitShadeStatusBarHeight); - } else { - constraintSet.connect(R.id.qs_frame, END, PARENT_ID, END); - constraintSet.connect(R.id.notification_stack_scroller, START, PARENT_ID, START); - if (mUseCombinedQSHeaders) { - constraintSet.constrainHeight(R.id.split_shade_status_bar, WRAP_CONTENT); - } - } - constraintSet.setMargin(R.id.notification_stack_scroller, START, - mShouldUseSplitNotificationShade ? 0 : panelMarginHorizontal); - constraintSet.setMargin(R.id.notification_stack_scroller, END, panelMarginHorizontal); - constraintSet.setMargin(R.id.notification_stack_scroller, TOP, topMargin); - constraintSet.setMargin(R.id.notification_stack_scroller, BOTTOM, - notificationsBottomMargin); - constraintSet.setMargin(R.id.qs_frame, START, panelMarginHorizontal); - constraintSet.setMargin(R.id.qs_frame, END, - mShouldUseSplitNotificationShade ? 0 : panelMarginHorizontal); - constraintSet.setMargin(R.id.qs_frame, TOP, topMargin); - constraintSet.applyTo(mNotificationContainerParent); mAmbientState.setStackTopMargin(topMargin); - mNotificationsQSContainerController.updateMargins(); - mNotificationsQSContainerController.setSplitShadeEnabled(mShouldUseSplitNotificationShade); + mNotificationsQSContainerController.updateResources(); updateKeyguardStatusViewAlignment(/* animate= */false); @@ -1140,15 +1095,6 @@ public class NotificationPanelViewController extends PanelViewController { } } - private static void ensureAllViewsHaveIds(ViewGroup parentView) { - for (int i = 0; i < parentView.getChildCount(); i++) { - View childView = parentView.getChildAt(i); - if (childView.getId() == View.NO_ID) { - childView.setId(View.generateViewId()); - } - } - } - private View reInflateStub(int viewId, int stubId, int layoutId, boolean enabled) { View view = mView.findViewById(viewId); if (view != null) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQSContainerController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQSContainerController.kt index ebb09b1af5e9..e4161a37e52e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQSContainerController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQSContainerController.kt @@ -1,6 +1,15 @@ package com.android.systemui.statusbar.phone +import android.view.View +import android.view.ViewGroup +import android.view.ViewGroup.LayoutParams.WRAP_CONTENT import android.view.WindowInsets +import androidx.constraintlayout.widget.ConstraintSet +import androidx.constraintlayout.widget.ConstraintSet.BOTTOM +import androidx.constraintlayout.widget.ConstraintSet.END +import androidx.constraintlayout.widget.ConstraintSet.PARENT_ID +import androidx.constraintlayout.widget.ConstraintSet.START +import androidx.constraintlayout.widget.ConstraintSet.TOP import com.android.systemui.R import com.android.systemui.flags.FeatureFlags import com.android.systemui.flags.Flags @@ -10,6 +19,7 @@ import com.android.systemui.plugins.qs.QSContainerController import com.android.systemui.recents.OverviewProxyService import com.android.systemui.recents.OverviewProxyService.OverviewProxyListener import com.android.systemui.shared.system.QuickStepContract +import com.android.systemui.util.Utils import com.android.systemui.util.ViewController import java.util.function.Consumer import javax.inject.Inject @@ -28,23 +38,20 @@ class NotificationsQSContainerController @Inject constructor( mView.invalidate() } } - var splitShadeEnabled = false - set(value) { - if (field != value) { - field = value - // in case device configuration changed while showing QS details/customizer - updateBottomSpacing() - } - } - + private var splitShadeEnabled = false private var isQSDetailShowing = false private var isQSCustomizing = false private var isQSCustomizerAnimating = false + private var splitShadeStatusBarHeight = 0 private var notificationsBottomMargin = 0 private var scrimShadeBottomMargin = 0 private var bottomStableInsets = 0 private var bottomCutoutInsets = 0 + private var panelMarginHorizontal = 0 + private var topMargin = 0 + + private val useCombinedQSHeaders = featureFlags.isEnabled(Flags.COMBINED_QS_HEADERS) private var isGestureNavigation = true private var taskbarVisible = false @@ -68,7 +75,6 @@ class NotificationsQSContainerController @Inject constructor( } public override fun onViewAttached() { - updateMargins() updateResources() overviewProxyService.addCallback(taskbarVisibilityListener) mView.setInsetsChangedListener(windowInsetsListener) @@ -83,7 +89,27 @@ class NotificationsQSContainerController @Inject constructor( mView.setConfigurationChangedListener(null) } - private fun updateResources() { + fun updateResources() { + val newSplitShadeEnabled = Utils.shouldUseSplitNotificationShade(resources) + val splitShadeEnabledChanged = newSplitShadeEnabled != splitShadeEnabled + splitShadeEnabled = newSplitShadeEnabled + notificationsBottomMargin = resources.getDimensionPixelSize( + R.dimen.notification_panel_margin_bottom) + splitShadeStatusBarHeight = Utils.getSplitShadeStatusBarHeight(context) + panelMarginHorizontal = resources.getDimensionPixelSize( + R.dimen.notification_panel_margin_horizontal) + topMargin = if (splitShadeEnabled) { + splitShadeStatusBarHeight + } else { + resources.getDimensionPixelSize(R.dimen.notification_panel_margin_top) + } + updateConstraints() + if (splitShadeEnabledChanged) { + // Let's do it at the end when all margins/paddings were already applied. + // We need to updateBottomSpacing() in case device configuration changed while showing + // QS details/customizer + updateBottomSpacing() + } val previousScrimShadeBottomMargin = scrimShadeBottomMargin scrimShadeBottomMargin = resources.getDimensionPixelSize( R.dimen.split_shade_notifications_scrim_margin_bottom @@ -94,15 +120,6 @@ class NotificationsQSContainerController @Inject constructor( } } - /** - * Update the notification bottom margin. - * - * Will not call updateBottomSpacing - */ - fun updateMargins() { - notificationsBottomMargin = mView.defaultNotificationsMarginBottom - } - override fun setCustomizerAnimating(animating: Boolean) { if (isQSCustomizerAnimating != animating) { isQSCustomizerAnimating = animating @@ -178,4 +195,66 @@ class NotificationsQSContainerController @Inject constructor( } return containerPadding to stackScrollMargin } -}
\ No newline at end of file + + fun updateConstraints() { + // To change the constraints at runtime, all children of the ConstraintLayout must have ids + ensureAllViewsHaveIds(mView) + val constraintSet = ConstraintSet() + constraintSet.clone(mView) + setKeyguardStatusViewConstraints(constraintSet) + setQsConstraints(constraintSet) + setNotificationsConstraints(constraintSet) + setSplitShadeStatusBarConstraints(constraintSet) + mView.applyConstraints(constraintSet) + } + + private fun setSplitShadeStatusBarConstraints(constraintSet: ConstraintSet) { + if (splitShadeEnabled) { + constraintSet.constrainHeight(R.id.split_shade_status_bar, splitShadeStatusBarHeight) + } else { + if (useCombinedQSHeaders) { + constraintSet.constrainHeight(R.id.split_shade_status_bar, WRAP_CONTENT) + } + } + } + + private fun setNotificationsConstraints(constraintSet: ConstraintSet) { + val startConstraintId = if (splitShadeEnabled) R.id.qs_edge_guideline else PARENT_ID + constraintSet.apply { + connect(R.id.notification_stack_scroller, START, startConstraintId, START) + setMargin(R.id.notification_stack_scroller, START, + if (splitShadeEnabled) 0 else panelMarginHorizontal) + setMargin(R.id.notification_stack_scroller, END, panelMarginHorizontal) + setMargin(R.id.notification_stack_scroller, TOP, topMargin) + setMargin(R.id.notification_stack_scroller, BOTTOM, notificationsBottomMargin) + } + } + + private fun setQsConstraints(constraintSet: ConstraintSet) { + val endConstraintId = if (splitShadeEnabled) R.id.qs_edge_guideline else PARENT_ID + constraintSet.apply { + connect(R.id.qs_frame, END, endConstraintId, END) + setMargin(R.id.qs_frame, START, panelMarginHorizontal) + setMargin(R.id.qs_frame, END, if (splitShadeEnabled) 0 else panelMarginHorizontal) + setMargin(R.id.qs_frame, TOP, topMargin) + } + } + + private fun setKeyguardStatusViewConstraints(constraintSet: ConstraintSet) { + val statusViewMarginHorizontal = resources.getDimensionPixelSize( + R.dimen.status_view_margin_horizontal) + constraintSet.apply { + setMargin(R.id.keyguard_status_view, START, statusViewMarginHorizontal) + setMargin(R.id.keyguard_status_view, END, statusViewMarginHorizontal) + } + } + + private fun ensureAllViewsHaveIds(parentView: ViewGroup) { + for (i in 0 until parentView.childCount) { + val childView = parentView.getChildAt(i) + if (childView.id == View.NO_ID) { + childView.id = View.generateViewId() + } + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java index c2b5f5657fb0..7caea06e6359 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java @@ -26,6 +26,7 @@ import android.view.WindowInsets; import androidx.annotation.Nullable; import androidx.constraintlayout.widget.ConstraintLayout; +import androidx.constraintlayout.widget.ConstraintSet; import com.android.systemui.R; import com.android.systemui.fragments.FragmentHostManager; @@ -123,10 +124,6 @@ public class NotificationsQuickSettingsContainer extends ConstraintLayout } } - public int getDefaultNotificationsMarginBottom() { - return ((LayoutParams) mStackScroller.getLayoutParams()).bottomMargin; - } - public void setInsetsChangedListener(Consumer<WindowInsets> onInsetsChangedListener) { mInsetsChangedListener = onInsetsChangedListener; } @@ -197,4 +194,7 @@ public class NotificationsQuickSettingsContainer extends ConstraintLayout } } + public void applyConstraints(ConstraintSet constraintSet) { + constraintSet.applyTo(this); + } } 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 6842295ec5d5..4bac08ea536b 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 @@ -56,13 +56,11 @@ import android.util.DisplayMetrics; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; -import android.view.ViewGroup; import android.view.ViewPropertyAnimator; import android.view.ViewStub; import android.view.accessibility.AccessibilityManager; import android.view.accessibility.AccessibilityNodeInfo; -import androidx.constraintlayout.widget.ConstraintLayout; import androidx.constraintlayout.widget.ConstraintSet; import androidx.test.filters.SmallTest; @@ -389,8 +387,6 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { when(mView.findViewById(R.id.keyguard_status_view)) .thenReturn(mock(KeyguardStatusView.class)); mNotificationContainerParent = new NotificationsQuickSettingsContainer(getContext(), null); - mNotificationContainerParent.addView(newViewWithId(R.id.qs_frame)); - mNotificationContainerParent.addView(newViewWithId(R.id.notification_stack_scroller)); mNotificationContainerParent.addView(mKeyguardStatusView); mNotificationContainerParent.onFinishInflate(); when(mView.findViewById(R.id.notification_container_parent)) @@ -679,31 +675,6 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { } @Test - public void testAllChildrenOfNotificationContainer_haveIds() { - enableSplitShade(/* enabled= */ true); - mNotificationContainerParent.removeAllViews(); - mNotificationContainerParent.addView(newViewWithId(1)); - mNotificationContainerParent.addView(newViewWithId(View.NO_ID)); - - mNotificationPanelViewController.updateResources(); - - assertThat(mNotificationContainerParent.getChildAt(0).getId()).isEqualTo(1); - assertThat(mNotificationContainerParent.getChildAt(1).getId()).isNotEqualTo(View.NO_ID); - } - - @Test - public void testSinglePaneShadeLayout_isAlignedToParent() { - enableSplitShade(/* enabled= */ false); - - mNotificationPanelViewController.updateResources(); - - assertThat(getConstraintSetLayout(R.id.qs_frame).endToEnd) - .isEqualTo(ConstraintSet.PARENT_ID); - assertThat(getConstraintSetLayout(R.id.notification_stack_scroller).startToStart) - .isEqualTo(ConstraintSet.PARENT_ID); - } - - @Test public void testKeyguardStatusViewInSplitShade_changesConstraintsDependingOnNotifications() { mStatusBarStateController.setState(KEYGUARD); enableSplitShade(/* enabled= */ true); @@ -752,46 +723,6 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { } @Test - public void testSplitShadeLayout_isAlignedToGuideline() { - enableSplitShade(/* enabled= */ true); - - mNotificationPanelViewController.updateResources(); - - assertThat(getConstraintSetLayout(R.id.qs_frame).endToEnd) - .isEqualTo(R.id.qs_edge_guideline); - assertThat(getConstraintSetLayout(R.id.notification_stack_scroller).startToStart) - .isEqualTo(R.id.qs_edge_guideline); - } - - @Test - public void testSplitShadeLayout_childrenHaveInsideMarginsOfZero() { - enableSplitShade(/* enabled= */ true); - - mNotificationPanelViewController.updateResources(); - - assertThat(getConstraintSetLayout(R.id.qs_frame).startMargin).isEqualTo(10); - assertThat(getConstraintSetLayout(R.id.qs_frame).endMargin).isEqualTo(0); - assertThat(getConstraintSetLayout(R.id.notification_stack_scroller).startMargin) - .isEqualTo(0); - assertThat(getConstraintSetLayout(R.id.notification_stack_scroller).endMargin) - .isEqualTo(10); - } - - @Test - public void testSinglePaneLayout_childrenHaveEqualMargins() { - enableSplitShade(/* enabled= */ false); - - mNotificationPanelViewController.updateResources(); - - assertThat(getConstraintSetLayout(R.id.qs_frame).startMargin).isEqualTo(10); - assertThat(getConstraintSetLayout(R.id.qs_frame).endMargin).isEqualTo(10); - assertThat(getConstraintSetLayout(R.id.notification_stack_scroller).startMargin) - .isEqualTo(10); - assertThat(getConstraintSetLayout(R.id.notification_stack_scroller).endMargin) - .isEqualTo(10); - } - - @Test public void testCanCollapsePanelOnTouch_trueForKeyGuard() { mStatusBarStateController.setState(KEYGUARD); @@ -1016,17 +947,6 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { } } - - private View newViewWithId(int id) { - View view = new View(mContext); - view.setId(id); - ConstraintLayout.LayoutParams layoutParams = new ConstraintLayout.LayoutParams( - ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); - // required as cloning ConstraintSet fails if view doesn't have layout params - view.setLayoutParams(layoutParams); - return view; - } - private ConstraintSet.Layout getConstraintSetLayout(@IdRes int id) { ConstraintSet constraintSet = new ConstraintSet(); constraintSet.clone(mNotificationContainerParent); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationQSContainerControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationQSContainerControllerTest.kt index 5fb4144bec3c..d65cc7833a68 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationQSContainerControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationQSContainerControllerTest.kt @@ -1,9 +1,14 @@ package com.android.systemui.statusbar.phone +import android.annotation.IdRes import android.testing.AndroidTestingRunner import android.testing.TestableLooper +import android.view.View +import android.view.ViewGroup import android.view.WindowInsets import android.view.WindowManagerPolicyConstants +import androidx.constraintlayout.widget.ConstraintLayout +import androidx.constraintlayout.widget.ConstraintSet import androidx.test.filters.SmallTest import com.android.systemui.R import com.android.systemui.SysuiTestCase @@ -13,6 +18,7 @@ import com.android.systemui.navigationbar.NavigationModeController import com.android.systemui.navigationbar.NavigationModeController.ModeChangedListener import com.android.systemui.recents.OverviewProxyService import com.android.systemui.recents.OverviewProxyService.OverviewProxyListener +import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -58,46 +64,54 @@ class NotificationQSContainerControllerTest : SysuiTestCase() { lateinit var taskbarVisibilityCaptor: ArgumentCaptor<OverviewProxyListener> @Captor lateinit var windowInsetsCallbackCaptor: ArgumentCaptor<Consumer<WindowInsets>> + @Captor + lateinit var constraintSetCaptor: ArgumentCaptor<ConstraintSet> - private lateinit var notificationsQSContainerController: NotificationsQSContainerController + private lateinit var controller: NotificationsQSContainerController private lateinit var navigationModeCallback: ModeChangedListener private lateinit var taskbarVisibilityCallback: OverviewProxyListener private lateinit var windowInsetsCallback: Consumer<WindowInsets> + private val testableResources = mContext.orCreateTestableResources + @Before fun setup() { MockitoAnnotations.initMocks(this) mContext.ensureTestableResources() + whenever(notificationsQSContainer.context).thenReturn(mContext) whenever(notificationsQSContainer.resources).thenReturn(mContext.resources) - notificationsQSContainerController = NotificationsQSContainerController( + controller = NotificationsQSContainerController( notificationsQSContainer, navigationModeController, overviewProxyService, featureFlags ) - mContext.orCreateTestableResources - .addOverride(R.dimen.split_shade_notifications_scrim_margin_bottom, SCRIM_MARGIN) - - whenever(notificationsQSContainer.defaultNotificationsMarginBottom) - .thenReturn(NOTIFICATIONS_MARGIN) + overrideResource(R.dimen.split_shade_notifications_scrim_margin_bottom, SCRIM_MARGIN) + overrideResource(R.dimen.notification_panel_margin_bottom, NOTIFICATIONS_MARGIN) + overrideResource(R.bool.config_use_split_notification_shade, false) whenever(navigationModeController.addListener(navigationModeCaptor.capture())) .thenReturn(GESTURES_NAVIGATION) doNothing().`when`(overviewProxyService).addCallback(taskbarVisibilityCaptor.capture()) doNothing().`when`(notificationsQSContainer) .setInsetsChangedListener(windowInsetsCallbackCaptor.capture()) + doNothing().`when`(notificationsQSContainer).applyConstraints(constraintSetCaptor.capture()) - notificationsQSContainerController.init() - notificationsQSContainerController.onViewAttached() + controller.init() + controller.onViewAttached() navigationModeCallback = navigationModeCaptor.value taskbarVisibilityCallback = taskbarVisibilityCaptor.value windowInsetsCallback = windowInsetsCallbackCaptor.value } + fun overrideResource(@IdRes id: Int, value: Any) { + mContext.orCreateTestableResources.addOverride(id, value) + } + @Test fun testTaskbarVisibleInSplitShade() { - notificationsQSContainerController.splitShadeEnabled = true + enableSplitShade() useNewFooter(false) given(taskbarVisible = true, @@ -115,7 +129,7 @@ class NotificationQSContainerControllerTest : SysuiTestCase() { @Test fun testTaskbarVisibleInSplitShade_newFooter() { - notificationsQSContainerController.splitShadeEnabled = true + enableSplitShade() useNewFooter(true) given(taskbarVisible = true, @@ -136,7 +150,7 @@ class NotificationQSContainerControllerTest : SysuiTestCase() { @Test fun testTaskbarNotVisibleInSplitShade() { // when taskbar is not visible, it means we're on the home screen - notificationsQSContainerController.splitShadeEnabled = true + enableSplitShade() useNewFooter(false) given(taskbarVisible = false, @@ -154,7 +168,7 @@ class NotificationQSContainerControllerTest : SysuiTestCase() { @Test fun testTaskbarNotVisibleInSplitShade_newFooter() { // when taskbar is not visible, it means we're on the home screen - notificationsQSContainerController.splitShadeEnabled = true + enableSplitShade() useNewFooter(true) given(taskbarVisible = false, @@ -173,7 +187,7 @@ class NotificationQSContainerControllerTest : SysuiTestCase() { @Test fun testTaskbarNotVisibleInSplitShadeWithCutout() { - notificationsQSContainerController.splitShadeEnabled = true + enableSplitShade() useNewFooter(false) given(taskbarVisible = false, @@ -190,7 +204,7 @@ class NotificationQSContainerControllerTest : SysuiTestCase() { @Test fun testTaskbarNotVisibleInSplitShadeWithCutout_newFooter() { - notificationsQSContainerController.splitShadeEnabled = true + enableSplitShade() useNewFooter(true) given(taskbarVisible = false, @@ -209,7 +223,7 @@ class NotificationQSContainerControllerTest : SysuiTestCase() { @Test fun testTaskbarVisibleInSinglePaneShade() { - notificationsQSContainerController.splitShadeEnabled = false + disableSplitShade() useNewFooter(false) given(taskbarVisible = true, @@ -225,7 +239,7 @@ class NotificationQSContainerControllerTest : SysuiTestCase() { @Test fun testTaskbarVisibleInSinglePaneShade_newFooter() { - notificationsQSContainerController.splitShadeEnabled = false + disableSplitShade() useNewFooter(true) given(taskbarVisible = true, @@ -243,7 +257,7 @@ class NotificationQSContainerControllerTest : SysuiTestCase() { @Test fun testTaskbarNotVisibleInSinglePaneShade() { - notificationsQSContainerController.splitShadeEnabled = false + disableSplitShade() useNewFooter(false) given(taskbarVisible = false, @@ -264,7 +278,7 @@ class NotificationQSContainerControllerTest : SysuiTestCase() { @Test fun testTaskbarNotVisibleInSinglePaneShade_newFooter() { - notificationsQSContainerController.splitShadeEnabled = false + disableSplitShade() useNewFooter(true) given(taskbarVisible = false, @@ -285,8 +299,8 @@ class NotificationQSContainerControllerTest : SysuiTestCase() { @Test fun testCustomizingInSinglePaneShade() { - notificationsQSContainerController.splitShadeEnabled = false - notificationsQSContainerController.setCustomizerShowing(true) + disableSplitShade() + controller.setCustomizerShowing(true) useNewFooter(false) // always sets spacings to 0 @@ -305,8 +319,8 @@ class NotificationQSContainerControllerTest : SysuiTestCase() { @Test fun testCustomizingInSinglePaneShade_newFooter() { - notificationsQSContainerController.splitShadeEnabled = false - notificationsQSContainerController.setCustomizerShowing(true) + disableSplitShade() + controller.setCustomizerShowing(true) useNewFooter(true) // always sets spacings to 0 @@ -325,8 +339,8 @@ class NotificationQSContainerControllerTest : SysuiTestCase() { @Test fun testDetailShowingInSinglePaneShade() { - notificationsQSContainerController.splitShadeEnabled = false - notificationsQSContainerController.setDetailShowing(true) + disableSplitShade() + controller.setDetailShowing(true) useNewFooter(false) // always sets spacings to 0 @@ -345,8 +359,8 @@ class NotificationQSContainerControllerTest : SysuiTestCase() { @Test fun testDetailShowingInSinglePaneShade_newFooter() { - notificationsQSContainerController.splitShadeEnabled = false - notificationsQSContainerController.setDetailShowing(true) + disableSplitShade() + controller.setDetailShowing(true) useNewFooter(true) // always sets spacings to 0 @@ -365,8 +379,8 @@ class NotificationQSContainerControllerTest : SysuiTestCase() { @Test fun testDetailShowingInSplitShade() { - notificationsQSContainerController.splitShadeEnabled = true - notificationsQSContainerController.setDetailShowing(true) + enableSplitShade() + controller.setDetailShowing(true) useNewFooter(false) given(taskbarVisible = false, @@ -383,8 +397,8 @@ class NotificationQSContainerControllerTest : SysuiTestCase() { @Test fun testDetailShowingInSplitShade_newFooter() { - notificationsQSContainerController.splitShadeEnabled = true - notificationsQSContainerController.setDetailShowing(true) + enableSplitShade() + controller.setDetailShowing(true) useNewFooter(true) given(taskbarVisible = false, @@ -402,16 +416,86 @@ class NotificationQSContainerControllerTest : SysuiTestCase() { @Test fun testNotificationsMarginBottomIsUpdated() { Mockito.clearInvocations(notificationsQSContainer) - notificationsQSContainerController.splitShadeEnabled = true + enableSplitShade() verify(notificationsQSContainer).setNotificationsMarginBottom(NOTIFICATIONS_MARGIN) - whenever(notificationsQSContainer.defaultNotificationsMarginBottom).thenReturn(100) - notificationsQSContainerController.updateMargins() - notificationsQSContainerController.splitShadeEnabled = false - + overrideResource(R.dimen.notification_panel_margin_bottom, 100) + disableSplitShade() verify(notificationsQSContainer).setNotificationsMarginBottom(100) } + @Test + fun testSplitShadeLayout_isAlignedToGuideline() { + enableSplitShade() + controller.updateResources() + assertThat(getConstraintSetLayout(R.id.qs_frame).endToEnd) + .isEqualTo(R.id.qs_edge_guideline) + assertThat(getConstraintSetLayout(R.id.notification_stack_scroller).startToStart) + .isEqualTo(R.id.qs_edge_guideline) + } + + @Test + fun testSinglePaneLayout_childrenHaveEqualMargins() { + disableSplitShade() + controller.updateResources() + val qsStartMargin = getConstraintSetLayout(R.id.qs_frame).startMargin + val qsEndMargin = getConstraintSetLayout(R.id.qs_frame).endMargin + val notifStartMargin = getConstraintSetLayout(R.id.notification_stack_scroller).startMargin + val notifEndMargin = getConstraintSetLayout(R.id.notification_stack_scroller).endMargin + assertThat(qsStartMargin == qsEndMargin && + notifStartMargin == notifEndMargin && + qsStartMargin == notifStartMargin + ).isTrue() + } + + @Test + fun testSplitShadeLayout_childrenHaveInsideMarginsOfZero() { + enableSplitShade() + controller.updateResources() + assertThat(getConstraintSetLayout(R.id.qs_frame).endMargin).isEqualTo(0) + assertThat(getConstraintSetLayout(R.id.notification_stack_scroller).startMargin) + .isEqualTo(0) + } + + @Test + fun testSinglePaneShadeLayout_isAlignedToParent() { + disableSplitShade() + controller.updateResources() + assertThat(getConstraintSetLayout(R.id.qs_frame).endToEnd) + .isEqualTo(ConstraintSet.PARENT_ID) + assertThat(getConstraintSetLayout(R.id.notification_stack_scroller).startToStart) + .isEqualTo(ConstraintSet.PARENT_ID) + } + + @Test + fun testAllChildrenOfNotificationContainer_haveIds() { + // set dimen to 0 to avoid triggering updating bottom spacing + overrideResource(R.dimen.split_shade_notifications_scrim_margin_bottom, 0) + val container = NotificationsQuickSettingsContainer(context, null) + container.removeAllViews() + container.addView(newViewWithId(1)) + container.addView(newViewWithId(View.NO_ID)) + val controller = NotificationsQSContainerController(container, navigationModeController, + overviewProxyService, featureFlags) + controller.updateResources() + + assertThat(container.getChildAt(0).id).isEqualTo(1) + assertThat(container.getChildAt(1).id).isNotEqualTo(View.NO_ID) + } + + private fun disableSplitShade() { + setSplitShadeEnabled(false) + } + + private fun enableSplitShade() { + setSplitShadeEnabled(true) + } + + private fun setSplitShadeEnabled(enabled: Boolean) { + overrideResource(R.bool.config_use_split_notification_shade, enabled) + controller.updateResources() + } + private fun given( taskbarVisible: Boolean, navigationMode: Int, @@ -458,4 +542,18 @@ class NotificationQSContainerControllerTest : SysuiTestCase() { private fun useNewFooter(useNewFooter: Boolean) { whenever(featureFlags.isEnabled(Flags.NEW_FOOTER)).thenReturn(useNewFooter) } -}
\ No newline at end of file + + private fun getConstraintSetLayout(@IdRes id: Int): ConstraintSet.Layout { + return constraintSetCaptor.value.getConstraint(id).layout + } + + private fun newViewWithId(id: Int): View { + val view = View(mContext) + view.id = id + val layoutParams = ConstraintLayout.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT) + // required as cloning ConstraintSet fails if view doesn't have layout params + view.layoutParams = layoutParams + return view + } +} |