Merge "Add master switch to enable/disable RESTRICTED bucket." into rvc-dev
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user