Loading services/core/java/com/android/server/am/AppBatteryTracker.java +92 −14 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -360,6 +361,7 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy> mUidBatteryUsageInWindow.removeAt(i); } } mInjector.getPolicy().onUserRemovedLocked(userId); } } Loading @@ -368,6 +370,7 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy> synchronized (mLock) { mUidBatteryUsage.delete(uid); mUidBatteryUsageInWindow.delete(uid); mInjector.getPolicy().onUidRemovedLocked(uid); } } Loading Loading @@ -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. Loading Loading @@ -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}. Loading Loading @@ -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. */ Loading Loading @@ -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; Loading @@ -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 = Loading Loading @@ -1511,6 +1539,8 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy> mBgCurrentDrainBgRestrictedThreshold[1] = mDefaultBgCurrentDrainBgRestrictedHighThreshold; mBgCurrentDrainWindowMs = mDefaultBgCurrentDrainWindowMs; mBgCurrentDrainInteractionGracePeriodMs = mDefaultBgCurrentDrainInteractionGracePeriodMs; mBgCurrentDrainMediaPlaybackMinDuration = mDefaultBgCurrentDrainMediaPlaybackMinDuration; mBgCurrentDrainLocationMinDuration = mDefaultBgCurrentDrainLocationMinDuration; Loading Loading @@ -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; Loading Loading @@ -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, Loading Loading @@ -1668,6 +1708,7 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy> super.onSystemReady(); updateCurrentDrainThreshold(); updateCurrentDrainWindow(); updateCurrentDrainInteractionGracePeriod(); updateCurrentDrainMediaPlaybackMinDuration(); updateCurrentDrainLocationMinDuration(); updateCurrentDrainEventDurationBasedThresholdEnabled(); Loading @@ -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; Loading Loading @@ -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); Loading @@ -1788,13 +1832,17 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy> long[] ts = null; ImmutableBatteryUsage[] usages = null; if (rbPercentage >= rbThreshold) { 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)); notifyController = excessive = true; // It's beeen long enough since last interaction with this app. notifyController = true; } excessive = true; } if (decoupleThresholds && brPercentage >= brThreshold) { if (ts == null) { Loading @@ -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 (now > lastInteractionTime + mBgCurrentDrainInteractionGracePeriodMs) { if (lastRestrictBucketTs == 0) { ts[TIME_STAMP_INDEX_RESTRICTED_BUCKET] = now; pair.second[TIME_STAMP_INDEX_RESTRICTED_BUCKET] = usage; } notifyController = excessive = true; // It's been long enough since last interaction with this app. notifyController = 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 Loading @@ -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 { Loading @@ -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. } } Loading Loading @@ -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) { Loading Loading @@ -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); Loading Loading @@ -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); Loading services/tests/mockingservicestests/src/com/android/server/am/BackgroundRestrictionTest.java +46 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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, Loading Loading @@ -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}, Loading Loading @@ -1061,6 +1096,7 @@ public final class BackgroundRestrictionTest { } finally { closeIfNotNull(bgCurrentDrainMonitor); closeIfNotNull(bgCurrentDrainWindow); closeIfNotNull(bgCurrentDrainInteractionGracePeriod); closeIfNotNull(bgCurrentDrainRestrictedBucketThreshold); closeIfNotNull(bgCurrentDrainBgRestrictedThreshold); closeIfNotNull(bgPromptFgsWithNotiToBgRestricted); Loading Loading @@ -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; Loading Loading @@ -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, Loading Loading @@ -2176,6 +2221,7 @@ public final class BackgroundRestrictionTest { } finally { closeIfNotNull(bgCurrentDrainMonitor); closeIfNotNull(bgCurrentDrainWindow); closeIfNotNull(bgCurrentDrainInteractionGracePeriod); closeIfNotNull(bgCurrentDrainRestrictedBucketThreshold); closeIfNotNull(bgCurrentDrainBgRestrictedThreshold); closeIfNotNull(bgCurrentDrainRestrictedBucketHighThreshold); Loading Loading
services/core/java/com/android/server/am/AppBatteryTracker.java +92 −14 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -360,6 +361,7 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy> mUidBatteryUsageInWindow.removeAt(i); } } mInjector.getPolicy().onUserRemovedLocked(userId); } } Loading @@ -368,6 +370,7 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy> synchronized (mLock) { mUidBatteryUsage.delete(uid); mUidBatteryUsageInWindow.delete(uid); mInjector.getPolicy().onUidRemovedLocked(uid); } } Loading Loading @@ -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. Loading Loading @@ -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}. Loading Loading @@ -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. */ Loading Loading @@ -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; Loading @@ -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 = Loading Loading @@ -1511,6 +1539,8 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy> mBgCurrentDrainBgRestrictedThreshold[1] = mDefaultBgCurrentDrainBgRestrictedHighThreshold; mBgCurrentDrainWindowMs = mDefaultBgCurrentDrainWindowMs; mBgCurrentDrainInteractionGracePeriodMs = mDefaultBgCurrentDrainInteractionGracePeriodMs; mBgCurrentDrainMediaPlaybackMinDuration = mDefaultBgCurrentDrainMediaPlaybackMinDuration; mBgCurrentDrainLocationMinDuration = mDefaultBgCurrentDrainLocationMinDuration; Loading Loading @@ -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; Loading Loading @@ -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, Loading Loading @@ -1668,6 +1708,7 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy> super.onSystemReady(); updateCurrentDrainThreshold(); updateCurrentDrainWindow(); updateCurrentDrainInteractionGracePeriod(); updateCurrentDrainMediaPlaybackMinDuration(); updateCurrentDrainLocationMinDuration(); updateCurrentDrainEventDurationBasedThresholdEnabled(); Loading @@ -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; Loading Loading @@ -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); Loading @@ -1788,13 +1832,17 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy> long[] ts = null; ImmutableBatteryUsage[] usages = null; if (rbPercentage >= rbThreshold) { 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)); notifyController = excessive = true; // It's beeen long enough since last interaction with this app. notifyController = true; } excessive = true; } if (decoupleThresholds && brPercentage >= brThreshold) { if (ts == null) { Loading @@ -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 (now > lastInteractionTime + mBgCurrentDrainInteractionGracePeriodMs) { if (lastRestrictBucketTs == 0) { ts[TIME_STAMP_INDEX_RESTRICTED_BUCKET] = now; pair.second[TIME_STAMP_INDEX_RESTRICTED_BUCKET] = usage; } notifyController = excessive = true; // It's been long enough since last interaction with this app. notifyController = 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 Loading @@ -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 { Loading @@ -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. } } Loading Loading @@ -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) { Loading Loading @@ -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); Loading Loading @@ -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); Loading
services/tests/mockingservicestests/src/com/android/server/am/BackgroundRestrictionTest.java +46 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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, Loading Loading @@ -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}, Loading Loading @@ -1061,6 +1096,7 @@ public final class BackgroundRestrictionTest { } finally { closeIfNotNull(bgCurrentDrainMonitor); closeIfNotNull(bgCurrentDrainWindow); closeIfNotNull(bgCurrentDrainInteractionGracePeriod); closeIfNotNull(bgCurrentDrainRestrictedBucketThreshold); closeIfNotNull(bgCurrentDrainBgRestrictedThreshold); closeIfNotNull(bgPromptFgsWithNotiToBgRestricted); Loading Loading @@ -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; Loading Loading @@ -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, Loading Loading @@ -2176,6 +2221,7 @@ public final class BackgroundRestrictionTest { } finally { closeIfNotNull(bgCurrentDrainMonitor); closeIfNotNull(bgCurrentDrainWindow); closeIfNotNull(bgCurrentDrainInteractionGracePeriod); closeIfNotNull(bgCurrentDrainRestrictedBucketThreshold); closeIfNotNull(bgCurrentDrainBgRestrictedThreshold); closeIfNotNull(bgCurrentDrainRestrictedBucketHighThreshold); Loading