From 3555ebc8b5133ab05cca2424c79f8a9e2aacc02e Mon Sep 17 00:00:00 2001 From: Fabian Kozynski Date: Tue, 7 Dec 2021 15:53:14 -0500 Subject: [PATCH 1/2] Add privacy indicators to combined QS header Use alpha 0 in icons and battery when privacy indicators are visible in QQS constraint. Test: manual, using handheld and split shade layout Bug: 202847414 Change-Id: I8b523c9f87c78fd4eac99a421eebaec90e37cadf --- .../res/layout/combined_qs_header.xml | 12 ++++++++++ packages/SystemUI/res/xml/qqs_header.xml | 19 ++++++++++++++- packages/SystemUI/res/xml/qs_header.xml | 11 ++++++++- packages/SystemUI/res/xml/split_header.xml | 24 +++++++++++++++++++ .../phone/SplitShadeHeaderController.kt | 17 ++++++++++++- 5 files changed, 80 insertions(+), 3 deletions(-) diff --git a/packages/SystemUI/res/layout/combined_qs_header.xml b/packages/SystemUI/res/layout/combined_qs_header.xml index 1f10e5dfeed83..405863dc9d92c 100644 --- a/packages/SystemUI/res/layout/combined_qs_header.xml +++ b/packages/SystemUI/res/layout/combined_qs_header.xml @@ -101,4 +101,16 @@ app:layout_constraintBottom_toBottomOf="parent" /> + + + + \ No newline at end of file diff --git a/packages/SystemUI/res/xml/qqs_header.xml b/packages/SystemUI/res/xml/qqs_header.xml index 3d7b549fc54b8..c5b4c5d776b9a 100644 --- a/packages/SystemUI/res/xml/qqs_header.xml +++ b/packages/SystemUI/res/xml/qqs_header.xml @@ -48,6 +48,14 @@ /> + + + + + + - + + + \ No newline at end of file diff --git a/packages/SystemUI/res/xml/qs_header.xml b/packages/SystemUI/res/xml/qs_header.xml index 6a0ab866966ce..8248fcdb50fb9 100644 --- a/packages/SystemUI/res/xml/qs_header.xml +++ b/packages/SystemUI/res/xml/qs_header.xml @@ -58,5 +58,14 @@ /> - + + + \ No newline at end of file diff --git a/packages/SystemUI/res/xml/split_header.xml b/packages/SystemUI/res/xml/split_header.xml index 44d42a05cd46e..03401b3d51d1f 100644 --- a/packages/SystemUI/res/xml/split_header.xml +++ b/packages/SystemUI/res/xml/split_header.xml @@ -53,5 +53,29 @@ /> + + + + + + + \ No newline at end of file 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 8cf7288c9cd5e..3f479731d4c73 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SplitShadeHeaderController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SplitShadeHeaderController.kt @@ -19,12 +19,14 @@ package com.android.systemui.statusbar.phone import android.view.View import androidx.constraintlayout.motion.widget.MotionLayout import com.android.settingslib.Utils +import com.android.systemui.Dumpable import com.android.systemui.R import com.android.systemui.animation.ShadeInterpolation import com.android.systemui.battery.BatteryMeterView import com.android.systemui.battery.BatteryMeterViewController import com.android.systemui.flags.FeatureFlags import com.android.systemui.flags.Flags +import com.android.systemui.qs.ChipVisibilityListener import com.android.systemui.qs.HeaderPrivacyIconsController import com.android.systemui.qs.carrier.QSCarrierGroupController import com.android.systemui.statusbar.phone.dagger.StatusBarComponent.StatusBarScope @@ -97,6 +99,18 @@ class SplitShadeHeaderController @Inject constructor( } } + private val chipVisibilityListener: ChipVisibilityListener = object : ChipVisibilityListener { + override fun onChipVisibilityRefreshed(visible: Boolean) { + if (statusBar is MotionLayout) { + val state = statusBar.getConstraintSet(R.id.qqs_header_constraint).apply { + setAlpha(R.id.statusIcons, if (visible) 0f else 1f) + setAlpha(R.id.batteryRemainingIcon, if (visible) 0f else 1f) + } + statusBar.updateState(R.id.qqs_header_constraint, state) + } + } + } + init { if (statusBar is MotionLayout) { val context = statusBar.context @@ -107,6 +121,7 @@ class SplitShadeHeaderController @Inject constructor( .load(context, resources.getXml(R.xml.qs_header)) statusBar.getConstraintSet(R.id.split_header_constraint) .load(context, resources.getXml(R.xml.split_header)) + privacyIconsController.chipVisibilityListener = chipVisibilityListener } } @@ -149,7 +164,7 @@ class SplitShadeHeaderController @Inject constructor( } private fun onSplitShadeModeChanged() { - if (splitShadeMode) { + if (splitShadeMode || combinedHeaders) { privacyIconsController.onParentVisible() } else { privacyIconsController.onParentInvisible() From 3cd40e0641ed706da18753aefdf9f947f5cdc457 Mon Sep 17 00:00:00 2001 From: Fabian Kozynski Date: Wed, 10 Nov 2021 12:20:07 -0500 Subject: [PATCH 2/2] Fix some entrance animations for new QSHeaders * Use qsVisible to indicate whether the shade is visible and the header should be shown. * When in lockscreen, use LockscreenShadeTransitionController#dragProgress to track shade expansion. * Use this shade expansion to fade out the KeyguardStatusBarView Test: manual, with and without flag, handheld and split shade Test: atest SystemUITests Bug: 202847414 Change-Id: Id57adff2fd75eba86832e8790816ef2d9afcf83d --- .../res/xml/combined_qs_header_scene.xml | 13 +++- .../LockscreenShadeTransitionController.kt | 7 ++- .../KeyguardStatusBarViewController.java | 2 +- .../NotificationPanelViewController.java | 47 +++++++++++---- .../phone/SplitShadeHeaderController.kt | 59 ++++++++++++++++--- .../KeyguardStatusBarViewControllerTest.java | 14 ++++- .../phone/SplitShadeHeaderControllerTest.kt | 5 +- 7 files changed, 123 insertions(+), 24 deletions(-) diff --git a/packages/SystemUI/res/xml/combined_qs_header_scene.xml b/packages/SystemUI/res/xml/combined_qs_header_scene.xml index d61e4a95bb680..91607d2f9bea6 100644 --- a/packages/SystemUI/res/xml/combined_qs_header_scene.xml +++ b/packages/SystemUI/res/xml/combined_qs_header_scene.xml @@ -23,11 +23,22 @@ app:constraintSetEnd="@id/qs_header_constraint" app:constraintSetStart="@id/qqs_header_constraint"> + + + diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt index 0fb08e4034838..491a1750a93e2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt @@ -298,8 +298,8 @@ class LockscreenShadeTransitionController @Inject constructor( nsslController.setTransitionToFullShadeAmount(field) notificationPanelController.setTransitionToFullShadeAmount(field, false /* animate */, 0 /* delay */) - val progress = MathUtils.saturate(dragDownAmount / scrimTransitionDistance) - qS.setTransitionToFullShadeAmount(field, progress) + dragProgress = MathUtils.saturate(dragDownAmount / scrimTransitionDistance) + qS.setTransitionToFullShadeAmount(field, dragProgress) // TODO: appear media also in split shade val mediaAmount = if (useSplitShade) 0f else field mediaHierarchyManager.setTransitionToFullShadeAmount(mediaAmount) @@ -308,6 +308,9 @@ class LockscreenShadeTransitionController @Inject constructor( } } + var dragProgress = 0f + private set + private fun transitionToShadeAmountCommon(dragDownAmount: Float) { val scrimProgress = MathUtils.saturate(dragDownAmount / scrimTransitionDistance) scrimController.setTransitionToFullShadeProgress(scrimProgress) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java index e7d5724fa9bf1..81871634fbaf8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java @@ -392,7 +392,7 @@ public class KeyguardStatusBarViewController extends ViewController 0 + ? mLockscreenShadeTransitionController.getDragProgress() + : getExpandedFraction(); + mSplitShadeHeaderController.setShadeExpandedFraction(shadeExpandedFraction); + mSplitShadeHeaderController.setQsExpandedFraction(qsExpansionFraction); + mSplitShadeHeaderController.setShadeExpanded(mQsVisible); + + if (mCommunalViewController != null) { mCommunalViewController.updateQsExpansion(qsExpansionFraction); } @@ -3629,11 +3646,15 @@ public class NotificationPanelViewController extends PanelViewController { return !isFullWidth() || !mShowIconsWhenExpanded; } - public final QS.ScrollListener mScrollListener = scrollY -> { - if (scrollY > 0 && !mQsFullyExpanded) { - if (DEBUG) Log.d(TAG, "Scrolling while not expanded. Forcing expand"); - // If we are scrolling QS, we should be fully expanded. - expandWithQs(); + public final QS.ScrollListener mScrollListener = new QS.ScrollListener() { + @Override + public void onQsPanelScrollChanged(int scrollY) { + mSplitShadeHeaderController.setQsScrollY(scrollY); + if (scrollY > 0 && !mQsFullyExpanded) { + if (DEBUG) Log.d(TAG, "Scrolling while not expanded. Forcing expand"); + // If we are scrolling QS, we should be fully expanded. + expandWithQs(); + } } }; @@ -4684,8 +4705,6 @@ public class NotificationPanelViewController extends PanelViewController { // would reset maybeAnimateBottomAreaAlpha(); updateQsState(); - mSplitShadeHeaderController.setShadeExpanded( - mBarState == SHADE || mBarState == SHADE_LOCKED); } @Override @@ -4715,6 +4734,9 @@ public class NotificationPanelViewController extends PanelViewController { * {@link KeyguardStatusBarViewController} and remove this method. */ boolean shouldHeadsUpBeVisible(); + + /** Return the fraction of the shade that's expanded, when in lockscreen. */ + float getLockscreenShadeDragProgress(); } private final NotificationPanelViewStateProvider mNotificationPanelViewStateProvider = @@ -4733,6 +4755,11 @@ public class NotificationPanelViewController extends PanelViewController { public boolean shouldHeadsUpBeVisible() { return mHeadsUpAppearanceController.shouldBeVisible(); } + + @Override + public float getLockscreenShadeDragProgress() { + return mLockscreenShadeTransitionController.getDragProgress(); + } }; /** 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 3f479731d4c73..a1be5acdac134 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SplitShadeHeaderController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SplitShadeHeaderController.kt @@ -24,6 +24,7 @@ import com.android.systemui.R import com.android.systemui.animation.ShadeInterpolation import com.android.systemui.battery.BatteryMeterView import com.android.systemui.battery.BatteryMeterViewController +import com.android.systemui.dump.DumpManager import com.android.systemui.flags.FeatureFlags import com.android.systemui.flags.Flags import com.android.systemui.qs.ChipVisibilityListener @@ -32,6 +33,8 @@ import com.android.systemui.qs.carrier.QSCarrierGroupController import com.android.systemui.statusbar.phone.dagger.StatusBarComponent.StatusBarScope import com.android.systemui.statusbar.phone.dagger.StatusBarViewModule.SPLIT_SHADE_BATTERY_CONTROLLER import com.android.systemui.statusbar.phone.dagger.StatusBarViewModule.SPLIT_SHADE_HEADER +import java.io.FileDescriptor +import java.io.PrintWriter import javax.inject.Inject import javax.inject.Named @@ -42,12 +45,23 @@ class SplitShadeHeaderController @Inject constructor( private val privacyIconsController: HeaderPrivacyIconsController, qsCarrierGroupControllerBuilder: QSCarrierGroupController.Builder, featureFlags: FeatureFlags, - @Named(SPLIT_SHADE_BATTERY_CONTROLLER) batteryMeterViewController: BatteryMeterViewController -) { + @Named(SPLIT_SHADE_BATTERY_CONTROLLER) batteryMeterViewController: BatteryMeterViewController, + dumpManager: DumpManager +) : Dumpable { companion object { private val HEADER_TRANSITION_ID = R.id.header_transition private val SPLIT_HEADER_TRANSITION_ID = R.id.split_header_transition + private val QQS_HEADER_CONSTRAINT = R.id.qqs_header_constraint + private val QS_HEADER_CONSTRAINT = R.id.qs_header_constraint + private val SPLIT_HEADER_CONSTRAINT = R.id.split_header_constraint + + private fun Int.stateToString() = when (this) { + QQS_HEADER_CONSTRAINT -> "QQS Header" + QS_HEADER_CONSTRAINT -> "QS Header" + SPLIT_HEADER_CONSTRAINT -> "Split Header" + else -> "Unknown state" + } } private val combinedHeaders = featureFlags.isEnabled(Flags.COMBINED_QS_HEADERS) @@ -99,14 +113,22 @@ class SplitShadeHeaderController @Inject constructor( } } + var qsScrollY = 0 + set(value) { + if (field != value) { + field = value + updateScrollY() + } + } + private val chipVisibilityListener: ChipVisibilityListener = object : ChipVisibilityListener { override fun onChipVisibilityRefreshed(visible: Boolean) { if (statusBar is MotionLayout) { - val state = statusBar.getConstraintSet(R.id.qqs_header_constraint).apply { + val state = statusBar.getConstraintSet(QQS_HEADER_CONSTRAINT).apply { setAlpha(R.id.statusIcons, if (visible) 0f else 1f) setAlpha(R.id.batteryRemainingIcon, if (visible) 0f else 1f) } - statusBar.updateState(R.id.qqs_header_constraint, state) + statusBar.updateState(QQS_HEADER_CONSTRAINT, state) } } } @@ -115,11 +137,11 @@ class SplitShadeHeaderController @Inject constructor( if (statusBar is MotionLayout) { val context = statusBar.context val resources = statusBar.resources - statusBar.getConstraintSet(R.id.qqs_header_constraint) + statusBar.getConstraintSet(QQS_HEADER_CONSTRAINT) .load(context, resources.getXml(R.xml.qqs_header)) - statusBar.getConstraintSet(R.id.qs_header_constraint) + statusBar.getConstraintSet(QS_HEADER_CONSTRAINT) .load(context, resources.getXml(R.xml.qs_header)) - statusBar.getConstraintSet(R.id.split_header_constraint) + statusBar.getConstraintSet(SPLIT_HEADER_CONSTRAINT) .load(context, resources.getXml(R.xml.split_header)) privacyIconsController.chipVisibilityListener = chipVisibilityListener } @@ -149,10 +171,19 @@ class SplitShadeHeaderController @Inject constructor( qsCarrierGroupController = qsCarrierGroupControllerBuilder .setQSCarrierGroup(statusBar.findViewById(R.id.carrier_group)) .build() + + dumpManager.registerDumpable(this) + updateVisibility() updateConstraints() } + private fun updateScrollY() { + if (!splitShadeMode && combinedHeaders) { + statusBar.scrollY = qsScrollY + } + } + private fun onShadeExpandedChanged() { if (shadeExpanded) { privacyIconsController.startListening() @@ -198,6 +229,7 @@ class SplitShadeHeaderController @Inject constructor( statusBar.setTransition(HEADER_TRANSITION_ID) statusBar.transitionToStart() updatePosition() + updateScrollY() } } @@ -226,4 +258,17 @@ class SplitShadeHeaderController @Inject constructor( iconContainer.addIgnoredSlots(carrierIconSlots) } } + + override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array) { + pw.println("visible: $visible") + pw.println("shadeExpanded: $shadeExpanded") + pw.println("shadeExpandedFraction: $shadeExpandedFraction") + pw.println("splitShadeMode: $splitShadeMode") + pw.println("qsExpandedFraction: $qsExpandedFraction") + pw.println("qsScrollY: $qsScrollY") + if (combinedHeaders) { + statusBar as MotionLayout + pw.println("currentState: ${statusBar.currentState.stateToString()}") + } + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.java index 8d05e6693e334..37cf7485b8ab7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.java @@ -278,11 +278,11 @@ public class KeyguardStatusBarViewControllerTest extends SysuiTestCase { } @Test - public void updateViewState_qsExpansionOne_viewHidden() { + public void updateViewState_dragProgressOne_viewHidden() { mController.onViewAttached(); updateStateToKeyguard(); - mNotificationPanelViewStateProvider.setQsExpansionFraction(1f); + mNotificationPanelViewStateProvider.setLockscreenShadeDragProgress(1f); mController.updateViewState(); @@ -356,6 +356,7 @@ public class KeyguardStatusBarViewControllerTest extends SysuiTestCase { private float mPanelViewExpandedHeight = 100f; private float mQsExpansionFraction = 0f; private boolean mShouldHeadsUpBeVisible = false; + private float mLockscreenShadeDragProgress = 0f; @Override public float getPanelViewExpandedHeight() { @@ -372,6 +373,11 @@ public class KeyguardStatusBarViewControllerTest extends SysuiTestCase { return mShouldHeadsUpBeVisible; } + @Override + public float getLockscreenShadeDragProgress() { + return mLockscreenShadeDragProgress; + } + public void setPanelViewExpandedHeight(float panelViewExpandedHeight) { this.mPanelViewExpandedHeight = panelViewExpandedHeight; } @@ -383,5 +389,9 @@ public class KeyguardStatusBarViewControllerTest extends SysuiTestCase { public void setShouldHeadsUpBeVisible(boolean shouldHeadsUpBeVisible) { this.mShouldHeadsUpBeVisible = shouldHeadsUpBeVisible; } + + public void setLockscreenShadeDragProgress(float lockscreenShadeDragProgress) { + this.mLockscreenShadeDragProgress = lockscreenShadeDragProgress; + } } } 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 a8544a9a15e4c..2b1826eab5aae 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 @@ -8,6 +8,7 @@ import com.android.systemui.SysuiTestCase import com.android.systemui.animation.ShadeInterpolation import com.android.systemui.battery.BatteryMeterView import com.android.systemui.battery.BatteryMeterViewController +import com.android.systemui.dump.DumpManager import com.android.systemui.flags.FeatureFlags import com.android.systemui.flags.Flags import com.android.systemui.qs.HeaderPrivacyIconsController @@ -37,6 +38,7 @@ class SplitShadeHeaderControllerTest : SysuiTestCase() { @Mock private lateinit var batteryMeterView: BatteryMeterView @Mock private lateinit var batteryMeterViewController: BatteryMeterViewController @Mock private lateinit var privacyIconsController: HeaderPrivacyIconsController + @Mock private lateinit var dumpManager: DumpManager @JvmField @Rule val mockitoRule = MockitoJUnit.rule() var viewVisibility = View.GONE @@ -66,7 +68,8 @@ class SplitShadeHeaderControllerTest : SysuiTestCase() { privacyIconsController, qsCarrierGroupControllerBuilder, featureFlags, - batteryMeterViewController + batteryMeterViewController, + dumpManager ) carrierIconSlots = listOf( context.getString(com.android.internal.R.string.status_bar_mobile))