diff --git a/packages/SystemUI/res-keyguard/layout/qs_footer_actions.xml b/packages/SystemUI/res-keyguard/layout/footer_actions.xml similarity index 96% rename from packages/SystemUI/res-keyguard/layout/qs_footer_actions.xml rename to packages/SystemUI/res-keyguard/layout/footer_actions.xml index 181ba078e948b..dfc3e63a4e2bf 100644 --- a/packages/SystemUI/res-keyguard/layout/qs_footer_actions.xml +++ b/packages/SystemUI/res-keyguard/layout/footer_actions.xml @@ -14,9 +14,10 @@ ** See the License for the specific language governing permissions and ** limitations under the License. --> - + @@ -101,4 +102,4 @@ - \ No newline at end of file + \ 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 fe0b14aaad8d2..e70084b803083 100644 --- a/packages/SystemUI/res/layout/qs_footer_impl.xml +++ b/packages/SystemUI/res/layout/qs_footer_impl.xml @@ -68,7 +68,8 @@ - + 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 df02730fc8663..6b14c96b58e27 100644 --- a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml +++ b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml @@ -56,7 +56,18 @@ android:clipToPadding="false" android:focusable="true" android:paddingBottom="24dp" - android:importantForAccessibility="yes" /> + android:importantForAccessibility="yes"> + + + diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooterActionsController.kt b/packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt similarity index 75% rename from packages/SystemUI/src/com/android/systemui/qs/QSFooterActionsController.kt rename to packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt index dbf62a4361971..bedb330381340 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSFooterActionsController.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt @@ -1,3 +1,19 @@ +/* + * 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.content.Intent @@ -16,6 +32,8 @@ 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.statusbar.phone.MultiUserSwitchController import com.android.systemui.statusbar.phone.SettingsButton @@ -27,8 +45,13 @@ import com.android.systemui.util.ViewController import javax.inject.Inject import javax.inject.Named -class QSFooterActionsController @Inject constructor( - view: QSFooterActionsView, +/** + * Manages [FooterActionsView] behaviour, both when it's placed in QS or QQS (split shade). + * Main difference between QS and QQS behaviour is condition when buttons should be visible, + * determined by [buttonsVisibleState] + */ +class FooterActionsController @Inject constructor( + view: FooterActionsView, private val qsPanelController: QSPanelController, private val activityStarter: ActivityStarter, private val userManager: UserManager, @@ -40,15 +63,20 @@ class QSFooterActionsController @Inject constructor( private val tunerService: TunerService, private val globalActionsDialog: GlobalActionsDialogLite, private val uiEventLogger: UiEventLogger, - @Named(PM_LITE_ENABLED) private val showPMLiteButton: Boolean -) : ViewController(view) { + @Named(PM_LITE_ENABLED) private val showPMLiteButton: Boolean, + private val buttonsVisibleState: ExpansionState +) : ViewController(view) { + + enum class ExpansionState { COLLAPSED, EXPANDED } private var listening: Boolean = false + var expanded = false set(value) { - field = value - mView.setExpanded(value, isTunerEnabled(), - multiUserSwitchController.isMultiUserEnabled) + if (field != value) { + field = value + updateView() + } } private val settingsButton: SettingsButton = view.findViewById(R.id.settings_button) @@ -64,7 +92,7 @@ class QSFooterActionsController @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 (!expanded || falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) { + if (!buttonsVisible() || falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) { return@OnClickListener } if (v === settingsButton) { @@ -98,10 +126,26 @@ class QSFooterActionsController @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( @@ -128,7 +172,12 @@ class QSFooterActionsController @Inject constructor( activityStarter.postQSRunnableDismissingKeyguard { qsPanelController.showEdit(view) } }) - mView.updateEverything(isTunerEnabled(), multiUserSwitchController.isMultiUserEnabled) + updateView() + } + + private fun updateView() { + mView.updateEverything(buttonsVisible(), isTunerEnabled(), + multiUserSwitchController.isMultiUserEnabled) } override fun onViewDetached() { @@ -148,7 +197,8 @@ class QSFooterActionsController @Inject constructor( } fun disable(state2: Int) { - mView.disable(state2, isTunerEnabled(), multiUserSwitchController.isMultiUserEnabled) + mView.disable(buttonsVisible(), state2, isTunerEnabled(), + multiUserSwitchController.isMultiUserEnabled) } fun setExpansion(headerExpansionFraction: Float) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/FooterActionsControllerBuilder.kt b/packages/SystemUI/src/com/android/systemui/qs/FooterActionsControllerBuilder.kt new file mode 100644 index 0000000000000..fcfa72a82acb6 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/FooterActionsControllerBuilder.kt @@ -0,0 +1,67 @@ +/* + * 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.UserManager +import com.android.internal.logging.MetricsLogger +import com.android.internal.logging.UiEventLogger +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.statusbar.phone.MultiUserSwitchController +import com.android.systemui.statusbar.policy.DeviceProvisionedController +import com.android.systemui.statusbar.policy.UserInfoController +import com.android.systemui.tuner.TunerService +import javax.inject.Inject +import javax.inject.Named + +class FooterActionsControllerBuilder @Inject constructor( + private val qsPanelController: QSPanelController, + private val activityStarter: ActivityStarter, + private val userManager: UserManager, + private val userInfoController: UserInfoController, + private val multiUserSwitchController: MultiUserSwitchController, + 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 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, qsPanelController, activityStarter, userManager, + userInfoController, multiUserSwitchController, deviceProvisionedController, + falsingManager, metricsLogger, tunerService, globalActionsDialog, uiEventLogger, + showPMLiteButton, buttonsVisibleState) + } +} \ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooterActionsView.kt b/packages/SystemUI/src/com/android/systemui/qs/FooterActionsView.kt similarity index 84% rename from packages/SystemUI/src/com/android/systemui/qs/QSFooterActionsView.kt rename to packages/SystemUI/src/com/android/systemui/qs/FooterActionsView.kt index 66a29a36f351c..941e54a553935 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSFooterActionsView.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/FooterActionsView.kt @@ -37,7 +37,7 @@ import com.android.systemui.statusbar.phone.SettingsButton * in split shade mode visible also in collapsed state. May contain up to 5 buttons: settings, * edit tiles, power off and conditionally: user switch and tuner */ -class QSFooterActionsView(context: Context?, attrs: AttributeSet?) : LinearLayout(context, attrs) { +class FooterActionsView(context: Context?, attrs: AttributeSet?) : LinearLayout(context, attrs) { private lateinit var settingsContainer: View private lateinit var settingsButton: SettingsButton private lateinit var multiUserSwitch: MultiUserSwitch @@ -48,7 +48,6 @@ class QSFooterActionsView(context: Context?, attrs: AttributeSet?) : LinearLayou private var settingsCogAnimator: TouchAnimator? = null private var qsDisabled = false - private var isExpanded = false private var expansionAmount = 0f override fun onFinishInflate() { @@ -102,27 +101,30 @@ class QSFooterActionsView(context: Context?, attrs: AttributeSet?) : LinearLayou setExpansion(expansionAmount) } - fun setExpanded(expanded: Boolean, isTunerEnabled: Boolean, multiUserEnabled: Boolean) { - if (isExpanded == expanded) return - isExpanded = expanded - updateEverything(isTunerEnabled, multiUserEnabled) - } - fun setExpansion(headerExpansionFraction: Float) { expansionAmount = headerExpansionFraction if (settingsCogAnimator != null) settingsCogAnimator!!.setPosition(headerExpansionFraction) } - fun disable(state2: Int, isTunerEnabled: Boolean, multiUserEnabled: Boolean) { + fun disable( + buttonsVisible: Boolean, + state2: Int, + isTunerEnabled: Boolean, + multiUserEnabled: Boolean + ) { val disabled = state2 and StatusBarManager.DISABLE2_QUICK_SETTINGS != 0 if (disabled == qsDisabled) return qsDisabled = disabled - updateEverything(isTunerEnabled, multiUserEnabled) + updateEverything(buttonsVisible, isTunerEnabled, multiUserEnabled) } - fun updateEverything(isTunerEnabled: Boolean, multiUserEnabled: Boolean) { + fun updateEverything( + buttonsVisible: Boolean, + isTunerEnabled: Boolean, + multiUserEnabled: Boolean + ) { post { - updateVisibilities(isTunerEnabled, multiUserEnabled) + updateVisibilities(buttonsVisible, isTunerEnabled, multiUserEnabled) updateClickabilities() isClickable = false } @@ -134,16 +136,16 @@ class QSFooterActionsView(context: Context?, attrs: AttributeSet?) : LinearLayou settingsButton.isClickable = settingsButton.visibility == VISIBLE } - private fun updateVisibilities(isTunerEnabled: Boolean, multiUserEnabled: Boolean) { + private fun updateVisibilities( + buttonsVisible: Boolean, + isTunerEnabled: Boolean, + multiUserEnabled: Boolean + ) { settingsContainer.visibility = if (qsDisabled) GONE else VISIBLE tunerIcon.visibility = if (isTunerEnabled) VISIBLE else INVISIBLE - multiUserSwitch.visibility = if (showUserSwitcher(multiUserEnabled)) VISIBLE else GONE + multiUserSwitch.visibility = if (buttonsVisible && multiUserEnabled) VISIBLE else GONE val isDemo = UserManager.isDeviceInDemoMode(context) - settingsButton.visibility = if (isDemo || !isExpanded) INVISIBLE else VISIBLE - } - - private fun showUserSwitcher(multiUserEnabled: Boolean): Boolean { - return isExpanded && multiUserEnabled + settingsButton.visibility = if (isDemo || !buttonsVisible) INVISIBLE else VISIBLE } fun onUserInfoChanged(picture: Drawable?, isGuestUser: Boolean) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java index 4fcd46c96fe3d..8659b8b868d46 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java @@ -14,6 +14,9 @@ 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; @@ -43,6 +46,7 @@ import java.util.List; import java.util.concurrent.Executor; import javax.inject.Inject; +import javax.inject.Named; /** */ @QSScope @@ -67,13 +71,15 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha * position to the normal QS panel. These views will only show once the animation is complete, * to prevent overlapping of semi transparent views */ - private final ArrayList mQuickQsViews = new ArrayList<>(); + private final ArrayList mAnimatedQsViews = new ArrayList<>(); private final QuickQSPanel mQuickQsPanel; private final QSPanelController mQsPanelController; private final QuickQSPanelController mQuickQSPanelController; private final QuickStatusBarHeader mQuickStatusBarHeader; private final QSSecurityFooter mSecurityFooter; private final QS mQs; + private final View mQSFooterActions; + private final View mQQSFooterActions; private PagedTileLayout mPagedLayout; @@ -88,6 +94,7 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha // This animates fading of SecurityFooter and media divider private TouchAnimator mAllPagesDelayedAnimator; private TouchAnimator mBrightnessAnimator; + private TouchAnimator mQQSFooterActionsAnimator; private HeightExpansionAnimator mQQSTileHeightAnimator; private HeightExpansionAnimator mOtherTilesExpandAnimator; @@ -110,12 +117,16 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha QSPanelController qsPanelController, QuickQSPanelController quickQSPanelController, QSTileHost qsTileHost, QSSecurityFooter securityFooter, @Main Executor executor, TunerService tunerService, - QSExpansionPathInterpolator qsExpansionPathInterpolator) { + QSExpansionPathInterpolator qsExpansionPathInterpolator, + @Named(QS_FOOTER) FooterActionsView qsFooterActionsView, + @Named(QQS_FOOTER) FooterActionsView qqsFooterActionsView) { mQs = qs; mQuickQsPanel = quickPanel; mQsPanelController = qsPanelController; mQuickQSPanelController = quickQSPanelController; mQuickStatusBarHeader = quickStatusBarHeader; + mQQSFooterActions = qqsFooterActionsView; + mQSFooterActions = qsFooterActionsView; mSecurityFooter = securityFooter; mHost = qsTileHost; mExecutor = executor; @@ -262,7 +273,7 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha clearAnimationState(); mAllViews.clear(); - mQuickQsViews.clear(); + mAnimatedQsViews.clear(); mQQSTileHeightAnimator = null; mOtherTilesExpandAnimator = null; @@ -360,7 +371,7 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha firstPageBuilder.addFloat(quickTileView.getSecondaryLabel(), "alpha", 0, 1); - mQuickQsViews.add(tileView); + mAnimatedQsViews.add(tileView); mAllViews.add(quickTileView); mAllViews.add(quickTileView.getSecondaryLabel()); } else if (mFullRows && isIconInAnimatedRow(count)) { @@ -417,6 +428,13 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha .addFloat(tileLayout, "alpha", 0, 1); mFirstPageDelayedAnimator = builder.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 = new Builder().setStartDelay(EXPANDED_TILE_DELAY); builder.addFloat(mSecurityFooter.getView(), "alpha", 0, 1); @@ -452,6 +470,20 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha .addFloat(tileLayout, "alpha", 0, 1).build(); } + private void updateQQSFooterAnimation() { + int[] qsPosition = new int[2]; + int[] qqsPosition = new int[2]; + View commonView = mQs.getView(); + getRelativePositionInt(qsPosition, mQSFooterActions, commonView); + getRelativePositionInt(qqsPosition, mQQSFooterActions, commonView); + int translationY = (qsPosition[1] - qqsPosition[1]) + - mQuickStatusBarHeader.getOffsetTranslation(); + mQQSFooterActionsAnimator = new TouchAnimator.Builder() + .addFloat(mQQSFooterActions, "translationY", 0, translationY) + .build(); + mAnimatedQsViews.add(mQSFooterActions); + } + private boolean isIconInAnimatedRow(int count) { if (mPagedLayout == null) { return false; @@ -521,6 +553,9 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha if (mBrightnessAnimator != null) { mBrightnessAnimator.setPosition(position); } + if (mQQSFooterActionsAnimator != null) { + mQQSFooterActionsAnimator.setPosition(position); + } } } @@ -532,9 +567,9 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha @Override public void onAnimationAtEnd() { mQuickQsPanel.setVisibility(View.INVISIBLE); - final int N = mQuickQsViews.size(); + final int N = mAnimatedQsViews.size(); for (int i = 0; i < N; i++) { - mQuickQsViews.get(i).setVisibility(View.VISIBLE); + mAnimatedQsViews.get(i).setVisibility(View.VISIBLE); } } @@ -542,9 +577,9 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha public void onAnimationStarted() { updateQQSVisibility(); if (mOnFirstPage) { - final int N = mQuickQsViews.size(); + final int N = mAnimatedQsViews.size(); for (int i = 0; i < N; i++) { - mQuickQsViews.get(i).setVisibility(View.INVISIBLE); + mAnimatedQsViews.get(i).setVisibility(View.INVISIBLE); } } } @@ -569,9 +604,9 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha if (mOtherTilesExpandAnimator != null) { mOtherTilesExpandAnimator.resetViewsHeights(); } - final int N2 = mQuickQsViews.size(); + final int N2 = mAnimatedQsViews.size(); for (int i = 0; i < N2; i++) { - mQuickQsViews.get(i).setVisibility(View.VISIBLE); + mAnimatedQsViews.get(i).setVisibility(View.VISIBLE); } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooterView.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooterView.java index 7db13bdb64bbe..4d23958d56ab4 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSFooterView.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooterView.java @@ -41,7 +41,7 @@ import com.android.systemui.R; /** * Footer of expanded Quick Settings, tiles page indicator, (optionally) build number and - * {@link QSFooterActionsView} + * {@link FooterActionsView} */ public class QSFooterView extends FrameLayout { private PageIndicator mPageIndicator; @@ -75,7 +75,7 @@ public class QSFooterView extends FrameLayout { protected void onFinishInflate() { super.onFinishInflate(); mPageIndicator = findViewById(R.id.footer_page_indicator); - mActionsContainer = requireViewById(R.id.qs_footer_actions_container); + mActionsContainer = requireViewById(R.id.qs_footer_actions); mBuildText = findViewById(R.id.build); updateResources(); diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java index c8ae5904e8e90..e7c06e3c7eded 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java @@ -16,6 +16,8 @@ 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; @@ -29,6 +31,7 @@ import com.android.systemui.settings.UserTracker; import com.android.systemui.util.ViewController; import javax.inject.Inject; +import javax.inject.Named; /** * Controller for {@link QSFooterView}. @@ -39,7 +42,7 @@ public class QSFooterViewController extends ViewController impleme private final UserTracker mUserTracker; private final QSPanelController mQsPanelController; private final QuickQSPanelController mQuickQSPanelController; - private final QSFooterActionsController mQsFooterActionsController; + private final FooterActionsController mFooterActionsController; private final TextView mBuildText; private final PageIndicator mPageIndicator; @@ -48,12 +51,12 @@ public class QSFooterViewController extends ViewController impleme UserTracker userTracker, QSPanelController qsPanelController, QuickQSPanelController quickQSPanelController, - QSFooterActionsController qsFooterActionsController) { + @Named(QS_FOOTER) FooterActionsController footerActionsController) { super(view); mUserTracker = userTracker; mQsPanelController = qsPanelController; mQuickQSPanelController = quickQSPanelController; - mQsFooterActionsController = qsFooterActionsController; + mFooterActionsController = footerActionsController; mBuildText = mView.findViewById(R.id.build); mPageIndicator = mView.findViewById(R.id.footer_page_indicator); @@ -62,7 +65,7 @@ public class QSFooterViewController extends ViewController impleme @Override protected void onInit() { super.onInit(); - mQsFooterActionsController.init(); + mFooterActionsController.init(); } @Override @@ -70,7 +73,7 @@ public class QSFooterViewController extends ViewController impleme mView.addOnLayoutChangeListener( (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> { mView.updateExpansion(); - mQsFooterActionsController.updateAnimator(right - left, + mFooterActionsController.updateAnimator(right - left, mQuickQSPanelController.getNumQuickTiles()); } ); @@ -104,25 +107,25 @@ public class QSFooterViewController extends ViewController impleme @Override public void setExpanded(boolean expanded) { - mQsFooterActionsController.setExpanded(expanded); + mFooterActionsController.setExpanded(expanded); mView.setExpanded(expanded); } @Override public void setExpansion(float expansion) { mView.setExpansion(expansion); - mQsFooterActionsController.setExpansion(expansion); + mFooterActionsController.setExpansion(expansion); } @Override public void setListening(boolean listening) { - mQsFooterActionsController.setListening(listening); + mFooterActionsController.setListening(listening); } @Override public void setKeyguardShowing(boolean keyguardShowing) { mView.setKeyguardShowing(); - mQsFooterActionsController.setKeyguardShowing(); + mFooterActionsController.setKeyguardShowing(); } /** */ @@ -134,6 +137,6 @@ public class QSFooterViewController extends ViewController impleme @Override public void disable(int state1, int state2, boolean animate) { mView.disable(state2); - mQsFooterActionsController.disable(state2); + mFooterActionsController.disable(state2); } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java index 8c7a2cda271af..921ee35e38905 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java @@ -17,6 +17,7 @@ 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; @@ -53,6 +54,7 @@ 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, @@ -61,12 +63,14 @@ public class QuickQSPanelController extends QSPanelControllerBase @Named(QUICK_QS_PANEL) MediaHost mediaHost, MetricsLogger metricsLogger, UiEventLogger uiEventLogger, QSLogger qsLogger, DumpManager dumpManager, - QuickQSBrightnessController quickQSBrightnessController + QuickQSBrightnessController quickQSBrightnessController, + @Named(QQS_FOOTER) FooterActionsController footerActionsController ) { super(view, qsTileHost, qsCustomizerController, usingMediaPlayer, mediaHost, metricsLogger, uiEventLogger, qsLogger, dumpManager); mBrightnessController = quickQSBrightnessController; mBrightnessMirrorHandler = new BrightnessMirrorHandler(mBrightnessController); + mFooterActionsController = footerActionsController; } @Override @@ -76,6 +80,8 @@ public class QuickQSPanelController extends QSPanelControllerBase mMediaHost.setShowsOnlyActiveMedia(true); mMediaHost.init(MediaHierarchyManager.LOCATION_QQS); mBrightnessController.init(mShouldUseSplitNotificationShade); + mFooterActionsController.init(); + refreshFooterVisibility(); } @Override @@ -96,12 +102,21 @@ public class QuickQSPanelController extends QSPanelControllerBase void setListening(boolean listening) { super.setListening(listening); mBrightnessController.setListening(listening); + mFooterActionsController.setListening(listening); } public boolean isListening() { return mView.isListening(); } + private void refreshFooterVisibility() { + if (mShouldUseSplitNotificationShade) { + mFooterActionsController.showFooter(); + } else { + mFooterActionsController.hideFooter(); + } + } + private void setMaxTiles(int parseNumTiles) { mView.setMaxTiles(parseNumTiles); setTiles(); @@ -116,6 +131,7 @@ public class QuickQSPanelController extends QSPanelControllerBase @Override protected void onScreenRotated() { mBrightnessController.refreshVisibility(mShouldUseSplitNotificationShade); + refreshFooterVisibility(); } @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 2de2d040f6e3e..386769cd399e4 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java +++ b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java @@ -26,9 +26,12 @@ import com.android.systemui.R; import com.android.systemui.battery.BatteryMeterView; import com.android.systemui.dagger.qualifiers.RootView; import com.android.systemui.plugins.qs.QS; +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; -import com.android.systemui.qs.QSFooterActionsView; import com.android.systemui.qs.QSFooterView; import com.android.systemui.qs.QSFooterViewController; import com.android.systemui.qs.QSFragment; @@ -50,6 +53,8 @@ import dagger.Provides; @Module public interface QSFragmentModule { 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"; /** @@ -123,8 +128,40 @@ public interface QSFragmentModule { /** */ @Provides - static QSFooterActionsView providesQSFooterActionsView(@RootView View view) { - return view.findViewById(R.id.qs_footer_actions_container); + @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(); } /** */ diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterActionsControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/FooterActionsControllerTest.kt similarity index 87% rename from packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterActionsControllerTest.kt rename to packages/SystemUI/tests/src/com/android/systemui/qs/FooterActionsControllerTest.kt index 9378b2be2945a..e54a6ec46b9c1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterActionsControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/FooterActionsControllerTest.kt @@ -12,6 +12,7 @@ import com.android.systemui.Dependency 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.statusbar.phone.MultiUserSwitchController import com.android.systemui.statusbar.policy.DeviceProvisionedController import com.android.systemui.statusbar.policy.UserInfoController @@ -29,7 +30,7 @@ import org.mockito.MockitoAnnotations import org.mockito.Mockito.`when` as whenever @SmallTest -class QSFooterActionsControllerTest : LeakCheckedTest() { +class FooterActionsControllerTest : LeakCheckedTest() { @Mock private lateinit var userManager: UserManager @Mock @@ -47,10 +48,10 @@ class QSFooterActionsControllerTest : LeakCheckedTest() { @Mock private lateinit var uiEventLogger: UiEventLogger @Mock - private lateinit var controller: QSFooterActionsController + private lateinit var controller: FooterActionsController private val metricsLogger: MetricsLogger = FakeMetricsLogger() - private lateinit var view: QSFooterActionsView + private lateinit var view: FooterActionsView private val falsingManager: FalsingManagerFake = FalsingManagerFake() @Before @@ -60,12 +61,13 @@ class QSFooterActionsControllerTest : LeakCheckedTest() { val fakeTunerService = Dependency.get(TunerService::class.java) as FakeTunerService view = LayoutInflater.from(context) - .inflate(R.layout.qs_footer_actions, null) as QSFooterActionsView + .inflate(R.layout.footer_actions, null) as FooterActionsView - controller = QSFooterActionsController(view, qsPanelController, activityStarter, + controller = FooterActionsController(view, qsPanelController, activityStarter, userManager, userInfoController, multiUserSwitchController, deviceProvisionedController, falsingManager, metricsLogger, fakeTunerService, - globalActionsDialog, uiEventLogger, showPMLiteButton = true) + globalActionsDialog, uiEventLogger, showPMLiteButton = true, + buttonsVisibleState = ExpansionState.EXPANDED) controller.init() controller.onViewAttached() } 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 8c6c358385ed9..8b19c50f915e0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterViewControllerTest.java @@ -59,7 +59,7 @@ public class QSFooterViewControllerTest extends LeakCheckedTest { @Mock private TextView mBuildText; @Mock - private QSFooterActionsController mQSFooterActionsController; + private FooterActionsController mFooterActionsController; private QSFooterViewController mController; @@ -79,7 +79,7 @@ public class QSFooterViewControllerTest extends LeakCheckedTest { when(mView.findViewById(R.id.build)).thenReturn(mBuildText); mController = new QSFooterViewController(mView, mUserTracker, mQSPanelController, - mQuickQSPanelController, mQSFooterActionsController); + mQuickQSPanelController, mFooterActionsController); 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 66a006fd4fbab..912bea2f4c970 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt @@ -68,6 +68,8 @@ class QuickQSPanelControllerTest : SysuiTestCase() { private lateinit var featureFlags: FeatureFlags @Mock private lateinit var quickQsBrightnessController: QuickQSBrightnessController + @Mock + private lateinit var footerActionsController: FooterActionsController private lateinit var controller: QuickQSPanelController @@ -90,7 +92,8 @@ class QuickQSPanelControllerTest : SysuiTestCase() { uiEventLogger, qsLogger, dumpManager, - quickQsBrightnessController + quickQsBrightnessController, + footerActionsController ) controller.init()