diff options
author | Kweku Adams <kwekua@google.com> | 2020-05-08 15:01:03 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2020-05-08 15:01:03 +0000 |
commit | 86a71e6e9345e2c9a37cc68639be183f3bb717df (patch) | |
tree | d19d52ed1a918cf2d4168fc50b5fe183c5af6c9f | |
parent | 2a338b2fe4aeaedb276c337c08553e95dd54209a (diff) | |
parent | 2d79ce5f5000640e5f13027ce989e91691653911 (diff) |
Merge "Add master switch to enable/disable RESTRICTED bucket." into rvc-dev
4 files changed, 107 insertions, 4 deletions
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 cb5cb175ff24..980372d58f33 100644 --- a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java +++ b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java @@ -293,6 +293,13 @@ public class AppStandbyController implements AppStandbyInternal { * {@link #setAppStandbyBucket(String, int, int, int, int)} will not be propagated. */ boolean mLinkCrossProfileApps; + /** + * Whether we should allow apps into the + * {@link android.app.usage.UsageStatsManager#STANDBY_BUCKET_RESTRICTED} bucket or not. + * If false, any attempts to put an app into the bucket will put the app into the + * {@link android.app.usage.UsageStatsManager#STANDBY_BUCKET_RARE} bucket instead. + */ + private boolean mAllowRestrictedBucket; private volatile boolean mAppIdleEnabled; private boolean mIsCharging; @@ -688,6 +695,10 @@ public class AppStandbyController implements AppStandbyInternal { return; } final int oldBucket = app.currentBucket; + if (oldBucket == STANDBY_BUCKET_NEVER) { + // None of this should bring an app out of the NEVER bucket. + return; + } int newBucket = Math.max(oldBucket, STANDBY_BUCKET_ACTIVE); // Undo EXEMPTED boolean predictionLate = predictionTimedOut(app, elapsedRealtime); // Compute age-based bucket @@ -743,11 +754,18 @@ public class AppStandbyController implements AppStandbyInternal { Slog.d(TAG, "Bringing down to RESTRICTED due to timeout"); } } + if (newBucket == STANDBY_BUCKET_RESTRICTED && !mAllowRestrictedBucket) { + newBucket = STANDBY_BUCKET_RARE; + // Leave the reason alone. + if (DEBUG) { + Slog.d(TAG, "Bringing up from RESTRICTED to RARE due to off switch"); + } + } if (DEBUG) { Slog.d(TAG, " Old bucket=" + oldBucket + ", newBucket=" + newBucket); } - if (oldBucket < newBucket || predictionLate) { + if (oldBucket != newBucket || predictionLate) { mAppIdleHistory.setAppStandbyBucket(packageName, userId, elapsedRealtime, newBucket, reason); maybeInformListeners(packageName, userId, elapsedRealtime, @@ -1197,8 +1215,8 @@ public class AppStandbyController implements AppStandbyInternal { final int reason = REASON_MAIN_FORCED_BY_SYSTEM | (REASON_SUB_MASK & restrictReason); final long nowElapsed = mInjector.elapsedRealtime(); - setAppStandbyBucket(packageName, userId, STANDBY_BUCKET_RESTRICTED, reason, - nowElapsed, false); + final int bucket = mAllowRestrictedBucket ? STANDBY_BUCKET_RESTRICTED : STANDBY_BUCKET_RARE; + setAppStandbyBucket(packageName, userId, bucket, reason, nowElapsed, false); } @Override @@ -1268,6 +1286,9 @@ public class AppStandbyController implements AppStandbyInternal { Slog.e(TAG, "Tried to set bucket of uninstalled app: " + packageName); return; } + if (newBucket == STANDBY_BUCKET_RESTRICTED && !mAllowRestrictedBucket) { + newBucket = STANDBY_BUCKET_RARE; + } AppIdleHistory.AppUsageHistory app = mAppIdleHistory.getAppUsageHistory(packageName, userId, elapsedRealtime); boolean predicted = (reason & REASON_MAIN_MASK) == REASON_MAIN_PREDICTED; @@ -1386,6 +1407,7 @@ public class AppStandbyController implements AppStandbyInternal { Slog.d(TAG, " Keeping at WORKING_SET due to min timeout"); } } else if (newBucket == STANDBY_BUCKET_RARE + && mAllowRestrictedBucket && getBucketForLocked(packageName, userId, elapsedRealtime) == STANDBY_BUCKET_RESTRICTED) { // Prediction doesn't think the app will be used anytime soon and @@ -1727,6 +1749,8 @@ public class AppStandbyController implements AppStandbyInternal { pw.println(); pw.print("mAppIdleEnabled="); pw.print(mAppIdleEnabled); + pw.print(" mAllowRestrictedBucket="); + pw.print(mAllowRestrictedBucket); pw.print(" mIsCharging="); pw.print(mIsCharging); pw.println(); @@ -1828,6 +1852,12 @@ public class AppStandbyController implements AppStandbyInternal { return mPowerWhitelistManager.isWhitelisted(packageName, false); } + boolean isRestrictedBucketEnabled() { + return Global.getInt(mContext.getContentResolver(), + Global.ENABLE_RESTRICTED_BUCKET, + Global.DEFAULT_ENABLE_RESTRICTED_BUCKET) == 1; + } + File getDataSystemDirectory() { return Environment.getDataSystemDirectory(); } @@ -2066,6 +2096,8 @@ public class AppStandbyController implements AppStandbyInternal { final ContentResolver cr = mContext.getContentResolver(); cr.registerContentObserver(Global.getUriFor(Global.APP_IDLE_CONSTANTS), false, this); cr.registerContentObserver(Global.getUriFor(Global.APP_STANDBY_ENABLED), false, this); + cr.registerContentObserver(Global.getUriFor(Global.ENABLE_RESTRICTED_BUCKET), + false, this); cr.registerContentObserver(Global.getUriFor(Global.ADAPTIVE_BATTERY_MANAGEMENT_ENABLED), false, this); } @@ -2164,6 +2196,8 @@ public class AppStandbyController implements AppStandbyInternal { mLinkCrossProfileApps = mParser.getBoolean( KEY_CROSS_PROFILE_APPS_SHARE_STANDBY_BUCKETS, DEFAULT_CROSS_PROFILE_APPS_SHARE_STANDBY_BUCKETS); + + mAllowRestrictedBucket = mInjector.isRestrictedBucketEnabled(); } // Check if app_idle_enabled has changed. Do this after getting the rest of the settings diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index c0d0c21af1ab..ae88ba5e08c5 100755 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -11956,8 +11956,24 @@ public final class Settings { "adaptive_battery_management_enabled"; /** + * Whether or not apps are allowed into the + * {@link android.app.usage.UsageStatsManager#STANDBY_BUCKET_RESTRICTED} bucket. + * Type: int (0 for false, 1 for true) + * Default: {@value #DEFAULT_ENABLE_RESTRICTED_BUCKET} + * + * @hide + */ + public static final String ENABLE_RESTRICTED_BUCKET = "enable_restricted_bucket"; + + /** + * @see #ENABLE_RESTRICTED_BUCKET + * @hide + */ + public static final int DEFAULT_ENABLE_RESTRICTED_BUCKET = 1; + + /** * Whether or not app auto restriction is enabled. When it is enabled, settings app will - * auto restrict the app if it has bad behavior(e.g. hold wakelock for long time). + * auto restrict the app if it has bad behavior (e.g. hold wakelock for long time). * * Type: boolean (0 for false, 1 for true) * Default: 1 diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java index 4a9eba2202e3..29c31eaddfa6 100644 --- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java +++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java @@ -264,6 +264,7 @@ public class SettingsBackupTest { Settings.Global.ENABLE_DELETION_HELPER_NO_THRESHOLD_TOGGLE, Settings.Global.ENABLE_DISKSTATS_LOGGING, Settings.Global.ENABLE_EPHEMERAL_FEATURE, + Settings.Global.ENABLE_RESTRICTED_BUCKET, Settings.Global.DYNAMIC_POWER_SAVINGS_ENABLED, Settings.Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD, Settings.Global.SMART_REPLIES_IN_NOTIFICATIONS_FLAGS, diff --git a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java index 6718db768fdb..48e22f6c685c 100644 --- a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java +++ b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java @@ -165,6 +165,7 @@ public class AppStandbyControllerTests { long mElapsedRealtime; boolean mIsAppIdleEnabled = true; boolean mIsCharging; + boolean mIsRestrictedBucketEnabled = true; List<String> mNonIdleWhitelistApps = new ArrayList<>(); boolean mDisplayOn; DisplayManager.DisplayListener mDisplayListener; @@ -212,6 +213,11 @@ public class AppStandbyControllerTests { } @Override + boolean isRestrictedBucketEnabled() { + return mIsRestrictedBucketEnabled; + } + + @Override File getDataSystemDirectory() { return new File(getContext().getFilesDir(), Long.toString(Math.randomLongInternal())); } @@ -511,6 +517,10 @@ public class AppStandbyControllerTests { assertEquals(bucket, getStandbyBucket(mController, PACKAGE_1)); } + private void assertNotBucket(int bucket) { + assertNotEquals(bucket, getStandbyBucket(mController, PACKAGE_1)); + } + @Test public void testBuckets() throws Exception { assertTimeout(mController, 0, STANDBY_BUCKET_NEVER); @@ -946,6 +956,48 @@ public class AppStandbyControllerTests { } @Test + public void testRestrictedBucketDisabled() { + mInjector.mIsRestrictedBucketEnabled = false; + // Get the controller to read the new value. Capturing the ContentObserver isn't possible + // at the moment. + mController.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY); + + reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1); + mInjector.mElapsedRealtime += RESTRICTED_THRESHOLD; + + // Nothing should be able to put it into the RESTRICTED bucket. + mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED, + REASON_MAIN_TIMEOUT); + assertNotBucket(STANDBY_BUCKET_RESTRICTED); + mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED, + REASON_MAIN_PREDICTED); + assertNotBucket(STANDBY_BUCKET_RESTRICTED); + mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED, + REASON_MAIN_FORCED_BY_SYSTEM); + assertNotBucket(STANDBY_BUCKET_RESTRICTED); + mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED, + REASON_MAIN_FORCED_BY_USER); + assertNotBucket(STANDBY_BUCKET_RESTRICTED); + } + + @Test + public void testRestrictedBucket_EnabledToDisabled() { + reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1); + mInjector.mElapsedRealtime += RESTRICTED_THRESHOLD; + mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RESTRICTED, + REASON_MAIN_FORCED_BY_SYSTEM); + assertBucket(STANDBY_BUCKET_RESTRICTED); + + mInjector.mIsRestrictedBucketEnabled = false; + // Get the controller to read the new value. Capturing the ContentObserver isn't possible + // at the moment. + mController.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY); + + mController.checkIdleStates(USER_ID); + assertNotBucket(STANDBY_BUCKET_RESTRICTED); + } + + @Test public void testPredictionRaiseFromRestrictedTimeout_highBucket() { reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1); |