diff options
| author | 2022-02-02 18:17:01 +0000 | |
|---|---|---|
| committer | 2022-02-02 18:17:01 +0000 | |
| commit | 0cd1d1d476002a9bc2faed91350cdbff715f65e2 (patch) | |
| tree | 0e85e6dade0078dc13c7a96ffafb0ad8d4a485fb | |
| parent | 282f084626f07fcc3cd6641a526e9ae7a5aff1c0 (diff) | |
| parent | 2fb9aa4f116e69e4840d6a518387824fc6c903ed (diff) | |
Merge changes from topic "216302612"
* changes:
Change footer action buttons
Pin footer actions to bottom of QSContainerImpl
Remove QQS Footer Actions
27 files changed, 507 insertions, 331 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 @@ <com.android.systemui.qs.FooterActionsView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" - android:layout_height="48dp" - android:gravity="center_vertical"> + android:layout_height="@dimen/qs_footer_height" + android:gravity="center_vertical" + android:layout_gravity="bottom" +> <com.android.systemui.statusbar.phone.MultiUserSwitch android:id="@+id/multi_user_switch" 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 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +** Copyright 2022, 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. +--> + +<!-- Action buttons for footer in QS/QQS, containing settings button, power off button etc --> +<com.android.systemui.qs.FooterActionsView + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:androidprv="http://schemas.android.com/apk/prv/res/android" + android:layout_width="match_parent" + android:layout_height="@dimen/qs_footer_height" + android:gravity="center_vertical" + android:layout_gravity="bottom" +> + + <View + android:layout_height="1dp" + android:layout_width="0dp" + android:layout_weight="1" + /> + + <LinearLayout + android:layout_height="match_parent" + android:layout_width="wrap_content" + > + + <com.android.systemui.statusbar.phone.MultiUserSwitch + android:id="@+id/multi_user_switch" + android:layout_width="@dimen/qs_footer_action_button_size" + android:layout_height="@dimen/qs_footer_action_button_size" + android:layout_marginEnd="@dimen/qs_tile_margin_horizontal" + android:background="@drawable/qs_footer_action_circle" + android:focusable="true"> + + <ImageView + android:id="@+id/multi_user_avatar" + android:layout_width="@dimen/multi_user_avatar_expanded_size" + android:layout_height="@dimen/multi_user_avatar_expanded_size" + android:layout_gravity="center" + android:scaleType="centerInside" /> + </com.android.systemui.statusbar.phone.MultiUserSwitch> + + <com.android.systemui.statusbar.AlphaOptimizedFrameLayout + android:id="@+id/settings_button_container" + android:layout_width="@dimen/qs_footer_action_button_size" + android:layout_height="@dimen/qs_footer_action_button_size" + android:layout_marginEnd="@dimen/qs_tile_margin_horizontal" + android:background="@drawable/qs_footer_action_circle" + android:clipChildren="false" + android:clipToPadding="false"> + + <com.android.systemui.statusbar.phone.SettingsButton + android:id="@+id/settings_button" + android:layout_width="match_parent" + android:layout_height="@dimen/qs_footer_action_button_size" + android:layout_gravity="center" + android:background="@android:color/transparent" + android:contentDescription="@string/accessibility_quick_settings_settings" + android:padding="@dimen/qs_footer_icon_padding" + android:scaleType="centerInside" + android:src="@drawable/ic_settings" + android:tint="?android:attr/textColorPrimary" /> + + <com.android.systemui.statusbar.AlphaOptimizedImageView + android:id="@+id/tuner_icon" + android:layout_width="8dp" + android:layout_height="8dp" + android:layout_gravity="center_horizontal|bottom" + android:layout_marginBottom="@dimen/qs_footer_icon_padding" + android:src="@drawable/tuner" + android:tint="?android:attr/textColorTertiary" + android:visibility="invisible" /> + + </com.android.systemui.statusbar.AlphaOptimizedFrameLayout> + + <com.android.systemui.statusbar.AlphaOptimizedImageView + android:id="@+id/pm_lite" + android:layout_width="@dimen/qs_footer_action_button_size" + android:layout_height="@dimen/qs_footer_action_button_size" + android:background="@drawable/qs_footer_action_circle_color" + android:clickable="true" + android:clipToPadding="false" + android:focusable="true" + android:padding="@dimen/qs_footer_icon_padding" + android:src="@*android:drawable/ic_lock_power_off" + android:contentDescription="@string/accessibility_quick_settings_power_menu" + android:tint="?androidprv:attr/textColorOnAccent" /> + + </LinearLayout> +</com.android.systemui.qs.FooterActionsView>
\ 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 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2022 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. + --> +<inset xmlns:android="http://schemas.android.com/apk/res/android" + android:insetTop="@dimen/qs_footer_action_inset" + android:insetBottom="@dimen/qs_footer_action_inset" + android:insetLeft="@dimen/qs_footer_action_inset" + android:insetRight="@dimen/qs_footer_action_inset"> + <ripple + android:color="?android:attr/colorControlHighlight"> + <item android:id="@android:id/mask"> + <shape android:shape="oval"> + <solid android:color="@android:color/white"/> + </shape> + </item> + <item> + <shape android:shape="oval"> + <solid android:color="?attr/offStateColor"/> + </shape> + </item> + + </ripple> +</inset>
\ 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 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2022 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. + --> +<inset xmlns:android="http://schemas.android.com/apk/res/android" + android:insetTop="@dimen/qs_footer_action_inset" + android:insetBottom="@dimen/qs_footer_action_inset" + android:insetLeft="@dimen/qs_footer_action_inset" + android:insetRight="@dimen/qs_footer_action_inset"> + <ripple + android:color="?android:attr/colorControlHighlight"> + <item android:id="@android:id/mask"> + <shape android:shape="oval"> + <solid android:color="@android:color/white"/> + </shape> + </item> + <item> + <shape android:shape="oval"> + <solid android:color="?android:attr/colorAccent"/> + </shape> + </item> + + </ripple> +</inset>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/qs_footer_impl.xml b/packages/SystemUI/res/layout/qs_footer_impl.xml index 5cd9e9485fda..b6e34998a7cd 100644 --- a/packages/SystemUI/res/layout/qs_footer_impl.xml +++ b/packages/SystemUI/res/layout/qs_footer_impl.xml @@ -19,7 +19,7 @@ <com.android.systemui.qs.QSFooterView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/qs_footer" android:layout_width="match_parent" - android:layout_height="@dimen/qs_footer_height" + android:layout_height="wrap_content" android:layout_marginStart="@dimen/qs_footer_margin" android:layout_marginEnd="@dimen/qs_footer_margin" android:layout_marginBottom="@dimen/qs_footers_margin_bottom" @@ -36,7 +36,7 @@ <LinearLayout android:layout_width="match_parent" - android:layout_height="48dp" + android:layout_height="@dimen/qs_footer_height" android:layout_gravity="center_vertical"> <TextView @@ -80,8 +80,13 @@ </LinearLayout> - <include layout="@layout/footer_actions" - android:id="@+id/qs_footer_actions"/> + <ViewStub + android:id="@+id/footer_stub" + android:inflatedId="@+id/qs_footer_actions" + android:layout="@layout/footer_actions" + android:layout_height="@dimen/qs_footer_height" + android:layout_width="match_parent" + /> </LinearLayout> diff --git a/packages/SystemUI/res/layout/qs_panel.xml b/packages/SystemUI/res/layout/qs_panel.xml index f5c6036a5a86..22abd0c2f034 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" /> + <ViewStub + android:id="@+id/container_stub" + android:inflatedId="@+id/qs_footer_actions" + android:layout="@layout/new_footer_actions" + android:layout_height="@dimen/qs_footer_height" + android:layout_width="match_parent" + android:layout_gravity="bottom" + /> + <include android:id="@+id/qs_customize" layout="@layout/qs_customize_panel" 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"> - - <include - layout="@layout/footer_actions" - android:id="@+id/qqs_footer_actions" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginTop="@dimen/qqs_layout_margin_top" - android:layout_marginStart="@dimen/qs_footer_margin" - android:layout_marginEnd="@dimen/qs_footer_margin" - /> </com.android.systemui.qs.QuickQSPanel> </RelativeLayout> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 74bb9e45a6f2..dba7290dba09 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -327,7 +327,7 @@ <!-- The height of the quick settings footer that holds the user switcher, settings icon, etc. --> - <dimen name="qs_footer_height">96dp</dimen> + <dimen name="qs_footer_height">48dp</dimen> <!-- The size of each of the icon buttons in the QS footer --> <dimen name="qs_footer_action_button_size">48dp</dimen> @@ -491,7 +491,7 @@ <dimen name="qs_tile_text_size">14sp</dimen> <dimen name="qs_panel_padding">16dp</dimen> <dimen name="qs_dual_tile_padding_horizontal">6dp</dimen> - <dimen name="qs_panel_padding_bottom">0dp</dimen> + <dimen name="qs_panel_padding_bottom">@dimen/qs_footer_height</dimen> <dimen name="qs_panel_padding_top">48dp</dimen> <dimen name="qs_detail_header_padding">0dp</dimen> <dimen name="qs_detail_image_width">56dp</dimen> diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.java b/packages/SystemUI/src/com/android/systemui/flags/Flags.java index c894b7023d75..357a68fc6502 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 7ac9205c7922..4aedbc983d9c 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt @@ -29,14 +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.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.qs.dagger.QSScope import com.android.systemui.settings.UserTracker import com.android.systemui.statusbar.phone.MultiUserSwitchController import com.android.systemui.statusbar.phone.SettingsButton @@ -54,13 +56,14 @@ 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, 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,20 +71,34 @@ 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 + private val handler: Handler, + private val featureFlags: FeatureFlags ) : ViewController<FooterActionsView>(view) { - enum class ExpansionState { COLLAPSED, EXPANDED } - + 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) 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 +116,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 (!visible || falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) { return@OnClickListener } if (v === settingsButton) { @@ -110,9 +126,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,24 +149,14 @@ 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 updateVisibility() { + val previousVisibility = mView.visibility + mView.visibility = if (visible) View.VISIBLE else View.INVISIBLE + if (previousVisibility != mView.visibility) updateView() } private fun startSettingsActivity() { @@ -204,24 +208,23 @@ class FooterActionsController @Inject constructor( } fun setExpansion(headerExpansionFraction: Float) { - mView.setExpansion(headerExpansionFraction) - } - - fun updateAnimator(width: Int, numTiles: Int) { - mView.updateAnimator(width, numTiles) - } - - fun setKeyguardShowing() { - mView.setKeyguardShowing() - } - - fun refreshVisibility(shouldBeVisible: Boolean) { - if (shouldBeVisible) { - showFooter() + 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 { - hideFooter() + alphaAnimator.setPosition(headerExpansionFraction) } } + fun setKeyguardShowing(showing: Boolean) { + setExpansion(lastExpansion) + } + 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/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/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/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}; @@ -78,12 +75,6 @@ public class QSContainerImpl extends FrameLayout implements Dumpable { } @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 // don't want to do anything with them. @@ -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 5327b7e3ba26..bef4f43b9d11 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}. @@ -43,8 +40,6 @@ public class QSFooterViewController extends ViewController<QSFooterView> 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; @@ -56,14 +51,10 @@ public class QSFooterViewController extends ViewController<QSFooterView> impleme UserTracker userTracker, FalsingManager falsingManager, ActivityStarter activityStarter, - QSPanelController qsPanelController, - QuickQSPanelController quickQSPanelController, - @Named(QS_FOOTER) FooterActionsController footerActionsController) { + QSPanelController qsPanelController) { super(view); mUserTracker = userTracker; mQsPanelController = qsPanelController; - mQuickQSPanelController = quickQSPanelController; - mFooterActionsController = footerActionsController; mFalsingManager = falsingManager; mActivityStarter = activityStarter; @@ -73,21 +64,7 @@ public class QSFooterViewController extends ViewController<QSFooterView> impleme } @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)) { @@ -114,9 +91,7 @@ public class QSFooterViewController extends ViewController<QSFooterView> impleme } @Override - protected void onViewDetached() { - setListening(false); - } + protected void onViewDetached() {} @Override public void setVisibility(int visibility) { @@ -126,25 +101,17 @@ public class QSFooterViewController extends ViewController<QSFooterView> 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(); } /** */ @@ -156,6 +123,5 @@ public class QSFooterViewController extends ViewController<QSFooterView> 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/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<QuickQSPanel> // 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<QuickQSPanel> @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<QuickQSPanel> 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<QuickQSPanel> 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<QuickQSPanel> @Override protected void onConfigurationChanged() { mBrightnessController.refreshVisibility(mShouldUseSplitNotificationShade); - mFooterActionsController.refreshVisibility(mShouldUseSplitNotificationShade); } @Override 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 1958cafb0fb9..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,15 +21,15 @@ 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.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 +55,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"; /** @@ -122,46 +120,26 @@ 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 - @Named(QS_FOOTER) - 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); } /** */ @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 static QSFooter providesQSFooter(QSFooterViewController qsFooterViewController) { qsFooterViewController.init(); 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 1a885336be5e..b457ebf60c71 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<NotificationsQuickSettingsContainer>(view), QSContainerController { var qsExpanded = false @@ -108,7 +111,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<Int, Int> { 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 cecbcdb829c6..95e3b70b4c5e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java @@ -52,6 +52,7 @@ public class NotificationsQuickSettingsContainer extends ConstraintLayout private Consumer<QS> mQSFragmentAttachedListener = qs -> {}; private QS mQs; private View mQSScrollView; + private View mQSContainer; public NotificationsQuickSettingsContainer(Context context, AttributeSet attrs) { super(context, attrs); @@ -70,6 +71,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 @@ -89,6 +91,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 354bb5192251..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,9 +15,10 @@ 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.qs.FooterActionsController.ExpansionState import com.android.systemui.settings.UserTracker import com.android.systemui.statusbar.phone.MultiUserSwitchController import com.android.systemui.statusbar.policy.DeviceProvisionedController @@ -54,12 +55,16 @@ 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 @Mock private lateinit var uiEventLogger: UiEventLogger @Mock + private lateinit var featureFlags: FeatureFlags + private lateinit var controller: FooterActionsController private val metricsLogger: MetricsLogger = FakeMetricsLogger() @@ -76,15 +81,18 @@ class FooterActionsControllerTest : LeakCheckedTest() { injectLeakCheckedDependencies(*LeakCheckedTest.ALL_SUPPORTED_CLASSES) val fakeTunerService = Dependency.get(TunerService::class.java) as FakeTunerService + 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 - 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, - Handler(testableLooper.looper)) + globalActionsDialog, uiEventLogger, showPMLiteButton = true, fakeSettings, + Handler(testableLooper.looper), featureFlags) controller.init() ViewUtils.attachView(view) // View looper is the testable looper associated with the test @@ -98,7 +106,7 @@ class FooterActionsControllerTest : LeakCheckedTest() { @Test fun testLogPowerMenuClick() { - controller.expanded = true + controller.visible = true falsingManager.setFalseTap(false) view.findViewById<View>(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/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<QSPanel.OnConfigurationChangedListener> @@ -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()) } } 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 77e90256ab70..bbb2346797b9 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<ModeChangedListener> @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()) @@ -246,7 +414,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) } @@ -263,4 +437,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 |