Merge "Don't auto move into restricted bucket if there's a recent interaction" into tm-dev
This commit is contained in:
@@ -67,6 +67,7 @@ import android.util.Pair;
|
||||
import android.util.Slog;
|
||||
import android.util.SparseArray;
|
||||
import android.util.SparseBooleanArray;
|
||||
import android.util.SparseLongArray;
|
||||
import android.util.TimeUtils;
|
||||
import android.util.proto.ProtoOutputStream;
|
||||
|
||||
@@ -360,6 +361,7 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
|
||||
mUidBatteryUsageInWindow.removeAt(i);
|
||||
}
|
||||
}
|
||||
mInjector.getPolicy().onUserRemovedLocked(userId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -368,6 +370,7 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
|
||||
synchronized (mLock) {
|
||||
mUidBatteryUsage.delete(uid);
|
||||
mUidBatteryUsageInWindow.delete(uid);
|
||||
mInjector.getPolicy().onUidRemovedLocked(uid);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1207,6 +1210,14 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
|
||||
static final String KEY_BG_CURRENT_DRAIN_WINDOW =
|
||||
DEVICE_CONFIG_SUBNAMESPACE_PREFIX + "current_drain_window";
|
||||
|
||||
/**
|
||||
* The grace period after an interaction event with the app, if the background current
|
||||
* drain goes beyond the threshold within that period, the system won't apply the
|
||||
* restrictions.
|
||||
*/
|
||||
static final String KEY_BG_CURRENT_DRAIN_INTERACTION_GRACE_PERIOD =
|
||||
DEVICE_CONFIG_SUBNAMESPACE_PREFIX + "current_drain_interaction_grace_period";
|
||||
|
||||
/**
|
||||
* Similar to {@link #KEY_BG_CURRENT_DRAIN_THRESHOLD_TO_RESTRICTED_BUCKET}, but a higher
|
||||
* value for the legitimate cases with higher background current drain.
|
||||
@@ -1309,6 +1320,11 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
|
||||
*/
|
||||
final long mDefaultBgCurrentDrainWindowMs;
|
||||
|
||||
/**
|
||||
* Default value to {@link #mBgCurrentDrainInteractionGracePeriodMs}.
|
||||
*/
|
||||
final long mDefaultBgCurrentDrainInteractionGracePeriodMs;
|
||||
|
||||
/**
|
||||
* Default value to the {@link #INDEX_HIGH_CURRENT_DRAIN_THRESHOLD} of
|
||||
* the {@link #mBgCurrentDrainRestrictedBucketThreshold}.
|
||||
@@ -1393,6 +1409,11 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
|
||||
*/
|
||||
volatile long mBgCurrentDrainWindowMs;
|
||||
|
||||
/**
|
||||
* @see #KEY_BG_CURRENT_DRAIN_INTERACTION_GRACE_PERIOD.
|
||||
*/
|
||||
volatile long mBgCurrentDrainInteractionGracePeriodMs;
|
||||
|
||||
/**
|
||||
* @see #KEY_BG_CURRENT_DRAIN_MEDIA_PLAYBACK_MIN_DURATION.
|
||||
*/
|
||||
@@ -1455,6 +1476,12 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
|
||||
private final SparseArray<Pair<long[], ImmutableBatteryUsage[]>> mHighBgBatteryPackages =
|
||||
new SparseArray<>();
|
||||
|
||||
/**
|
||||
* The timestamp of the last interaction, key is the UID.
|
||||
*/
|
||||
@GuardedBy("mLock")
|
||||
private final SparseLongArray mLastInteractionTime = new SparseLongArray();
|
||||
|
||||
@NonNull
|
||||
private final Object mLock;
|
||||
|
||||
@@ -1478,6 +1505,7 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
|
||||
isLowRamDeviceStatic() ? val[1] : val[0];
|
||||
mDefaultBgCurrentDrainWindowMs = resources.getInteger(
|
||||
R.integer.config_bg_current_drain_window) * 1_000;
|
||||
mDefaultBgCurrentDrainInteractionGracePeriodMs = mDefaultBgCurrentDrainWindowMs;
|
||||
val = getFloatArray(resources.obtainTypedArray(
|
||||
R.array.config_bg_current_drain_high_threshold_to_restricted_bucket));
|
||||
mDefaultBgCurrentDrainRestrictedBucketHighThreshold =
|
||||
@@ -1511,6 +1539,8 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
|
||||
mBgCurrentDrainBgRestrictedThreshold[1] =
|
||||
mDefaultBgCurrentDrainBgRestrictedHighThreshold;
|
||||
mBgCurrentDrainWindowMs = mDefaultBgCurrentDrainWindowMs;
|
||||
mBgCurrentDrainInteractionGracePeriodMs =
|
||||
mDefaultBgCurrentDrainInteractionGracePeriodMs;
|
||||
mBgCurrentDrainMediaPlaybackMinDuration =
|
||||
mDefaultBgCurrentDrainMediaPlaybackMinDuration;
|
||||
mBgCurrentDrainLocationMinDuration = mDefaultBgCurrentDrainLocationMinDuration;
|
||||
@@ -1542,6 +1572,9 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
|
||||
case KEY_BG_CURRENT_DRAIN_WINDOW:
|
||||
updateCurrentDrainWindow();
|
||||
break;
|
||||
case KEY_BG_CURRENT_DRAIN_INTERACTION_GRACE_PERIOD:
|
||||
updateCurrentDrainInteractionGracePeriod();
|
||||
break;
|
||||
case KEY_BG_CURRENT_DRAIN_MEDIA_PLAYBACK_MIN_DURATION:
|
||||
updateCurrentDrainMediaPlaybackMinDuration();
|
||||
break;
|
||||
@@ -1626,6 +1659,13 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
|
||||
mDefaultBgCurrentDrainWindowMs);
|
||||
}
|
||||
|
||||
private void updateCurrentDrainInteractionGracePeriod() {
|
||||
mBgCurrentDrainInteractionGracePeriodMs = DeviceConfig.getLong(
|
||||
DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
|
||||
KEY_BG_CURRENT_DRAIN_INTERACTION_GRACE_PERIOD,
|
||||
mDefaultBgCurrentDrainInteractionGracePeriodMs);
|
||||
}
|
||||
|
||||
private void updateCurrentDrainMediaPlaybackMinDuration() {
|
||||
mBgCurrentDrainMediaPlaybackMinDuration = DeviceConfig.getLong(
|
||||
DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
|
||||
@@ -1668,6 +1708,7 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
|
||||
super.onSystemReady();
|
||||
updateCurrentDrainThreshold();
|
||||
updateCurrentDrainWindow();
|
||||
updateCurrentDrainInteractionGracePeriod();
|
||||
updateCurrentDrainMediaPlaybackMinDuration();
|
||||
updateCurrentDrainLocationMinDuration();
|
||||
updateCurrentDrainEventDurationBasedThresholdEnabled();
|
||||
@@ -1685,8 +1726,10 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
|
||||
synchronized (mLock) {
|
||||
final Pair<long[], ImmutableBatteryUsage[]> pair = mHighBgBatteryPackages.get(uid);
|
||||
if (pair != null) {
|
||||
final long lastInteractionTime = mLastInteractionTime.get(uid, 0L);
|
||||
final long[] ts = pair.first;
|
||||
final int restrictedLevel = ts[TIME_STAMP_INDEX_RESTRICTED_BUCKET] > 0
|
||||
final int restrictedLevel = ts[TIME_STAMP_INDEX_RESTRICTED_BUCKET]
|
||||
> (lastInteractionTime + mBgCurrentDrainInteractionGracePeriodMs)
|
||||
&& mTracker.mAppRestrictionController.isAutoRestrictAbusiveAppEnabled()
|
||||
? RESTRICTION_LEVEL_RESTRICTED_BUCKET
|
||||
: RESTRICTION_LEVEL_ADAPTIVE_BUCKET;
|
||||
@@ -1777,6 +1820,7 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
|
||||
// We're already in the background restricted level, nothing more we could do.
|
||||
return;
|
||||
}
|
||||
final long lastInteractionTime = mLastInteractionTime.get(uid, 0L);
|
||||
final long now = SystemClock.elapsedRealtime();
|
||||
final int thresholdIndex = getCurrentDrainThresholdIndex(uid, now,
|
||||
mBgCurrentDrainWindowMs);
|
||||
@@ -1788,13 +1832,17 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
|
||||
long[] ts = null;
|
||||
ImmutableBatteryUsage[] usages = null;
|
||||
if (rbPercentage >= rbThreshold) {
|
||||
// New findings to us, track it and let the controller know.
|
||||
ts = new long[TIME_STAMP_INDEX_LAST];
|
||||
ts[TIME_STAMP_INDEX_RESTRICTED_BUCKET] = now;
|
||||
usages = new ImmutableBatteryUsage[TIME_STAMP_INDEX_LAST];
|
||||
usages[TIME_STAMP_INDEX_RESTRICTED_BUCKET] = usage;
|
||||
mHighBgBatteryPackages.put(uid, Pair.create(ts, usages));
|
||||
notifyController = excessive = true;
|
||||
if (now > lastInteractionTime + mBgCurrentDrainInteractionGracePeriodMs) {
|
||||
// New findings to us, track it and let the controller know.
|
||||
ts = new long[TIME_STAMP_INDEX_LAST];
|
||||
ts[TIME_STAMP_INDEX_RESTRICTED_BUCKET] = now;
|
||||
usages = new ImmutableBatteryUsage[TIME_STAMP_INDEX_LAST];
|
||||
usages[TIME_STAMP_INDEX_RESTRICTED_BUCKET] = usage;
|
||||
mHighBgBatteryPackages.put(uid, Pair.create(ts, usages));
|
||||
// It's beeen long enough since last interaction with this app.
|
||||
notifyController = true;
|
||||
}
|
||||
excessive = true;
|
||||
}
|
||||
if (decoupleThresholds && brPercentage >= brThreshold) {
|
||||
if (ts == null) {
|
||||
@@ -1812,11 +1860,15 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
|
||||
final long[] ts = pair.first;
|
||||
final long lastRestrictBucketTs = ts[TIME_STAMP_INDEX_RESTRICTED_BUCKET];
|
||||
if (rbPercentage >= rbThreshold) {
|
||||
if (lastRestrictBucketTs == 0) {
|
||||
ts[TIME_STAMP_INDEX_RESTRICTED_BUCKET] = now;
|
||||
pair.second[TIME_STAMP_INDEX_RESTRICTED_BUCKET] = usage;
|
||||
if (now > lastInteractionTime + mBgCurrentDrainInteractionGracePeriodMs) {
|
||||
if (lastRestrictBucketTs == 0) {
|
||||
ts[TIME_STAMP_INDEX_RESTRICTED_BUCKET] = now;
|
||||
pair.second[TIME_STAMP_INDEX_RESTRICTED_BUCKET] = usage;
|
||||
}
|
||||
// It's been long enough since last interaction with this app.
|
||||
notifyController = true;
|
||||
}
|
||||
notifyController = excessive = true;
|
||||
excessive = true;
|
||||
} else {
|
||||
// It's actually back to normal, but we don't untrack it until
|
||||
// explicit user interactions, because the restriction could be the cause
|
||||
@@ -1833,7 +1885,7 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
|
||||
&& (now > lastRestrictBucketTs + mBgCurrentDrainWindowMs));
|
||||
if (notifyController) {
|
||||
ts[TIME_STAMP_INDEX_BG_RESTRICTED] = now;
|
||||
pair.second[TIME_STAMP_INDEX_RESTRICTED_BUCKET] = usage;
|
||||
pair.second[TIME_STAMP_INDEX_BG_RESTRICTED] = usage;
|
||||
}
|
||||
excessive = true;
|
||||
} else {
|
||||
@@ -1841,7 +1893,7 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
|
||||
// user consent to unrestrict it; or if it's in restricted bucket level,
|
||||
// resetting this won't lift it from that level.
|
||||
ts[TIME_STAMP_INDEX_BG_RESTRICTED] = 0;
|
||||
pair.second[TIME_STAMP_INDEX_RESTRICTED_BUCKET] = null;
|
||||
pair.second[TIME_STAMP_INDEX_BG_RESTRICTED] = null;
|
||||
// Now need to notify the controller.
|
||||
}
|
||||
}
|
||||
@@ -1902,6 +1954,7 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
|
||||
void onUserInteractionStarted(String packageName, int uid) {
|
||||
boolean changed = false;
|
||||
synchronized (mLock) {
|
||||
mLastInteractionTime.put(uid, SystemClock.elapsedRealtime());
|
||||
final int curLevel = mTracker.mAppRestrictionController.getRestrictionLevel(
|
||||
uid, packageName);
|
||||
if (curLevel == RESTRICTION_LEVEL_BACKGROUND_RESTRICTED) {
|
||||
@@ -1940,9 +1993,30 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
|
||||
@VisibleForTesting
|
||||
void reset() {
|
||||
mHighBgBatteryPackages.clear();
|
||||
mLastInteractionTime.clear();
|
||||
mTracker.reset();
|
||||
}
|
||||
|
||||
@GuardedBy("mLock")
|
||||
void onUserRemovedLocked(final @UserIdInt int userId) {
|
||||
for (int i = mHighBgBatteryPackages.size() - 1; i >= 0; i--) {
|
||||
if (UserHandle.getUserId(mHighBgBatteryPackages.keyAt(i)) == userId) {
|
||||
mHighBgBatteryPackages.removeAt(i);
|
||||
}
|
||||
}
|
||||
for (int i = mLastInteractionTime.size() - 1; i >= 0; i--) {
|
||||
if (UserHandle.getUserId(mLastInteractionTime.keyAt(i)) == userId) {
|
||||
mLastInteractionTime.removeAt(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@GuardedBy("mLock")
|
||||
void onUidRemovedLocked(final int uid) {
|
||||
mHighBgBatteryPackages.remove(uid);
|
||||
mLastInteractionTime.delete(uid);
|
||||
}
|
||||
|
||||
@Override
|
||||
void dump(PrintWriter pw, String prefix) {
|
||||
pw.print(prefix);
|
||||
@@ -1976,6 +2050,10 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
|
||||
pw.print('=');
|
||||
pw.println(mBgCurrentDrainWindowMs);
|
||||
pw.print(prefix);
|
||||
pw.print(KEY_BG_CURRENT_DRAIN_INTERACTION_GRACE_PERIOD);
|
||||
pw.print('=');
|
||||
pw.println(mBgCurrentDrainInteractionGracePeriodMs);
|
||||
pw.print(prefix);
|
||||
pw.print(KEY_BG_CURRENT_DRAIN_MEDIA_PLAYBACK_MIN_DURATION);
|
||||
pw.print('=');
|
||||
pw.println(mBgCurrentDrainMediaPlaybackMinDuration);
|
||||
|
||||
@@ -582,6 +582,7 @@ public final class BackgroundRestrictionTest {
|
||||
|
||||
DeviceConfigSession<Boolean> bgCurrentDrainMonitor = null;
|
||||
DeviceConfigSession<Long> bgCurrentDrainWindow = null;
|
||||
DeviceConfigSession<Long> bgCurrentDrainInteractionGracePeriod = null;
|
||||
DeviceConfigSession<Float> bgCurrentDrainRestrictedBucketThreshold = null;
|
||||
DeviceConfigSession<Float> bgCurrentDrainBgRestrictedThreshold = null;
|
||||
DeviceConfigSession<Boolean> bgPromptFgsWithNotiToBgRestricted = null;
|
||||
@@ -617,6 +618,14 @@ public final class BackgroundRestrictionTest {
|
||||
R.integer.config_bg_current_drain_window));
|
||||
bgCurrentDrainWindow.set(windowMs);
|
||||
|
||||
bgCurrentDrainInteractionGracePeriod = new DeviceConfigSession<>(
|
||||
DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
|
||||
AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_INTERACTION_GRACE_PERIOD,
|
||||
DeviceConfig::getLong,
|
||||
(long) mContext.getResources().getInteger(
|
||||
R.integer.config_bg_current_drain_window));
|
||||
bgCurrentDrainInteractionGracePeriod.set(windowMs);
|
||||
|
||||
bgCurrentDrainRestrictedBucketThreshold = new DeviceConfigSession<>(
|
||||
DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
|
||||
AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_THRESHOLD_TO_RESTRICTED_BUCKET,
|
||||
@@ -768,6 +777,32 @@ public final class BackgroundRestrictionTest {
|
||||
|
||||
clearInvocations(mInjector.getAppStandbyInternal());
|
||||
|
||||
// It won't be restricted since user just interacted with it.
|
||||
runTestBgCurrentDrainMonitorOnce(listener, stats, uids,
|
||||
zeros, new double[]{0, restrictBucketThresholdMah - 1},
|
||||
zeros, new double[]{restrictBucketThresholdMah + 1, 0},
|
||||
() -> {
|
||||
doReturn(mCurrentTimeMillis).when(stats).getStatsStartTimestamp();
|
||||
doReturn(mCurrentTimeMillis + windowMs)
|
||||
.when(stats).getStatsEndTimestamp();
|
||||
mCurrentTimeMillis += windowMs + 1;
|
||||
try {
|
||||
listener.verify(timeout, testUid, testPkgName,
|
||||
RESTRICTION_LEVEL_RESTRICTED_BUCKET);
|
||||
fail("There shouldn't be any level change events");
|
||||
} catch (Exception e) {
|
||||
// Expected.
|
||||
}
|
||||
verify(mInjector.getAppStandbyInternal(), never()).restrictApp(
|
||||
eq(testPkgName),
|
||||
eq(testUser),
|
||||
anyInt(), anyInt());
|
||||
});
|
||||
|
||||
// Sleep a while.
|
||||
Thread.sleep(windowMs);
|
||||
clearInvocations(mInjector.getAppStandbyInternal());
|
||||
// Now it should have been restricted.
|
||||
runTestBgCurrentDrainMonitorOnce(listener, stats, uids,
|
||||
zeros, new double[]{0, restrictBucketThresholdMah - 1},
|
||||
zeros, new double[]{restrictBucketThresholdMah + 1, 0},
|
||||
@@ -1061,6 +1096,7 @@ public final class BackgroundRestrictionTest {
|
||||
} finally {
|
||||
closeIfNotNull(bgCurrentDrainMonitor);
|
||||
closeIfNotNull(bgCurrentDrainWindow);
|
||||
closeIfNotNull(bgCurrentDrainInteractionGracePeriod);
|
||||
closeIfNotNull(bgCurrentDrainRestrictedBucketThreshold);
|
||||
closeIfNotNull(bgCurrentDrainBgRestrictedThreshold);
|
||||
closeIfNotNull(bgPromptFgsWithNotiToBgRestricted);
|
||||
@@ -1610,6 +1646,7 @@ public final class BackgroundRestrictionTest {
|
||||
|
||||
DeviceConfigSession<Boolean> bgCurrentDrainMonitor = null;
|
||||
DeviceConfigSession<Long> bgCurrentDrainWindow = null;
|
||||
DeviceConfigSession<Long> bgCurrentDrainInteractionGracePeriod = null;
|
||||
DeviceConfigSession<Float> bgCurrentDrainRestrictedBucketThreshold = null;
|
||||
DeviceConfigSession<Float> bgCurrentDrainBgRestrictedThreshold = null;
|
||||
DeviceConfigSession<Float> bgCurrentDrainRestrictedBucketHighThreshold = null;
|
||||
@@ -1655,6 +1692,14 @@ public final class BackgroundRestrictionTest {
|
||||
R.integer.config_bg_current_drain_window));
|
||||
bgCurrentDrainWindow.set(windowMs);
|
||||
|
||||
bgCurrentDrainInteractionGracePeriod = new DeviceConfigSession<>(
|
||||
DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
|
||||
AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_INTERACTION_GRACE_PERIOD,
|
||||
DeviceConfig::getLong,
|
||||
(long) mContext.getResources().getInteger(
|
||||
R.integer.config_bg_current_drain_window));
|
||||
bgCurrentDrainInteractionGracePeriod.set(windowMs);
|
||||
|
||||
bgCurrentDrainRestrictedBucketThreshold = new DeviceConfigSession<>(
|
||||
DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
|
||||
AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_THRESHOLD_TO_RESTRICTED_BUCKET,
|
||||
@@ -2176,6 +2221,7 @@ public final class BackgroundRestrictionTest {
|
||||
} finally {
|
||||
closeIfNotNull(bgCurrentDrainMonitor);
|
||||
closeIfNotNull(bgCurrentDrainWindow);
|
||||
closeIfNotNull(bgCurrentDrainInteractionGracePeriod);
|
||||
closeIfNotNull(bgCurrentDrainRestrictedBucketThreshold);
|
||||
closeIfNotNull(bgCurrentDrainBgRestrictedThreshold);
|
||||
closeIfNotNull(bgCurrentDrainRestrictedBucketHighThreshold);
|
||||
|
||||
Reference in New Issue
Block a user