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:
committed by
Jordan Demeulenaere
parent
ea08a5217b
commit
dcd089d3e7
@@ -548,6 +548,12 @@ public final class SystemUiDeviceConfigFlags {
|
||||
*/
|
||||
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.
|
||||
|
||||
@@ -40,11 +40,13 @@ import android.widget.Button
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.GuardedBy
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
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_STOP_BUTTON_FOR_USER_ALLOWLISTED_APPS
|
||||
import com.android.internal.jank.InteractionJankMonitor
|
||||
import com.android.systemui.Dumpable
|
||||
import com.android.systemui.R
|
||||
@@ -87,6 +89,7 @@ class FgsManagerController @Inject constructor(
|
||||
private val LOG_TAG = FgsManagerController::class.java.simpleName
|
||||
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_STOP_BUTTON_FOR_USER_ALLOWLISTED_APPS = true
|
||||
}
|
||||
|
||||
var changesSinceDialog = false
|
||||
@@ -96,6 +99,8 @@ class FgsManagerController @Inject constructor(
|
||||
private set
|
||||
var showFooterDot = false
|
||||
private set
|
||||
var showStopBtnForUserAllowlistedApps = false
|
||||
private set
|
||||
|
||||
private val lock = Any()
|
||||
|
||||
@@ -163,6 +168,9 @@ class FgsManagerController @Inject constructor(
|
||||
isAvailable = it.getBoolean(TASK_MANAGER_ENABLED, isAvailable)
|
||||
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(
|
||||
@@ -173,6 +181,10 @@ class FgsManagerController @Inject constructor(
|
||||
NAMESPACE_SYSTEMUI,
|
||||
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)
|
||||
|
||||
@@ -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 showDialog(viewLaunchedFrom: View?) {
|
||||
@@ -505,6 +531,13 @@ class FgsManagerController @Inject constructor(
|
||||
PowerExemptionManager.REASON_PROC_STATE_PERSISTENT_UI,
|
||||
PowerExemptionManager.REASON_ROLE_DIALER,
|
||||
PowerExemptionManager.REASON_SYSTEM_MODULE -> UIControl.HIDE_BUTTON
|
||||
|
||||
PowerExemptionManager.REASON_ALLOWLISTED_PACKAGE ->
|
||||
if (showStopBtnForUserAllowlistedApps) {
|
||||
UIControl.NORMAL
|
||||
} else {
|
||||
UIControl.HIDE_BUTTON
|
||||
}
|
||||
else -> UIControl.NORMAL
|
||||
}
|
||||
uiControlInitialized = true
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.systemui.qs;
|
||||
|
||||
import static android.os.PowerExemptionManager.REASON_ALLOWLISTED_PACKAGE;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.argThat;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
@@ -34,6 +36,7 @@ import android.content.pm.PackageManager;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.os.Binder;
|
||||
import android.os.RemoteException;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.DeviceConfig;
|
||||
import android.testing.AndroidTestingRunner;
|
||||
import android.testing.TestableLooper;
|
||||
@@ -222,7 +225,41 @@ public class FgsManagerControllerTest extends SysuiTestCase {
|
||||
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 {
|
||||
ArgumentCaptor<IForegroundServiceObserver> iForegroundServiceObserverArgumentCaptor =
|
||||
|
||||
Reference in New Issue
Block a user