Allow preventing unrestricted Apps from being Stopped

This CL adds a flag to allow toggling the behavior on whether or not
the foreground service task manager should show a stop button for
unrestricted apps.

Bug: 230449539
Test: Manual - device_config put systemui \
      show_stop_button_for_user_allowlisted_apps true|false
Test: atest FgsManagerControllerTest
Change-Id: I4cfe54933d7c6807a7ffbac9ee709c7d8d6b83d3
Merged-In: I4cfe54933d7c6807a7ffbac9ee709c7d8d6b83d3
This commit is contained in:
Jing Ji
2022-06-23 20:43:36 -07:00
committed by Jordan Demeulenaere
parent ea08a5217b
commit dcd089d3e7
3 changed files with 76 additions and 0 deletions

View File

@@ -548,6 +548,12 @@ public final class SystemUiDeviceConfigFlags {
*/ */
public static final String TASK_MANAGER_SHOW_FOOTER_DOT = "task_manager_show_footer_dot"; public static final String TASK_MANAGER_SHOW_FOOTER_DOT = "task_manager_show_footer_dot";
/**
* (boolean) Whether the task manager should show a stop button if the app is allowlisted
* by the user.
*/
public static final String TASK_MANAGER_SHOW_STOP_BUTTON_FOR_USER_ALLOWLISTED_APPS =
"show_stop_button_for_user_allowlisted_apps";
/** /**
* (boolean) Whether the clipboard overlay is enabled. * (boolean) Whether the clipboard overlay is enabled.

View File

@@ -40,11 +40,13 @@ import android.widget.Button
import android.widget.ImageView import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
import androidx.annotation.GuardedBy import androidx.annotation.GuardedBy
import androidx.annotation.VisibleForTesting
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags.TASK_MANAGER_ENABLED import com.android.internal.config.sysui.SystemUiDeviceConfigFlags.TASK_MANAGER_ENABLED
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags.TASK_MANAGER_SHOW_FOOTER_DOT import com.android.internal.config.sysui.SystemUiDeviceConfigFlags.TASK_MANAGER_SHOW_FOOTER_DOT
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags.TASK_MANAGER_SHOW_STOP_BUTTON_FOR_USER_ALLOWLISTED_APPS
import com.android.internal.jank.InteractionJankMonitor import com.android.internal.jank.InteractionJankMonitor
import com.android.systemui.Dumpable import com.android.systemui.Dumpable
import com.android.systemui.R import com.android.systemui.R
@@ -87,6 +89,7 @@ class FgsManagerController @Inject constructor(
private val LOG_TAG = FgsManagerController::class.java.simpleName private val LOG_TAG = FgsManagerController::class.java.simpleName
private const val DEFAULT_TASK_MANAGER_ENABLED = true private const val DEFAULT_TASK_MANAGER_ENABLED = true
private const val DEFAULT_TASK_MANAGER_SHOW_FOOTER_DOT = false private const val DEFAULT_TASK_MANAGER_SHOW_FOOTER_DOT = false
private const val DEFAULT_TASK_MANAGER_SHOW_STOP_BUTTON_FOR_USER_ALLOWLISTED_APPS = true
} }
var changesSinceDialog = false var changesSinceDialog = false
@@ -96,6 +99,8 @@ class FgsManagerController @Inject constructor(
private set private set
var showFooterDot = false var showFooterDot = false
private set private set
var showStopBtnForUserAllowlistedApps = false
private set
private val lock = Any() private val lock = Any()
@@ -163,6 +168,9 @@ class FgsManagerController @Inject constructor(
isAvailable = it.getBoolean(TASK_MANAGER_ENABLED, isAvailable) isAvailable = it.getBoolean(TASK_MANAGER_ENABLED, isAvailable)
showFooterDot = showFooterDot =
it.getBoolean(TASK_MANAGER_SHOW_FOOTER_DOT, showFooterDot) it.getBoolean(TASK_MANAGER_SHOW_FOOTER_DOT, showFooterDot)
showStopBtnForUserAllowlistedApps = it.getBoolean(
TASK_MANAGER_SHOW_STOP_BUTTON_FOR_USER_ALLOWLISTED_APPS,
showStopBtnForUserAllowlistedApps)
} }
isAvailable = deviceConfigProxy.getBoolean( isAvailable = deviceConfigProxy.getBoolean(
@@ -173,6 +181,10 @@ class FgsManagerController @Inject constructor(
NAMESPACE_SYSTEMUI, NAMESPACE_SYSTEMUI,
TASK_MANAGER_SHOW_FOOTER_DOT, DEFAULT_TASK_MANAGER_SHOW_FOOTER_DOT TASK_MANAGER_SHOW_FOOTER_DOT, DEFAULT_TASK_MANAGER_SHOW_FOOTER_DOT
) )
showStopBtnForUserAllowlistedApps = deviceConfigProxy.getBoolean(
NAMESPACE_SYSTEMUI,
TASK_MANAGER_SHOW_STOP_BUTTON_FOR_USER_ALLOWLISTED_APPS,
DEFAULT_TASK_MANAGER_SHOW_STOP_BUTTON_FOR_USER_ALLOWLISTED_APPS)
dumpManager.registerDumpable(this) dumpManager.registerDumpable(this)
@@ -275,6 +287,20 @@ class FgsManagerController @Inject constructor(
} }
} }
@VisibleForTesting
@JvmName("getNumVisibleButtons")
internal fun getNumVisibleButtons(): Int {
synchronized(lock) {
return getNumVisibleButtonsLocked()
}
}
private fun getNumVisibleButtonsLocked(): Int {
return runningServiceTokens.keys.count {
it.uiControl != UIControl.HIDE_BUTTON && currentProfileIds.contains(it.userId)
}
}
fun shouldUpdateFooterVisibility() = dialog == null fun shouldUpdateFooterVisibility() = dialog == null
fun showDialog(viewLaunchedFrom: View?) { fun showDialog(viewLaunchedFrom: View?) {
@@ -505,6 +531,13 @@ class FgsManagerController @Inject constructor(
PowerExemptionManager.REASON_PROC_STATE_PERSISTENT_UI, PowerExemptionManager.REASON_PROC_STATE_PERSISTENT_UI,
PowerExemptionManager.REASON_ROLE_DIALER, PowerExemptionManager.REASON_ROLE_DIALER,
PowerExemptionManager.REASON_SYSTEM_MODULE -> UIControl.HIDE_BUTTON PowerExemptionManager.REASON_SYSTEM_MODULE -> UIControl.HIDE_BUTTON
PowerExemptionManager.REASON_ALLOWLISTED_PACKAGE ->
if (showStopBtnForUserAllowlistedApps) {
UIControl.NORMAL
} else {
UIControl.HIDE_BUTTON
}
else -> UIControl.NORMAL else -> UIControl.NORMAL
} }
uiControlInitialized = true uiControlInitialized = true

View File

@@ -16,6 +16,8 @@
package com.android.systemui.qs; package com.android.systemui.qs;
import static android.os.PowerExemptionManager.REASON_ALLOWLISTED_PACKAGE;
import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq;
@@ -34,6 +36,7 @@ import android.content.pm.PackageManager;
import android.content.pm.UserInfo; import android.content.pm.UserInfo;
import android.os.Binder; import android.os.Binder;
import android.os.RemoteException; import android.os.RemoteException;
import android.os.UserHandle;
import android.provider.DeviceConfig; import android.provider.DeviceConfig;
import android.testing.AndroidTestingRunner; import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper; import android.testing.TestableLooper;
@@ -222,7 +225,41 @@ public class FgsManagerControllerTest extends SysuiTestCase {
Assert.assertEquals(2, mFmc.getNumRunningPackages()); Assert.assertEquals(2, mFmc.getNumRunningPackages());
} }
@Test
public void testButtonVisibilityOnShowAllowlistButtonFlagChange() throws Exception {
setUserProfiles(0);
setBackgroundRestrictionExemptionReason("pkg", 12345, REASON_ALLOWLISTED_PACKAGE);
final Binder binder = new Binder();
setShowStopButtonForUserAllowlistedApps(true);
mIForegroundServiceObserver.onForegroundStateChanged(binder, "pkg", 0, true);
Assert.assertEquals(1, mFmc.getNumVisibleButtons());
mIForegroundServiceObserver.onForegroundStateChanged(binder, "pkg", 0, false);
Assert.assertEquals(0, mFmc.getNumVisibleButtons());
setShowStopButtonForUserAllowlistedApps(false);
mIForegroundServiceObserver.onForegroundStateChanged(binder, "pkg", 0, true);
Assert.assertEquals(0, mFmc.getNumVisibleButtons());
}
private void setShowStopButtonForUserAllowlistedApps(boolean enable) {
mDeviceConfigProxyFake.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
SystemUiDeviceConfigFlags.TASK_MANAGER_SHOW_STOP_BUTTON_FOR_USER_ALLOWLISTED_APPS,
enable ? "true" : "false", false);
mBackgroundExecutor.advanceClockToLast();
mBackgroundExecutor.runAllReady();
}
private void setBackgroundRestrictionExemptionReason(String pkgName, int uid, int reason)
throws Exception {
Mockito.doReturn(uid)
.when(mPackageManager)
.getPackageUidAsUser(pkgName, UserHandle.getUserId(uid));
Mockito.doReturn(reason)
.when(mIActivityManager)
.getBackgroundRestrictionExemptionReason(uid);
}
FgsManagerController createFgsManagerController() throws RemoteException { FgsManagerController createFgsManagerController() throws RemoteException {
ArgumentCaptor<IForegroundServiceObserver> iForegroundServiceObserverArgumentCaptor = ArgumentCaptor<IForegroundServiceObserver> iForegroundServiceObserverArgumentCaptor =