Loading packages/SystemUI/res/layout/status_bar_expanded.xml +7 −0 Original line number Diff line number Diff line Loading @@ -69,6 +69,13 @@ systemui:layout_constraintEnd_toEndOf="parent" /> <androidx.constraintlayout.widget.Guideline android:id="@+id/qs_edge_guideline" android:layout_width="wrap_content" android:layout_height="wrap_content" systemui:layout_constraintGuide_percent="0.5" android:orientation="vertical"/> <com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout android:id="@+id/notification_stack_scroller" android:layout_marginTop="@dimen/notification_panel_margin_top" Loading packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java +30 −4 Original line number Diff line number Diff line Loading @@ -18,6 +18,10 @@ package com.android.systemui.statusbar.phone; import static android.view.View.GONE; import static androidx.constraintlayout.widget.ConstraintSet.END; import static androidx.constraintlayout.widget.ConstraintSet.PARENT_ID; import static androidx.constraintlayout.widget.ConstraintSet.START; import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE; import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE; import static com.android.systemui.classifier.Classifier.QUICK_SETTINGS; Loading Loading @@ -66,6 +70,8 @@ import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; import android.widget.TextView; import androidx.constraintlayout.widget.ConstraintSet; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.jank.InteractionJankMonitor; import com.android.internal.logging.MetricsLogger; Loading Loading @@ -762,6 +768,10 @@ public class NotificationPanelViewController extends PanelViewController { }); mView.setAccessibilityDelegate(mAccessibilityDelegate); // dynamically apply the split shade value overrides. if (Utils.shouldUseSplitNotificationShade(mFeatureFlags, mResources)) { updateResources(); } } @Override Loading Loading @@ -870,11 +880,21 @@ public class NotificationPanelViewController extends PanelViewController { mNotificationStackScrollLayoutController.setLayoutParams(lp); } if (Utils.shouldUseSplitNotificationShade(mFeatureFlags, mResources)) { // In order to change the constraints at runtime, all children of the Constraint Layout // must have ids. ensureAllViewsHaveIds(mNotificationContainerParent); ConstraintSet constraintSet = new ConstraintSet(); constraintSet.clone(mNotificationContainerParent); if (Utils.shouldUseSplitNotificationShade(mFeatureFlags, mResources)) { 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); } else { constraintSet.connect(R.id.qs_frame, END, PARENT_ID, END); constraintSet.connect(R.id.notification_stack_scroller, START, PARENT_ID, START); } constraintSet.applyTo(mNotificationContainerParent); } private static void ensureAllViewsHaveIds(ViewGroup parentView) { Loading Loading @@ -2007,6 +2027,10 @@ public class NotificationPanelViewController extends PanelViewController { } private float calculateQsTopPadding() { // in split shade mode we want notifications to be directly below status bar if (Utils.shouldUseSplitNotificationShade(mFeatureFlags, mResources) && !mKeyguardShowing) { return 0f; } if (mKeyguardShowing && (mQsExpandImmediate || mIsExpanding && mQsExpandedWhenExpandingStarted)) { Loading Loading @@ -2646,8 +2670,10 @@ public class NotificationPanelViewController extends PanelViewController { super.onTrackingStarted(); if (mQsFullyExpanded) { mQsExpandImmediate = true; if (!Utils.shouldUseSplitNotificationShade(mFeatureFlags, mResources)) { mNotificationStackScrollLayoutController.setShouldShowShelfOnly(true); } } if (mBarState == KEYGUARD || mBarState == StatusBarState.SHADE_LOCKED) { mAffordanceHelper.animateHideLeftRightIcon(); } Loading packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java +51 −9 Original line number Diff line number Diff line Loading @@ -48,6 +48,8 @@ import android.view.ViewGroup; 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; import com.android.internal.logging.MetricsLogger; Loading Loading @@ -222,14 +224,13 @@ public class NotificationPanelViewTest extends SysuiTestCase { @Mock private BroadcastDispatcher mBroadcastDispatcher; @Mock private NotificationsQuickSettingsContainer mNotificationContainerParent; @Mock private AmbientState mAmbientState; @Mock private UserManager mUserManager; private NotificationPanelViewController mNotificationPanelViewController; private View.AccessibilityDelegate mAccessibiltyDelegate; private NotificationsQuickSettingsContainer mNotificationContainerParent; @Before public void setup() { Loading Loading @@ -262,6 +263,7 @@ public class NotificationPanelViewTest extends SysuiTestCase { when(mView.findViewById(R.id.keyguard_status_view)) .thenReturn(mock(KeyguardStatusView.class)); when(mView.findViewById(R.id.keyguard_header)).thenReturn(mKeyguardStatusBar); mNotificationContainerParent = new NotificationsQuickSettingsContainer(getContext(), null); when(mView.findViewById(R.id.notification_container_parent)) .thenReturn(mNotificationContainerParent); FlingAnimationUtils.Builder flingAnimationUtilsBuilder = new FlingAnimationUtils.Builder( Loading Loading @@ -440,16 +442,11 @@ public class NotificationPanelViewTest extends SysuiTestCase { @Test public void testAllChildrenOfNotificationContainer_haveIds() { when(mNotificationContainerParent.getChildCount()).thenReturn(2); when(mResources.getBoolean(R.bool.config_use_split_notification_shade)).thenReturn(true); when(mFeatureFlags.isTwoColumnNotificationShadeEnabled()).thenReturn(true); View view1 = new View(mContext); view1.setId(1); when(mNotificationContainerParent.getChildAt(0)).thenReturn(view1); View view2 = mock(View.class); when(mNotificationContainerParent.getChildAt(1)).thenReturn(view2); mNotificationContainerParent.addView(newViewWithId(1)); mNotificationContainerParent.addView(newViewWithId(View.NO_ID)); mNotificationPanelViewController.updateResources(); Loading @@ -457,6 +454,51 @@ public class NotificationPanelViewTest extends SysuiTestCase { assertThat(mNotificationContainerParent.getChildAt(1).getId()).isNotEqualTo(View.NO_ID); } @Test public void testSinglePaneShadeLayout_isAlignedToParent() { when(mFeatureFlags.isTwoColumnNotificationShadeEnabled()).thenReturn(false); mNotificationContainerParent.addView(newViewWithId(R.id.qs_frame)); mNotificationContainerParent.addView(newViewWithId(R.id.notification_stack_scroller)); mNotificationPanelViewController.updateResources(); ConstraintSet constraintSet = new ConstraintSet(); constraintSet.clone(mNotificationContainerParent); ConstraintSet.Layout qsFrameLayout = constraintSet.getConstraint(R.id.qs_frame).layout; ConstraintSet.Layout stackScrollerLayout = constraintSet.getConstraint( R.id.notification_stack_scroller).layout; assertThat(qsFrameLayout.endToEnd).isEqualTo(ConstraintSet.PARENT_ID); assertThat(stackScrollerLayout.startToStart).isEqualTo(ConstraintSet.PARENT_ID); } @Test public void testSplitShadeLayout_isAlignedToGuideline() { when(mResources.getBoolean(R.bool.config_use_split_notification_shade)).thenReturn(true); when(mFeatureFlags.isTwoColumnNotificationShadeEnabled()).thenReturn(true); mNotificationContainerParent.addView(newViewWithId(R.id.qs_frame)); mNotificationContainerParent.addView(newViewWithId(R.id.notification_stack_scroller)); mNotificationPanelViewController.updateResources(); ConstraintSet constraintSet = new ConstraintSet(); constraintSet.clone(mNotificationContainerParent); ConstraintSet.Layout qsFrameLayout = constraintSet.getConstraint(R.id.qs_frame).layout; ConstraintSet.Layout stackScrollerLayout = constraintSet.getConstraint( R.id.notification_stack_scroller).layout; assertThat(qsFrameLayout.endToEnd).isEqualTo(R.id.qs_edge_guideline); assertThat(stackScrollerLayout.startToStart).isEqualTo(R.id.qs_edge_guideline); } 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 void onTouchEvent(MotionEvent ev) { mTouchHandler.onTouch(mView, ev); } Loading Loading
packages/SystemUI/res/layout/status_bar_expanded.xml +7 −0 Original line number Diff line number Diff line Loading @@ -69,6 +69,13 @@ systemui:layout_constraintEnd_toEndOf="parent" /> <androidx.constraintlayout.widget.Guideline android:id="@+id/qs_edge_guideline" android:layout_width="wrap_content" android:layout_height="wrap_content" systemui:layout_constraintGuide_percent="0.5" android:orientation="vertical"/> <com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout android:id="@+id/notification_stack_scroller" android:layout_marginTop="@dimen/notification_panel_margin_top" Loading
packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java +30 −4 Original line number Diff line number Diff line Loading @@ -18,6 +18,10 @@ package com.android.systemui.statusbar.phone; import static android.view.View.GONE; import static androidx.constraintlayout.widget.ConstraintSet.END; import static androidx.constraintlayout.widget.ConstraintSet.PARENT_ID; import static androidx.constraintlayout.widget.ConstraintSet.START; import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE; import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE; import static com.android.systemui.classifier.Classifier.QUICK_SETTINGS; Loading Loading @@ -66,6 +70,8 @@ import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; import android.widget.TextView; import androidx.constraintlayout.widget.ConstraintSet; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.jank.InteractionJankMonitor; import com.android.internal.logging.MetricsLogger; Loading Loading @@ -762,6 +768,10 @@ public class NotificationPanelViewController extends PanelViewController { }); mView.setAccessibilityDelegate(mAccessibilityDelegate); // dynamically apply the split shade value overrides. if (Utils.shouldUseSplitNotificationShade(mFeatureFlags, mResources)) { updateResources(); } } @Override Loading Loading @@ -870,11 +880,21 @@ public class NotificationPanelViewController extends PanelViewController { mNotificationStackScrollLayoutController.setLayoutParams(lp); } if (Utils.shouldUseSplitNotificationShade(mFeatureFlags, mResources)) { // In order to change the constraints at runtime, all children of the Constraint Layout // must have ids. ensureAllViewsHaveIds(mNotificationContainerParent); ConstraintSet constraintSet = new ConstraintSet(); constraintSet.clone(mNotificationContainerParent); if (Utils.shouldUseSplitNotificationShade(mFeatureFlags, mResources)) { 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); } else { constraintSet.connect(R.id.qs_frame, END, PARENT_ID, END); constraintSet.connect(R.id.notification_stack_scroller, START, PARENT_ID, START); } constraintSet.applyTo(mNotificationContainerParent); } private static void ensureAllViewsHaveIds(ViewGroup parentView) { Loading Loading @@ -2007,6 +2027,10 @@ public class NotificationPanelViewController extends PanelViewController { } private float calculateQsTopPadding() { // in split shade mode we want notifications to be directly below status bar if (Utils.shouldUseSplitNotificationShade(mFeatureFlags, mResources) && !mKeyguardShowing) { return 0f; } if (mKeyguardShowing && (mQsExpandImmediate || mIsExpanding && mQsExpandedWhenExpandingStarted)) { Loading Loading @@ -2646,8 +2670,10 @@ public class NotificationPanelViewController extends PanelViewController { super.onTrackingStarted(); if (mQsFullyExpanded) { mQsExpandImmediate = true; if (!Utils.shouldUseSplitNotificationShade(mFeatureFlags, mResources)) { mNotificationStackScrollLayoutController.setShouldShowShelfOnly(true); } } if (mBarState == KEYGUARD || mBarState == StatusBarState.SHADE_LOCKED) { mAffordanceHelper.animateHideLeftRightIcon(); } Loading
packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java +51 −9 Original line number Diff line number Diff line Loading @@ -48,6 +48,8 @@ import android.view.ViewGroup; 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; import com.android.internal.logging.MetricsLogger; Loading Loading @@ -222,14 +224,13 @@ public class NotificationPanelViewTest extends SysuiTestCase { @Mock private BroadcastDispatcher mBroadcastDispatcher; @Mock private NotificationsQuickSettingsContainer mNotificationContainerParent; @Mock private AmbientState mAmbientState; @Mock private UserManager mUserManager; private NotificationPanelViewController mNotificationPanelViewController; private View.AccessibilityDelegate mAccessibiltyDelegate; private NotificationsQuickSettingsContainer mNotificationContainerParent; @Before public void setup() { Loading Loading @@ -262,6 +263,7 @@ public class NotificationPanelViewTest extends SysuiTestCase { when(mView.findViewById(R.id.keyguard_status_view)) .thenReturn(mock(KeyguardStatusView.class)); when(mView.findViewById(R.id.keyguard_header)).thenReturn(mKeyguardStatusBar); mNotificationContainerParent = new NotificationsQuickSettingsContainer(getContext(), null); when(mView.findViewById(R.id.notification_container_parent)) .thenReturn(mNotificationContainerParent); FlingAnimationUtils.Builder flingAnimationUtilsBuilder = new FlingAnimationUtils.Builder( Loading Loading @@ -440,16 +442,11 @@ public class NotificationPanelViewTest extends SysuiTestCase { @Test public void testAllChildrenOfNotificationContainer_haveIds() { when(mNotificationContainerParent.getChildCount()).thenReturn(2); when(mResources.getBoolean(R.bool.config_use_split_notification_shade)).thenReturn(true); when(mFeatureFlags.isTwoColumnNotificationShadeEnabled()).thenReturn(true); View view1 = new View(mContext); view1.setId(1); when(mNotificationContainerParent.getChildAt(0)).thenReturn(view1); View view2 = mock(View.class); when(mNotificationContainerParent.getChildAt(1)).thenReturn(view2); mNotificationContainerParent.addView(newViewWithId(1)); mNotificationContainerParent.addView(newViewWithId(View.NO_ID)); mNotificationPanelViewController.updateResources(); Loading @@ -457,6 +454,51 @@ public class NotificationPanelViewTest extends SysuiTestCase { assertThat(mNotificationContainerParent.getChildAt(1).getId()).isNotEqualTo(View.NO_ID); } @Test public void testSinglePaneShadeLayout_isAlignedToParent() { when(mFeatureFlags.isTwoColumnNotificationShadeEnabled()).thenReturn(false); mNotificationContainerParent.addView(newViewWithId(R.id.qs_frame)); mNotificationContainerParent.addView(newViewWithId(R.id.notification_stack_scroller)); mNotificationPanelViewController.updateResources(); ConstraintSet constraintSet = new ConstraintSet(); constraintSet.clone(mNotificationContainerParent); ConstraintSet.Layout qsFrameLayout = constraintSet.getConstraint(R.id.qs_frame).layout; ConstraintSet.Layout stackScrollerLayout = constraintSet.getConstraint( R.id.notification_stack_scroller).layout; assertThat(qsFrameLayout.endToEnd).isEqualTo(ConstraintSet.PARENT_ID); assertThat(stackScrollerLayout.startToStart).isEqualTo(ConstraintSet.PARENT_ID); } @Test public void testSplitShadeLayout_isAlignedToGuideline() { when(mResources.getBoolean(R.bool.config_use_split_notification_shade)).thenReturn(true); when(mFeatureFlags.isTwoColumnNotificationShadeEnabled()).thenReturn(true); mNotificationContainerParent.addView(newViewWithId(R.id.qs_frame)); mNotificationContainerParent.addView(newViewWithId(R.id.notification_stack_scroller)); mNotificationPanelViewController.updateResources(); ConstraintSet constraintSet = new ConstraintSet(); constraintSet.clone(mNotificationContainerParent); ConstraintSet.Layout qsFrameLayout = constraintSet.getConstraint(R.id.qs_frame).layout; ConstraintSet.Layout stackScrollerLayout = constraintSet.getConstraint( R.id.notification_stack_scroller).layout; assertThat(qsFrameLayout.endToEnd).isEqualTo(R.id.qs_edge_guideline); assertThat(stackScrollerLayout.startToStart).isEqualTo(R.id.qs_edge_guideline); } 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 void onTouchEvent(MotionEvent ev) { mTouchHandler.onTouch(mView, ev); } Loading