From 94f300dfe5529bedfa28020a62ddfe4a8d2479c3 Mon Sep 17 00:00:00 2001 From: Fabian Kozynski Date: Fri, 29 Oct 2021 10:01:11 -0400 Subject: [PATCH] [DO NOT MERGE] Unify QS Headers in a ConstraintLayout This is a POC and is missing several features: * Tight integration with the other surfaces to set margins * Expansion animation from QQS into QS * Privacy indicators To enable: adb shell am broadcast -a com.android.systemui.action.SET_FLAG --ei id 501 --ez 1 Test: manual Bug: 204204226 Change-Id: I5b2d5f5880ceff1adb1e4365cde15171c5c15d38 --- .../res/layout/combined_qs_header.xml | 114 ++++++++++++++++++ .../res/layout/status_bar_expanded.xml | 6 +- packages/SystemUI/res/xml/qqs_header.xml | 82 +++++++++++++ packages/SystemUI/res/xml/qs_header.xml | 79 ++++++++++++ packages/SystemUI/res/xml/split_header.xml | 77 ++++++++++++ .../android/systemui/flags/FeatureFlags.java | 7 ++ .../src/com/android/systemui/flags/Flags.java | 11 +- .../systemui/qs/QuickStatusBarHeader.java | 17 ++- .../qs/QuickStatusBarHeaderController.java | 3 +- .../NotificationPanelViewController.java | 14 ++- .../phone/SplitShadeHeaderController.kt | 33 ++++- .../phone/dagger/StatusBarViewModule.java | 15 ++- .../qs/QuickStatusBarHeaderControllerTest.kt | 5 +- .../NotificationPanelViewControllerTest.java | 6 +- .../phone/SplitShadeHeaderControllerTest.kt | 13 +- 15 files changed, 457 insertions(+), 25 deletions(-) create mode 100644 packages/SystemUI/res/layout/combined_qs_header.xml create mode 100644 packages/SystemUI/res/xml/qqs_header.xml create mode 100644 packages/SystemUI/res/xml/qs_header.xml create mode 100644 packages/SystemUI/res/xml/split_header.xml diff --git a/packages/SystemUI/res/layout/combined_qs_header.xml b/packages/SystemUI/res/layout/combined_qs_header.xml new file mode 100644 index 0000000000000..f0b59d825417d --- /dev/null +++ b/packages/SystemUI/res/layout/combined_qs_header.xml @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml index cc1af873ce2be..82186c13394ef 100644 --- a/packages/SystemUI/res/layout/status_bar_expanded.xml +++ b/packages/SystemUI/res/layout/status_bar_expanded.xml @@ -75,7 +75,11 @@ android:clipToPadding="false" android:clipChildren="false"> - + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/SystemUI/res/xml/qs_header.xml b/packages/SystemUI/res/xml/qs_header.xml new file mode 100644 index 0000000000000..72e518eab839d --- /dev/null +++ b/packages/SystemUI/res/xml/qs_header.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/SystemUI/res/xml/split_header.xml b/packages/SystemUI/res/xml/split_header.xml new file mode 100644 index 0000000000000..a3ee1e2fae645 --- /dev/null +++ b/packages/SystemUI/res/xml/split_header.xml @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.java b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.java index 48bb281429c2a..ab083a920a10a 100644 --- a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.java +++ b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.java @@ -183,6 +183,13 @@ public class FeatureFlags { return isEnabled(Flags.NEW_USER_SWITCHER); } + /** + * Use the new single view QS headers + */ + public boolean useCombinedQSHeaders() { + return isEnabled(Flags.COMBINED_QS_HEADERS); + } + /** static method for the system setting */ public static boolean isProviderModelSettingEnabled(Context context) { return FeatureFlagUtils.isEnabled(context, FeatureFlagUtils.SETTINGS_PROVIDER_MODEL); diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.java b/packages/SystemUI/src/com/android/systemui/flags/Flags.java index 3761d42ae98c7..f09c797a6608e 100644 --- a/packages/SystemUI/src/com/android/systemui/flags/Flags.java +++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.java @@ -77,21 +77,24 @@ public class Flags { public static final BooleanFlag NEW_USER_SWITCHER = new BooleanFlag(500, true); + public static final BooleanFlag COMBINED_QS_HEADERS = + new BooleanFlag(501, false); + /***************************************/ // 600- status bar public static final BooleanFlag COMBINED_STATUS_BAR_SIGNAL_ICONS = - new BooleanFlag(501, false); + new BooleanFlag(601, false); /***************************************/ // 700 - dialer/calls public static final BooleanFlag ONGOING_CALL_STATUS_BAR_CHIP = - new BooleanFlag(600, true); + new BooleanFlag(700, true); public static final BooleanFlag ONGOING_CALL_IN_IMMERSIVE = - new BooleanFlag(601, true); + new BooleanFlag(701, true); public static final BooleanFlag ONGOING_CALL_IN_IMMERSIVE_CHIP_TAP = - new BooleanFlag(602, true); + new BooleanFlag(702, true); // Pay no attention to the reflection behind the curtain. // ========================== Curtain ========================== diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java index 071e0535e7c28..fbfba1b6d0d12 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java @@ -102,6 +102,8 @@ public class QuickStatusBarHeader extends FrameLayout { private boolean mHasCenterCutout; private boolean mConfigShowBatteryEstimate; + private boolean mUseCombinedQSHeader; + public QuickStatusBarHeader(Context context, AttributeSet attrs) { super(context, attrs); } @@ -158,7 +160,9 @@ public class QuickStatusBarHeader extends FrameLayout { void onAttach(TintedIconManager iconManager, QSExpansionPathInterpolator qsExpansionPathInterpolator, - List rssiIgnoredSlots) { + List rssiIgnoredSlots, + boolean useCombinedQSHeader) { + mUseCombinedQSHeader = useCombinedQSHeader; mTintedIconManager = iconManager; mRssiIgnoredSlots = rssiIgnoredSlots; int fillColor = Utils.getColorAttrDefaultColor(getContext(), @@ -233,8 +237,11 @@ public class QuickStatusBarHeader extends FrameLayout { // status bar is already displayed out of QS in split shade boolean shouldUseSplitShade = resources.getBoolean(R.bool.config_use_split_notification_shade); - mStatusIconsView.setVisibility(shouldUseSplitShade ? View.GONE : View.VISIBLE); - mDatePrivacyView.setVisibility(shouldUseSplitShade ? View.GONE : View.VISIBLE); + + mStatusIconsView.setVisibility( + shouldUseSplitShade || mUseCombinedQSHeader ? View.GONE : View.VISIBLE); + mDatePrivacyView.setVisibility( + shouldUseSplitShade || mUseCombinedQSHeader ? View.GONE : View.VISIBLE); mConfigShowBatteryEstimate = resources.getBoolean(R.bool.config_showBatteryEstimateQSBH); @@ -273,8 +280,8 @@ public class QuickStatusBarHeader extends FrameLayout { } MarginLayoutParams qqsLP = (MarginLayoutParams) mHeaderQsPanel.getLayoutParams(); - qqsLP.topMargin = mContext.getResources() - .getDimensionPixelSize(R.dimen.qqs_layout_margin_top); + qqsLP.topMargin = shouldUseSplitShade || !mUseCombinedQSHeader ? mContext.getResources() + .getDimensionPixelSize(R.dimen.qqs_layout_margin_top) : qsOffsetHeight; mHeaderQsPanel.setLayoutParams(qqsLP); updateBatteryMode(); diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java index 38428c53fead7..1b3450436c6fb 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java @@ -225,7 +225,8 @@ class QuickStatusBarHeaderController extends ViewController>() - verify(view).onAttach(any(), any(), capture(captor)) + verify(view).onAttach(any(), any(), capture(captor), anyBoolean()) assertThat(captor.value).containsExactly( mContext.getString(com.android.internal.R.string.status_bar_mobile) @@ -260,7 +261,7 @@ class QuickStatusBarHeaderControllerTest : SysuiTestCase() { controller.init() val captor = argumentCaptor>() - verify(view).onAttach(any(), any(), capture(captor)) + verify(view).onAttach(any(), any(), capture(captor), anyBoolean()) assertThat(captor.value).containsExactly( mContext.getString(com.android.internal.R.string.status_bar_no_calling), 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 fabe5a141a6bf..23378ab6e80a6 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 @@ -90,6 +90,7 @@ import com.android.systemui.classifier.FalsingManagerFake; import com.android.systemui.controls.dagger.ControlsComponent; import com.android.systemui.doze.DozeLog; import com.android.systemui.dump.DumpManager; +import com.android.systemui.flags.FeatureFlags; import com.android.systemui.fragments.FragmentHostManager; import com.android.systemui.fragments.FragmentService; import com.android.systemui.media.KeyguardMediaController; @@ -303,6 +304,8 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { private DumpManager mDumpManager; @Mock private NotificationsQSContainerController mNotificationsQSContainerController; + @Mock + private FeatureFlags mFeatureFlags; private SysuiStatusBarStateController mStatusBarStateController; private NotificationPanelViewController mNotificationPanelViewController; @@ -447,7 +450,8 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { mLockscreenGestureLogger, new PanelExpansionStateManager(), mNotificationRemoteInputManager, - mControlsComponent); + mControlsComponent, + mFeatureFlags); mNotificationPanelViewController.initDependencies( mStatusBar, () -> {}, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/SplitShadeHeaderControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/SplitShadeHeaderControllerTest.kt index a9e8164e8b873..0cf0bd300419d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/SplitShadeHeaderControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/SplitShadeHeaderControllerTest.kt @@ -1,8 +1,7 @@ package com.android.systemui.statusbar.phone -import android.content.Context -import android.content.res.Resources import android.test.suitebuilder.annotation.SmallTest +import android.testing.AndroidTestingRunner import android.view.View import com.android.systemui.R import com.android.systemui.SysuiTestCase @@ -15,14 +14,16 @@ import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Rule import org.junit.Test +import org.junit.runner.RunWith import org.mockito.ArgumentMatchers.any import org.mockito.ArgumentMatchers.anyInt import org.mockito.Mock -import org.mockito.Mockito.`when` as whenever import org.mockito.Mockito.verify import org.mockito.junit.MockitoJUnit +import org.mockito.Mockito.`when` as whenever @SmallTest +@RunWith(AndroidTestingRunner::class) class SplitShadeHeaderControllerTest : SysuiTestCase() { @Mock private lateinit var view: View @@ -33,8 +34,7 @@ class SplitShadeHeaderControllerTest : SysuiTestCase() { @Mock private lateinit var featureFlags: FeatureFlags @Mock private lateinit var batteryMeterView: BatteryMeterView @Mock private lateinit var batteryMeterViewController: BatteryMeterViewController - @Mock private lateinit var resources: Resources - @Mock private lateinit var context: Context + @JvmField @Rule val mockitoRule = MockitoJUnit.rule() var viewVisibility = View.GONE @@ -45,8 +45,8 @@ class SplitShadeHeaderControllerTest : SysuiTestCase() { whenever(view.findViewById(R.id.batteryRemainingIcon)) .thenReturn(batteryMeterView) whenever(view.findViewById(R.id.statusIcons)).thenReturn(statusIcons) + whenever(view.context).thenReturn(context) whenever(statusIcons.context).thenReturn(context) - whenever(context.resources).thenReturn(resources) whenever(qsCarrierGroupControllerBuilder.setQSCarrierGroup(any())) .thenReturn(qsCarrierGroupControllerBuilder) whenever(qsCarrierGroupControllerBuilder.build()).thenReturn(qsCarrierGroupController) @@ -55,6 +55,7 @@ class SplitShadeHeaderControllerTest : SysuiTestCase() { null } whenever(view.visibility).thenAnswer { _ -> viewVisibility } + whenever(featureFlags.useCombinedQSHeaders()).thenReturn(false) splitShadeHeaderController = SplitShadeHeaderController(view, statusBarIconController, qsCarrierGroupControllerBuilder, featureFlags, batteryMeterViewController) }