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)
}