Merge "Add master switch to enable/disable RESTRICTED bucket." into rvc-dev

This commit is contained in:
Kweku Adams
2020-05-08 15:01:03 +00:00
committed by Android (Google) Code Review
4 changed files with 107 additions and 4 deletions

View File

@@ -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

View File

@@ -11955,9 +11955,25 @@ public final class Settings {
public static final String ADAPTIVE_BATTERY_MANAGEMENT_ENABLED =
"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

View File

@@ -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,

View File

@@ -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;
@@ -211,6 +212,11 @@ public class AppStandbyControllerTests {
return mNonIdleWhitelistApps.contains(packageName);
}
@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);
@@ -945,6 +955,48 @@ public class AppStandbyControllerTests {
assertBucket(STANDBY_BUCKET_RESTRICTED);
}
@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);