[DO NOT MERGE] Unify QS Headers in a ConstraintLayout am: 94f300dfe5

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/16148684

Change-Id: Id9a704aff8ff5546434623a5b748a83e81ff3d0f
This commit is contained in:
Fabian Kozynski
2021-11-04 19:58:31 +00:00
committed by Automerger Merge Worker
15 changed files with 457 additions and 25 deletions

View File

@@ -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>

View File

@@ -75,7 +75,11 @@
android:clipToPadding="false" android:clipToPadding="false"
android:clipChildren="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 <include
layout="@layout/keyguard_status_view" layout="@layout/keyguard_status_view"

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -183,6 +183,13 @@ public class FeatureFlags {
return isEnabled(Flags.NEW_USER_SWITCHER); 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 */ /** static method for the system setting */
public static boolean isProviderModelSettingEnabled(Context context) { public static boolean isProviderModelSettingEnabled(Context context) {
return FeatureFlagUtils.isEnabled(context, FeatureFlagUtils.SETTINGS_PROVIDER_MODEL); return FeatureFlagUtils.isEnabled(context, FeatureFlagUtils.SETTINGS_PROVIDER_MODEL);

View File

@@ -77,21 +77,24 @@ public class Flags {
public static final BooleanFlag NEW_USER_SWITCHER = public static final BooleanFlag NEW_USER_SWITCHER =
new BooleanFlag(500, true); new BooleanFlag(500, true);
public static final BooleanFlag COMBINED_QS_HEADERS =
new BooleanFlag(501, false);
/***************************************/ /***************************************/
// 600- status bar // 600- status bar
public static final BooleanFlag COMBINED_STATUS_BAR_SIGNAL_ICONS = public static final BooleanFlag COMBINED_STATUS_BAR_SIGNAL_ICONS =
new BooleanFlag(501, false); new BooleanFlag(601, false);
/***************************************/ /***************************************/
// 700 - dialer/calls // 700 - dialer/calls
public static final BooleanFlag ONGOING_CALL_STATUS_BAR_CHIP = 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 = 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 = 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. // Pay no attention to the reflection behind the curtain.
// ========================== Curtain ========================== // ========================== Curtain ==========================

View File

@@ -102,6 +102,8 @@ public class QuickStatusBarHeader extends FrameLayout {
private boolean mHasCenterCutout; private boolean mHasCenterCutout;
private boolean mConfigShowBatteryEstimate; private boolean mConfigShowBatteryEstimate;
private boolean mUseCombinedQSHeader;
public QuickStatusBarHeader(Context context, AttributeSet attrs) { public QuickStatusBarHeader(Context context, AttributeSet attrs) {
super(context, attrs); super(context, attrs);
} }
@@ -158,7 +160,9 @@ public class QuickStatusBarHeader extends FrameLayout {
void onAttach(TintedIconManager iconManager, void onAttach(TintedIconManager iconManager,
QSExpansionPathInterpolator qsExpansionPathInterpolator, QSExpansionPathInterpolator qsExpansionPathInterpolator,
List<String> rssiIgnoredSlots) { List<String> rssiIgnoredSlots,
boolean useCombinedQSHeader) {
mUseCombinedQSHeader = useCombinedQSHeader;
mTintedIconManager = iconManager; mTintedIconManager = iconManager;
mRssiIgnoredSlots = rssiIgnoredSlots; mRssiIgnoredSlots = rssiIgnoredSlots;
int fillColor = Utils.getColorAttrDefaultColor(getContext(), 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 // status bar is already displayed out of QS in split shade
boolean shouldUseSplitShade = boolean shouldUseSplitShade =
resources.getBoolean(R.bool.config_use_split_notification_shade); 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); mConfigShowBatteryEstimate = resources.getBoolean(R.bool.config_showBatteryEstimateQSBH);
@@ -273,8 +280,8 @@ public class QuickStatusBarHeader extends FrameLayout {
} }
MarginLayoutParams qqsLP = (MarginLayoutParams) mHeaderQsPanel.getLayoutParams(); MarginLayoutParams qqsLP = (MarginLayoutParams) mHeaderQsPanel.getLayoutParams();
qqsLP.topMargin = mContext.getResources() qqsLP.topMargin = shouldUseSplitShade || !mUseCombinedQSHeader ? mContext.getResources()
.getDimensionPixelSize(R.dimen.qqs_layout_margin_top); .getDimensionPixelSize(R.dimen.qqs_layout_margin_top) : qsOffsetHeight;
mHeaderQsPanel.setLayoutParams(qqsLP); mHeaderQsPanel.setLayoutParams(qqsLP);
updateBatteryMode(); updateBatteryMode();

View File

@@ -225,7 +225,8 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader
); );
} }
mView.onAttach(mIconManager, mQSExpansionPathInterpolator, rssiIgnoredSlots); mView.onAttach(mIconManager, mQSExpansionPathInterpolator, rssiIgnoredSlots,
mFeatureFlags.useCombinedQSHeaders());
mDemoModeController.addCallback(mDemoModeReceiver); mDemoModeController.addCallback(mDemoModeReceiver);

View File

@@ -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.PARENT_ID;
import static androidx.constraintlayout.widget.ConstraintSet.START; import static androidx.constraintlayout.widget.ConstraintSet.START;
import static androidx.constraintlayout.widget.ConstraintSet.TOP; 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.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE;
import static com.android.keyguard.KeyguardClockSwitch.LARGE; 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.DisplayId;
import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.doze.DozeLog; import com.android.systemui.doze.DozeLog;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.fragments.FragmentHostManager.FragmentListener; import com.android.systemui.fragments.FragmentHostManager.FragmentListener;
import com.android.systemui.fragments.FragmentService; import com.android.systemui.fragments.FragmentService;
import com.android.systemui.media.KeyguardMediaController; import com.android.systemui.media.KeyguardMediaController;
@@ -420,6 +422,9 @@ public class NotificationPanelViewController extends PanelViewController {
private boolean mIsFullWidth; private boolean mIsFullWidth;
private boolean mBlockingExpansionForCurrentTouch; 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. * Following variables maintain state of events when input focus transfer may occur.
*/ */
@@ -689,7 +694,8 @@ public class NotificationPanelViewController extends PanelViewController {
LockscreenGestureLogger lockscreenGestureLogger, LockscreenGestureLogger lockscreenGestureLogger,
PanelExpansionStateManager panelExpansionStateManager, PanelExpansionStateManager panelExpansionStateManager,
NotificationRemoteInputManager remoteInputManager, NotificationRemoteInputManager remoteInputManager,
ControlsComponent controlsComponent) { ControlsComponent controlsComponent,
FeatureFlags featureFlags) {
super(view, super(view,
falsingManager, falsingManager,
dozeLog, dozeLog,
@@ -805,6 +811,8 @@ public class NotificationPanelViewController extends PanelViewController {
mMaxKeyguardNotifications = resources.getInteger(R.integer.keyguard_max_notification_count); mMaxKeyguardNotifications = resources.getInteger(R.integer.keyguard_max_notification_count);
updateUserSwitcherFlags(); updateUserSwitcherFlags();
onFinishInflate(); onFinishInflate();
mUseCombinedQSHeaders = featureFlags.useCombinedQSHeaders();
} }
private void onFinishInflate() { private void onFinishInflate() {
@@ -1004,6 +1012,9 @@ public class NotificationPanelViewController extends PanelViewController {
} else { } else {
constraintSet.connect(R.id.qs_frame, END, PARENT_ID, END); constraintSet.connect(R.id.qs_frame, END, PARENT_ID, END);
constraintSet.connect(R.id.notification_stack_scroller, START, PARENT_ID, START); 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.notification_stack_scroller).layout.mWidth = panelWidth;
constraintSet.getConstraint(R.id.qs_frame).layout.mWidth = qsWidth; constraintSet.getConstraint(R.id.qs_frame).layout.mWidth = qsWidth;
@@ -2218,6 +2229,7 @@ public class NotificationPanelViewController extends PanelViewController {
float qsExpansionFraction = computeQsExpansionFraction(); float qsExpansionFraction = computeQsExpansionFraction();
mQs.setQsExpansion(qsExpansionFraction, getExpandedFraction(), getHeaderTranslation(), mQs.setQsExpansion(qsExpansionFraction, getExpandedFraction(), getHeaderTranslation(),
mNotificationStackScrollLayoutController.getNotificationSquishinessFraction()); mNotificationStackScrollLayoutController.getNotificationSquishinessFraction());
mSplitShadeHeaderController.setQsExpandedFraction(qsExpansionFraction);
mMediaHierarchyManager.setQsExpansion(qsExpansionFraction); mMediaHierarchyManager.setQsExpansion(qsExpansionFraction);
int qsPanelBottomY = calculateQsBottomPosition(qsExpansionFraction); int qsPanelBottomY = calculateQsBottomPosition(qsExpansionFraction);
mScrimController.setQsPosition(qsExpansionFraction, qsPanelBottomY); mScrimController.setQsPosition(qsExpansionFraction, qsPanelBottomY);

View File

@@ -17,6 +17,8 @@
package com.android.systemui.statusbar.phone package com.android.systemui.statusbar.phone
import android.view.View import android.view.View
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
import com.android.systemui.R import com.android.systemui.R
import com.android.systemui.animation.ShadeInterpolation import com.android.systemui.animation.ShadeInterpolation
import com.android.systemui.battery.BatteryMeterView import com.android.systemui.battery.BatteryMeterView
@@ -37,6 +39,7 @@ class SplitShadeHeaderController @Inject constructor(
batteryMeterViewController: BatteryMeterViewController batteryMeterViewController: BatteryMeterViewController
) { ) {
private val combinedHeaders = featureFlags.useCombinedQSHeaders()
// TODO(b/194178072) Handle RSSI hiding when multi carrier // TODO(b/194178072) Handle RSSI hiding when multi carrier
private val iconManager: StatusBarIconController.IconManager private val iconManager: StatusBarIconController.IconManager
private val qsCarrierGroupController: QSCarrierGroupController 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 { init {
batteryMeterViewController.init() batteryMeterViewController.init()
val batteryIcon: BatteryMeterView = statusBar.findViewById(R.id.batteryRemainingIcon) val batteryIcon: BatteryMeterView = statusBar.findViewById(R.id.batteryRemainingIcon)
@@ -91,7 +107,7 @@ class SplitShadeHeaderController @Inject constructor(
} }
private fun updateVisibility() { private fun updateVisibility() {
val visibility = if (!splitShadeMode) { val visibility = if (!splitShadeMode && !combinedHeaders) {
View.GONE View.GONE
} else if (shadeExpanded) { } else if (shadeExpanded) {
View.VISIBLE View.VISIBLE
@@ -102,6 +118,21 @@ class SplitShadeHeaderController @Inject constructor(
statusBar.visibility = visibility statusBar.visibility = visibility
visible = visibility == View.VISIBLE 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() { private fun updateListeners() {

View File

@@ -19,11 +19,13 @@ package com.android.systemui.statusbar.phone.dagger;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewStub;
import com.android.keyguard.LockIconView; import com.android.keyguard.LockIconView;
import com.android.systemui.R; import com.android.systemui.R;
import com.android.systemui.battery.BatteryMeterView; import com.android.systemui.battery.BatteryMeterView;
import com.android.systemui.biometrics.AuthRippleView; import com.android.systemui.biometrics.AuthRippleView;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.statusbar.NotificationShelf; import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.NotificationShelfController; import com.android.systemui.statusbar.NotificationShelfController;
import com.android.systemui.statusbar.notification.row.dagger.NotificationShelfComponent; import com.android.systemui.statusbar.notification.row.dagger.NotificationShelfComponent;
@@ -126,9 +128,16 @@ public abstract class StatusBarViewModule {
@Provides @Provides
@Named(SPLIT_SHADE_HEADER) @Named(SPLIT_SHADE_HEADER)
@StatusBarComponent.StatusBarScope @StatusBarComponent.StatusBarScope
public static View getSlitShadeStatusBarView( public static View getSplitShadeStatusBarView(
NotificationShadeWindowView notificationShadeWindowView) { NotificationShadeWindowView notificationShadeWindowView,
return notificationShadeWindowView.findViewById(R.id.split_shade_status_bar); 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;
} }
/** */ /** */

View File

@@ -50,6 +50,7 @@ import org.junit.runner.RunWith
import org.mockito.Answers import org.mockito.Answers
import org.mockito.ArgumentMatchers.anyInt import org.mockito.ArgumentMatchers.anyInt
import org.mockito.Mock import org.mockito.Mock
import org.mockito.Mockito.anyBoolean
import org.mockito.Mockito.reset import org.mockito.Mockito.reset
import org.mockito.Mockito.verify import org.mockito.Mockito.verify
import org.mockito.Mockito.`when` import org.mockito.Mockito.`when`
@@ -247,7 +248,7 @@ class QuickStatusBarHeaderControllerTest : SysuiTestCase() {
controller.init() controller.init()
val captor = argumentCaptor<List<String>>() val captor = argumentCaptor<List<String>>()
verify(view).onAttach(any(), any(), capture(captor)) verify(view).onAttach(any(), any(), capture(captor), anyBoolean())
assertThat(captor.value).containsExactly( assertThat(captor.value).containsExactly(
mContext.getString(com.android.internal.R.string.status_bar_mobile) mContext.getString(com.android.internal.R.string.status_bar_mobile)
@@ -260,7 +261,7 @@ class QuickStatusBarHeaderControllerTest : SysuiTestCase() {
controller.init() controller.init()
val captor = argumentCaptor<List<String>>() val captor = argumentCaptor<List<String>>()
verify(view).onAttach(any(), any(), capture(captor)) verify(view).onAttach(any(), any(), capture(captor), anyBoolean())
assertThat(captor.value).containsExactly( assertThat(captor.value).containsExactly(
mContext.getString(com.android.internal.R.string.status_bar_no_calling), mContext.getString(com.android.internal.R.string.status_bar_no_calling),

View File

@@ -90,6 +90,7 @@ import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.controls.dagger.ControlsComponent; import com.android.systemui.controls.dagger.ControlsComponent;
import com.android.systemui.doze.DozeLog; import com.android.systemui.doze.DozeLog;
import com.android.systemui.dump.DumpManager; import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.fragments.FragmentHostManager; import com.android.systemui.fragments.FragmentHostManager;
import com.android.systemui.fragments.FragmentService; import com.android.systemui.fragments.FragmentService;
import com.android.systemui.media.KeyguardMediaController; import com.android.systemui.media.KeyguardMediaController;
@@ -303,6 +304,8 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
private DumpManager mDumpManager; private DumpManager mDumpManager;
@Mock @Mock
private NotificationsQSContainerController mNotificationsQSContainerController; private NotificationsQSContainerController mNotificationsQSContainerController;
@Mock
private FeatureFlags mFeatureFlags;
private SysuiStatusBarStateController mStatusBarStateController; private SysuiStatusBarStateController mStatusBarStateController;
private NotificationPanelViewController mNotificationPanelViewController; private NotificationPanelViewController mNotificationPanelViewController;
@@ -447,7 +450,8 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
mLockscreenGestureLogger, mLockscreenGestureLogger,
new PanelExpansionStateManager(), new PanelExpansionStateManager(),
mNotificationRemoteInputManager, mNotificationRemoteInputManager,
mControlsComponent); mControlsComponent,
mFeatureFlags);
mNotificationPanelViewController.initDependencies( mNotificationPanelViewController.initDependencies(
mStatusBar, mStatusBar,
() -> {}, () -> {},

View File

@@ -1,8 +1,7 @@
package com.android.systemui.statusbar.phone package com.android.systemui.statusbar.phone
import android.content.Context
import android.content.res.Resources
import android.test.suitebuilder.annotation.SmallTest import android.test.suitebuilder.annotation.SmallTest
import android.testing.AndroidTestingRunner
import android.view.View import android.view.View
import com.android.systemui.R import com.android.systemui.R
import com.android.systemui.SysuiTestCase import com.android.systemui.SysuiTestCase
@@ -15,14 +14,16 @@ import com.google.common.truth.Truth.assertThat
import org.junit.Before import org.junit.Before
import org.junit.Rule import org.junit.Rule
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.any import org.mockito.ArgumentMatchers.any
import org.mockito.ArgumentMatchers.anyInt import org.mockito.ArgumentMatchers.anyInt
import org.mockito.Mock import org.mockito.Mock
import org.mockito.Mockito.`when` as whenever
import org.mockito.Mockito.verify import org.mockito.Mockito.verify
import org.mockito.junit.MockitoJUnit import org.mockito.junit.MockitoJUnit
import org.mockito.Mockito.`when` as whenever
@SmallTest @SmallTest
@RunWith(AndroidTestingRunner::class)
class SplitShadeHeaderControllerTest : SysuiTestCase() { class SplitShadeHeaderControllerTest : SysuiTestCase() {
@Mock private lateinit var view: View @Mock private lateinit var view: View
@@ -33,8 +34,7 @@ class SplitShadeHeaderControllerTest : SysuiTestCase() {
@Mock private lateinit var featureFlags: FeatureFlags @Mock private lateinit var featureFlags: FeatureFlags
@Mock private lateinit var batteryMeterView: BatteryMeterView @Mock private lateinit var batteryMeterView: BatteryMeterView
@Mock private lateinit var batteryMeterViewController: BatteryMeterViewController @Mock private lateinit var batteryMeterViewController: BatteryMeterViewController
@Mock private lateinit var resources: Resources
@Mock private lateinit var context: Context
@JvmField @Rule val mockitoRule = MockitoJUnit.rule() @JvmField @Rule val mockitoRule = MockitoJUnit.rule()
var viewVisibility = View.GONE var viewVisibility = View.GONE
@@ -45,8 +45,8 @@ class SplitShadeHeaderControllerTest : SysuiTestCase() {
whenever<BatteryMeterView>(view.findViewById(R.id.batteryRemainingIcon)) whenever<BatteryMeterView>(view.findViewById(R.id.batteryRemainingIcon))
.thenReturn(batteryMeterView) .thenReturn(batteryMeterView)
whenever<StatusIconContainer>(view.findViewById(R.id.statusIcons)).thenReturn(statusIcons) whenever<StatusIconContainer>(view.findViewById(R.id.statusIcons)).thenReturn(statusIcons)
whenever(view.context).thenReturn(context)
whenever(statusIcons.context).thenReturn(context) whenever(statusIcons.context).thenReturn(context)
whenever(context.resources).thenReturn(resources)
whenever(qsCarrierGroupControllerBuilder.setQSCarrierGroup(any())) whenever(qsCarrierGroupControllerBuilder.setQSCarrierGroup(any()))
.thenReturn(qsCarrierGroupControllerBuilder) .thenReturn(qsCarrierGroupControllerBuilder)
whenever(qsCarrierGroupControllerBuilder.build()).thenReturn(qsCarrierGroupController) whenever(qsCarrierGroupControllerBuilder.build()).thenReturn(qsCarrierGroupController)
@@ -55,6 +55,7 @@ class SplitShadeHeaderControllerTest : SysuiTestCase() {
null null
} }
whenever(view.visibility).thenAnswer { _ -> viewVisibility } whenever(view.visibility).thenAnswer { _ -> viewVisibility }
whenever(featureFlags.useCombinedQSHeaders()).thenReturn(false)
splitShadeHeaderController = SplitShadeHeaderController(view, statusBarIconController, splitShadeHeaderController = SplitShadeHeaderController(view, statusBarIconController,
qsCarrierGroupControllerBuilder, featureFlags, batteryMeterViewController) qsCarrierGroupControllerBuilder, featureFlags, batteryMeterViewController)
} }