Use the reason code from standby bucketing in bg restriction if needed
If the bg restriction level is inferred from the app standby bucket,
use the reason code from the app standby as the one of being in
such a bg restriction level.
Also fixed an issue where we'd need to restrict the offending bg apps
when it's backgrounded.
Bug: 225951652
Bug: 203105544
Test: atest FrameworksMockingServicesTests:BackgroundRestrictionTest
Change-Id: I5925e90e19d2f8c99d43c0637560d8629c887ed4
diff --git a/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java b/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java
index 5681107..c3fc4d1 100644
--- a/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java
+++ b/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java
@@ -1,6 +1,7 @@
package com.android.server.usage;
import android.annotation.CurrentTimeMillisLong;
+import android.annotation.ElapsedRealtimeLong;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
@@ -150,6 +151,12 @@
boolean shouldObfuscateInstantApps);
/**
+ * Return the bucketing reason code of the given app.
+ */
+ int getAppStandbyBucketReason(@NonNull String packageName, @UserIdInt int userId,
+ @ElapsedRealtimeLong long elapsedRealtime);
+
+ /**
* Put the specified app in the
* {@link android.app.usage.UsageStatsManager#STANDBY_BUCKET_RESTRICTED}
* bucket. If it has been used by the user recently, the restriction will delayed until an
diff --git a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
index 1e4ecc2..b520102 100644
--- a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
+++ b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
@@ -1436,8 +1436,8 @@
}
}
- @VisibleForTesting
- int getAppStandbyBucketReason(String packageName, int userId, long elapsedRealtime) {
+ @Override
+ public int getAppStandbyBucketReason(String packageName, int userId, long elapsedRealtime) {
synchronized (mAppIdleLock) {
return mAppIdleHistory.getAppStandbyReason(packageName, userId, elapsedRealtime);
}
diff --git a/services/core/java/com/android/server/am/AppRestrictionController.java b/services/core/java/com/android/server/am/AppRestrictionController.java
index 41ff083..b8fb9e8 100644
--- a/services/core/java/com/android/server/am/AppRestrictionController.java
+++ b/services/core/java/com/android/server/am/AppRestrictionController.java
@@ -1086,6 +1086,12 @@
}
final @RestrictionLevel int level = calcAppRestrictionLevel(
userId, uid, info.mPackageName, info.mStandbyBucket, false, false);
+ if (DEBUG_BG_RESTRICTION_CONTROLLER) {
+ Slog.i(TAG, "Proposed restriction level of " + info.mPackageName + "/"
+ + UserHandle.formatUid(uid) + ": "
+ + ActivityManager.restrictionLevelToName(level)
+ + " " + info.mStandbyBucket);
+ }
applyRestrictionLevel(info.mPackageName, uid, level,
info.mStandbyBucket, true, reason, subReason);
}
@@ -1185,6 +1191,25 @@
return level;
}
+ private static @RestrictionLevel int standbyBucketToRestrictionLevel(
+ @UsageStatsManager.StandbyBuckets int standbyBucket) {
+ switch (standbyBucket) {
+ case STANDBY_BUCKET_EXEMPTED:
+ return RESTRICTION_LEVEL_EXEMPTED;
+ case STANDBY_BUCKET_NEVER:
+ return RESTRICTION_LEVEL_BACKGROUND_RESTRICTED;
+ case STANDBY_BUCKET_ACTIVE:
+ case STANDBY_BUCKET_WORKING_SET:
+ case STANDBY_BUCKET_FREQUENT:
+ case STANDBY_BUCKET_RARE:
+ return RESTRICTION_LEVEL_ADAPTIVE_BUCKET;
+ case STANDBY_BUCKET_RESTRICTED:
+ return RESTRICTION_LEVEL_RESTRICTED_BUCKET;
+ default:
+ return RESTRICTION_LEVEL_UNKNOWN;
+ }
+ }
+
/**
* Get the restriction level of the given UID, if it hosts multiple packages,
* return least restricted one (or if any of them is exempted).
@@ -1380,12 +1405,23 @@
int curBucket, boolean allowUpdateBucket, int reason, int subReason) {
int curLevel;
int prevReason;
+ final AppStandbyInternal appStandbyInternal = mInjector.getAppStandbyInternal();
synchronized (mSettingsLock) {
curLevel = getRestrictionLevel(uid, pkgName);
if (curLevel == level) {
// Nothing to do.
return;
}
+ final int levelOfBucket = standbyBucketToRestrictionLevel(curBucket);
+ if (levelOfBucket == level) {
+ // If the standby bucket yield the same level, use the reason from standby bucket.
+ final int bucketReason = appStandbyInternal.getAppStandbyBucketReason(
+ pkgName, UserHandle.getUserId(uid), SystemClock.elapsedRealtime());
+ if (bucketReason != 0) {
+ reason = bucketReason & REASON_MAIN_MASK;
+ subReason = bucketReason & REASON_SUB_MASK;
+ }
+ }
if (DEBUG_BG_RESTRICTION_CONTROLLER) {
Slog.i(TAG, "Updating the restriction level of " + pkgName + "/"
+ UserHandle.formatUid(uid) + " from "
@@ -1393,7 +1429,6 @@
+ ActivityManager.restrictionLevelToName(level)
+ " reason=" + reason + ", subReason=" + subReason);
}
-
prevReason = mRestrictionSettings.getReason(pkgName, uid);
mRestrictionSettings.update(pkgName, uid, level, reason, subReason);
}
@@ -1401,7 +1436,6 @@
if (!allowUpdateBucket || curBucket == STANDBY_BUCKET_EXEMPTED) {
return;
}
- final AppStandbyInternal appStandbyInternal = mInjector.getAppStandbyInternal();
if (level >= RESTRICTION_LEVEL_RESTRICTED_BUCKET
&& curLevel < RESTRICTION_LEVEL_RESTRICTED_BUCKET) {
if (!mConstantsObserver.mRestrictedBucketEnabled) {
@@ -1422,8 +1456,10 @@
final int index = mActiveUids.indexOfKey(uid, pkgName);
if (index >= 0) {
// It's currently active, enqueue it.
+ final int localReason = reason;
+ final int localSubReason = subReason;
mActiveUids.add(uid, pkgName, () -> appStandbyInternal.restrictApp(
- pkgName, UserHandle.getUserId(uid), reason, subReason));
+ pkgName, UserHandle.getUserId(uid), localReason, localSubReason));
doIt = false;
}
}
@@ -1841,9 +1877,6 @@
}
void handleUidInactive(int uid, boolean disabled) {
- if (!mConstantsObserver.mBgAutoRestrictedBucket) {
- return;
- }
final ArrayList<Runnable> pendingTasks = mTmpRunnables;
synchronized (mSettingsLock) {
final int index = mActiveUids.indexOfKey(uid);
@@ -1866,14 +1899,12 @@
}
void handleUidActive(int uid) {
- if (!mConstantsObserver.mBgAutoRestrictedBucket) {
- return;
- }
synchronized (mSettingsLock) {
final AppStandbyInternal appStandbyInternal = mInjector.getAppStandbyInternal();
final int userId = UserHandle.getUserId(uid);
mRestrictionSettings.forEachPackageInUidLocked(uid, (pkgName, level, reason) -> {
- if (level == RESTRICTION_LEVEL_BACKGROUND_RESTRICTED) {
+ if (mConstantsObserver.mBgAutoRestrictedBucket
+ && level == RESTRICTION_LEVEL_BACKGROUND_RESTRICTED) {
mActiveUids.add(uid, pkgName, () -> appStandbyInternal.restrictApp(pkgName,
userId, reason & REASON_MAIN_MASK, reason & REASON_SUB_MASK));
} else {