Merge changes from topic "remove_fgs_manager_tile"

* changes:
  Create QS footer entry point for fgs manager
  Remove the foreground service manager tile
This commit is contained in:
Evan Severson
2022-01-26 01:57:29 +00:00
committed by Android (Google) Code Review
14 changed files with 171 additions and 165 deletions

View File

@@ -1,42 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
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.
-->
<!-- Remove when Fgs manager tile is removed -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="48dp"
android:height="48dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M2,4h4v4h-4z"
android:fillColor="#000000"/>
<path
android:pathData="M8,4h14v4h-14z"
android:fillColor="#000000"/>
<path
android:pathData="M2,10h4v4h-4z"
android:fillColor="#000000"/>
<path
android:pathData="M8,10h14v4h-14z"
android:fillColor="#000000"/>
<path
android:pathData="M2,16h4v4h-4z"
android:fillColor="#000000"/>
<path
android:pathData="M8,16h14v4h-14z"
android:fillColor="#000000"/>
</vector>

View File

@@ -82,7 +82,7 @@
<!-- Tiles native to System UI. Order should match "quick_settings_tiles_default" -->
<string name="quick_settings_tiles_stock" translatable="false">
internet,bt,flashlight,dnd,alarm,airplane,controls,wallet,rotation,battery,cast,screenrecord,mictoggle,cameratoggle,location,hotspot,inversion,saver,dark,work,night,reverse,reduce_brightness,qr_code_scanner,onehanded,fgsmanager,color_correction
internet,bt,flashlight,dnd,alarm,airplane,controls,wallet,rotation,battery,cast,screenrecord,mictoggle,cameratoggle,location,hotspot,inversion,saver,dark,work,night,reverse,reduce_brightness,qr_code_scanner,onehanded,color_correction
</string>
<!-- The tiles to display in QuickSettings -->

View File

@@ -2355,6 +2355,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

@@ -308,14 +308,4 @@
<item>Off</item>
<item>On</item>
</string-array>
<!-- State names for fgsmanager tile: unavailable, off, on.
This subtitle is shown when the tile is in that particular state but does not set its own
subtitle, so some of these may never appear on screen. They should still be translated as
if they could appear.[CHAR LIMIT=32] -->
<string-array name="tile_states_fgsmanager">
<item>Unavailable</item>
<item>Off</item>
<item>On</item>
</string-array>
</resources>

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

@@ -39,7 +39,6 @@ import com.android.systemui.qs.tiles.ColorInversionTile;
import com.android.systemui.qs.tiles.DataSaverTile;
import com.android.systemui.qs.tiles.DeviceControlsTile;
import com.android.systemui.qs.tiles.DndTile;
import com.android.systemui.qs.tiles.FgsManagerTile;
import com.android.systemui.qs.tiles.FlashlightTile;
import com.android.systemui.qs.tiles.HotspotTile;
import com.android.systemui.qs.tiles.InternetTile;
@@ -99,7 +98,6 @@ public class QSFactoryImpl implements QSFactory {
private final Provider<QuickAccessWalletTile> mQuickAccessWalletTileProvider;
private final Provider<QRCodeScannerTile> mQRCodeScannerTileProvider;
private final Provider<OneHandedModeTile> mOneHandedModeTileProvider;
private final Provider<FgsManagerTile> mFgsManagerTileProvider;
private final Lazy<QSHost> mQsHostLazy;
private final Provider<CustomTile.Builder> mCustomTileBuilderProvider;
@@ -137,7 +135,6 @@ public class QSFactoryImpl implements QSFactory {
Provider<QuickAccessWalletTile> quickAccessWalletTileProvider,
Provider<QRCodeScannerTile> qrCodeScannerTileProvider,
Provider<OneHandedModeTile> oneHandedModeTileProvider,
Provider<FgsManagerTile> fgsManagerTileProvider,
Provider<ColorCorrectionTile> colorCorrectionTileProvider) {
mQsHostLazy = qsHostLazy;
mCustomTileBuilderProvider = customTileBuilderProvider;
@@ -171,7 +168,6 @@ public class QSFactoryImpl implements QSFactory {
mQuickAccessWalletTileProvider = quickAccessWalletTileProvider;
mQRCodeScannerTileProvider = qrCodeScannerTileProvider;
mOneHandedModeTileProvider = oneHandedModeTileProvider;
mFgsManagerTileProvider = fgsManagerTileProvider;
mColorCorrectionTileProvider = colorCorrectionTileProvider;
}
@@ -246,8 +242,6 @@ public class QSFactoryImpl implements QSFactory {
return mQRCodeScannerTileProvider.get();
case "onehanded":
return mOneHandedModeTileProvider.get();
case "fgsmanager":
return mFgsManagerTileProvider.get();
case "color_correction":
return mColorCorrectionTileProvider.get();
}

View File

@@ -653,7 +653,6 @@ internal object SubtitleArrayMapping {
"qr_code_scanner" to R.array.tile_states_qr_code_scanner,
"alarm" to R.array.tile_states_alarm,
"onehanded" to R.array.tile_states_onehanded,
"fgsmanager" to R.array.tile_states_fgsmanager,
"color_correction" to R.array.tile_states_color_correction
)

View File

@@ -1,96 +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.tiles
import android.content.Intent
import android.os.Handler
import android.os.Looper
import android.provider.DeviceConfig
import android.view.View
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags
import com.android.internal.logging.MetricsLogger
import com.android.systemui.DejankUtils
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.plugins.ActivityStarter
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.plugins.qs.QSTile
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.qs.QSHost
import com.android.systemui.qs.logging.QSLogger
import com.android.systemui.qs.tileimpl.QSTileImpl
import com.android.systemui.statusbar.policy.RunningFgsController
import com.android.systemui.statusbar.policy.RunningFgsController.UserPackageTime
import java.util.concurrent.Executor
import javax.inject.Inject
/**
* Quicksettings tile for the foreground services manager (task manager)
*/
class FgsManagerTile @Inject constructor(
host: QSHost?,
@Background backgroundLooper: Looper?,
@Background private val backgroundExecutor: Executor?,
@Main mainHandler: Handler?,
falsingManager: FalsingManager?,
metricsLogger: MetricsLogger?,
statusBarStateController: StatusBarStateController?,
activityStarter: ActivityStarter?,
qsLogger: QSLogger?,
private val fgsManagerDialogFactory: FgsManagerDialogFactory,
private val runningFgsController: RunningFgsController
) : QSTileImpl<QSTile.State>(host, backgroundLooper, mainHandler, falsingManager, metricsLogger,
statusBarStateController, activityStarter, qsLogger), RunningFgsController.Callback {
override fun handleInitialize() {
super.handleInitialize()
mUiHandler.post { runningFgsController.observe(lifecycle, this) }
}
override fun isAvailable(): Boolean {
return DejankUtils.whitelistIpcs<Boolean> {
DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI,
SystemUiDeviceConfigFlags.TASK_MANAGER_ENABLED, false)
}
}
override fun newTileState(): QSTile.State {
return QSTile.State()
}
override fun handleClick(view: View?) {
mUiHandler.post { fgsManagerDialogFactory.create(view) }
}
override fun handleUpdateState(state: QSTile.State?, arg: Any?) {
state?.label = tileLabel
state?.secondaryLabel = runningFgsController.getPackagesWithFgs().size.toString()
state?.handlesLongClick = false
state?.icon = ResourceIcon.get(R.drawable.ic_list)
}
override fun getMetricsCategory(): Int = 0
override fun getLongClickIntent(): Intent? = null
// Inline the string so we don't waste translator time since this isn't used in the mocks.
// TODO If mocks change need to remember to move this to strings.xml
override fun getTileLabel(): CharSequence = "Active apps"
override fun onFgsPackagesChanged(packages: List<UserPackageTime>) = refreshState()
}

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

View File

@@ -34,7 +34,6 @@ import com.android.systemui.qs.tiles.ColorInversionTile
import com.android.systemui.qs.tiles.DataSaverTile
import com.android.systemui.qs.tiles.DeviceControlsTile
import com.android.systemui.qs.tiles.DndTile
import com.android.systemui.qs.tiles.FgsManagerTile
import com.android.systemui.qs.tiles.FlashlightTile
import com.android.systemui.qs.tiles.HotspotTile
import com.android.systemui.qs.tiles.InternetTile
@@ -92,7 +91,6 @@ private val specMap = mapOf(
"wallet" to QuickAccessWalletTile::class.java,
"qr_code_scanner" to QRCodeScannerTile::class.java,
"onehanded" to OneHandedModeTile::class.java,
"fgsmanager" to FgsManagerTile::class.java,
"color_correction" to ColorCorrectionTile::class.java
)
@@ -133,7 +131,6 @@ class QSFactoryImplTest : SysuiTestCase() {
@Mock private lateinit var quickAccessWalletTile: QuickAccessWalletTile
@Mock private lateinit var qrCodeScannerTile: QRCodeScannerTile
@Mock private lateinit var oneHandedModeTile: OneHandedModeTile
@Mock private lateinit var fgsManagerTile: FgsManagerTile
@Mock private lateinit var colorCorrectionTile: ColorCorrectionTile
private lateinit var factory: QSFactoryImpl
@@ -178,7 +175,6 @@ class QSFactoryImplTest : SysuiTestCase() {
{ quickAccessWalletTile },
{ qrCodeScannerTile },
{ oneHandedModeTile },
{ fgsManagerTile },
{ colorCorrectionTile }
)
// When adding/removing tiles, fix also [specMap]