Merge "Showing action buttons in collapsed QS in split shade" into sc-v2-dev

This commit is contained in:
Michał Brzeziński
2021-08-11 17:59:24 +00:00
committed by Android (Google) Code Review
14 changed files with 297 additions and 69 deletions

View File

@@ -14,9 +14,10 @@
** See the License for the specific language governing permissions and ** See the License for the specific language governing permissions and
** limitations under the License. ** limitations under the License.
--> -->
<com.android.systemui.qs.QSFooterActionsView
<!-- 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:android="http://schemas.android.com/apk/res/android"
android:id="@+id/qs_footer_actions_container"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="48dp" android:layout_height="48dp"
android:gravity="center_vertical"> android:gravity="center_vertical">
@@ -101,4 +102,4 @@
</com.android.systemui.statusbar.AlphaOptimizedFrameLayout> </com.android.systemui.statusbar.AlphaOptimizedFrameLayout>
</com.android.systemui.qs.QSFooterActionsView> </com.android.systemui.qs.FooterActionsView>

View File

@@ -68,7 +68,8 @@
</LinearLayout> </LinearLayout>
<include layout="@layout/qs_footer_actions"/> <include layout="@layout/footer_actions"
android:id="@+id/qs_footer_actions"/>
</LinearLayout> </LinearLayout>

View File

@@ -56,7 +56,18 @@
android:clipToPadding="false" android:clipToPadding="false"
android:focusable="true" android:focusable="true"
android:paddingBottom="24dp" android:paddingBottom="24dp"
android:importantForAccessibility="yes" /> 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="16dp"
android:layout_marginStart="@dimen/qs_footer_margin"
android:layout_marginEnd="@dimen/qs_footer_margin"
/>
</com.android.systemui.qs.QuickQSPanel>
</RelativeLayout> </RelativeLayout>
</com.android.systemui.qs.QuickStatusBarHeader> </com.android.systemui.qs.QuickStatusBarHeader>

View File

@@ -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 package com.android.systemui.qs
import android.content.Intent import android.content.Intent
@@ -16,6 +32,8 @@ import com.android.systemui.animation.ActivityLaunchAnimator
import com.android.systemui.globalactions.GlobalActionsDialogLite import com.android.systemui.globalactions.GlobalActionsDialogLite
import com.android.systemui.plugins.ActivityStarter import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.plugins.FalsingManager 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.QSFlagsModule.PM_LITE_ENABLED
import com.android.systemui.statusbar.phone.MultiUserSwitchController import com.android.systemui.statusbar.phone.MultiUserSwitchController
import com.android.systemui.statusbar.phone.SettingsButton import com.android.systemui.statusbar.phone.SettingsButton
@@ -27,8 +45,13 @@ import com.android.systemui.util.ViewController
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Named 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 qsPanelController: QSPanelController,
private val activityStarter: ActivityStarter, private val activityStarter: ActivityStarter,
private val userManager: UserManager, private val userManager: UserManager,
@@ -40,15 +63,20 @@ class QSFooterActionsController @Inject constructor(
private val tunerService: TunerService, private val tunerService: TunerService,
private val globalActionsDialog: GlobalActionsDialogLite, private val globalActionsDialog: GlobalActionsDialogLite,
private val uiEventLogger: UiEventLogger, private val uiEventLogger: UiEventLogger,
@Named(PM_LITE_ENABLED) private val showPMLiteButton: Boolean @Named(PM_LITE_ENABLED) private val showPMLiteButton: Boolean,
) : ViewController<QSFooterActionsView>(view) { private val buttonsVisibleState: ExpansionState
) : ViewController<FooterActionsView>(view) {
enum class ExpansionState { COLLAPSED, EXPANDED }
private var listening: Boolean = false private var listening: Boolean = false
var expanded = false var expanded = false
set(value) { set(value) {
if (field != value) {
field = value field = value
mView.setExpanded(value, isTunerEnabled(), updateView()
multiUserSwitchController.isMultiUserEnabled) }
} }
private val settingsButton: SettingsButton = view.findViewById(R.id.settings_button) private val settingsButton: SettingsButton = view.findViewById(R.id.settings_button)
@@ -64,7 +92,7 @@ class QSFooterActionsController @Inject constructor(
private val onClickListener = View.OnClickListener { v -> private val onClickListener = View.OnClickListener { v ->
// Don't do anything until views are unhidden. Don't do anything if the tap looks // Don't do anything until views are unhidden. Don't do anything if the tap looks
// suspicious. // suspicious.
if (!expanded || falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) { if (!buttonsVisible() || falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
return@OnClickListener return@OnClickListener
} }
if (v === settingsButton) { 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() { override fun onInit() {
multiUserSwitchController.init() multiUserSwitchController.init()
} }
fun hideFooter() {
mView.visibility = View.GONE
}
fun showFooter() {
mView.visibility = View.VISIBLE
updateView()
}
private fun startSettingsActivity() { private fun startSettingsActivity() {
val animationController = settingsButtonContainer?.let { val animationController = settingsButtonContainer?.let {
ActivityLaunchAnimator.Controller.fromView( ActivityLaunchAnimator.Controller.fromView(
@@ -128,7 +172,12 @@ class QSFooterActionsController @Inject constructor(
activityStarter.postQSRunnableDismissingKeyguard { qsPanelController.showEdit(view) } activityStarter.postQSRunnableDismissingKeyguard { qsPanelController.showEdit(view) }
}) })
mView.updateEverything(isTunerEnabled(), multiUserSwitchController.isMultiUserEnabled) updateView()
}
private fun updateView() {
mView.updateEverything(buttonsVisible(), isTunerEnabled(),
multiUserSwitchController.isMultiUserEnabled)
} }
override fun onViewDetached() { override fun onViewDetached() {
@@ -148,7 +197,8 @@ class QSFooterActionsController @Inject constructor(
} }
fun disable(state2: Int) { fun disable(state2: Int) {
mView.disable(state2, isTunerEnabled(), multiUserSwitchController.isMultiUserEnabled) mView.disable(buttonsVisible(), state2, isTunerEnabled(),
multiUserSwitchController.isMultiUserEnabled)
} }
fun setExpansion(headerExpansionFraction: Float) { fun setExpansion(headerExpansionFraction: Float) {

View File

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

View File

@@ -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, * 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 * 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 settingsContainer: View
private lateinit var settingsButton: SettingsButton private lateinit var settingsButton: SettingsButton
private lateinit var multiUserSwitch: MultiUserSwitch private lateinit var multiUserSwitch: MultiUserSwitch
@@ -48,7 +48,6 @@ class QSFooterActionsView(context: Context?, attrs: AttributeSet?) : LinearLayou
private var settingsCogAnimator: TouchAnimator? = null private var settingsCogAnimator: TouchAnimator? = null
private var qsDisabled = false private var qsDisabled = false
private var isExpanded = false
private var expansionAmount = 0f private var expansionAmount = 0f
override fun onFinishInflate() { override fun onFinishInflate() {
@@ -102,27 +101,30 @@ class QSFooterActionsView(context: Context?, attrs: AttributeSet?) : LinearLayou
setExpansion(expansionAmount) setExpansion(expansionAmount)
} }
fun setExpanded(expanded: Boolean, isTunerEnabled: Boolean, multiUserEnabled: Boolean) {
if (isExpanded == expanded) return
isExpanded = expanded
updateEverything(isTunerEnabled, multiUserEnabled)
}
fun setExpansion(headerExpansionFraction: Float) { fun setExpansion(headerExpansionFraction: Float) {
expansionAmount = headerExpansionFraction expansionAmount = headerExpansionFraction
if (settingsCogAnimator != null) settingsCogAnimator!!.setPosition(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 val disabled = state2 and StatusBarManager.DISABLE2_QUICK_SETTINGS != 0
if (disabled == qsDisabled) return if (disabled == qsDisabled) return
qsDisabled = disabled qsDisabled = disabled
updateEverything(isTunerEnabled, multiUserEnabled) updateEverything(buttonsVisible, isTunerEnabled, multiUserEnabled)
} }
fun updateEverything(isTunerEnabled: Boolean, multiUserEnabled: Boolean) { fun updateEverything(
buttonsVisible: Boolean,
isTunerEnabled: Boolean,
multiUserEnabled: Boolean
) {
post { post {
updateVisibilities(isTunerEnabled, multiUserEnabled) updateVisibilities(buttonsVisible, isTunerEnabled, multiUserEnabled)
updateClickabilities() updateClickabilities()
isClickable = false isClickable = false
} }
@@ -134,16 +136,16 @@ class QSFooterActionsView(context: Context?, attrs: AttributeSet?) : LinearLayou
settingsButton.isClickable = settingsButton.visibility == VISIBLE 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 settingsContainer.visibility = if (qsDisabled) GONE else VISIBLE
tunerIcon.visibility = if (isTunerEnabled) VISIBLE else INVISIBLE 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) val isDemo = UserManager.isDeviceInDemoMode(context)
settingsButton.visibility = if (isDemo || !isExpanded) INVISIBLE else VISIBLE settingsButton.visibility = if (isDemo || !buttonsVisible) INVISIBLE else VISIBLE
}
private fun showUserSwitcher(multiUserEnabled: Boolean): Boolean {
return isExpanded && multiUserEnabled
} }
fun onUserInfoChanged(picture: Drawable?, isGuestUser: Boolean) { fun onUserInfoChanged(picture: Drawable?, isGuestUser: Boolean) {

View File

@@ -14,6 +14,9 @@
package com.android.systemui.qs; 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.TimeInterpolator;
import android.animation.ValueAnimator; import android.animation.ValueAnimator;
import android.util.Log; import android.util.Log;
@@ -43,6 +46,7 @@ import java.util.List;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named;
/** */ /** */
@QSScope @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, * position to the normal QS panel. These views will only show once the animation is complete,
* to prevent overlapping of semi transparent views * to prevent overlapping of semi transparent views
*/ */
private final ArrayList<View> mQuickQsViews = new ArrayList<>(); private final ArrayList<View> mAnimatedQsViews = new ArrayList<>();
private final QuickQSPanel mQuickQsPanel; private final QuickQSPanel mQuickQsPanel;
private final QSPanelController mQsPanelController; private final QSPanelController mQsPanelController;
private final QuickQSPanelController mQuickQSPanelController; private final QuickQSPanelController mQuickQSPanelController;
private final QuickStatusBarHeader mQuickStatusBarHeader; private final QuickStatusBarHeader mQuickStatusBarHeader;
private final QSSecurityFooter mSecurityFooter; private final QSSecurityFooter mSecurityFooter;
private final QS mQs; private final QS mQs;
private final View mQSFooterActions;
private final View mQQSFooterActions;
private PagedTileLayout mPagedLayout; private PagedTileLayout mPagedLayout;
@@ -88,6 +94,7 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
// This animates fading of SecurityFooter and media divider // This animates fading of SecurityFooter and media divider
private TouchAnimator mAllPagesDelayedAnimator; private TouchAnimator mAllPagesDelayedAnimator;
private TouchAnimator mBrightnessAnimator; private TouchAnimator mBrightnessAnimator;
private TouchAnimator mQQSFooterActionsAnimator;
private HeightExpansionAnimator mQQSTileHeightAnimator; private HeightExpansionAnimator mQQSTileHeightAnimator;
private HeightExpansionAnimator mOtherTilesExpandAnimator; private HeightExpansionAnimator mOtherTilesExpandAnimator;
@@ -110,12 +117,16 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
QSPanelController qsPanelController, QSPanelController qsPanelController,
QuickQSPanelController quickQSPanelController, QSTileHost qsTileHost, QuickQSPanelController quickQSPanelController, QSTileHost qsTileHost,
QSSecurityFooter securityFooter, @Main Executor executor, TunerService tunerService, QSSecurityFooter securityFooter, @Main Executor executor, TunerService tunerService,
QSExpansionPathInterpolator qsExpansionPathInterpolator) { QSExpansionPathInterpolator qsExpansionPathInterpolator,
@Named(QS_FOOTER) FooterActionsView qsFooterActionsView,
@Named(QQS_FOOTER) FooterActionsView qqsFooterActionsView) {
mQs = qs; mQs = qs;
mQuickQsPanel = quickPanel; mQuickQsPanel = quickPanel;
mQsPanelController = qsPanelController; mQsPanelController = qsPanelController;
mQuickQSPanelController = quickQSPanelController; mQuickQSPanelController = quickQSPanelController;
mQuickStatusBarHeader = quickStatusBarHeader; mQuickStatusBarHeader = quickStatusBarHeader;
mQQSFooterActions = qqsFooterActionsView;
mQSFooterActions = qsFooterActionsView;
mSecurityFooter = securityFooter; mSecurityFooter = securityFooter;
mHost = qsTileHost; mHost = qsTileHost;
mExecutor = executor; mExecutor = executor;
@@ -262,7 +273,7 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
clearAnimationState(); clearAnimationState();
mAllViews.clear(); mAllViews.clear();
mQuickQsViews.clear(); mAnimatedQsViews.clear();
mQQSTileHeightAnimator = null; mQQSTileHeightAnimator = null;
mOtherTilesExpandAnimator = null; mOtherTilesExpandAnimator = null;
@@ -360,7 +371,7 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
firstPageBuilder.addFloat(quickTileView.getSecondaryLabel(), "alpha", 0, 1); firstPageBuilder.addFloat(quickTileView.getSecondaryLabel(), "alpha", 0, 1);
mQuickQsViews.add(tileView); mAnimatedQsViews.add(tileView);
mAllViews.add(quickTileView); mAllViews.add(quickTileView);
mAllViews.add(quickTileView.getSecondaryLabel()); mAllViews.add(quickTileView.getSecondaryLabel());
} else if (mFullRows && isIconInAnimatedRow(count)) { } else if (mFullRows && isIconInAnimatedRow(count)) {
@@ -417,6 +428,13 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
.addFloat(tileLayout, "alpha", 0, 1); .addFloat(tileLayout, "alpha", 0, 1);
mFirstPageDelayedAnimator = builder.build(); 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 // Fade in the security footer and the divider as we reach the final position
builder = new Builder().setStartDelay(EXPANDED_TILE_DELAY); builder = new Builder().setStartDelay(EXPANDED_TILE_DELAY);
builder.addFloat(mSecurityFooter.getView(), "alpha", 0, 1); 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(); .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) { private boolean isIconInAnimatedRow(int count) {
if (mPagedLayout == null) { if (mPagedLayout == null) {
return false; return false;
@@ -521,6 +553,9 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
if (mBrightnessAnimator != null) { if (mBrightnessAnimator != null) {
mBrightnessAnimator.setPosition(position); mBrightnessAnimator.setPosition(position);
} }
if (mQQSFooterActionsAnimator != null) {
mQQSFooterActionsAnimator.setPosition(position);
}
} }
} }
@@ -532,9 +567,9 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
@Override @Override
public void onAnimationAtEnd() { public void onAnimationAtEnd() {
mQuickQsPanel.setVisibility(View.INVISIBLE); mQuickQsPanel.setVisibility(View.INVISIBLE);
final int N = mQuickQsViews.size(); final int N = mAnimatedQsViews.size();
for (int i = 0; i < N; i++) { 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() { public void onAnimationStarted() {
updateQQSVisibility(); updateQQSVisibility();
if (mOnFirstPage) { if (mOnFirstPage) {
final int N = mQuickQsViews.size(); final int N = mAnimatedQsViews.size();
for (int i = 0; i < N; i++) { 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) { if (mOtherTilesExpandAnimator != null) {
mOtherTilesExpandAnimator.resetViewsHeights(); mOtherTilesExpandAnimator.resetViewsHeights();
} }
final int N2 = mQuickQsViews.size(); final int N2 = mAnimatedQsViews.size();
for (int i = 0; i < N2; i++) { for (int i = 0; i < N2; i++) {
mQuickQsViews.get(i).setVisibility(View.VISIBLE); mAnimatedQsViews.get(i).setVisibility(View.VISIBLE);
} }
} }

View File

@@ -41,7 +41,7 @@ import com.android.systemui.R;
/** /**
* Footer of expanded Quick Settings, tiles page indicator, (optionally) build number and * Footer of expanded Quick Settings, tiles page indicator, (optionally) build number and
* {@link QSFooterActionsView} * {@link FooterActionsView}
*/ */
public class QSFooterView extends FrameLayout { public class QSFooterView extends FrameLayout {
private PageIndicator mPageIndicator; private PageIndicator mPageIndicator;
@@ -75,7 +75,7 @@ public class QSFooterView extends FrameLayout {
protected void onFinishInflate() { protected void onFinishInflate() {
super.onFinishInflate(); super.onFinishInflate();
mPageIndicator = findViewById(R.id.footer_page_indicator); 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); mBuildText = findViewById(R.id.build);
updateResources(); updateResources();

View File

@@ -16,6 +16,8 @@
package com.android.systemui.qs; package com.android.systemui.qs;
import static com.android.systemui.qs.dagger.QSFragmentModule.QS_FOOTER;
import android.content.ClipData; import android.content.ClipData;
import android.content.ClipboardManager; import android.content.ClipboardManager;
import android.text.TextUtils; import android.text.TextUtils;
@@ -29,6 +31,7 @@ import com.android.systemui.settings.UserTracker;
import com.android.systemui.util.ViewController; import com.android.systemui.util.ViewController;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named;
/** /**
* Controller for {@link QSFooterView}. * Controller for {@link QSFooterView}.
@@ -39,7 +42,7 @@ public class QSFooterViewController extends ViewController<QSFooterView> impleme
private final UserTracker mUserTracker; private final UserTracker mUserTracker;
private final QSPanelController mQsPanelController; private final QSPanelController mQsPanelController;
private final QuickQSPanelController mQuickQSPanelController; private final QuickQSPanelController mQuickQSPanelController;
private final QSFooterActionsController mQsFooterActionsController; private final FooterActionsController mFooterActionsController;
private final TextView mBuildText; private final TextView mBuildText;
private final PageIndicator mPageIndicator; private final PageIndicator mPageIndicator;
@@ -48,12 +51,12 @@ public class QSFooterViewController extends ViewController<QSFooterView> impleme
UserTracker userTracker, UserTracker userTracker,
QSPanelController qsPanelController, QSPanelController qsPanelController,
QuickQSPanelController quickQSPanelController, QuickQSPanelController quickQSPanelController,
QSFooterActionsController qsFooterActionsController) { @Named(QS_FOOTER) FooterActionsController footerActionsController) {
super(view); super(view);
mUserTracker = userTracker; mUserTracker = userTracker;
mQsPanelController = qsPanelController; mQsPanelController = qsPanelController;
mQuickQSPanelController = quickQSPanelController; mQuickQSPanelController = quickQSPanelController;
mQsFooterActionsController = qsFooterActionsController; mFooterActionsController = footerActionsController;
mBuildText = mView.findViewById(R.id.build); mBuildText = mView.findViewById(R.id.build);
mPageIndicator = mView.findViewById(R.id.footer_page_indicator); mPageIndicator = mView.findViewById(R.id.footer_page_indicator);
@@ -62,7 +65,7 @@ public class QSFooterViewController extends ViewController<QSFooterView> impleme
@Override @Override
protected void onInit() { protected void onInit() {
super.onInit(); super.onInit();
mQsFooterActionsController.init(); mFooterActionsController.init();
} }
@Override @Override
@@ -70,7 +73,7 @@ public class QSFooterViewController extends ViewController<QSFooterView> impleme
mView.addOnLayoutChangeListener( mView.addOnLayoutChangeListener(
(v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> { (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
mView.updateExpansion(); mView.updateExpansion();
mQsFooterActionsController.updateAnimator(right - left, mFooterActionsController.updateAnimator(right - left,
mQuickQSPanelController.getNumQuickTiles()); mQuickQSPanelController.getNumQuickTiles());
} }
); );
@@ -104,25 +107,25 @@ public class QSFooterViewController extends ViewController<QSFooterView> impleme
@Override @Override
public void setExpanded(boolean expanded) { public void setExpanded(boolean expanded) {
mQsFooterActionsController.setExpanded(expanded); mFooterActionsController.setExpanded(expanded);
mView.setExpanded(expanded); mView.setExpanded(expanded);
} }
@Override @Override
public void setExpansion(float expansion) { public void setExpansion(float expansion) {
mView.setExpansion(expansion); mView.setExpansion(expansion);
mQsFooterActionsController.setExpansion(expansion); mFooterActionsController.setExpansion(expansion);
} }
@Override @Override
public void setListening(boolean listening) { public void setListening(boolean listening) {
mQsFooterActionsController.setListening(listening); mFooterActionsController.setListening(listening);
} }
@Override @Override
public void setKeyguardShowing(boolean keyguardShowing) { public void setKeyguardShowing(boolean keyguardShowing) {
mView.setKeyguardShowing(); mView.setKeyguardShowing();
mQsFooterActionsController.setKeyguardShowing(); mFooterActionsController.setKeyguardShowing();
} }
/** */ /** */
@@ -134,6 +137,6 @@ public class QSFooterViewController extends ViewController<QSFooterView> impleme
@Override @Override
public void disable(int state1, int state2, boolean animate) { public void disable(int state1, int state2, boolean animate) {
mView.disable(state2); mView.disable(state2);
mQsFooterActionsController.disable(state2); mFooterActionsController.disable(state2);
} }
} }

View File

@@ -17,6 +17,7 @@
package com.android.systemui.qs; package com.android.systemui.qs;
import static com.android.systemui.media.dagger.MediaModule.QUICK_QS_PANEL; 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 static com.android.systemui.qs.dagger.QSFragmentModule.QS_USING_MEDIA_PLAYER;
import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.MetricsLogger;
@@ -53,6 +54,7 @@ public class QuickQSPanelController extends QSPanelControllerBase<QuickQSPanel>
// brightness is visible only in split shade // brightness is visible only in split shade
private final QuickQSBrightnessController mBrightnessController; private final QuickQSBrightnessController mBrightnessController;
private final BrightnessMirrorHandler mBrightnessMirrorHandler; private final BrightnessMirrorHandler mBrightnessMirrorHandler;
private final FooterActionsController mFooterActionsController;
@Inject @Inject
QuickQSPanelController(QuickQSPanel view, QSTileHost qsTileHost, QuickQSPanelController(QuickQSPanel view, QSTileHost qsTileHost,
@@ -61,12 +63,14 @@ public class QuickQSPanelController extends QSPanelControllerBase<QuickQSPanel>
@Named(QUICK_QS_PANEL) MediaHost mediaHost, @Named(QUICK_QS_PANEL) MediaHost mediaHost,
MetricsLogger metricsLogger, UiEventLogger uiEventLogger, QSLogger qsLogger, MetricsLogger metricsLogger, UiEventLogger uiEventLogger, QSLogger qsLogger,
DumpManager dumpManager, DumpManager dumpManager,
QuickQSBrightnessController quickQSBrightnessController QuickQSBrightnessController quickQSBrightnessController,
@Named(QQS_FOOTER) FooterActionsController footerActionsController
) { ) {
super(view, qsTileHost, qsCustomizerController, usingMediaPlayer, mediaHost, metricsLogger, super(view, qsTileHost, qsCustomizerController, usingMediaPlayer, mediaHost, metricsLogger,
uiEventLogger, qsLogger, dumpManager); uiEventLogger, qsLogger, dumpManager);
mBrightnessController = quickQSBrightnessController; mBrightnessController = quickQSBrightnessController;
mBrightnessMirrorHandler = new BrightnessMirrorHandler(mBrightnessController); mBrightnessMirrorHandler = new BrightnessMirrorHandler(mBrightnessController);
mFooterActionsController = footerActionsController;
} }
@Override @Override
@@ -76,6 +80,8 @@ public class QuickQSPanelController extends QSPanelControllerBase<QuickQSPanel>
mMediaHost.setShowsOnlyActiveMedia(true); mMediaHost.setShowsOnlyActiveMedia(true);
mMediaHost.init(MediaHierarchyManager.LOCATION_QQS); mMediaHost.init(MediaHierarchyManager.LOCATION_QQS);
mBrightnessController.init(mShouldUseSplitNotificationShade); mBrightnessController.init(mShouldUseSplitNotificationShade);
mFooterActionsController.init();
refreshFooterVisibility();
} }
@Override @Override
@@ -96,12 +102,21 @@ public class QuickQSPanelController extends QSPanelControllerBase<QuickQSPanel>
void setListening(boolean listening) { void setListening(boolean listening) {
super.setListening(listening); super.setListening(listening);
mBrightnessController.setListening(listening); mBrightnessController.setListening(listening);
mFooterActionsController.setListening(listening);
} }
public boolean isListening() { public boolean isListening() {
return mView.isListening(); return mView.isListening();
} }
private void refreshFooterVisibility() {
if (mShouldUseSplitNotificationShade) {
mFooterActionsController.showFooter();
} else {
mFooterActionsController.hideFooter();
}
}
private void setMaxTiles(int parseNumTiles) { private void setMaxTiles(int parseNumTiles) {
mView.setMaxTiles(parseNumTiles); mView.setMaxTiles(parseNumTiles);
setTiles(); setTiles();
@@ -116,6 +131,7 @@ public class QuickQSPanelController extends QSPanelControllerBase<QuickQSPanel>
@Override @Override
protected void onScreenRotated() { protected void onScreenRotated() {
mBrightnessController.refreshVisibility(mShouldUseSplitNotificationShade); mBrightnessController.refreshVisibility(mShouldUseSplitNotificationShade);
refreshFooterVisibility();
} }
@Override @Override

View File

@@ -26,9 +26,12 @@ import com.android.systemui.R;
import com.android.systemui.battery.BatteryMeterView; import com.android.systemui.battery.BatteryMeterView;
import com.android.systemui.dagger.qualifiers.RootView; import com.android.systemui.dagger.qualifiers.RootView;
import com.android.systemui.plugins.qs.QS; 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.QSContainerImpl;
import com.android.systemui.qs.QSFooter; import com.android.systemui.qs.QSFooter;
import com.android.systemui.qs.QSFooterActionsView;
import com.android.systemui.qs.QSFooterView; import com.android.systemui.qs.QSFooterView;
import com.android.systemui.qs.QSFooterViewController; import com.android.systemui.qs.QSFooterViewController;
import com.android.systemui.qs.QSFragment; import com.android.systemui.qs.QSFragment;
@@ -50,6 +53,8 @@ import dagger.Provides;
@Module @Module
public interface QSFragmentModule { public interface QSFragmentModule {
String QS_SECURITY_FOOTER_VIEW = "qs_security_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"; String QS_USING_MEDIA_PLAYER = "qs_using_media_player";
/** /**
@@ -123,8 +128,40 @@ public interface QSFragmentModule {
/** */ /** */
@Provides @Provides
static QSFooterActionsView providesQSFooterActionsView(@RootView View view) { @Named(QS_FOOTER)
return view.findViewById(R.id.qs_footer_actions_container); 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();
} }
/** */ /** */

View File

@@ -12,6 +12,7 @@ import com.android.systemui.Dependency
import com.android.systemui.classifier.FalsingManagerFake import com.android.systemui.classifier.FalsingManagerFake
import com.android.systemui.globalactions.GlobalActionsDialogLite import com.android.systemui.globalactions.GlobalActionsDialogLite
import com.android.systemui.plugins.ActivityStarter 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.phone.MultiUserSwitchController
import com.android.systemui.statusbar.policy.DeviceProvisionedController import com.android.systemui.statusbar.policy.DeviceProvisionedController
import com.android.systemui.statusbar.policy.UserInfoController import com.android.systemui.statusbar.policy.UserInfoController
@@ -29,7 +30,7 @@ import org.mockito.MockitoAnnotations
import org.mockito.Mockito.`when` as whenever import org.mockito.Mockito.`when` as whenever
@SmallTest @SmallTest
class QSFooterActionsControllerTest : LeakCheckedTest() { class FooterActionsControllerTest : LeakCheckedTest() {
@Mock @Mock
private lateinit var userManager: UserManager private lateinit var userManager: UserManager
@Mock @Mock
@@ -47,10 +48,10 @@ class QSFooterActionsControllerTest : LeakCheckedTest() {
@Mock @Mock
private lateinit var uiEventLogger: UiEventLogger private lateinit var uiEventLogger: UiEventLogger
@Mock @Mock
private lateinit var controller: QSFooterActionsController private lateinit var controller: FooterActionsController
private val metricsLogger: MetricsLogger = FakeMetricsLogger() private val metricsLogger: MetricsLogger = FakeMetricsLogger()
private lateinit var view: QSFooterActionsView private lateinit var view: FooterActionsView
private val falsingManager: FalsingManagerFake = FalsingManagerFake() private val falsingManager: FalsingManagerFake = FalsingManagerFake()
@Before @Before
@@ -60,12 +61,13 @@ class QSFooterActionsControllerTest : LeakCheckedTest() {
val fakeTunerService = Dependency.get(TunerService::class.java) as FakeTunerService val fakeTunerService = Dependency.get(TunerService::class.java) as FakeTunerService
view = LayoutInflater.from(context) 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, userManager, userInfoController, multiUserSwitchController,
deviceProvisionedController, falsingManager, metricsLogger, fakeTunerService, deviceProvisionedController, falsingManager, metricsLogger, fakeTunerService,
globalActionsDialog, uiEventLogger, showPMLiteButton = true) globalActionsDialog, uiEventLogger, showPMLiteButton = true,
buttonsVisibleState = ExpansionState.EXPANDED)
controller.init() controller.init()
controller.onViewAttached() controller.onViewAttached()
} }

View File

@@ -59,7 +59,7 @@ public class QSFooterViewControllerTest extends LeakCheckedTest {
@Mock @Mock
private TextView mBuildText; private TextView mBuildText;
@Mock @Mock
private QSFooterActionsController mQSFooterActionsController; private FooterActionsController mFooterActionsController;
private QSFooterViewController mController; private QSFooterViewController mController;
@@ -79,7 +79,7 @@ public class QSFooterViewControllerTest extends LeakCheckedTest {
when(mView.findViewById(R.id.build)).thenReturn(mBuildText); when(mView.findViewById(R.id.build)).thenReturn(mBuildText);
mController = new QSFooterViewController(mView, mUserTracker, mQSPanelController, mController = new QSFooterViewController(mView, mUserTracker, mQSPanelController,
mQuickQSPanelController, mQSFooterActionsController); mQuickQSPanelController, mFooterActionsController);
mController.init(); mController.init();
} }

View File

@@ -68,6 +68,8 @@ class QuickQSPanelControllerTest : SysuiTestCase() {
private lateinit var featureFlags: FeatureFlags private lateinit var featureFlags: FeatureFlags
@Mock @Mock
private lateinit var quickQsBrightnessController: QuickQSBrightnessController private lateinit var quickQsBrightnessController: QuickQSBrightnessController
@Mock
private lateinit var footerActionsController: FooterActionsController
private lateinit var controller: QuickQSPanelController private lateinit var controller: QuickQSPanelController
@@ -90,7 +92,8 @@ class QuickQSPanelControllerTest : SysuiTestCase() {
uiEventLogger, uiEventLogger,
qsLogger, qsLogger,
dumpManager, dumpManager,
quickQsBrightnessController quickQsBrightnessController,
footerActionsController
) )
controller.init() controller.init()