Create QS footer entry point for fgs manager

Bug: 201579707
Test: `atest SystemUITests`

Change-Id: If393e54f5b5ed24123365836f5c0554899730a31
This commit is contained in:
Evan Severson
2022-01-19 11:01:53 -08:00
parent 8b0657c489
commit 5e147cc424
7 changed files with 170 additions and 5 deletions

View File

@@ -2345,6 +2345,11 @@
<!-- Title for User Switch dialog. [CHAR LIMIT=20] -->
<string name="qs_user_switch_dialog_title">Select user</string>
<!-- Label for the entry point to open the dialog which shows currently running applications [CHAR LIMIT=NONE]-->
<plurals name="fgs_manager_footer_label">
<item quantity="one"><xliff:g id="count" example="1">%s</xliff:g> app running in the background</item>
<item quantity="other"><xliff:g id="count" example="2">%s</xliff:g> apps running in the background</item>
</plurals>
<!-- Title for dialog listing applications currently running in the backing [CHAR LIMIT=NONE]-->
<string name="fgs_manager_dialog_title">Apps running in the background</string>
<!-- Label of the button to stop the app from running in the background [CHAR LIMIT=12]-->

View File

@@ -85,6 +85,7 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
private final QSPanelController mQsPanelController;
private final QuickQSPanelController mQuickQSPanelController;
private final QuickStatusBarHeader mQuickStatusBarHeader;
private final QSFgsManagerFooter mFgsManagerFooter;
private final QSSecurityFooter mSecurityFooter;
private final QS mQs;
private final View mQSFooterActions;
@@ -151,7 +152,8 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
public QSAnimator(QS qs, QuickQSPanel quickPanel, QuickStatusBarHeader quickStatusBarHeader,
QSPanelController qsPanelController,
QuickQSPanelController quickQSPanelController, QSTileHost qsTileHost,
QSSecurityFooter securityFooter, @Main Executor executor, TunerService tunerService,
QSFgsManagerFooter fgsManagerFooter, QSSecurityFooter securityFooter,
@Main Executor executor, TunerService tunerService,
QSExpansionPathInterpolator qsExpansionPathInterpolator,
@Named(QS_FOOTER) FooterActionsView qsFooterActionsView,
@Named(QQS_FOOTER) FooterActionsView qqsFooterActionsView) {
@@ -162,6 +164,7 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
mQuickStatusBarHeader = quickStatusBarHeader;
mQQSFooterActions = qqsFooterActionsView;
mQSFooterActions = qsFooterActionsView;
mFgsManagerFooter = fgsManagerFooter;
mSecurityFooter = securityFooter;
mHost = qsTileHost;
mExecutor = executor;
@@ -481,6 +484,7 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
// 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);
builder.addFloat(mSecurityFooter.getView(), "alpha", 0, 1);
if (mQsPanelController.shouldUseHorizontalLayout()
&& mQsPanelController.mMediaHost.hostView != null) {
@@ -490,6 +494,7 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
mQsPanelController.mMediaHost.hostView.setAlpha(1.0f);
}
mAllPagesDelayedAnimator = builder.build();
mAllViews.add(mFgsManagerFooter.getView());
mAllViews.add(mSecurityFooter.getView());
translationYBuilder.setInterpolator(mQSExpansionPathInterpolator.getYInterpolator());
qqsTranslationYBuilder.setInterpolator(mQSExpansionPathInterpolator.getYInterpolator());

View File

@@ -0,0 +1,117 @@
/*
* 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.
*/
package com.android.systemui.qs;
import static android.provider.DeviceConfig.NAMESPACE_SYSTEMUI;
import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.TASK_MANAGER_ENABLED;
import static com.android.systemui.qs.dagger.QSFragmentModule.QS_FGS_MANAGER_FOOTER_VIEW;
import android.content.Context;
import android.provider.DeviceConfig;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import com.android.systemui.R;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.fgsmanager.FgsManagerDialogFactory;
import com.android.systemui.statusbar.policy.RunningFgsController;
import java.util.concurrent.Executor;
import javax.inject.Inject;
import javax.inject.Named;
/**
* Footer entry point for the foreground service manager
*/
public class QSFgsManagerFooter implements View.OnClickListener {
private final View mRootView;
private final TextView mFooterText;
private final Context mContext;
private final Executor mMainExecutor;
private final Executor mExecutor;
private final RunningFgsController mRunningFgsController;
private final FgsManagerDialogFactory mFgsManagerDialogFactory;
private boolean mIsInitialized = false;
private boolean mIsAvailable = false;
@Inject
QSFgsManagerFooter(@Named(QS_FGS_MANAGER_FOOTER_VIEW) View rootView,
@Main Executor mainExecutor, RunningFgsController runningFgsController,
@Background Executor executor,
FgsManagerDialogFactory fgsManagerDialogFactory) {
mRootView = rootView;
mFooterText = mRootView.findViewById(R.id.footer_text);
ImageView icon = mRootView.findViewById(R.id.primary_footer_icon);
icon.setImageResource(R.drawable.ic_info_outline);
mContext = rootView.getContext();
mMainExecutor = mainExecutor;
mExecutor = executor;
mRunningFgsController = runningFgsController;
mFgsManagerDialogFactory = fgsManagerDialogFactory;
}
public void init() {
if (mIsInitialized) {
return;
}
mRootView.setOnClickListener(this);
mRunningFgsController.addCallback(packages -> refreshState());
DeviceConfig.addOnPropertiesChangedListener(NAMESPACE_SYSTEMUI, mExecutor,
(DeviceConfig.OnPropertiesChangedListener) properties -> {
mIsAvailable = properties.getBoolean(TASK_MANAGER_ENABLED, mIsAvailable);
});
mIsAvailable = DeviceConfig.getBoolean(NAMESPACE_SYSTEMUI, TASK_MANAGER_ENABLED, false);
mIsInitialized = true;
}
@Override
public void onClick(View view) {
mFgsManagerDialogFactory.create(mRootView);
}
public void refreshState() {
mExecutor.execute(this::handleRefreshState);
}
public View getView() {
return mRootView;
}
private boolean isAvailable() {
return mIsAvailable;
}
public void handleRefreshState() {
int numPackages = mRunningFgsController.getPackagesWithFgs().size();
mMainExecutor.execute(() -> {
mFooterText.setText(mContext.getResources().getQuantityString(
R.plurals.fgs_manager_footer_label, numPackages, numPackages));
mRootView.setVisibility(numPackages > 0 && isAvailable() ? View.VISIBLE : View.GONE);
});
}
}

View File

@@ -85,6 +85,8 @@ public class QSPanel extends LinearLayout implements Tunable {
private final List<OnConfigurationChangedListener> mOnConfigurationChangedListeners =
new ArrayList<>();
@Nullable
protected View mFgsManagerFooter;
@Nullable
protected View mSecurityFooter;
@@ -448,7 +450,12 @@ public class QSPanel extends LinearLayout implements Tunable {
switchToParent(mSecurityFooter, mHeaderContainer, 0);
} else {
// Add after the footer
int index = indexOfChild(mFooter);
int index;
if (mFgsManagerFooter != null) {
index = indexOfChild(mFgsManagerFooter);
} else {
index = indexOfChild(mFooter);
}
switchToParent(mSecurityFooter, this, index + 1);
}
}
@@ -722,6 +729,17 @@ public class QSPanel extends LinearLayout implements Tunable {
switchSecurityFooter(shouldUseSplitNotificationShade);
}
/**
* Set the fgs manager footer view and switch it into the right place
* @param view the view in question
*/
public void setFgsManagerFooter(View view) {
mFgsManagerFooter = view;
// Add after the footer
int index = indexOfChild(mFooter);
switchToParent(mFgsManagerFooter, this, index + 1);
}
protected void setPageMargin(int pageMargin) {
if (mTileLayout instanceof PagedTileLayout) {
((PagedTileLayout) mTileLayout).setPageMargin(pageMargin);

View File

@@ -57,6 +57,7 @@ import javax.inject.Named;
public class QSPanelController extends QSPanelControllerBase<QSPanel> {
public static final String QS_REMOVE_LABELS = "sysui_remove_labels";
private final QSFgsManagerFooter mQSFgsManagerFooter;
private final QSSecurityFooter mQsSecurityFooter;
private final TunerService mTunerService;
private final QSCustomizerController mQsCustomizerController;
@@ -94,7 +95,8 @@ public class QSPanelController extends QSPanelControllerBase<QSPanel> {
};
@Inject
QSPanelController(QSPanel view, QSSecurityFooter qsSecurityFooter, TunerService tunerService,
QSPanelController(QSPanel view, QSFgsManagerFooter qsFgsManagerFooter,
QSSecurityFooter qsSecurityFooter, TunerService tunerService,
QSTileHost qstileHost, QSCustomizerController qsCustomizerController,
@Named(QS_USING_MEDIA_PLAYER) boolean usingMediaPlayer,
@Named(QS_PANEL) MediaHost mediaHost,
@@ -105,6 +107,7 @@ public class QSPanelController extends QSPanelControllerBase<QSPanel> {
FalsingManager falsingManager, CommandQueue commandQueue) {
super(view, qstileHost, qsCustomizerController, usingMediaPlayer, mediaHost,
metricsLogger, uiEventLogger, qsLogger, dumpManager);
mQSFgsManagerFooter = qsFgsManagerFooter;
mQsSecurityFooter = qsSecurityFooter;
mTunerService = tunerService;
mQsCustomizerController = qsCustomizerController;
@@ -128,6 +131,7 @@ public class QSPanelController extends QSPanelControllerBase<QSPanel> {
mMediaHost.init(MediaHierarchyManager.LOCATION_QS);
mQsCustomizerController.init();
mBrightnessSliderController.init();
mQSFgsManagerFooter.init();
}
private void updateMediaExpansion() {
@@ -146,6 +150,7 @@ public class QSPanelController extends QSPanelControllerBase<QSPanel> {
refreshAllTiles();
}
mView.addOnConfigurationChangedListener(mOnConfigurationChangedListener);
mView.setFgsManagerFooter(mQSFgsManagerFooter.getView());
mView.setSecurityFooter(mQsSecurityFooter.getView(), mShouldUseSplitNotificationShade);
switchTileLayout(true);
mBrightnessMirrorHandler.onQsPanelAttached();
@@ -230,6 +235,7 @@ public class QSPanelController extends QSPanelControllerBase<QSPanel> {
public void refreshAllTiles() {
mBrightnessController.checkRestrictionAndSetEnabled();
super.refreshAllTiles();
mQSFgsManagerFooter.refreshState();
mQsSecurityFooter.refreshState();
}

View File

@@ -53,6 +53,7 @@ import dagger.Provides;
*/
@Module
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";
@@ -205,4 +206,15 @@ public interface QSFragmentModule {
static StatusIconContainer providesStatusIconContainer(QuickStatusBarHeader qsHeader) {
return qsHeader.findViewById(R.id.statusIcons);
}
/** */
@Provides
@QSScope
@Named(QS_FGS_MANAGER_FOOTER_VIEW)
static View providesQSFgsManagerFooterView(
@QSThemedContext LayoutInflater layoutInflater,
QSPanel qsPanel
) {
return layoutInflater.inflate(R.layout.quick_settings_security_footer, qsPanel, false);
}
}

View File

@@ -80,6 +80,8 @@ public class QSPanelControllerTest extends SysuiTestCase {
@Mock
private TunerService mTunerService;
@Mock
private QSFgsManagerFooter mQSFgsManagerFooter;
@Mock
private QSSecurityFooter mQSSecurityFooter;
@Mock
private QSLogger mQSLogger;
@@ -127,8 +129,8 @@ public class QSPanelControllerTest extends SysuiTestCase {
.thenReturn(mQSTileRevealController);
when(mMediaHost.getDisappearParameters()).thenReturn(new DisappearParameters());
mController = new QSPanelController(mQSPanel, mQSSecurityFooter, mTunerService,
mQSTileHost, mQSCustomizerController, true, mMediaHost,
mController = new QSPanelController(mQSPanel, mQSFgsManagerFooter, mQSSecurityFooter,
mTunerService, mQSTileHost, mQSCustomizerController, true, mMediaHost,
mQSTileRevealControllerFactory, mDumpManager, mMetricsLogger, mUiEventLogger,
mQSLogger, mBrightnessControllerFactory, mToggleSliderViewControllerFactory,
mFalsingManager, mCommandQueue