diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java index 8451d6baeb0a2..d7201054dea6d 100644 --- a/services/core/java/com/android/server/am/ActivityManagerConstants.java +++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java @@ -58,6 +58,8 @@ final class ActivityManagerConstants extends ContentObserver { private static final String KEY_CONTENT_PROVIDER_RETAIN_TIME = "content_provider_retain_time"; private static final String KEY_GC_TIMEOUT = "gc_timeout"; private static final String KEY_GC_MIN_INTERVAL = "gc_min_interval"; + private static final String KEY_FORCE_BACKGROUND_CHECK_ON_RESTRICTED_APPS = + "force_bg_check_on_restricted"; private static final String KEY_FULL_PSS_MIN_INTERVAL = "full_pss_min_interval"; private static final String KEY_FULL_PSS_LOWERED_INTERVAL = "full_pss_lowered_interval"; private static final String KEY_POWER_CHECK_INTERVAL = "power_check_interval"; @@ -96,6 +98,7 @@ final class ActivityManagerConstants extends ContentObserver { private static final long DEFAULT_GC_TIMEOUT = 5*1000; private static final long DEFAULT_GC_MIN_INTERVAL = 60*1000; private static final long DEFAULT_FULL_PSS_MIN_INTERVAL = 20*60*1000; + private static final boolean DEFAULT_FORCE_BACKGROUND_CHECK_ON_RESTRICTED_APPS = true; private static final long DEFAULT_FULL_PSS_LOWERED_INTERVAL = 5*60*1000; private static final long DEFAULT_POWER_CHECK_INTERVAL = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000; private static final int DEFAULT_POWER_CHECK_MAX_CPU_1 = 25; @@ -177,6 +180,14 @@ final class ActivityManagerConstants extends ContentObserver { // The minimum amount of time between successive GC requests for a process. long GC_MIN_INTERVAL = DEFAULT_GC_MIN_INTERVAL; + /** + * Whether or not Background Check should be forced on any apps in the + * {@link android.app.usage.UsageStatsManager#STANDBY_BUCKET_RESTRICTED} bucket, + * regardless of target SDK version. + */ + boolean FORCE_BACKGROUND_CHECK_ON_RESTRICTED_APPS = + DEFAULT_FORCE_BACKGROUND_CHECK_ON_RESTRICTED_APPS; + // The minimum amount of time between successive PSS requests for a process. long FULL_PSS_MIN_INTERVAL = DEFAULT_FULL_PSS_MIN_INTERVAL; @@ -380,6 +391,9 @@ final class ActivityManagerConstants extends ContentObserver { case KEY_IMPERCEPTIBLE_KILL_EXEMPT_PROC_STATES: updateImperceptibleKillExemptions(); break; + case KEY_FORCE_BACKGROUND_CHECK_ON_RESTRICTED_APPS: + updateForceRestrictedBackgroundCheck(); + break; default: break; } @@ -427,6 +441,7 @@ final class ActivityManagerConstants extends ContentObserver { updateMaxCachedProcesses(); updateActivityStartsLoggingEnabled(); updateBackgroundActivityStarts(); + updateForceRestrictedBackgroundCheck(); updateForegroundServiceStartsLoggingEnabled(); updateBackgroundFgsStartsRestriction(); updateOomAdjUpdatePolicy(); @@ -571,6 +586,13 @@ final class ActivityManagerConstants extends ContentObserver { == OOMADJ_UPDATE_POLICY_QUICK; } + private void updateForceRestrictedBackgroundCheck() { + FORCE_BACKGROUND_CHECK_ON_RESTRICTED_APPS = DeviceConfig.getBoolean( + DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, + KEY_FORCE_BACKGROUND_CHECK_ON_RESTRICTED_APPS, + DEFAULT_FORCE_BACKGROUND_CHECK_ON_RESTRICTED_APPS); + } + private void updateImperceptibleKillExemptions() { IMPERCEPTIBLE_KILL_EXEMPT_PACKAGES.clear(); IMPERCEPTIBLE_KILL_EXEMPT_PACKAGES.addAll(mDefaultImperceptibleKillExemptPackages); @@ -658,6 +680,8 @@ final class ActivityManagerConstants extends ContentObserver { pw.println(GC_TIMEOUT); pw.print(" "); pw.print(KEY_GC_MIN_INTERVAL); pw.print("="); pw.println(GC_MIN_INTERVAL); + pw.print(" "); pw.print(KEY_FORCE_BACKGROUND_CHECK_ON_RESTRICTED_APPS); pw.print("="); + pw.println(FORCE_BACKGROUND_CHECK_ON_RESTRICTED_APPS); pw.print(" "); pw.print(KEY_FULL_PSS_MIN_INTERVAL); pw.print("="); pw.println(FULL_PSS_MIN_INTERVAL); pw.print(" "); pw.print(KEY_FULL_PSS_LOWERED_INTERVAL); pw.print("="); diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 4c5f705433d65..2b160dddedbb9 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -184,6 +184,7 @@ import android.app.WindowConfiguration.WindowingMode; import android.app.backup.IBackupManager; import android.app.usage.UsageEvents; import android.app.usage.UsageEvents.Event; +import android.app.usage.UsageStatsManager; import android.app.usage.UsageStatsManagerInternal; import android.appwidget.AppWidgetManager; import android.content.AutofillOptions; @@ -6051,6 +6052,11 @@ public class ActivityManagerService extends IActivityManager.Stub } } + private boolean isInRestrictedBucket(int userId, String packageName, long nowElapsed) { + return UsageStatsManager.STANDBY_BUCKET_RESTRICTED + <= mUsageStatsService.getAppStandbyBucket(packageName, userId, nowElapsed); + } + // Unified app-op and target sdk check int appRestrictedInBackgroundLocked(int uid, String packageName, int packageTargetSdk) { // Apps that target O+ are always subject to background check @@ -6060,7 +6066,17 @@ public class ActivityManagerService extends IActivityManager.Stub } return ActivityManager.APP_START_MODE_DELAYED_RIGID; } - // ...and legacy apps get an AppOp check + // It's a legacy app. If it's in the RESTRICTED bucket, always restrict on battery. + if (mOnBattery // Short-circuit in common case. + && mConstants.FORCE_BACKGROUND_CHECK_ON_RESTRICTED_APPS + && isInRestrictedBucket( + UserHandle.getUserId(uid), packageName, SystemClock.elapsedRealtime())) { + if (DEBUG_BACKGROUND_CHECK) { + Slog.i(TAG, "Legacy app " + uid + "/" + packageName + " in RESTRICTED bucket"); + } + return ActivityManager.APP_START_MODE_DELAYED; + } + // Not in the RESTRICTED bucket so policy is based on AppOp check. int appop = mAppOpsService.noteOperation(AppOpsManager.OP_RUN_IN_BACKGROUND, uid, packageName, null, false, ""); if (DEBUG_BACKGROUND_CHECK) {