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.
|
* {@link #setAppStandbyBucket(String, int, int, int, int)} will not be propagated.
|
||||||
*/
|
*/
|
||||||
boolean mLinkCrossProfileApps;
|
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 volatile boolean mAppIdleEnabled;
|
||||||
private boolean mIsCharging;
|
private boolean mIsCharging;
|
||||||
@@ -688,6 +695,10 @@ public class AppStandbyController implements AppStandbyInternal {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final int oldBucket = app.currentBucket;
|
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
|
int newBucket = Math.max(oldBucket, STANDBY_BUCKET_ACTIVE); // Undo EXEMPTED
|
||||||
boolean predictionLate = predictionTimedOut(app, elapsedRealtime);
|
boolean predictionLate = predictionTimedOut(app, elapsedRealtime);
|
||||||
// Compute age-based bucket
|
// Compute age-based bucket
|
||||||
@@ -743,11 +754,18 @@ public class AppStandbyController implements AppStandbyInternal {
|
|||||||
Slog.d(TAG, "Bringing down to RESTRICTED due to timeout");
|
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) {
|
if (DEBUG) {
|
||||||
Slog.d(TAG, " Old bucket=" + oldBucket
|
Slog.d(TAG, " Old bucket=" + oldBucket
|
||||||
+ ", newBucket=" + newBucket);
|
+ ", newBucket=" + newBucket);
|
||||||
}
|
}
|
||||||
if (oldBucket < newBucket || predictionLate) {
|
if (oldBucket != newBucket || predictionLate) {
|
||||||
mAppIdleHistory.setAppStandbyBucket(packageName, userId,
|
mAppIdleHistory.setAppStandbyBucket(packageName, userId,
|
||||||
elapsedRealtime, newBucket, reason);
|
elapsedRealtime, newBucket, reason);
|
||||||
maybeInformListeners(packageName, userId, elapsedRealtime,
|
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 int reason = REASON_MAIN_FORCED_BY_SYSTEM | (REASON_SUB_MASK & restrictReason);
|
||||||
final long nowElapsed = mInjector.elapsedRealtime();
|
final long nowElapsed = mInjector.elapsedRealtime();
|
||||||
setAppStandbyBucket(packageName, userId, STANDBY_BUCKET_RESTRICTED, reason,
|
final int bucket = mAllowRestrictedBucket ? STANDBY_BUCKET_RESTRICTED : STANDBY_BUCKET_RARE;
|
||||||
nowElapsed, false);
|
setAppStandbyBucket(packageName, userId, bucket, reason, nowElapsed, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -1268,6 +1286,9 @@ public class AppStandbyController implements AppStandbyInternal {
|
|||||||
Slog.e(TAG, "Tried to set bucket of uninstalled app: " + packageName);
|
Slog.e(TAG, "Tried to set bucket of uninstalled app: " + packageName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (newBucket == STANDBY_BUCKET_RESTRICTED && !mAllowRestrictedBucket) {
|
||||||
|
newBucket = STANDBY_BUCKET_RARE;
|
||||||
|
}
|
||||||
AppIdleHistory.AppUsageHistory app = mAppIdleHistory.getAppUsageHistory(packageName,
|
AppIdleHistory.AppUsageHistory app = mAppIdleHistory.getAppUsageHistory(packageName,
|
||||||
userId, elapsedRealtime);
|
userId, elapsedRealtime);
|
||||||
boolean predicted = (reason & REASON_MAIN_MASK) == REASON_MAIN_PREDICTED;
|
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");
|
Slog.d(TAG, " Keeping at WORKING_SET due to min timeout");
|
||||||
}
|
}
|
||||||
} else if (newBucket == STANDBY_BUCKET_RARE
|
} else if (newBucket == STANDBY_BUCKET_RARE
|
||||||
|
&& mAllowRestrictedBucket
|
||||||
&& getBucketForLocked(packageName, userId, elapsedRealtime)
|
&& getBucketForLocked(packageName, userId, elapsedRealtime)
|
||||||
== STANDBY_BUCKET_RESTRICTED) {
|
== STANDBY_BUCKET_RESTRICTED) {
|
||||||
// Prediction doesn't think the app will be used anytime soon and
|
// Prediction doesn't think the app will be used anytime soon and
|
||||||
@@ -1727,6 +1749,8 @@ public class AppStandbyController implements AppStandbyInternal {
|
|||||||
|
|
||||||
pw.println();
|
pw.println();
|
||||||
pw.print("mAppIdleEnabled="); pw.print(mAppIdleEnabled);
|
pw.print("mAppIdleEnabled="); pw.print(mAppIdleEnabled);
|
||||||
|
pw.print(" mAllowRestrictedBucket=");
|
||||||
|
pw.print(mAllowRestrictedBucket);
|
||||||
pw.print(" mIsCharging=");
|
pw.print(" mIsCharging=");
|
||||||
pw.print(mIsCharging);
|
pw.print(mIsCharging);
|
||||||
pw.println();
|
pw.println();
|
||||||
@@ -1828,6 +1852,12 @@ public class AppStandbyController implements AppStandbyInternal {
|
|||||||
return mPowerWhitelistManager.isWhitelisted(packageName, false);
|
return mPowerWhitelistManager.isWhitelisted(packageName, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean isRestrictedBucketEnabled() {
|
||||||
|
return Global.getInt(mContext.getContentResolver(),
|
||||||
|
Global.ENABLE_RESTRICTED_BUCKET,
|
||||||
|
Global.DEFAULT_ENABLE_RESTRICTED_BUCKET) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
File getDataSystemDirectory() {
|
File getDataSystemDirectory() {
|
||||||
return Environment.getDataSystemDirectory();
|
return Environment.getDataSystemDirectory();
|
||||||
}
|
}
|
||||||
@@ -2066,6 +2096,8 @@ public class AppStandbyController implements AppStandbyInternal {
|
|||||||
final ContentResolver cr = mContext.getContentResolver();
|
final ContentResolver cr = mContext.getContentResolver();
|
||||||
cr.registerContentObserver(Global.getUriFor(Global.APP_IDLE_CONSTANTS), false, this);
|
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.APP_STANDBY_ENABLED), false, this);
|
||||||
|
cr.registerContentObserver(Global.getUriFor(Global.ENABLE_RESTRICTED_BUCKET),
|
||||||
|
false, this);
|
||||||
cr.registerContentObserver(Global.getUriFor(Global.ADAPTIVE_BATTERY_MANAGEMENT_ENABLED),
|
cr.registerContentObserver(Global.getUriFor(Global.ADAPTIVE_BATTERY_MANAGEMENT_ENABLED),
|
||||||
false, this);
|
false, this);
|
||||||
}
|
}
|
||||||
@@ -2164,6 +2196,8 @@ public class AppStandbyController implements AppStandbyInternal {
|
|||||||
mLinkCrossProfileApps = mParser.getBoolean(
|
mLinkCrossProfileApps = mParser.getBoolean(
|
||||||
KEY_CROSS_PROFILE_APPS_SHARE_STANDBY_BUCKETS,
|
KEY_CROSS_PROFILE_APPS_SHARE_STANDBY_BUCKETS,
|
||||||
DEFAULT_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
|
// 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 =
|
public static final String ADAPTIVE_BATTERY_MANAGEMENT_ENABLED =
|
||||||
"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
|
* 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)
|
* Type: boolean (0 for false, 1 for true)
|
||||||
* Default: 1
|
* Default: 1
|
||||||
|
|||||||
@@ -264,6 +264,7 @@ public class SettingsBackupTest {
|
|||||||
Settings.Global.ENABLE_DELETION_HELPER_NO_THRESHOLD_TOGGLE,
|
Settings.Global.ENABLE_DELETION_HELPER_NO_THRESHOLD_TOGGLE,
|
||||||
Settings.Global.ENABLE_DISKSTATS_LOGGING,
|
Settings.Global.ENABLE_DISKSTATS_LOGGING,
|
||||||
Settings.Global.ENABLE_EPHEMERAL_FEATURE,
|
Settings.Global.ENABLE_EPHEMERAL_FEATURE,
|
||||||
|
Settings.Global.ENABLE_RESTRICTED_BUCKET,
|
||||||
Settings.Global.DYNAMIC_POWER_SAVINGS_ENABLED,
|
Settings.Global.DYNAMIC_POWER_SAVINGS_ENABLED,
|
||||||
Settings.Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD,
|
Settings.Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD,
|
||||||
Settings.Global.SMART_REPLIES_IN_NOTIFICATIONS_FLAGS,
|
Settings.Global.SMART_REPLIES_IN_NOTIFICATIONS_FLAGS,
|
||||||
|
|||||||
@@ -165,6 +165,7 @@ public class AppStandbyControllerTests {
|
|||||||
long mElapsedRealtime;
|
long mElapsedRealtime;
|
||||||
boolean mIsAppIdleEnabled = true;
|
boolean mIsAppIdleEnabled = true;
|
||||||
boolean mIsCharging;
|
boolean mIsCharging;
|
||||||
|
boolean mIsRestrictedBucketEnabled = true;
|
||||||
List<String> mNonIdleWhitelistApps = new ArrayList<>();
|
List<String> mNonIdleWhitelistApps = new ArrayList<>();
|
||||||
boolean mDisplayOn;
|
boolean mDisplayOn;
|
||||||
DisplayManager.DisplayListener mDisplayListener;
|
DisplayManager.DisplayListener mDisplayListener;
|
||||||
@@ -211,6 +212,11 @@ public class AppStandbyControllerTests {
|
|||||||
return mNonIdleWhitelistApps.contains(packageName);
|
return mNonIdleWhitelistApps.contains(packageName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
boolean isRestrictedBucketEnabled() {
|
||||||
|
return mIsRestrictedBucketEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
File getDataSystemDirectory() {
|
File getDataSystemDirectory() {
|
||||||
return new File(getContext().getFilesDir(), Long.toString(Math.randomLongInternal()));
|
return new File(getContext().getFilesDir(), Long.toString(Math.randomLongInternal()));
|
||||||
@@ -511,6 +517,10 @@ public class AppStandbyControllerTests {
|
|||||||
assertEquals(bucket, getStandbyBucket(mController, PACKAGE_1));
|
assertEquals(bucket, getStandbyBucket(mController, PACKAGE_1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void assertNotBucket(int bucket) {
|
||||||
|
assertNotEquals(bucket, getStandbyBucket(mController, PACKAGE_1));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBuckets() throws Exception {
|
public void testBuckets() throws Exception {
|
||||||
assertTimeout(mController, 0, STANDBY_BUCKET_NEVER);
|
assertTimeout(mController, 0, STANDBY_BUCKET_NEVER);
|
||||||
@@ -945,6 +955,48 @@ public class AppStandbyControllerTests {
|
|||||||
assertBucket(STANDBY_BUCKET_RESTRICTED);
|
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
|
@Test
|
||||||
public void testPredictionRaiseFromRestrictedTimeout_highBucket() {
|
public void testPredictionRaiseFromRestrictedTimeout_highBucket() {
|
||||||
reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1);
|
reportEvent(mController, USER_INTERACTION, mInjector.mElapsedRealtime, PACKAGE_1);
|
||||||
|
|||||||
Reference in New Issue
Block a user