Loading services/core/java/com/android/server/am/AppRestrictionController.java +45 −1 Original line number Diff line number Diff line Loading @@ -186,6 +186,12 @@ public final class AppRestrictionController { */ private static final boolean ENABLE_SHOW_FOREGROUND_SERVICE_MANAGER = true; /** * Whether or not to show the action to the foreground service manager when * posting the notification for background restriction. */ private static final boolean ENABLE_SHOW_FGS_MANAGER_ACTION_ON_BG_RESTRICTION = false; private final Context mContext; private final HandlerThread mBgHandlerThread; private final BgHandler mBgHandler; Loading Loading @@ -665,6 +671,14 @@ public final class AppRestrictionController { static final String KEY_BG_PROMPT_FGS_WITH_NOTIFICATION_TO_BG_RESTRICTED = DEVICE_CONFIG_SUBNAMESPACE_PREFIX + "prompt_fgs_with_noti_to_bg_restricted"; /** * The behavior for an app with a FGS and its notification is still showing, when the system * detects it's running for a very long time, should we prompt the user. * {@code true} - we'll show the prompt to user, {@code false} - we'll not show it. */ static final String KEY_BG_PROMPT_FGS_WITH_NOTIFICATION_ON_LONG_RUNNING = DEVICE_CONFIG_SUBNAMESPACE_PREFIX + "prompt_fgs_with_noti_on_long_running"; /** * The list of packages to be exempted from all these background restrictions. */ Loading @@ -686,6 +700,11 @@ public final class AppRestrictionController { */ static final long DEFAULT_BG_LONG_FGS_NOTIFICATION_MINIMAL_INTERVAL_MS = 30 * ONE_DAY; /** * Default value to {@link #mBgPromptFgsWithNotiOnLongRunning}. */ static final boolean DEFAULT_BG_PROMPT_FGS_WITH_NOTIFICATION_ON_LONG_RUNNING = false; /** * Default value to {@link #mBgPromptFgsWithNotiToBgRestricted}. */ Loading @@ -711,6 +730,11 @@ public final class AppRestrictionController { */ volatile boolean mBgPromptFgsWithNotiToBgRestricted; /** * @see #KEY_BG_PROMPT_FGS_WITH_NOTIFICATION_ON_LONG_RUNNING. */ volatile boolean mBgPromptFgsWithNotiOnLongRunning; ConstantsObserver(Handler handler, Context context) { super(handler); mDefaultBgPromptFgsWithNotiToBgRestricted = context.getResources().getBoolean( Loading @@ -736,6 +760,9 @@ public final class AppRestrictionController { case KEY_BG_PROMPT_FGS_WITH_NOTIFICATION_TO_BG_RESTRICTED: updateBgPromptFgsWithNotiToBgRestricted(); break; case KEY_BG_PROMPT_FGS_WITH_NOTIFICATION_ON_LONG_RUNNING: updateBgPromptFgsWithNotiOnLongRunning(); break; case KEY_BG_RESTRICTION_EXEMPTED_PACKAGES: updateBgRestrictionExemptedPackages(); break; Loading Loading @@ -772,6 +799,7 @@ public final class AppRestrictionController { updateBgAbusiveNotificationMinimalInterval(); updateBgLongFgsNotificationMinimalInterval(); updateBgPromptFgsWithNotiToBgRestricted(); updateBgPromptFgsWithNotiOnLongRunning(); updateBgRestrictionExemptedPackages(); } Loading Loading @@ -807,6 +835,13 @@ public final class AppRestrictionController { mDefaultBgPromptFgsWithNotiToBgRestricted); } private void updateBgPromptFgsWithNotiOnLongRunning() { mBgPromptFgsWithNotiOnLongRunning = DeviceConfig.getBoolean( DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_BG_PROMPT_FGS_WITH_NOTIFICATION_ON_LONG_RUNNING, DEFAULT_BG_PROMPT_FGS_WITH_NOTIFICATION_ON_LONG_RUNNING); } private void updateBgRestrictionExemptedPackages() { final String settings = DeviceConfig.getString( DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, Loading Loading @@ -1691,7 +1726,9 @@ public final class AppRestrictionController { return; } } if (ENABLE_SHOW_FOREGROUND_SERVICE_MANAGER && hasForegroundServices) { if (ENABLE_SHOW_FOREGROUND_SERVICE_MANAGER && ENABLE_SHOW_FGS_MANAGER_ACTION_ON_BG_RESTRICTION && hasForegroundServices) { final Intent trampoline = new Intent(ACTION_FGS_MANAGER_TRAMPOLINE); trampoline.setPackage("android"); trampoline.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName); Loading @@ -1716,6 +1753,13 @@ public final class AppRestrictionController { void postLongRunningFgsIfNecessary(String packageName, int uid) { PendingIntent pendingIntent; if (!mBgController.mConstantsObserver.mBgPromptFgsWithNotiOnLongRunning && mBgController.hasForegroundServiceNotifications(packageName, uid)) { if (DEBUG_BG_RESTRICTION_CONTROLLER) { Slog.i(TAG, "Not prompt long-running due to FGS with notification"); } return; } if (ENABLE_SHOW_FOREGROUND_SERVICE_MANAGER) { final Intent intent = new Intent(ACTION_SHOW_FOREGROUND_SERVICE_MANAGER); intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); Loading services/tests/mockingservicestests/src/com/android/server/am/BackgroundRestrictionTest.java +51 −0 Original line number Diff line number Diff line Loading @@ -1067,6 +1067,8 @@ public final class BackgroundRestrictionTest { final int testUid2 = UserHandle.getUid(testUser2, TEST_PACKAGE_APPID_BASE + testPkgIndex2); final int testPid2 = 1235; final int fgsNotificationId = 1000; final long windowMs = 2_000; final long thresholdMs = 1_000; final long shortMs = 100; Loading @@ -1074,6 +1076,7 @@ public final class BackgroundRestrictionTest { DeviceConfigSession<Boolean> longRunningFGSMonitor = null; DeviceConfigSession<Long> longRunningFGSWindow = null; DeviceConfigSession<Long> longRunningFGSThreshold = null; DeviceConfigSession<Boolean> longRunningFGSWithNotification = null; try { longRunningFGSMonitor = new DeviceConfigSession<>( Loading @@ -1097,6 +1100,13 @@ public final class BackgroundRestrictionTest { AppFGSPolicy.DEFAULT_BG_FGS_LONG_RUNNING_THRESHOLD); longRunningFGSThreshold.set(thresholdMs); longRunningFGSWithNotification = new DeviceConfigSession<>( DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, ConstantsObserver.KEY_BG_PROMPT_FGS_WITH_NOTIFICATION_ON_LONG_RUNNING, DeviceConfig::getBoolean, ConstantsObserver.DEFAULT_BG_PROMPT_FGS_WITH_NOTIFICATION_ON_LONG_RUNNING); longRunningFGSWithNotification.set(true); // Basic case mAppFGSTracker.onForegroundServiceStateChanged(testPkgName1, testUid1, testPid1, true); Loading Loading @@ -1196,10 +1206,42 @@ public final class BackgroundRestrictionTest { mAppFGSTracker.onForegroundServiceStateChanged(testPkgName1, testUid1, testPid1, false); checkNotificationGone(testPkgName1, timeout(windowMs), notificationId); // Start over with the flag to not show prompt when it has an active notification. clearInvocations(mInjector.getNotificationManager()); mBgRestrictionController.resetRestrictionSettings(); longRunningFGSWithNotification.set(false); // Start an FGS with notification. mAppFGSTracker.onForegroundServiceStateChanged(testPkgName1, testUid1, testPid1, true); mAppFGSTracker.onForegroundServiceNotificationUpdated( testPkgName1, testUid1, fgsNotificationId); mAppFGSTracker.mNotificationListener.onNotificationPosted(new StatusBarNotification( testPkgName1, null, fgsNotificationId, null, testUid1, testPid1, new Notification(), UserHandle.of(testUser1), null, mCurrentTimeMillis), null); // Verify we won't prompt the user because it has a visible FGS notification. checkNotificationShown( new String[] {testPkgName1}, timeout(windowMs * 2).times(0), false); // Pretend we have the notification dismissed. mAppFGSTracker.onForegroundServiceNotificationUpdated( testPkgName1, testUid1, -fgsNotificationId); // Verify we have the notification. notificationId = checkNotificationShown( new String[] {testPkgName1}, timeout(windowMs * 2).times(2), true)[0]; // Stop the FGS. mAppFGSTracker.onForegroundServiceStateChanged(testPkgName1, testUid1, testPid1, false); checkNotificationGone(testPkgName1, timeout(windowMs), notificationId); } finally { closeIfNotNull(longRunningFGSMonitor); closeIfNotNull(longRunningFGSWindow); closeIfNotNull(longRunningFGSThreshold); closeIfNotNull(longRunningFGSWithNotification); } } Loading @@ -1225,6 +1267,7 @@ public final class BackgroundRestrictionTest { DeviceConfigSession<Long> longRunningFGSThreshold = null; DeviceConfigSession<Long> mediaPlaybackFGSThreshold = null; DeviceConfigSession<Long> locationFGSThreshold = null; DeviceConfigSession<Boolean> longRunningFGSWithNotification = null; doReturn(testPkgName1).when(mInjector).getPackageName(testPid1); doReturn(testPkgName2).when(mInjector).getPackageName(testPid2); Loading Loading @@ -1265,6 +1308,13 @@ public final class BackgroundRestrictionTest { AppFGSPolicy.DEFAULT_BG_FGS_LOCATION_THRESHOLD); locationFGSThreshold.set(thresholdMs); longRunningFGSWithNotification = new DeviceConfigSession<>( DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, ConstantsObserver.KEY_BG_PROMPT_FGS_WITH_NOTIFICATION_ON_LONG_RUNNING, DeviceConfig::getBoolean, ConstantsObserver.DEFAULT_BG_PROMPT_FGS_WITH_NOTIFICATION_ON_LONG_RUNNING); longRunningFGSWithNotification.set(true); // Long-running FGS with type "location", but ran for a very short time. runTestLongFGSExemptionOnce(testPkgName1, testUid1, testPid1, FOREGROUND_SERVICE_TYPE_LOCATION, 0, null, OP_NONE, null, null, Loading Loading @@ -1372,6 +1422,7 @@ public final class BackgroundRestrictionTest { closeIfNotNull(longRunningFGSThreshold); closeIfNotNull(mediaPlaybackFGSThreshold); closeIfNotNull(locationFGSThreshold); closeIfNotNull(longRunningFGSWithNotification); } } Loading Loading
services/core/java/com/android/server/am/AppRestrictionController.java +45 −1 Original line number Diff line number Diff line Loading @@ -186,6 +186,12 @@ public final class AppRestrictionController { */ private static final boolean ENABLE_SHOW_FOREGROUND_SERVICE_MANAGER = true; /** * Whether or not to show the action to the foreground service manager when * posting the notification for background restriction. */ private static final boolean ENABLE_SHOW_FGS_MANAGER_ACTION_ON_BG_RESTRICTION = false; private final Context mContext; private final HandlerThread mBgHandlerThread; private final BgHandler mBgHandler; Loading Loading @@ -665,6 +671,14 @@ public final class AppRestrictionController { static final String KEY_BG_PROMPT_FGS_WITH_NOTIFICATION_TO_BG_RESTRICTED = DEVICE_CONFIG_SUBNAMESPACE_PREFIX + "prompt_fgs_with_noti_to_bg_restricted"; /** * The behavior for an app with a FGS and its notification is still showing, when the system * detects it's running for a very long time, should we prompt the user. * {@code true} - we'll show the prompt to user, {@code false} - we'll not show it. */ static final String KEY_BG_PROMPT_FGS_WITH_NOTIFICATION_ON_LONG_RUNNING = DEVICE_CONFIG_SUBNAMESPACE_PREFIX + "prompt_fgs_with_noti_on_long_running"; /** * The list of packages to be exempted from all these background restrictions. */ Loading @@ -686,6 +700,11 @@ public final class AppRestrictionController { */ static final long DEFAULT_BG_LONG_FGS_NOTIFICATION_MINIMAL_INTERVAL_MS = 30 * ONE_DAY; /** * Default value to {@link #mBgPromptFgsWithNotiOnLongRunning}. */ static final boolean DEFAULT_BG_PROMPT_FGS_WITH_NOTIFICATION_ON_LONG_RUNNING = false; /** * Default value to {@link #mBgPromptFgsWithNotiToBgRestricted}. */ Loading @@ -711,6 +730,11 @@ public final class AppRestrictionController { */ volatile boolean mBgPromptFgsWithNotiToBgRestricted; /** * @see #KEY_BG_PROMPT_FGS_WITH_NOTIFICATION_ON_LONG_RUNNING. */ volatile boolean mBgPromptFgsWithNotiOnLongRunning; ConstantsObserver(Handler handler, Context context) { super(handler); mDefaultBgPromptFgsWithNotiToBgRestricted = context.getResources().getBoolean( Loading @@ -736,6 +760,9 @@ public final class AppRestrictionController { case KEY_BG_PROMPT_FGS_WITH_NOTIFICATION_TO_BG_RESTRICTED: updateBgPromptFgsWithNotiToBgRestricted(); break; case KEY_BG_PROMPT_FGS_WITH_NOTIFICATION_ON_LONG_RUNNING: updateBgPromptFgsWithNotiOnLongRunning(); break; case KEY_BG_RESTRICTION_EXEMPTED_PACKAGES: updateBgRestrictionExemptedPackages(); break; Loading Loading @@ -772,6 +799,7 @@ public final class AppRestrictionController { updateBgAbusiveNotificationMinimalInterval(); updateBgLongFgsNotificationMinimalInterval(); updateBgPromptFgsWithNotiToBgRestricted(); updateBgPromptFgsWithNotiOnLongRunning(); updateBgRestrictionExemptedPackages(); } Loading Loading @@ -807,6 +835,13 @@ public final class AppRestrictionController { mDefaultBgPromptFgsWithNotiToBgRestricted); } private void updateBgPromptFgsWithNotiOnLongRunning() { mBgPromptFgsWithNotiOnLongRunning = DeviceConfig.getBoolean( DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_BG_PROMPT_FGS_WITH_NOTIFICATION_ON_LONG_RUNNING, DEFAULT_BG_PROMPT_FGS_WITH_NOTIFICATION_ON_LONG_RUNNING); } private void updateBgRestrictionExemptedPackages() { final String settings = DeviceConfig.getString( DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, Loading Loading @@ -1691,7 +1726,9 @@ public final class AppRestrictionController { return; } } if (ENABLE_SHOW_FOREGROUND_SERVICE_MANAGER && hasForegroundServices) { if (ENABLE_SHOW_FOREGROUND_SERVICE_MANAGER && ENABLE_SHOW_FGS_MANAGER_ACTION_ON_BG_RESTRICTION && hasForegroundServices) { final Intent trampoline = new Intent(ACTION_FGS_MANAGER_TRAMPOLINE); trampoline.setPackage("android"); trampoline.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName); Loading @@ -1716,6 +1753,13 @@ public final class AppRestrictionController { void postLongRunningFgsIfNecessary(String packageName, int uid) { PendingIntent pendingIntent; if (!mBgController.mConstantsObserver.mBgPromptFgsWithNotiOnLongRunning && mBgController.hasForegroundServiceNotifications(packageName, uid)) { if (DEBUG_BG_RESTRICTION_CONTROLLER) { Slog.i(TAG, "Not prompt long-running due to FGS with notification"); } return; } if (ENABLE_SHOW_FOREGROUND_SERVICE_MANAGER) { final Intent intent = new Intent(ACTION_SHOW_FOREGROUND_SERVICE_MANAGER); intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); Loading
services/tests/mockingservicestests/src/com/android/server/am/BackgroundRestrictionTest.java +51 −0 Original line number Diff line number Diff line Loading @@ -1067,6 +1067,8 @@ public final class BackgroundRestrictionTest { final int testUid2 = UserHandle.getUid(testUser2, TEST_PACKAGE_APPID_BASE + testPkgIndex2); final int testPid2 = 1235; final int fgsNotificationId = 1000; final long windowMs = 2_000; final long thresholdMs = 1_000; final long shortMs = 100; Loading @@ -1074,6 +1076,7 @@ public final class BackgroundRestrictionTest { DeviceConfigSession<Boolean> longRunningFGSMonitor = null; DeviceConfigSession<Long> longRunningFGSWindow = null; DeviceConfigSession<Long> longRunningFGSThreshold = null; DeviceConfigSession<Boolean> longRunningFGSWithNotification = null; try { longRunningFGSMonitor = new DeviceConfigSession<>( Loading @@ -1097,6 +1100,13 @@ public final class BackgroundRestrictionTest { AppFGSPolicy.DEFAULT_BG_FGS_LONG_RUNNING_THRESHOLD); longRunningFGSThreshold.set(thresholdMs); longRunningFGSWithNotification = new DeviceConfigSession<>( DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, ConstantsObserver.KEY_BG_PROMPT_FGS_WITH_NOTIFICATION_ON_LONG_RUNNING, DeviceConfig::getBoolean, ConstantsObserver.DEFAULT_BG_PROMPT_FGS_WITH_NOTIFICATION_ON_LONG_RUNNING); longRunningFGSWithNotification.set(true); // Basic case mAppFGSTracker.onForegroundServiceStateChanged(testPkgName1, testUid1, testPid1, true); Loading Loading @@ -1196,10 +1206,42 @@ public final class BackgroundRestrictionTest { mAppFGSTracker.onForegroundServiceStateChanged(testPkgName1, testUid1, testPid1, false); checkNotificationGone(testPkgName1, timeout(windowMs), notificationId); // Start over with the flag to not show prompt when it has an active notification. clearInvocations(mInjector.getNotificationManager()); mBgRestrictionController.resetRestrictionSettings(); longRunningFGSWithNotification.set(false); // Start an FGS with notification. mAppFGSTracker.onForegroundServiceStateChanged(testPkgName1, testUid1, testPid1, true); mAppFGSTracker.onForegroundServiceNotificationUpdated( testPkgName1, testUid1, fgsNotificationId); mAppFGSTracker.mNotificationListener.onNotificationPosted(new StatusBarNotification( testPkgName1, null, fgsNotificationId, null, testUid1, testPid1, new Notification(), UserHandle.of(testUser1), null, mCurrentTimeMillis), null); // Verify we won't prompt the user because it has a visible FGS notification. checkNotificationShown( new String[] {testPkgName1}, timeout(windowMs * 2).times(0), false); // Pretend we have the notification dismissed. mAppFGSTracker.onForegroundServiceNotificationUpdated( testPkgName1, testUid1, -fgsNotificationId); // Verify we have the notification. notificationId = checkNotificationShown( new String[] {testPkgName1}, timeout(windowMs * 2).times(2), true)[0]; // Stop the FGS. mAppFGSTracker.onForegroundServiceStateChanged(testPkgName1, testUid1, testPid1, false); checkNotificationGone(testPkgName1, timeout(windowMs), notificationId); } finally { closeIfNotNull(longRunningFGSMonitor); closeIfNotNull(longRunningFGSWindow); closeIfNotNull(longRunningFGSThreshold); closeIfNotNull(longRunningFGSWithNotification); } } Loading @@ -1225,6 +1267,7 @@ public final class BackgroundRestrictionTest { DeviceConfigSession<Long> longRunningFGSThreshold = null; DeviceConfigSession<Long> mediaPlaybackFGSThreshold = null; DeviceConfigSession<Long> locationFGSThreshold = null; DeviceConfigSession<Boolean> longRunningFGSWithNotification = null; doReturn(testPkgName1).when(mInjector).getPackageName(testPid1); doReturn(testPkgName2).when(mInjector).getPackageName(testPid2); Loading Loading @@ -1265,6 +1308,13 @@ public final class BackgroundRestrictionTest { AppFGSPolicy.DEFAULT_BG_FGS_LOCATION_THRESHOLD); locationFGSThreshold.set(thresholdMs); longRunningFGSWithNotification = new DeviceConfigSession<>( DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, ConstantsObserver.KEY_BG_PROMPT_FGS_WITH_NOTIFICATION_ON_LONG_RUNNING, DeviceConfig::getBoolean, ConstantsObserver.DEFAULT_BG_PROMPT_FGS_WITH_NOTIFICATION_ON_LONG_RUNNING); longRunningFGSWithNotification.set(true); // Long-running FGS with type "location", but ran for a very short time. runTestLongFGSExemptionOnce(testPkgName1, testUid1, testPid1, FOREGROUND_SERVICE_TYPE_LOCATION, 0, null, OP_NONE, null, null, Loading Loading @@ -1372,6 +1422,7 @@ public final class BackgroundRestrictionTest { closeIfNotNull(longRunningFGSThreshold); closeIfNotNull(mediaPlaybackFGSThreshold); closeIfNotNull(locationFGSThreshold); closeIfNotNull(longRunningFGSWithNotification); } } Loading