diff options
15 files changed, 457 insertions, 25 deletions
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 000000000000..f0b59d825417 --- /dev/null +++ b/packages/SystemUI/res/layout/combined_qs_header.xml @@ -0,0 +1,114 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<androidx.constraintlayout.widget.ConstraintLayout + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + android:id="@+id/split_shade_status_bar" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:minHeight="@dimen/split_shade_header_min_height" + android:clickable="false" + android:focusable="true" + android:paddingLeft="@dimen/qs_panel_padding" + android:paddingRight="@dimen/qs_panel_padding" + android:visibility="gone" + android:theme="@style/Theme.SystemUI.QuickSettings.Header"> + + <androidx.constraintlayout.widget.Guideline + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:id="@+id/center" + app:layout_constraintGuide_percent="0.5" + android:orientation="vertical" /> + + <com.android.systemui.statusbar.policy.Clock + android:id="@+id/clock" + android:layout_width="wrap_content" + android:layout_height="0dp" + app:layout_constraintHeight_min="@dimen/split_shade_header_min_height" + android:gravity="start|center_vertical" + android:paddingStart="@dimen/status_bar_left_clock_starting_padding" + android:paddingEnd="@dimen/status_bar_left_clock_end_padding" + android:singleLine="true" + android:textAppearance="@style/TextAppearance.QS.Status" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toStartOf="@id/date" + /> + + <com.android.systemui.statusbar.policy.DateView + android:id="@+id/date" + android:layout_width="wrap_content" + android:layout_height="0dp" + app:layout_constraintHeight_min="@dimen/split_shade_header_min_height" + android:layout_gravity="start|center_vertical" + android:gravity="center_vertical" + android:singleLine="true" + android:textAppearance="@style/TextAppearance.QS.Status" + app:datePattern="@string/abbrev_wday_month_day_no_year_alarm" + app:layout_constraintStart_toEndOf="@id/clock" + app:layout_constraintEnd_toStartOf="@id/carrier_group" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintHorizontal_bias="0" + /> + + <include + android:id="@+id/carrier_group" + layout="@layout/qs_carrier_group" + android:layout_width="0dp" + android:layout_height="0dp" + app:layout_constraintHeight_min="@dimen/split_shade_header_min_height" + app:layout_constrainedWidth="true" + android:layout_gravity="end|center_vertical" + android:layout_marginStart="8dp" + android:focusable="false" + android:minHeight="@dimen/split_shade_header_min_height" + android:minWidth="48dp" + app:layout_constraintStart_toEndOf="@id/date" + app:layout_constraintEnd_toStartOf="@id/statusIcons" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintHorizontal_bias="1" + /> + + <com.android.systemui.statusbar.phone.StatusIconContainer + android:id="@+id/statusIcons" + android:layout_width="wrap_content" + android:layout_height="0dp" + app:layout_constraintHeight_min="@dimen/split_shade_header_min_height" + android:paddingEnd="@dimen/signal_cluster_battery_padding" + app:layout_constraintStart_toEndOf="@id/carrier_group" + app:layout_constraintEnd_toStartOf="@id/batteryRemainingIcon" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="parent" + /> + + <com.android.systemui.battery.BatteryMeterView + android:id="@+id/batteryRemainingIcon" + android:layout_width="wrap_content" + android:layout_height="0dp" + app:layout_constraintHeight_min="@dimen/split_shade_header_min_height" + app:textAppearance="@style/TextAppearance.QS.Status" + app:layout_constraintStart_toEndOf="@id/statusIcons" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="parent" + /> + +</androidx.constraintlayout.widget.ConstraintLayout>
\ 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 cc1af873ce2b..82186c13394e 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"> - <include layout="@layout/split_shade_header"/> + <ViewStub + android:id="@+id/qs_header_stub" + android:layout_height="wrap_content" + android:layout_width="match_parent" + /> <include layout="@layout/keyguard_status_view" diff --git a/packages/SystemUI/res/xml/qqs_header.xml b/packages/SystemUI/res/xml/qqs_header.xml new file mode 100644 index 000000000000..fdf73d53e905 --- /dev/null +++ b/packages/SystemUI/res/xml/qqs_header.xml @@ -0,0 +1,82 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<ConstraintSet + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto"> + + <Constraint + android:id="@+id/clock" + android:layout_width="wrap_content" + android:layout_height="0dp" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toStartOf="@id/date" + app:layout_constraintHorizontal_bias="0" + app:layout_constraintHorizontal_chainStyle="packed" + /> + + <Constraint + android:id="@+id/date" + android:layout_width="wrap_content" + android:layout_height="0dp" + app:layout_constraintStart_toEndOf="@id/clock" + app:layout_constraintEnd_toStartOf="@id/carrier_group" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintHorizontal_bias="0" + /> + + <Constraint + android:id="@+id/carrier_group" + android:layout_width="0dp" + android:layout_height="0dp" + app:layout_constrainedWidth="true" + android:layout_gravity="end|center_vertical" + android:layout_marginStart="8dp" + app:layout_constraintStart_toEndOf="@id/date" + app:layout_constraintEnd_toStartOf="@id/statusIcons" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="parent" + android:visibility="invisible" + app:layout_constraintHorizontal_bias="1" + /> + + <Constraint + android:id="@+id/statusIcons" + android:layout_width="wrap_content" + android:layout_height="0dp" + app:layout_constraintStart_toEndOf="@id/carrier_group" + app:layout_constraintEnd_toStartOf="@id/batteryRemainingIcon" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintHorizontal_bias="1" + /> + + <Constraint + android:id="@+id/batteryRemainingIcon" + android:layout_width="wrap_content" + android:layout_height="0dp" + app:layout_constraintStart_toEndOf="@id/statusIcons" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintHorizontal_bias="1" + /> + +</ConstraintSet>
\ 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 000000000000..72e518eab839 --- /dev/null +++ b/packages/SystemUI/res/xml/qs_header.xml @@ -0,0 +1,79 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<ConstraintSet + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto"> + + <Constraint + android:id="@+id/clock" + android:layout_width="wrap_content" + android:layout_height="48dp" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/date" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toStartOf="@id/carrier_group" + app:layout_constraintHorizontal_bias="0" + /> + + <Constraint + android:id="@+id/date" + android:layout_width="wrap_content" + android:layout_height="48dp" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toTopOf="@id/clock" + app:layout_constraintHorizontal_bias="0" + /> + + <Constraint + android:id="@+id/carrier_group" + android:layout_width="0dp" + android:layout_height="48dp" + app:layout_constrainedWidth="true" + android:layout_gravity="end|center_vertical" + android:layout_marginStart="8dp" + app:layout_constraintStart_toEndOf="@id/clock" + app:layout_constraintEnd_toStartOf="@id/statusIcons" + app:layout_constraintTop_toTopOf="@id/clock" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintHorizontal_bias="1" + /> + + <Constraint + android:id="@+id/statusIcons" + android:layout_width="wrap_content" + android:layout_height="48dp" + app:layout_constraintStart_toEndOf="@id/carrier_group" + app:layout_constraintEnd_toStartOf="@id/batteryRemainingIcon" + app:layout_constraintTop_toTopOf="@id/clock" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintHorizontal_bias="1" + /> + + <Constraint + android:id="@+id/batteryRemainingIcon" + android:layout_width="wrap_content" + android:layout_height="48dp" + app:layout_constraintStart_toEndOf="@id/statusIcons" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toTopOf="@id/clock" + app:layout_constraintBottom_toBottomOf="parent" + /> + +</ConstraintSet>
\ 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 000000000000..a3ee1e2fae64 --- /dev/null +++ b/packages/SystemUI/res/xml/split_header.xml @@ -0,0 +1,77 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<ConstraintSet + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto"> + + <Constraint + android:id="@+id/clock" + android:layout_width="wrap_content" + android:layout_height="0dp" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toStartOf="@id/date" + /> + + <Constraint + android:id="@+id/date" + android:layout_width="wrap_content" + android:layout_height="0dp" + app:layout_constraintStart_toEndOf="@id/clock" + app:layout_constraintEnd_toStartOf="@id/carrier_group" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintHorizontal_bias="0" + /> + + <Constraint + android:id="@+id/carrier_group" + android:layout_width="0dp" + android:layout_height="0dp" + app:layout_constrainedWidth="true" + android:layout_gravity="end|center_vertical" + android:layout_marginStart="8dp" + app:layout_constraintStart_toEndOf="@id/date" + app:layout_constraintEnd_toStartOf="@id/statusIcons" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintHorizontal_bias="1" + /> + + <Constraint + android:id="@+id/statusIcons" + android:layout_width="wrap_content" + android:layout_height="0dp" + app:layout_constraintStart_toEndOf="@id/carrier_group" + app:layout_constraintEnd_toStartOf="@id/batteryRemainingIcon" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="parent" + /> + + <Constraint + android:id="@+id/batteryRemainingIcon" + android:layout_width="wrap_content" + android:layout_height="0dp" + app:layout_constraintStart_toEndOf="@id/statusIcons" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="parent" + /> + +</ConstraintSet>
\ 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 48bb281429c2..ab083a920a10 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 3761d42ae98c..f09c797a6608 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 071e0535e7c2..fbfba1b6d0d1 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<String> rssiIgnoredSlots) { + List<String> 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 38428c53fead..1b3450436c6f 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<QuickStatusBarHeader ); } - mView.onAttach(mIconManager, mQSExpansionPathInterpolator, rssiIgnoredSlots); + mView.onAttach(mIconManager, mQSExpansionPathInterpolator, rssiIgnoredSlots, + mFeatureFlags.useCombinedQSHeaders()); mDemoModeController.addCallback(mDemoModeReceiver); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java index 19e802594076..f6005a834661 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java @@ -22,6 +22,7 @@ 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 androidx.constraintlayout.widget.ConstraintSet.WRAP_CONTENT; import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE; import static com.android.keyguard.KeyguardClockSwitch.LARGE; @@ -116,6 +117,7 @@ import com.android.systemui.controls.dagger.ControlsComponent; import com.android.systemui.dagger.qualifiers.DisplayId; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.doze.DozeLog; +import com.android.systemui.flags.FeatureFlags; import com.android.systemui.fragments.FragmentHostManager.FragmentListener; import com.android.systemui.fragments.FragmentService; import com.android.systemui.media.KeyguardMediaController; @@ -420,6 +422,9 @@ public class NotificationPanelViewController extends PanelViewController { private boolean mIsFullWidth; private boolean mBlockingExpansionForCurrentTouch; + // TODO (b/204204226): no longer needed once refactor is complete + private final boolean mUseCombinedQSHeaders; + /** * Following variables maintain state of events when input focus transfer may occur. */ @@ -689,7 +694,8 @@ public class NotificationPanelViewController extends PanelViewController { LockscreenGestureLogger lockscreenGestureLogger, PanelExpansionStateManager panelExpansionStateManager, NotificationRemoteInputManager remoteInputManager, - ControlsComponent controlsComponent) { + ControlsComponent controlsComponent, + FeatureFlags featureFlags) { super(view, falsingManager, dozeLog, @@ -805,6 +811,8 @@ public class NotificationPanelViewController extends PanelViewController { mMaxKeyguardNotifications = resources.getInteger(R.integer.keyguard_max_notification_count); updateUserSwitcherFlags(); onFinishInflate(); + + mUseCombinedQSHeaders = featureFlags.useCombinedQSHeaders(); } private void onFinishInflate() { @@ -1004,6 +1012,9 @@ public class NotificationPanelViewController extends PanelViewController { } 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.getConstraint(R.id.notification_stack_scroller).layout.mWidth = panelWidth; constraintSet.getConstraint(R.id.qs_frame).layout.mWidth = qsWidth; @@ -2218,6 +2229,7 @@ public class NotificationPanelViewController extends PanelViewController { float qsExpansionFraction = computeQsExpansionFraction(); mQs.setQsExpansion(qsExpansionFraction, getExpandedFraction(), getHeaderTranslation(), mNotificationStackScrollLayoutController.getNotificationSquishinessFraction()); + mSplitShadeHeaderController.setQsExpandedFraction(qsExpansionFraction); mMediaHierarchyManager.setQsExpansion(qsExpansionFraction); int qsPanelBottomY = calculateQsBottomPosition(qsExpansionFraction); mScrimController.setQsPosition(qsExpansionFraction, qsPanelBottomY); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SplitShadeHeaderController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SplitShadeHeaderController.kt index 873289130139..bac4234389aa 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SplitShadeHeaderController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SplitShadeHeaderController.kt @@ -17,6 +17,8 @@ package com.android.systemui.statusbar.phone import android.view.View +import androidx.constraintlayout.widget.ConstraintLayout +import androidx.constraintlayout.widget.ConstraintSet import com.android.systemui.R import com.android.systemui.animation.ShadeInterpolation import com.android.systemui.battery.BatteryMeterView @@ -37,6 +39,7 @@ class SplitShadeHeaderController @Inject constructor( batteryMeterViewController: BatteryMeterViewController ) { + private val combinedHeaders = featureFlags.useCombinedQSHeaders() // TODO(b/194178072) Handle RSSI hiding when multi carrier private val iconManager: StatusBarIconController.IconManager private val qsCarrierGroupController: QSCarrierGroupController @@ -75,6 +78,19 @@ class SplitShadeHeaderController @Inject constructor( } } + var qsExpandedFraction = -1f + set(value) { + if (visible && field != value) { + field = value + updateVisibility() + } + } + + private val constraintSplit = ConstraintSet() + .apply { load(statusBar.context, R.xml.split_header) } + private val constraintQQS = ConstraintSet().apply { load(statusBar.context, R.xml.qqs_header) } + private val constraintQS = ConstraintSet().apply { load(statusBar.context, R.xml.qs_header) } + init { batteryMeterViewController.init() val batteryIcon: BatteryMeterView = statusBar.findViewById(R.id.batteryRemainingIcon) @@ -91,7 +107,7 @@ class SplitShadeHeaderController @Inject constructor( } private fun updateVisibility() { - val visibility = if (!splitShadeMode) { + val visibility = if (!splitShadeMode && !combinedHeaders) { View.GONE } else if (shadeExpanded) { View.VISIBLE @@ -102,6 +118,21 @@ class SplitShadeHeaderController @Inject constructor( statusBar.visibility = visibility visible = visibility == View.VISIBLE } + updateConstraints() + } + + private fun updateConstraints() { + if (!combinedHeaders) { + return + } + statusBar as ConstraintLayout + if (splitShadeMode) { + constraintSplit.applyTo(statusBar) + } else if (qsExpandedFraction == 1f) { + constraintQS.applyTo(statusBar) + } else { + constraintQQS.applyTo(statusBar) + } } private fun updateListeners() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java index 9de0c46ff078..2765fe37f846 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java @@ -19,11 +19,13 @@ package com.android.systemui.statusbar.phone.dagger; import android.annotation.Nullable; import android.view.LayoutInflater; import android.view.View; +import android.view.ViewStub; import com.android.keyguard.LockIconView; import com.android.systemui.R; import com.android.systemui.battery.BatteryMeterView; import com.android.systemui.biometrics.AuthRippleView; +import com.android.systemui.flags.FeatureFlags; import com.android.systemui.statusbar.NotificationShelf; import com.android.systemui.statusbar.NotificationShelfController; import com.android.systemui.statusbar.notification.row.dagger.NotificationShelfComponent; @@ -126,9 +128,16 @@ public abstract class StatusBarViewModule { @Provides @Named(SPLIT_SHADE_HEADER) @StatusBarComponent.StatusBarScope - public static View getSlitShadeStatusBarView( - NotificationShadeWindowView notificationShadeWindowView) { - return notificationShadeWindowView.findViewById(R.id.split_shade_status_bar); + public static View getSplitShadeStatusBarView( + NotificationShadeWindowView notificationShadeWindowView, + FeatureFlags featureFlags) { + ViewStub stub = notificationShadeWindowView.findViewById(R.id.qs_header_stub); + int layoutId = featureFlags.useCombinedQSHeaders() + ? R.layout.combined_qs_header + : R.layout.split_shade_header; + stub.setLayoutResource(layoutId); + View v = stub.inflate(); + return v; } /** */ diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt index 92b9f75936b9..f32ac849b000 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt @@ -50,6 +50,7 @@ import org.junit.runner.RunWith import org.mockito.Answers import org.mockito.ArgumentMatchers.anyInt import org.mockito.Mock +import org.mockito.Mockito.anyBoolean import org.mockito.Mockito.reset import org.mockito.Mockito.verify import org.mockito.Mockito.`when` @@ -247,7 +248,7 @@ class QuickStatusBarHeaderControllerTest : SysuiTestCase() { controller.init() val captor = argumentCaptor<List<String>>() - 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<List<String>>() - 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 fabe5a141a6b..23378ab6e80a 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 a9e8164e8b87..0cf0bd300419 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<BatteryMeterView>(view.findViewById(R.id.batteryRemainingIcon)) .thenReturn(batteryMeterView) whenever<StatusIconContainer>(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) } |