Merge "Moving adjusting constraints to NotificationsQSContainerController" into tm-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
c342d9b454
@@ -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;
|
||||
@@ -1080,14 +1076,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 =
|
||||
@@ -1097,49 +1089,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);
|
||||
|
||||
@@ -1150,15 +1105,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) {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
@@ -678,31 +674,6 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
|
||||
verify(mStatusBarKeyguardViewManager).showBouncer(true);
|
||||
}
|
||||
|
||||
@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);
|
||||
@@ -751,46 +722,6 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
|
||||
verify(mUserSwitcherStubView).inflate();
|
||||
}
|
||||
|
||||
@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);
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user