Loading core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java +6 −0 Original line number Diff line number Diff line Loading @@ -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. Loading packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt +33 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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 Loading @@ -96,6 +99,8 @@ class FgsManagerController @Inject constructor( private set var showFooterDot = false private set var showStopBtnForUserAllowlistedApps = false private set private val lock = Any() Loading Loading @@ -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( Loading @@ -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) Loading Loading @@ -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?) { Loading Loading @@ -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 Loading packages/SystemUI/tests/src/com/android/systemui/qs/FgsManagerControllerTest.java +37 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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 = Loading Loading
core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java +6 −0 Original line number Diff line number Diff line Loading @@ -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. Loading
packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt +33 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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 Loading @@ -96,6 +99,8 @@ class FgsManagerController @Inject constructor( private set var showFooterDot = false private set var showStopBtnForUserAllowlistedApps = false private set private val lock = Any() Loading Loading @@ -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( Loading @@ -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) Loading Loading @@ -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?) { Loading Loading @@ -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 Loading
packages/SystemUI/tests/src/com/android/systemui/qs/FgsManagerControllerTest.java +37 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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 = Loading