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 702a3549cbba7..b4c9a93959838 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -79,7 +79,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 3d44304f010ec..77e907c2e8614 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.java
+++ b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.java
@@ -187,6 +187,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 98149f407eb20..1343bdbf7be55 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -103,6 +103,8 @@ public class QuickStatusBarHeader extends FrameLayout {
private boolean mHasCenterCutout;
private boolean mConfigShowBatteryEstimate;
+ private boolean mUseCombinedQSHeader;
+
public QuickStatusBarHeader(Context context, AttributeSet attrs) {
super(context, attrs);
}
@@ -160,7 +162,9 @@ public class QuickStatusBarHeader extends FrameLayout {
void onAttach(TintedIconManager iconManager,
QSExpansionPathInterpolator qsExpansionPathInterpolator,
List rssiIgnoredSlots,
- StatusBarContentInsetsProvider insetsProvider) {
+ StatusBarContentInsetsProvider insetsProvider,
+ boolean useCombinedQSHeader) {
+ mUseCombinedQSHeader = useCombinedQSHeader;
mTintedIconManager = iconManager;
mRssiIgnoredSlots = rssiIgnoredSlots;
mInsetsProvider = insetsProvider;
@@ -236,8 +240,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);
@@ -276,8 +283,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 9e2b7306ab8ca..6a57e45d64f6d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
@@ -229,8 +229,8 @@ class QuickStatusBarHeaderController extends ViewController>()
- verify(view).onAttach(any(), any(), capture(captor), any())
+ verify(view).onAttach(any(), any(), capture(captor), any(), anyBoolean())
assertThat(captor.value).containsExactly(
mContext.getString(com.android.internal.R.string.status_bar_mobile)
@@ -264,7 +265,7 @@ class QuickStatusBarHeaderControllerTest : SysuiTestCase() {
controller.init()
val captor = argumentCaptor>()
- verify(view).onAttach(any(), any(), capture(captor), any())
+ verify(view).onAttach(any(), any(), capture(captor), any(), 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/SplitShadeHeaderControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/SplitShadeHeaderControllerTest.kt
index a9e8164e8b873..4f68a3d0ad284 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,6 @@ 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 +44,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 +54,7 @@ class SplitShadeHeaderControllerTest : SysuiTestCase() {
null
}
whenever(view.visibility).thenAnswer { _ -> viewVisibility }
+ whenever(featureFlags.useCombinedQSHeaders()).thenReturn(false)
splitShadeHeaderController = SplitShadeHeaderController(view, statusBarIconController,
qsCarrierGroupControllerBuilder, featureFlags, batteryMeterViewController)
}