From 1cbf60014b8d38aa1d477aef47a8296208989669 Mon Sep 17 00:00:00 2001 From: Fabian Kozynski Date: Wed, 26 Jan 2022 15:42:21 -0500 Subject: Remove QQS Footer Actions Test: manual in handheld and split shade Test: atest SystemUITests Bug: 216302612 Change-Id: I4e4cda397ab0e8d0e8b6c19214c893ce5a3e69d9 --- .../layout/quick_status_bar_expanded_header.xml | 10 --- .../android/systemui/qs/FooterActionsController.kt | 41 ++---------- .../systemui/qs/FooterActionsControllerBuilder.kt | 74 ---------------------- .../src/com/android/systemui/qs/QSAnimator.java | 26 +------- .../systemui/qs/QSFooterViewController.java | 5 +- .../systemui/qs/QuickQSPanelController.java | 10 +-- .../systemui/qs/dagger/QSFragmentModule.java | 37 ----------- .../systemui/qs/FooterActionsControllerTest.kt | 13 ++-- .../systemui/qs/QuickQSPanelControllerTest.kt | 9 +-- 9 files changed, 18 insertions(+), 207 deletions(-) delete mode 100644 packages/SystemUI/src/com/android/systemui/qs/FooterActionsControllerBuilder.kt diff --git a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml index 10a2f4c625c6..2c29f071dcbc 100644 --- a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml +++ b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml @@ -57,16 +57,6 @@ android:focusable="true" android:paddingBottom="24dp" android:importantForAccessibility="yes"> - - diff --git a/packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt b/packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt index 7ac9205c7922..398ac4cb8311 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt @@ -34,8 +34,6 @@ import com.android.systemui.animation.ActivityLaunchAnimator import com.android.systemui.globalactions.GlobalActionsDialogLite import com.android.systemui.plugins.ActivityStarter import com.android.systemui.plugins.FalsingManager -import com.android.systemui.qs.FooterActionsController.ExpansionState.COLLAPSED -import com.android.systemui.qs.FooterActionsController.ExpansionState.EXPANDED import com.android.systemui.qs.dagger.QSFlagsModule.PM_LITE_ENABLED import com.android.systemui.settings.UserTracker import com.android.systemui.statusbar.phone.MultiUserSwitchController @@ -56,11 +54,11 @@ import javax.inject.Named */ class FooterActionsController @Inject constructor( view: FooterActionsView, + multiUserSwitchControllerFactory: MultiUserSwitchController.Factory, private val activityStarter: ActivityStarter, private val userManager: UserManager, private val userTracker: UserTracker, private val userInfoController: UserInfoController, - private val multiUserSwitchController: MultiUserSwitchController, private val deviceProvisionedController: DeviceProvisionedController, private val falsingManager: FalsingManager, private val metricsLogger: MetricsLogger, @@ -68,13 +66,10 @@ class FooterActionsController @Inject constructor( private val globalActionsDialog: GlobalActionsDialogLite, private val uiEventLogger: UiEventLogger, @Named(PM_LITE_ENABLED) private val showPMLiteButton: Boolean, - private val buttonsVisibleState: ExpansionState, private val globalSetting: GlobalSettings, private val handler: Handler ) : ViewController(view) { - enum class ExpansionState { COLLAPSED, EXPANDED } - private var listening: Boolean = false var expanded = false @@ -82,6 +77,7 @@ class FooterActionsController @Inject constructor( private val settingsButton: SettingsButton = view.findViewById(R.id.settings_button) private val settingsButtonContainer: View? = view.findViewById(R.id.settings_button_container) private val powerMenuLite: View = view.findViewById(R.id.pm_lite) + private val multiUserSwitchController = multiUserSwitchControllerFactory.create(view) private val onUserInfoChangedListener = OnUserInfoChangedListener { _, picture, _ -> val isGuestUser: Boolean = userManager.isGuestUser(KeyguardUpdateMonitor.getCurrentUser()) @@ -99,9 +95,8 @@ class FooterActionsController @Inject constructor( } private val onClickListener = View.OnClickListener { v -> - // Don't do anything until views are unhidden. Don't do anything if the tap looks - // suspicious. - if (!buttonsVisible() || falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) { + // Don't do anything if the tap looks suspicious. + if (!expanded || falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) { return@OnClickListener } if (v === settingsButton) { @@ -110,9 +105,7 @@ class FooterActionsController @Inject constructor( activityStarter.postQSRunnableDismissingKeyguard {} return@OnClickListener } - metricsLogger.action( - if (expanded) MetricsProto.MetricsEvent.ACTION_QS_EXPANDED_SETTINGS_LAUNCH - else MetricsProto.MetricsEvent.ACTION_QS_COLLAPSED_SETTINGS_LAUNCH) + metricsLogger.action(MetricsProto.MetricsEvent.ACTION_QS_EXPANDED_SETTINGS_LAUNCH) if (settingsButton.isTunerClick) { activityStarter.postQSRunnableDismissingKeyguard { if (isTunerEnabled()) { @@ -135,26 +128,10 @@ class FooterActionsController @Inject constructor( } } - private fun buttonsVisible(): Boolean { - return when (buttonsVisibleState) { - EXPANDED -> expanded - COLLAPSED -> !expanded - } - } - override fun onInit() { multiUserSwitchController.init() } - fun hideFooter() { - mView.visibility = View.GONE - } - - fun showFooter() { - mView.visibility = View.VISIBLE - updateView() - } - private fun startSettingsActivity() { val animationController = settingsButtonContainer?.let { ActivityLaunchAnimator.Controller.fromView( @@ -215,13 +192,5 @@ class FooterActionsController @Inject constructor( mView.setKeyguardShowing() } - fun refreshVisibility(shouldBeVisible: Boolean) { - if (shouldBeVisible) { - showFooter() - } else { - hideFooter() - } - } - private fun isTunerEnabled() = tunerService.isTunerEnabled } diff --git a/packages/SystemUI/src/com/android/systemui/qs/FooterActionsControllerBuilder.kt b/packages/SystemUI/src/com/android/systemui/qs/FooterActionsControllerBuilder.kt deleted file mode 100644 index 7694be51cba6..000000000000 --- a/packages/SystemUI/src/com/android/systemui/qs/FooterActionsControllerBuilder.kt +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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. - */ - -package com.android.systemui.qs - -import android.os.Handler -import android.os.UserManager -import com.android.internal.logging.MetricsLogger -import com.android.internal.logging.UiEventLogger -import com.android.systemui.dagger.qualifiers.Main -import com.android.systemui.globalactions.GlobalActionsDialogLite -import com.android.systemui.plugins.ActivityStarter -import com.android.systemui.plugins.FalsingManager -import com.android.systemui.qs.FooterActionsController.ExpansionState -import com.android.systemui.qs.dagger.QSFlagsModule -import com.android.systemui.settings.UserTracker -import com.android.systemui.statusbar.phone.MultiUserSwitchController -import com.android.systemui.statusbar.policy.DeviceProvisionedController -import com.android.systemui.statusbar.policy.UserInfoController -import com.android.systemui.tuner.TunerService -import com.android.systemui.util.settings.GlobalSettings -import javax.inject.Inject -import javax.inject.Named - -class FooterActionsControllerBuilder @Inject constructor( - private val activityStarter: ActivityStarter, - private val userManager: UserManager, - private val userTracker: UserTracker, - private val userInfoController: UserInfoController, - private val multiUserSwitchControllerFactory: MultiUserSwitchController.Factory, - private val deviceProvisionedController: DeviceProvisionedController, - private val falsingManager: FalsingManager, - private val metricsLogger: MetricsLogger, - private val tunerService: TunerService, - private val globalActionsDialog: GlobalActionsDialogLite, - private val uiEventLogger: UiEventLogger, - @Named(QSFlagsModule.PM_LITE_ENABLED) private val showPMLiteButton: Boolean, - private val globalSettings: GlobalSettings, - @Main private val handler: Handler -) { - private lateinit var view: FooterActionsView - private lateinit var buttonsVisibleState: ExpansionState - - fun withView(view: FooterActionsView): FooterActionsControllerBuilder { - this.view = view - return this - } - - fun withButtonsVisibleWhen(state: ExpansionState): FooterActionsControllerBuilder { - buttonsVisibleState = state - return this - } - - fun build(): FooterActionsController { - return FooterActionsController(view, activityStarter, userManager, - userTracker, userInfoController, multiUserSwitchControllerFactory.create(view), - deviceProvisionedController, falsingManager, metricsLogger, tunerService, - globalActionsDialog, uiEventLogger, showPMLiteButton, buttonsVisibleState, - globalSettings, handler) - } -} \ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java index ded6ae0ac2ff..d1b569f7f438 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java @@ -14,9 +14,6 @@ package com.android.systemui.qs; -import static com.android.systemui.qs.dagger.QSFragmentModule.QQS_FOOTER; -import static com.android.systemui.qs.dagger.QSFragmentModule.QS_FOOTER; - import android.animation.TimeInterpolator; import android.animation.ValueAnimator; import android.util.Log; @@ -49,7 +46,6 @@ import java.util.List; import java.util.concurrent.Executor; import javax.inject.Inject; -import javax.inject.Named; /** */ @QSScope @@ -88,8 +84,6 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha private final QSFgsManagerFooter mFgsManagerFooter; private final QSSecurityFooter mSecurityFooter; private final QS mQs; - private final View mQSFooterActions; - private final View mQQSFooterActions; @Nullable private PagedTileLayout mPagedLayout; @@ -154,16 +148,12 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha QuickQSPanelController quickQSPanelController, QSTileHost qsTileHost, QSFgsManagerFooter fgsManagerFooter, QSSecurityFooter securityFooter, @Main Executor executor, TunerService tunerService, - QSExpansionPathInterpolator qsExpansionPathInterpolator, - @Named(QS_FOOTER) FooterActionsView qsFooterActionsView, - @Named(QQS_FOOTER) FooterActionsView qqsFooterActionsView) { + QSExpansionPathInterpolator qsExpansionPathInterpolator) { mQs = qs; mQuickQsPanel = quickPanel; mQsPanelController = qsPanelController; mQuickQSPanelController = quickQSPanelController; mQuickStatusBarHeader = quickStatusBarHeader; - mQQSFooterActions = qqsFooterActionsView; - mQSFooterActions = qsFooterActionsView; mFgsManagerFooter = fgsManagerFooter; mSecurityFooter = securityFooter; mHost = qsTileHost; @@ -476,12 +466,6 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha .setListener(this) .build(); - if (mQQSFooterActions.getVisibility() != View.GONE) { - // only when qqs footer is present (which means split shade mode) it needs to - // be animated - updateQQSFooterAnimation(); - } - // Fade in the security footer and the divider as we reach the final position Builder builder = new Builder().setStartDelay(EXPANDED_TILE_DELAY); builder.addFloat(mFgsManagerFooter.getView(), "alpha", 0, 1); @@ -627,14 +611,6 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha } } - private void updateQQSFooterAnimation() { - int translationY = getRelativeTranslationY(mQSFooterActions, mQQSFooterActions); - mQQSFooterActionsAnimator = new TouchAnimator.Builder() - .addFloat(mQQSFooterActions, "translationY", 0, translationY) - .build(); - mAnimatedQsViews.add(mQSFooterActions); - } - private int getRelativeTranslationY(View view1, View view2) { int[] qsPosition = new int[2]; int[] qqsPosition = new int[2]; diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java index 5327b7e3ba26..f13553901ba1 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java @@ -16,8 +16,6 @@ package com.android.systemui.qs; -import static com.android.systemui.qs.dagger.QSFragmentModule.QS_FOOTER; - import android.content.ClipData; import android.content.ClipboardManager; import android.text.TextUtils; @@ -33,7 +31,6 @@ import com.android.systemui.settings.UserTracker; import com.android.systemui.util.ViewController; import javax.inject.Inject; -import javax.inject.Named; /** * Controller for {@link QSFooterView}. @@ -58,7 +55,7 @@ public class QSFooterViewController extends ViewController impleme ActivityStarter activityStarter, QSPanelController qsPanelController, QuickQSPanelController quickQSPanelController, - @Named(QS_FOOTER) FooterActionsController footerActionsController) { + FooterActionsController footerActionsController) { super(view); mUserTracker = userTracker; mQsPanelController = qsPanelController; diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java index 92690c7d1202..2d2fa1f08452 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java @@ -17,7 +17,6 @@ package com.android.systemui.qs; import static com.android.systemui.media.dagger.MediaModule.QUICK_QS_PANEL; -import static com.android.systemui.qs.dagger.QSFragmentModule.QQS_FOOTER; import static com.android.systemui.qs.dagger.QSFragmentModule.QS_USING_MEDIA_PLAYER; import com.android.internal.logging.MetricsLogger; @@ -54,7 +53,6 @@ public class QuickQSPanelController extends QSPanelControllerBase // brightness is visible only in split shade private final QuickQSBrightnessController mBrightnessController; private final BrightnessMirrorHandler mBrightnessMirrorHandler; - private final FooterActionsController mFooterActionsController; @Inject QuickQSPanelController(QuickQSPanel view, QSTileHost qsTileHost, @@ -63,14 +61,12 @@ public class QuickQSPanelController extends QSPanelControllerBase @Named(QUICK_QS_PANEL) MediaHost mediaHost, MetricsLogger metricsLogger, UiEventLogger uiEventLogger, QSLogger qsLogger, DumpManager dumpManager, - QuickQSBrightnessController quickQSBrightnessController, - @Named(QQS_FOOTER) FooterActionsController footerActionsController + QuickQSBrightnessController quickQSBrightnessController ) { super(view, qsTileHost, qsCustomizerController, usingMediaPlayer, mediaHost, metricsLogger, uiEventLogger, qsLogger, dumpManager); mBrightnessController = quickQSBrightnessController; mBrightnessMirrorHandler = new BrightnessMirrorHandler(mBrightnessController); - mFooterActionsController = footerActionsController; } @Override @@ -80,8 +76,6 @@ public class QuickQSPanelController extends QSPanelControllerBase mMediaHost.setShowsOnlyActiveMedia(true); mMediaHost.init(MediaHierarchyManager.LOCATION_QQS); mBrightnessController.init(mShouldUseSplitNotificationShade); - mFooterActionsController.init(); - mFooterActionsController.refreshVisibility(mShouldUseSplitNotificationShade); } @Override @@ -102,7 +96,6 @@ public class QuickQSPanelController extends QSPanelControllerBase void setListening(boolean listening) { super.setListening(listening); mBrightnessController.setListening(listening); - mFooterActionsController.setListening(listening); } public boolean isListening() { @@ -123,7 +116,6 @@ public class QuickQSPanelController extends QSPanelControllerBase @Override protected void onConfigurationChanged() { mBrightnessController.refreshVisibility(mShouldUseSplitNotificationShade); - mFooterActionsController.refreshVisibility(mShouldUseSplitNotificationShade); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java index 1958cafb0fb9..4598fed03d17 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java +++ b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java @@ -27,9 +27,6 @@ import com.android.systemui.battery.BatteryMeterView; import com.android.systemui.dagger.qualifiers.RootView; import com.android.systemui.plugins.qs.QS; import com.android.systemui.privacy.OngoingPrivacyChip; -import com.android.systemui.qs.FooterActionsController; -import com.android.systemui.qs.FooterActionsController.ExpansionState; -import com.android.systemui.qs.FooterActionsControllerBuilder; import com.android.systemui.qs.FooterActionsView; import com.android.systemui.qs.QSContainerImpl; import com.android.systemui.qs.QSFooter; @@ -55,8 +52,6 @@ import dagger.Provides; public interface QSFragmentModule { String QS_FGS_MANAGER_FOOTER_VIEW = "qs_fgs_manager_footer"; String QS_SECURITY_FOOTER_VIEW = "qs_security_footer"; - String QQS_FOOTER = "qqs_footer"; - String QS_FOOTER = "qs_footer"; String QS_USING_MEDIA_PLAYER = "qs_using_media_player"; /** @@ -124,42 +119,10 @@ public interface QSFragmentModule { /** */ @Provides - @Named(QS_FOOTER) static FooterActionsView providesQSFooterActionsView(@RootView View view) { return view.findViewById(R.id.qs_footer_actions); } - /** */ - @Provides - @Named(QQS_FOOTER) - static FooterActionsView providesQQSFooterActionsView(@RootView View view) { - return view.findViewById(R.id.qqs_footer_actions); - } - - /** */ - @Provides - @Named(QQS_FOOTER) - static FooterActionsController providesQQSFooterActionsController( - FooterActionsControllerBuilder footerActionsControllerBuilder, - @Named(QQS_FOOTER) FooterActionsView qqsFooterActionsView) { - return footerActionsControllerBuilder - .withView(qqsFooterActionsView) - .withButtonsVisibleWhen(ExpansionState.COLLAPSED) - .build(); - } - - /** */ - @Provides - @Named(QS_FOOTER) - static FooterActionsController providesQSFooterActionsController( - FooterActionsControllerBuilder footerActionsControllerBuilder, - @Named(QS_FOOTER) FooterActionsView qsFooterActionsView) { - return footerActionsControllerBuilder - .withView(qsFooterActionsView) - .withButtonsVisibleWhen(ExpansionState.EXPANDED) - .build(); - } - /** */ @Provides @QSScope diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/FooterActionsControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/FooterActionsControllerTest.kt index 354bb5192251..de9340d4f304 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/FooterActionsControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/FooterActionsControllerTest.kt @@ -17,7 +17,6 @@ import com.android.systemui.R import com.android.systemui.classifier.FalsingManagerFake import com.android.systemui.globalactions.GlobalActionsDialogLite import com.android.systemui.plugins.ActivityStarter -import com.android.systemui.qs.FooterActionsController.ExpansionState import com.android.systemui.settings.UserTracker import com.android.systemui.statusbar.phone.MultiUserSwitchController import com.android.systemui.statusbar.policy.DeviceProvisionedController @@ -54,6 +53,8 @@ class FooterActionsControllerTest : LeakCheckedTest() { @Mock private lateinit var userInfoController: UserInfoController @Mock + private lateinit var multiUserSwitchControllerFactory: MultiUserSwitchController.Factory + @Mock private lateinit var multiUserSwitchController: MultiUserSwitchController @Mock private lateinit var globalActionsDialog: GlobalActionsDialogLite @@ -76,14 +77,16 @@ class FooterActionsControllerTest : LeakCheckedTest() { injectLeakCheckedDependencies(*LeakCheckedTest.ALL_SUPPORTED_CLASSES) val fakeTunerService = Dependency.get(TunerService::class.java) as FakeTunerService + whenever(multiUserSwitchControllerFactory.create(any())) + .thenReturn(multiUserSwitchController) + view = LayoutInflater.from(context) .inflate(R.layout.footer_actions, null) as FooterActionsView - controller = FooterActionsController(view, activityStarter, - userManager, userTracker, userInfoController, multiUserSwitchController, + controller = FooterActionsController(view, multiUserSwitchControllerFactory, + activityStarter, userManager, userTracker, userInfoController, deviceProvisionedController, falsingManager, metricsLogger, fakeTunerService, - globalActionsDialog, uiEventLogger, showPMLiteButton = true, - buttonsVisibleState = ExpansionState.EXPANDED, fakeSettings, + globalActionsDialog, uiEventLogger, showPMLiteButton = true, fakeSettings, Handler(testableLooper.looper)) controller.init() ViewUtils.attachView(view) diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt index 59948d310b4f..09c6d9e86a44 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt @@ -68,8 +68,6 @@ class QuickQSPanelControllerTest : SysuiTestCase() { private lateinit var tileView: QSTileView @Mock private lateinit var quickQsBrightnessController: QuickQSBrightnessController - @Mock - private lateinit var footerActionsController: FooterActionsController @Captor private lateinit var captor: ArgumentCaptor @@ -95,8 +93,7 @@ class QuickQSPanelControllerTest : SysuiTestCase() { uiEventLogger, qsLogger, dumpManager, - quickQsBrightnessController, - footerActionsController + quickQsBrightnessController ) controller.init() @@ -128,14 +125,12 @@ class QuickQSPanelControllerTest : SysuiTestCase() { } @Test - fun testBrightnessAndFooterVisibilityRefreshedWhenConfigurationChanged() { + fun testBrightnessRefreshedWhenConfigurationChanged() { // times(2) because both controller and base controller are registering their listeners verify(quickQSPanel, times(2)).addOnConfigurationChangedListener(captor.capture()) captor.allValues.forEach { it.onConfigurationChange(Configuration.EMPTY) } verify(quickQsBrightnessController).refreshVisibility(anyBoolean()) - // times(2) because footer visibility is also refreshed on controller init - verify(footerActionsController, times(2)).refreshVisibility(anyBoolean()) } } -- cgit v1.2.3-59-g8ed1b From d2b9b7473db3dec9a1aeb6b90b296687cb63eb1d Mon Sep 17 00:00:00 2001 From: Fabian Kozynski Date: Fri, 28 Jan 2022 11:40:54 -0500 Subject: Pin footer actions to bottom of QSContainerImpl These pins the actions and decouples the FooterAction controller from Footer controller. Pinning the actions is behind a flag, because the UI is not finalized. Fixes: 216302612 Test: atest com.android.systemui.qs com.android.systemui.statusbar.phone Test: manual in different screen sizes Change-Id: I0cd24596d0b900b2555202f59047ebad5c969afb --- .../res-keyguard/layout/footer_actions.xml | 6 +- packages/SystemUI/res/layout/qs_footer_impl.xml | 13 +- packages/SystemUI/res/layout/qs_panel.xml | 9 + packages/SystemUI/res/values/dimens.xml | 4 +- .../src/com/android/systemui/flags/Flags.java | 2 + .../android/systemui/qs/FooterActionsController.kt | 54 ++++-- .../com/android/systemui/qs/FooterActionsView.kt | 24 --- .../com/android/systemui/qs/QSContainerImpl.java | 22 +-- .../src/com/android/systemui/qs/QSFooter.java | 5 - .../src/com/android/systemui/qs/QSFooterView.java | 7 - .../systemui/qs/QSFooterViewController.java | 35 +--- .../src/com/android/systemui/qs/QSFragment.java | 18 +- .../systemui/qs/dagger/QSFragmentComponent.java | 4 + .../systemui/qs/dagger/QSFragmentModule.java | 19 ++- .../phone/NotificationsQSContainerController.kt | 11 +- .../phone/NotificationsQuickSettingsContainer.java | 12 ++ .../systemui/qs/FooterActionsControllerTest.kt | 9 +- .../systemui/qs/QSFooterViewControllerTest.java | 7 +- .../phone/NotificationQSContainerControllerTest.kt | 186 ++++++++++++++++++++- 19 files changed, 319 insertions(+), 128 deletions(-) diff --git a/packages/SystemUI/res-keyguard/layout/footer_actions.xml b/packages/SystemUI/res-keyguard/layout/footer_actions.xml index ecb3cb3961a4..339cab42048b 100644 --- a/packages/SystemUI/res-keyguard/layout/footer_actions.xml +++ b/packages/SystemUI/res-keyguard/layout/footer_actions.xml @@ -19,8 +19,10 @@ + android:layout_height="@dimen/qs_footer_height" + android:gravity="center_vertical" + android:layout_gravity="bottom" +> - + diff --git a/packages/SystemUI/res/layout/qs_panel.xml b/packages/SystemUI/res/layout/qs_panel.xml index f5c6036a5a86..d9e7a2ab55df 100644 --- a/packages/SystemUI/res/layout/qs_panel.xml +++ b/packages/SystemUI/res/layout/qs_panel.xml @@ -51,6 +51,15 @@ android:id="@+id/qs_detail" layout="@layout/qs_detail" /> + + - 96dp + 48dp 48dp @@ -490,7 +490,7 @@ 14sp 16dp 6dp - 0dp + @dimen/qs_footer_height 48dp 0dp 56dp diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.java b/packages/SystemUI/src/com/android/systemui/flags/Flags.java index 97edf3bac4a8..82ad31e5fc04 100644 --- a/packages/SystemUI/src/com/android/systemui/flags/Flags.java +++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.java @@ -107,6 +107,8 @@ public class Flags { public static final ResourceBooleanFlag QS_USER_DETAIL_SHORTCUT = new ResourceBooleanFlag(503, R.bool.flag_lockscreen_qs_user_detail_shortcut); + public static final BooleanFlag NEW_FOOTER = new BooleanFlag(504, false); + /***************************************/ // 600- status bar public static final BooleanFlag COMBINED_STATUS_BAR_SIGNAL_ICONS = diff --git a/packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt b/packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt index 398ac4cb8311..4aedbc983d9c 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt @@ -29,12 +29,16 @@ import com.android.internal.logging.MetricsLogger import com.android.internal.logging.UiEventLogger import com.android.internal.logging.nano.MetricsProto import com.android.keyguard.KeyguardUpdateMonitor +import com.android.settingslib.Utils import com.android.systemui.R import com.android.systemui.animation.ActivityLaunchAnimator +import com.android.systemui.flags.FeatureFlags +import com.android.systemui.flags.Flags import com.android.systemui.globalactions.GlobalActionsDialogLite import com.android.systemui.plugins.ActivityStarter import com.android.systemui.plugins.FalsingManager import com.android.systemui.qs.dagger.QSFlagsModule.PM_LITE_ENABLED +import com.android.systemui.qs.dagger.QSScope import com.android.systemui.settings.UserTracker import com.android.systemui.statusbar.phone.MultiUserSwitchController import com.android.systemui.statusbar.phone.SettingsButton @@ -52,6 +56,7 @@ import javax.inject.Named * Main difference between QS and QQS behaviour is condition when buttons should be visible, * determined by [buttonsVisibleState] */ +@QSScope class FooterActionsController @Inject constructor( view: FooterActionsView, multiUserSwitchControllerFactory: MultiUserSwitchController.Factory, @@ -67,12 +72,28 @@ class FooterActionsController @Inject constructor( private val uiEventLogger: UiEventLogger, @Named(PM_LITE_ENABLED) private val showPMLiteButton: Boolean, private val globalSetting: GlobalSettings, - private val handler: Handler + private val handler: Handler, + private val featureFlags: FeatureFlags ) : ViewController(view) { + private var lastExpansion = -1f private var listening: Boolean = false - var expanded = false + private val alphaAnimator = TouchAnimator.Builder() + .addFloat(mView, "alpha", 0f, 1f) + .setStartDelay(0.9f) + .build() + + var visible = true + set(value) { + field = value + updateVisibility() + } + + init { + view.elevation = resources.displayMetrics.density * 4f + view.setBackgroundColor(Utils.getColorAttrDefaultColor(context, R.attr.underSurfaceColor)) + } private val settingsButton: SettingsButton = view.findViewById(R.id.settings_button) private val settingsButtonContainer: View? = view.findViewById(R.id.settings_button_container) @@ -96,7 +117,7 @@ class FooterActionsController @Inject constructor( private val onClickListener = View.OnClickListener { v -> // Don't do anything if the tap looks suspicious. - if (!expanded || falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) { + if (!visible || falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) { return@OnClickListener } if (v === settingsButton) { @@ -132,6 +153,12 @@ class FooterActionsController @Inject constructor( multiUserSwitchController.init() } + private fun updateVisibility() { + val previousVisibility = mView.visibility + mView.visibility = if (visible) View.VISIBLE else View.INVISIBLE + if (previousVisibility != mView.visibility) updateView() + } + private fun startSettingsActivity() { val animationController = settingsButtonContainer?.let { ActivityLaunchAnimator.Controller.fromView( @@ -181,15 +208,22 @@ class FooterActionsController @Inject constructor( } fun setExpansion(headerExpansionFraction: Float) { - mView.setExpansion(headerExpansionFraction) - } - - fun updateAnimator(width: Int, numTiles: Int) { - mView.updateAnimator(width, numTiles) + if (featureFlags.isEnabled(Flags.NEW_FOOTER)) { + if (headerExpansionFraction != lastExpansion) { + if (headerExpansionFraction >= 1f) { + mView.animate().alpha(1f).setDuration(500L).start() + } else if (lastExpansion >= 1f && headerExpansionFraction < 1f) { + mView.animate().alpha(0f).setDuration(250L).start() + } + lastExpansion = headerExpansionFraction + } + } else { + alphaAnimator.setPosition(headerExpansionFraction) + } } - fun setKeyguardShowing() { - mView.setKeyguardShowing() + fun setKeyguardShowing(showing: Boolean) { + setExpansion(lastExpansion) } private fun isTunerEnabled() = tunerService.isTunerEnabled diff --git a/packages/SystemUI/src/com/android/systemui/qs/FooterActionsView.kt b/packages/SystemUI/src/com/android/systemui/qs/FooterActionsView.kt index e6fa2ae8dad1..18e0cfa910ad 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/FooterActionsView.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/FooterActionsView.kt @@ -44,8 +44,6 @@ class FooterActionsView(context: Context?, attrs: AttributeSet?) : LinearLayout( private lateinit var multiUserAvatar: ImageView private lateinit var tunerIcon: View - private var settingsCogAnimator: TouchAnimator? = null - private var qsDisabled = false private var expansionAmount = 0f @@ -66,19 +64,6 @@ class FooterActionsView(context: Context?, attrs: AttributeSet?) : LinearLayout( importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_YES } - fun updateAnimator(width: Int, numTiles: Int) { - val size = (mContext.resources.getDimensionPixelSize(R.dimen.qs_quick_tile_size) - - mContext.resources.getDimensionPixelSize(R.dimen.qs_tile_padding)) - val remaining = (width - numTiles * size) / (numTiles - 1) - val defSpace = mContext.resources.getDimensionPixelOffset(R.dimen.default_gear_space) - val translation = if (isLayoutRtl) (remaining - defSpace) else -(remaining - defSpace) - settingsCogAnimator = TouchAnimator.Builder() - .addFloat(settingsButton, "translationX", translation.toFloat(), 0f) - .addFloat(settingsButton, "rotation", -120f, 0f) - .build() - setExpansion(expansionAmount) - } - override fun onConfigurationChanged(newConfig: Configuration) { super.onConfigurationChanged(newConfig) updateResources() @@ -95,15 +80,6 @@ class FooterActionsView(context: Context?, attrs: AttributeSet?) : LinearLayout( tunerIcon.translationX = if (isLayoutRtl) (-tunerIconTranslation) else tunerIconTranslation } - fun setKeyguardShowing() { - setExpansion(expansionAmount) - } - - fun setExpansion(headerExpansionFraction: Float) { - expansionAmount = headerExpansionFraction - if (settingsCogAnimator != null) settingsCogAnimator!!.setPosition(headerExpansionFraction) - } - fun disable( state2: Int, isTunerEnabled: Boolean, diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java index e230e1bf8051..7800027ea967 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java @@ -19,10 +19,8 @@ package com.android.systemui.qs; import static android.app.StatusBarManager.DISABLE2_QUICK_SETTINGS; import android.content.Context; -import android.content.res.Configuration; import android.graphics.Canvas; import android.graphics.Path; -import android.graphics.Point; import android.graphics.PointF; import android.util.AttributeSet; import android.view.View; @@ -41,7 +39,6 @@ import java.io.PrintWriter; */ public class QSContainerImpl extends FrameLayout implements Dumpable { - private final Point mSizePoint = new Point(); private int mFancyClippingTop; private int mFancyClippingBottom; private final float[] mFancyClippingRadii = new float[] {0, 0, 0, 0, 0, 0, 0, 0}; @@ -77,12 +74,6 @@ public class QSContainerImpl extends FrameLayout implements Dumpable { return false; } - @Override - protected void onConfigurationChanged(Configuration newConfig) { - super.onConfigurationChanged(newConfig); - mSizePoint.set(0, 0); // Will be retrieved on next measure pass. - } - @Override public boolean performClick() { // Want to receive clicks so missing QQS tiles doesn't cause collapse, but @@ -152,10 +143,10 @@ public class QSContainerImpl extends FrameLayout implements Dumpable { void updateResources(QSPanelController qsPanelController, QuickStatusBarHeaderController quickStatusBarHeaderController) { mQSPanelContainer.setPaddingRelative( - getPaddingStart(), + mQSPanelContainer.getPaddingStart(), Utils.getQsHeaderSystemIconsAreaHeight(mContext), - getPaddingEnd(), - getPaddingBottom() + mQSPanelContainer.getPaddingEnd(), + mQSPanelContainer.getPaddingBottom() ); int sideMargins = getResources().getDimensionPixelSize(R.dimen.notification_side_paddings); @@ -241,13 +232,6 @@ public class QSContainerImpl extends FrameLayout implements Dumpable { } } - private int getDisplayHeight() { - if (mSizePoint.y == 0) { - getDisplay().getRealSize(mSizePoint); - } - return mSizePoint.y; - } - /** * Clip QS bottom using a concave shape. */ diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java index 0e0681b94c62..aac5672aa3f9 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java @@ -42,11 +42,6 @@ public interface QSFooter { */ void setExpansion(float expansion); - /** - * Sets whether or not this footer should set itself to listen for changes in any callbacks - * that it has implemented. - */ - void setListening(boolean listening); /** * Sets whether or not the keyguard is currently being shown. diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooterView.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooterView.java index 4622660a6c15..6c0ca49c81a8 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSFooterView.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooterView.java @@ -46,7 +46,6 @@ import com.android.systemui.R; public class QSFooterView extends FrameLayout { private PageIndicator mPageIndicator; private TextView mBuildText; - private View mActionsContainer; private View mEditButton; @Nullable @@ -78,7 +77,6 @@ public class QSFooterView extends FrameLayout { protected void onFinishInflate() { super.onFinishInflate(); mPageIndicator = findViewById(R.id.footer_page_indicator); - mActionsContainer = requireViewById(R.id.qs_footer_actions); mBuildText = findViewById(R.id.build); mEditButton = findViewById(android.R.id.edit); @@ -105,10 +103,6 @@ public class QSFooterView extends FrameLayout { } } - void updateExpansion() { - setExpansion(mExpansionAmount); - } - @Override protected void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); @@ -129,7 +123,6 @@ public class QSFooterView extends FrameLayout { @Nullable private TouchAnimator createFooterAnimator() { TouchAnimator.Builder builder = new TouchAnimator.Builder() - .addFloat(mActionsContainer, "alpha", 0, 1) .addFloat(mPageIndicator, "alpha", 0, 1) .addFloat(mBuildText, "alpha", 0, 1) .addFloat(mEditButton, "alpha", 0, 1) diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java index f13553901ba1..bef4f43b9d11 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java @@ -40,8 +40,6 @@ public class QSFooterViewController extends ViewController impleme private final UserTracker mUserTracker; private final QSPanelController mQsPanelController; - private final QuickQSPanelController mQuickQSPanelController; - private final FooterActionsController mFooterActionsController; private final TextView mBuildText; private final PageIndicator mPageIndicator; private final View mEditButton; @@ -53,14 +51,10 @@ public class QSFooterViewController extends ViewController impleme UserTracker userTracker, FalsingManager falsingManager, ActivityStarter activityStarter, - QSPanelController qsPanelController, - QuickQSPanelController quickQSPanelController, - FooterActionsController footerActionsController) { + QSPanelController qsPanelController) { super(view); mUserTracker = userTracker; mQsPanelController = qsPanelController; - mQuickQSPanelController = quickQSPanelController; - mFooterActionsController = footerActionsController; mFalsingManager = falsingManager; mActivityStarter = activityStarter; @@ -69,22 +63,8 @@ public class QSFooterViewController extends ViewController impleme mEditButton = mView.findViewById(android.R.id.edit); } - @Override - protected void onInit() { - super.onInit(); - mFooterActionsController.init(); - } - @Override protected void onViewAttached() { - mView.addOnLayoutChangeListener( - (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> { - mView.updateExpansion(); - mFooterActionsController.updateAnimator(right - left, - mQuickQSPanelController.getNumQuickTiles()); - } - ); - mBuildText.setOnLongClickListener(view -> { CharSequence buildText = mBuildText.getText(); if (!TextUtils.isEmpty(buildText)) { @@ -111,9 +91,7 @@ public class QSFooterViewController extends ViewController impleme } @Override - protected void onViewDetached() { - setListening(false); - } + protected void onViewDetached() {} @Override public void setVisibility(int visibility) { @@ -123,25 +101,17 @@ public class QSFooterViewController extends ViewController impleme @Override public void setExpanded(boolean expanded) { - mFooterActionsController.setExpanded(expanded); mView.setExpanded(expanded); } @Override public void setExpansion(float expansion) { mView.setExpansion(expansion); - mFooterActionsController.setExpansion(expansion); - } - - @Override - public void setListening(boolean listening) { - mFooterActionsController.setListening(listening); } @Override public void setKeyguardShowing(boolean keyguardShowing) { mView.setKeyguardShowing(); - mFooterActionsController.setKeyguardShowing(); } /** */ @@ -153,6 +123,5 @@ public class QSFooterViewController extends ViewController impleme @Override public void disable(int state1, int state2, boolean animate) { mView.disable(state2); - mFooterActionsController.disable(state2); } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java index 259b786dafb7..50952bd0ec28 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java @@ -118,6 +118,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca private QSPanelController mQSPanelController; private QuickQSPanelController mQuickQSPanelController; private QSCustomizerController mQSCustomizerController; + private FooterActionsController mQSFooterActionController; @Nullable private ScrollListener mScrollListener; /** @@ -188,9 +189,11 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca QSFragmentComponent qsFragmentComponent = mQsComponentFactory.create(this); mQSPanelController = qsFragmentComponent.getQSPanelController(); mQuickQSPanelController = qsFragmentComponent.getQuickQSPanelController(); + mQSFooterActionController = qsFragmentComponent.getQSFooterActionController(); mQSPanelController.init(); mQuickQSPanelController.init(); + mQSFooterActionController.init(); mQSPanelScrollView = view.findViewById(R.id.expanded_qs_scroll_view); mQSPanelScrollView.addOnLayoutChangeListener( @@ -380,6 +383,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca mContainer.disable(state1, state2, animate); mHeader.disable(state1, state2, animate); mFooter.disable(state1, state2, animate); + mQSFooterActionController.disable(state2); updateQsState(); } @@ -396,10 +400,10 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca : View.INVISIBLE); mHeader.setExpanded((keyguardShowing && !mHeaderAnimating && !mShowCollapsedOnKeyguard) || (expanded && !mStackScrollerOverscrolling), mQuickQSPanelController); - mFooter.setVisibility(!mQsDisabled && (expanded || !keyguardShowing || mHeaderAnimating - || mShowCollapsedOnKeyguard) - ? View.VISIBLE - : View.INVISIBLE); + boolean footerVisible = !mQsDisabled && (expanded || !keyguardShowing || mHeaderAnimating + || mShowCollapsedOnKeyguard); + mFooter.setVisibility(footerVisible ? View.VISIBLE : View.INVISIBLE); + mQSFooterActionController.setVisible(footerVisible); mFooter.setExpanded((keyguardShowing && !mHeaderAnimating && !mShowCollapsedOnKeyguard) || (expanded && !mStackScrollerOverscrolling)); mQSPanelController.setVisibility( @@ -465,6 +469,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca } mFooter.setKeyguardShowing(keyguardShowing); + mQSFooterActionController.setKeyguardShowing(keyguardShowing); updateQsState(); } @@ -480,14 +485,13 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca if (DEBUG) Log.d(TAG, "setListening " + listening); mListening = listening; mQSContainerImplController.setListening(listening); - mFooter.setListening(listening); + mQSFooterActionController.setListening(listening); mQSPanelController.setListening(mListening, mQsExpanded); } @Override public void setHeaderListening(boolean listening) { mQSContainerImplController.setListening(listening); - mFooter.setListening(listening); } @Override @@ -561,6 +565,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca } } mFooter.setExpansion(onKeyguardAndExpanded ? 1 : expansion); + mQSFooterActionController.setExpansion(onKeyguardAndExpanded ? 1 : expansion); mQSPanelController.setRevealExpansion(expansion); mQSPanelController.getTileLayout().setExpansion(expansion, proposedTranslation); mQuickQSPanelController.getTileLayout().setExpansion(expansion, proposedTranslation); @@ -711,6 +716,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca boolean customizing = isCustomizing(); mQSPanelScrollView.setVisibility(!customizing ? View.VISIBLE : View.INVISIBLE); mFooter.setVisibility(!customizing ? View.VISIBLE : View.INVISIBLE); + mQSFooterActionController.setVisible(!customizing); mHeader.setVisibility(!customizing ? View.VISIBLE : View.INVISIBLE); // Let the panel know the position changed and it needs to update where notifications // and whatnot are. diff --git a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentComponent.java b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentComponent.java index 63cbc21ddf74..594f4f86a680 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentComponent.java +++ b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentComponent.java @@ -16,6 +16,7 @@ package com.android.systemui.qs.dagger; +import com.android.systemui.qs.FooterActionsController; import com.android.systemui.qs.QSAnimator; import com.android.systemui.qs.QSContainerImplController; import com.android.systemui.qs.QSFooter; @@ -61,4 +62,7 @@ public interface QSFragmentComponent { /** Construct a {@link QSSquishinessController}. */ QSSquishinessController getQSSquishinessController(); + + /** Construct a {@link FooterActionsController}. */ + FooterActionsController getQSFooterActionController(); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java index 4598fed03d17..776ee1021db2 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java +++ b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java @@ -21,10 +21,13 @@ import static com.android.systemui.util.Utils.useQsMediaPlayer; import android.content.Context; import android.view.LayoutInflater; import android.view.View; +import android.view.ViewStub; import com.android.systemui.R; import com.android.systemui.battery.BatteryMeterView; import com.android.systemui.dagger.qualifiers.RootView; +import com.android.systemui.flags.FeatureFlags; +import com.android.systemui.flags.Flags; import com.android.systemui.plugins.qs.QS; import com.android.systemui.privacy.OngoingPrivacyChip; import com.android.systemui.qs.FooterActionsView; @@ -117,9 +120,21 @@ public interface QSFragmentModule { return view.findViewById(R.id.qs_footer); } - /** */ + /** + * Provides a {@link FooterActionsView}. + * + * This will replace a ViewStub either in {@link QSFooterView} or in {@link QSContainerImpl}. + */ @Provides - static FooterActionsView providesQSFooterActionsView(@RootView View view) { + static FooterActionsView providesQSFooterActionsView(@RootView View view, + FeatureFlags featureFlags) { + ViewStub stub; + if (featureFlags.isEnabled(Flags.NEW_FOOTER)) { + stub = view.requireViewById(R.id.container_stub); + } else { + stub = view.requireViewById(R.id.footer_stub); + } + stub.inflate(); return view.findViewById(R.id.qs_footer_actions); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQSContainerController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQSContainerController.kt index 34bb6d3e1a27..8f6600cddb0e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQSContainerController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQSContainerController.kt @@ -1,6 +1,8 @@ package com.android.systemui.statusbar.phone import android.view.WindowInsets +import com.android.systemui.flags.FeatureFlags +import com.android.systemui.flags.Flags import com.android.systemui.navigationbar.NavigationModeController import com.android.systemui.plugins.qs.QS import com.android.systemui.plugins.qs.QSContainerController @@ -14,7 +16,8 @@ import javax.inject.Inject class NotificationsQSContainerController @Inject constructor( view: NotificationsQuickSettingsContainer, private val navigationModeController: NavigationModeController, - private val overviewProxyService: OverviewProxyService + private val overviewProxyService: OverviewProxyService, + private val featureFlags: FeatureFlags ) : ViewController(view), QSContainerController { var qsExpanded = false @@ -104,7 +107,11 @@ class NotificationsQSContainerController @Inject constructor( } mView.setPadding(0, 0, 0, containerPadding) mView.setNotificationsMarginBottom(notificationsMargin) - mView.setQSScrollPaddingBottom(qsScrollPaddingBottom) + if (featureFlags.isEnabled(Flags.NEW_FOOTER)) { + mView.setQSContainerPaddingBottom(notificationsMargin) + } else { + mView.setQSScrollPaddingBottom(qsScrollPaddingBottom) + } } private fun calculateBottomSpacing(): Pair { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java index 9210a8b5db80..91abfa4407f4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java @@ -53,6 +53,7 @@ public class NotificationsQuickSettingsContainer extends ConstraintLayout private Consumer mQSFragmentAttachedListener = qs -> {}; private QS mQs; private View mQSScrollView; + private View mQSContainer; public NotificationsQuickSettingsContainer(Context context, AttributeSet attrs) { super(context, attrs); @@ -72,6 +73,7 @@ public class NotificationsQuickSettingsContainer extends ConstraintLayout mQs = (QS) fragment; mQSFragmentAttachedListener.accept(mQs); mQSScrollView = mQs.getView().findViewById(R.id.expanded_qs_scroll_view); + mQSContainer = mQs.getView().findViewById(R.id.quick_settings_container); } @Override @@ -91,6 +93,16 @@ public class NotificationsQuickSettingsContainer extends ConstraintLayout mQSScrollView.getPaddingLeft(), mQSScrollView.getPaddingTop(), mQSScrollView.getPaddingRight(), + paddingBottom); + } + } + + public void setQSContainerPaddingBottom(int paddingBottom) { + if (mQSContainer != null) { + mQSContainer.setPadding( + mQSContainer.getPaddingLeft(), + mQSContainer.getPaddingTop(), + mQSContainer.getPaddingRight(), paddingBottom ); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/FooterActionsControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/FooterActionsControllerTest.kt index de9340d4f304..f5fa0d030901 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/FooterActionsControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/FooterActionsControllerTest.kt @@ -15,6 +15,8 @@ import com.android.internal.logging.testing.FakeMetricsLogger import com.android.systemui.Dependency import com.android.systemui.R import com.android.systemui.classifier.FalsingManagerFake +import com.android.systemui.flags.FeatureFlags +import com.android.systemui.flags.Flags import com.android.systemui.globalactions.GlobalActionsDialogLite import com.android.systemui.plugins.ActivityStarter import com.android.systemui.settings.UserTracker @@ -61,6 +63,8 @@ class FooterActionsControllerTest : LeakCheckedTest() { @Mock private lateinit var uiEventLogger: UiEventLogger @Mock + private lateinit var featureFlags: FeatureFlags + private lateinit var controller: FooterActionsController private val metricsLogger: MetricsLogger = FakeMetricsLogger() @@ -79,6 +83,7 @@ class FooterActionsControllerTest : LeakCheckedTest() { whenever(multiUserSwitchControllerFactory.create(any())) .thenReturn(multiUserSwitchController) + whenever(featureFlags.isEnabled(Flags.NEW_FOOTER)).thenReturn(false) view = LayoutInflater.from(context) .inflate(R.layout.footer_actions, null) as FooterActionsView @@ -87,7 +92,7 @@ class FooterActionsControllerTest : LeakCheckedTest() { activityStarter, userManager, userTracker, userInfoController, deviceProvisionedController, falsingManager, metricsLogger, fakeTunerService, globalActionsDialog, uiEventLogger, showPMLiteButton = true, fakeSettings, - Handler(testableLooper.looper)) + Handler(testableLooper.looper), featureFlags) controller.init() ViewUtils.attachView(view) // View looper is the testable looper associated with the test @@ -101,7 +106,7 @@ class FooterActionsControllerTest : LeakCheckedTest() { @Test fun testLogPowerMenuClick() { - controller.expanded = true + controller.visible = true falsingManager.setFalseTap(false) view.findViewById(R.id.pm_lite).performClick() diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterViewControllerTest.java index f43e68f3e575..26aa37df0c0b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterViewControllerTest.java @@ -61,12 +61,8 @@ public class QSFooterViewControllerTest extends LeakCheckedTest { @Mock private ClipboardManager mClipboardManager; @Mock - private QuickQSPanelController mQuickQSPanelController; - @Mock private TextView mBuildText; @Mock - private FooterActionsController mFooterActionsController; - @Mock private FalsingManager mFalsingManager; @Mock private ActivityStarter mActivityStarter; @@ -93,8 +89,7 @@ public class QSFooterViewControllerTest extends LeakCheckedTest { when(mView.findViewById(android.R.id.edit)).thenReturn(mEditButton); mController = new QSFooterViewController(mView, mUserTracker, mFalsingManager, - mActivityStarter, mQSPanelController, mQuickQSPanelController, - mFooterActionsController); + mActivityStarter, mQSPanelController); mController.init(); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationQSContainerControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationQSContainerControllerTest.kt index 337e64592750..f82a26af0ce8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationQSContainerControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationQSContainerControllerTest.kt @@ -6,6 +6,8 @@ import android.view.WindowInsets import android.view.WindowManagerPolicyConstants import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase +import com.android.systemui.flags.FeatureFlags +import com.android.systemui.flags.Flags import com.android.systemui.navigationbar.NavigationModeController import com.android.systemui.navigationbar.NavigationModeController.ModeChangedListener import com.android.systemui.recents.OverviewProxyService @@ -46,6 +48,8 @@ class NotificationQSContainerControllerTest : SysuiTestCase() { private lateinit var overviewProxyService: OverviewProxyService @Mock private lateinit var notificationsQSContainer: NotificationsQuickSettingsContainer + @Mock + private lateinit var featureFlags: FeatureFlags @Captor lateinit var navigationModeCaptor: ArgumentCaptor @Captor @@ -64,7 +68,8 @@ class NotificationQSContainerControllerTest : SysuiTestCase() { notificationsQSContainerController = NotificationsQSContainerController( notificationsQSContainer, navigationModeController, - overviewProxyService + overviewProxyService, + featureFlags ) whenever(notificationsQSContainer.defaultNotificationsMarginBottom) .thenReturn(NOTIFICATIONS_MARGIN) @@ -85,6 +90,26 @@ class NotificationQSContainerControllerTest : SysuiTestCase() { @Test fun testTaskbarVisibleInSplitShade() { notificationsQSContainerController.splitShadeEnabled = true + useNewFooter(false) + + given(taskbarVisible = true, + navigationMode = GESTURES_NAVIGATION, + insets = windowInsets().withStableBottom()) + then(expectedContainerPadding = 0, // taskbar should disappear when shade is expanded + expectedNotificationsMargin = NOTIFICATIONS_MARGIN) + + given(taskbarVisible = true, + navigationMode = BUTTONS_NAVIGATION, + insets = windowInsets().withStableBottom()) + then(expectedContainerPadding = STABLE_INSET_BOTTOM, + expectedNotificationsMargin = NOTIFICATIONS_MARGIN) + } + + @Test + fun testTaskbarVisibleInSplitShade_newFooter() { + notificationsQSContainerController.splitShadeEnabled = true + useNewFooter(true) + given(taskbarVisible = true, navigationMode = GESTURES_NAVIGATION, insets = windowInsets().withStableBottom()) @@ -102,6 +127,26 @@ class NotificationQSContainerControllerTest : SysuiTestCase() { fun testTaskbarNotVisibleInSplitShade() { // when taskbar is not visible, it means we're on the home screen notificationsQSContainerController.splitShadeEnabled = true + useNewFooter(false) + + given(taskbarVisible = false, + navigationMode = GESTURES_NAVIGATION, + insets = windowInsets().withStableBottom()) + then(expectedContainerPadding = 0) + + given(taskbarVisible = false, + navigationMode = BUTTONS_NAVIGATION, + insets = windowInsets().withStableBottom()) + then(expectedContainerPadding = 0, // qs goes full height as it's not obscuring nav buttons + expectedNotificationsMargin = STABLE_INSET_BOTTOM + NOTIFICATIONS_MARGIN) + } + + @Test + fun testTaskbarNotVisibleInSplitShade_newFooter() { + // when taskbar is not visible, it means we're on the home screen + notificationsQSContainerController.splitShadeEnabled = true + useNewFooter(true) + given(taskbarVisible = false, navigationMode = GESTURES_NAVIGATION, insets = windowInsets().withStableBottom()) @@ -117,6 +162,25 @@ class NotificationQSContainerControllerTest : SysuiTestCase() { @Test fun testTaskbarNotVisibleInSplitShadeWithCutout() { notificationsQSContainerController.splitShadeEnabled = true + useNewFooter(false) + + given(taskbarVisible = false, + navigationMode = GESTURES_NAVIGATION, + insets = windowInsets().withCutout()) + then(expectedContainerPadding = CUTOUT_HEIGHT) + + given(taskbarVisible = false, + navigationMode = BUTTONS_NAVIGATION, + insets = windowInsets().withCutout().withStableBottom()) + then(expectedContainerPadding = 0, + expectedNotificationsMargin = STABLE_INSET_BOTTOM + NOTIFICATIONS_MARGIN) + } + + @Test + fun testTaskbarNotVisibleInSplitShadeWithCutout_newFooter() { + notificationsQSContainerController.splitShadeEnabled = true + useNewFooter(true) + given(taskbarVisible = false, navigationMode = GESTURES_NAVIGATION, insets = windowInsets().withCutout()) @@ -132,6 +196,24 @@ class NotificationQSContainerControllerTest : SysuiTestCase() { @Test fun testTaskbarVisibleInSinglePaneShade() { notificationsQSContainerController.splitShadeEnabled = false + useNewFooter(false) + + given(taskbarVisible = true, + navigationMode = GESTURES_NAVIGATION, + insets = windowInsets().withStableBottom()) + then(expectedContainerPadding = 0) + + given(taskbarVisible = true, + navigationMode = BUTTONS_NAVIGATION, + insets = windowInsets().withStableBottom()) + then(expectedContainerPadding = STABLE_INSET_BOTTOM) + } + + @Test + fun testTaskbarVisibleInSinglePaneShade_newFooter() { + notificationsQSContainerController.splitShadeEnabled = false + useNewFooter(true) + given(taskbarVisible = true, navigationMode = GESTURES_NAVIGATION, insets = windowInsets().withStableBottom()) @@ -146,6 +228,8 @@ class NotificationQSContainerControllerTest : SysuiTestCase() { @Test fun testTaskbarNotVisibleInSinglePaneShade() { notificationsQSContainerController.splitShadeEnabled = false + useNewFooter(false) + given(taskbarVisible = false, navigationMode = GESTURES_NAVIGATION, insets = emptyInsets()) @@ -159,14 +243,56 @@ class NotificationQSContainerControllerTest : SysuiTestCase() { given(taskbarVisible = false, navigationMode = BUTTONS_NAVIGATION, insets = windowInsets().withStableBottom()) - then(expectedContainerPadding = 0, - expectedQsPadding = STABLE_INSET_BOTTOM) + then(expectedContainerPadding = 0, expectedQsPadding = STABLE_INSET_BOTTOM) + } + + @Test + fun testTaskbarNotVisibleInSinglePaneShade_newFooter() { + notificationsQSContainerController.splitShadeEnabled = false + useNewFooter(true) + + given(taskbarVisible = false, + navigationMode = GESTURES_NAVIGATION, + insets = emptyInsets()) + then(expectedContainerPadding = 0) + + given(taskbarVisible = false, + navigationMode = GESTURES_NAVIGATION, + insets = windowInsets().withCutout().withStableBottom()) + then(expectedContainerPadding = CUTOUT_HEIGHT) + + given(taskbarVisible = false, + navigationMode = BUTTONS_NAVIGATION, + insets = windowInsets().withStableBottom()) + then(expectedContainerPadding = 0, expectedQsPadding = STABLE_INSET_BOTTOM) } @Test fun testCustomizingInSinglePaneShade() { notificationsQSContainerController.splitShadeEnabled = false notificationsQSContainerController.setCustomizerShowing(true) + useNewFooter(false) + + // always sets spacings to 0 + given(taskbarVisible = false, + navigationMode = GESTURES_NAVIGATION, + insets = windowInsets().withStableBottom()) + then(expectedContainerPadding = 0, + expectedNotificationsMargin = 0) + + given(taskbarVisible = false, + navigationMode = BUTTONS_NAVIGATION, + insets = emptyInsets()) + then(expectedContainerPadding = 0, + expectedNotificationsMargin = 0) + } + + @Test + fun testCustomizingInSinglePaneShade_newFooter() { + notificationsQSContainerController.splitShadeEnabled = false + notificationsQSContainerController.setCustomizerShowing(true) + useNewFooter(true) + // always sets spacings to 0 given(taskbarVisible = false, navigationMode = GESTURES_NAVIGATION, @@ -185,6 +311,28 @@ class NotificationQSContainerControllerTest : SysuiTestCase() { fun testDetailShowingInSinglePaneShade() { notificationsQSContainerController.splitShadeEnabled = false notificationsQSContainerController.setDetailShowing(true) + useNewFooter(false) + + // always sets spacings to 0 + given(taskbarVisible = false, + navigationMode = GESTURES_NAVIGATION, + insets = windowInsets().withStableBottom()) + then(expectedContainerPadding = 0, + expectedNotificationsMargin = 0) + + given(taskbarVisible = false, + navigationMode = BUTTONS_NAVIGATION, + insets = emptyInsets()) + then(expectedContainerPadding = 0, + expectedNotificationsMargin = 0) + } + + @Test + fun testDetailShowingInSinglePaneShade_newFooter() { + notificationsQSContainerController.splitShadeEnabled = false + notificationsQSContainerController.setDetailShowing(true) + useNewFooter(true) + // always sets spacings to 0 given(taskbarVisible = false, navigationMode = GESTURES_NAVIGATION, @@ -202,6 +350,26 @@ class NotificationQSContainerControllerTest : SysuiTestCase() { @Test fun testDetailShowingInSplitShade() { notificationsQSContainerController.splitShadeEnabled = true + useNewFooter(false) + + given(taskbarVisible = false, + navigationMode = GESTURES_NAVIGATION, + insets = windowInsets().withStableBottom()) + then(expectedContainerPadding = 0) + + notificationsQSContainerController.setDetailShowing(true) + // should not influence spacing + given(taskbarVisible = false, + navigationMode = BUTTONS_NAVIGATION, + insets = emptyInsets()) + then(expectedContainerPadding = 0) + } + + @Test + fun testDetailShowingInSplitShade_newFooter() { + notificationsQSContainerController.splitShadeEnabled = true + useNewFooter(true) + given(taskbarVisible = false, navigationMode = GESTURES_NAVIGATION, insets = windowInsets().withStableBottom()) @@ -234,7 +402,13 @@ class NotificationQSContainerControllerTest : SysuiTestCase() { verify(notificationsQSContainer) .setPadding(anyInt(), anyInt(), anyInt(), eq(expectedContainerPadding)) verify(notificationsQSContainer).setNotificationsMarginBottom(expectedNotificationsMargin) - verify(notificationsQSContainer).setQSScrollPaddingBottom(expectedQsPadding) + val newFooter = featureFlags.isEnabled(Flags.NEW_FOOTER) + if (newFooter) { + verify(notificationsQSContainer) + .setQSContainerPaddingBottom(expectedNotificationsMargin) + } else { + verify(notificationsQSContainer).setQSScrollPaddingBottom(expectedQsPadding) + } Mockito.clearInvocations(notificationsQSContainer) } @@ -251,4 +425,8 @@ class NotificationQSContainerControllerTest : SysuiTestCase() { whenever(stableInsetBottom).thenReturn(STABLE_INSET_BOTTOM) return this } + + private fun useNewFooter(useNewFooter: Boolean) { + whenever(featureFlags.isEnabled(Flags.NEW_FOOTER)).thenReturn(useNewFooter) + } } \ No newline at end of file -- cgit v1.2.3-59-g8ed1b From 2fb9aa4f116e69e4840d6a518387824fc6c903ed Mon Sep 17 00:00:00 2001 From: Fabian Kozynski Date: Mon, 31 Jan 2022 15:27:48 -0500 Subject: Change footer action buttons This changes the buttons to filled circles right aligned. The View in the footer is a placeholder until we put the security footers there. Test: manual Fixes: 217196619 Change-Id: If426fdf5e338d63a88ec2dbae4eb09264ed538f6 --- .../res-keyguard/layout/new_footer_actions.xml | 102 +++++++++++++++++++++ .../res/drawable/qs_footer_action_circle.xml | 36 ++++++++ .../res/drawable/qs_footer_action_circle_color.xml | 36 ++++++++ packages/SystemUI/res/layout/qs_panel.xml | 2 +- 4 files changed, 175 insertions(+), 1 deletion(-) create mode 100644 packages/SystemUI/res-keyguard/layout/new_footer_actions.xml create mode 100644 packages/SystemUI/res/drawable/qs_footer_action_circle.xml create mode 100644 packages/SystemUI/res/drawable/qs_footer_action_circle_color.xml diff --git a/packages/SystemUI/res-keyguard/layout/new_footer_actions.xml b/packages/SystemUI/res-keyguard/layout/new_footer_actions.xml new file mode 100644 index 000000000000..95bdd8948c7c --- /dev/null +++ b/packages/SystemUI/res-keyguard/layout/new_footer_actions.xml @@ -0,0 +1,102 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/SystemUI/res/drawable/qs_footer_action_circle.xml b/packages/SystemUI/res/drawable/qs_footer_action_circle.xml new file mode 100644 index 000000000000..f54c30f2e794 --- /dev/null +++ b/packages/SystemUI/res/drawable/qs_footer_action_circle.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/SystemUI/res/drawable/qs_footer_action_circle_color.xml b/packages/SystemUI/res/drawable/qs_footer_action_circle_color.xml new file mode 100644 index 000000000000..1a323bccfa65 --- /dev/null +++ b/packages/SystemUI/res/drawable/qs_footer_action_circle_color.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/SystemUI/res/layout/qs_panel.xml b/packages/SystemUI/res/layout/qs_panel.xml index d9e7a2ab55df..22abd0c2f034 100644 --- a/packages/SystemUI/res/layout/qs_panel.xml +++ b/packages/SystemUI/res/layout/qs_panel.xml @@ -54,7 +54,7 @@