Loading services/core/java/com/android/server/am/ActivityManagerShellCommand.java +13 −7 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_MOD import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_NORMAL; import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.am.AppBatteryTracker.BatteryUsage.BATTERY_USAGE_COUNT; import static com.android.server.am.LowMemDetector.ADJ_MEM_FACTOR_NOTHING; import android.app.ActivityManager; Loading Loading @@ -3256,12 +3257,12 @@ final class ActivityManagerShellCommand extends ShellCommand { return -1; } if (arg == null) { batteryTracker.mDebugUidPercentages.clear(); batteryTracker.clearDebugUidPercentage(); return 0; } String[] pairs = arg.split(","); int[] uids = new int[pairs.length]; double[] values = new double[pairs.length]; double[][] values = new double[pairs.length][]; try { for (int i = 0; i < pairs.length; i++) { String[] pair = pairs[i].split("="); Loading @@ -3270,16 +3271,21 @@ final class ActivityManagerShellCommand extends ShellCommand { return -1; } uids[i] = Integer.parseInt(pair[0]); values[i] = Double.parseDouble(pair[1]); final String[] vals = pair[1].split(":"); if (vals.length != BATTERY_USAGE_COUNT) { getErrPrintWriter().println("Malformed input"); return -1; } values[i] = new double[vals.length]; for (int j = 0; j < vals.length; j++) { values[i][j] = Double.parseDouble(vals[j]); } } } catch (NumberFormatException e) { getErrPrintWriter().println("Malformed input"); return -1; } batteryTracker.mDebugUidPercentages.clear(); for (int i = 0; i < pairs.length; i++) { batteryTracker.mDebugUidPercentages.put(uids[i], values[i]); } batteryTracker.setDebugUidPercentage(uids, values); return 0; } Loading services/core/java/com/android/server/am/AppBatteryExemptionTracker.java +59 −38 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.server.am; import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.am.AppBatteryTracker.BATTERY_USAGE_NONE; import static com.android.server.am.AppRestrictionController.DEVICE_CONFIG_SUBNAMESPACE_PREFIX; import static com.android.server.am.BaseAppStateDurationsTracker.EVENT_NUM; Loading @@ -32,6 +33,8 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.server.am.AppBatteryExemptionTracker.AppBatteryExemptionPolicy; import com.android.server.am.AppBatteryExemptionTracker.UidBatteryStates; import com.android.server.am.AppBatteryTracker.AppBatteryPolicy; import com.android.server.am.AppBatteryTracker.BatteryUsage; import com.android.server.am.AppBatteryTracker.ImmutableBatteryUsage; import com.android.server.am.BaseAppStateDurationsTracker.EventListener; import com.android.server.am.BaseAppStateTimeEvents.BaseTimeEvent; import com.android.server.am.BaseAppStateTracker.Injector; Loading Loading @@ -97,7 +100,8 @@ final class AppBatteryExemptionTracker if (!mInjector.getPolicy().isEnabled()) { return; } final double batteryUsage = mAppRestrictionController.getUidBatteryUsage(uid); final ImmutableBatteryUsage batteryUsage = mAppRestrictionController .getUidBatteryUsage(uid); synchronized (mLock) { UidBatteryStates pkg = mPkgEvents.get(uid, DEFAULT_NAME); if (pkg == null) { Loading @@ -120,22 +124,23 @@ final class AppBatteryExemptionTracker * @return The to-be-exempted battery usage of the given UID in the given duration; it could * be considered as "exempted" due to various use cases, i.e. media playback. */ double getUidBatteryExemptedUsageSince(int uid, long since, long now) { ImmutableBatteryUsage getUidBatteryExemptedUsageSince(int uid, long since, long now) { if (!mInjector.getPolicy().isEnabled()) { return 0.0d; return BATTERY_USAGE_NONE; } Pair<Double, Double> result; Pair<ImmutableBatteryUsage, ImmutableBatteryUsage> result; synchronized (mLock) { final UidBatteryStates pkg = mPkgEvents.get(uid, DEFAULT_NAME); if (pkg == null) { return 0.0d; return BATTERY_USAGE_NONE; } result = pkg.getBatteryUsageSince(since, now); } if (result.second > 0.0d) { if (!result.second.isEmpty()) { // We have an open event (just start, no stop), get the battery usage till now. final double batteryUsage = mAppRestrictionController.getUidBatteryUsage(uid); return result.first + batteryUsage - result.second; final ImmutableBatteryUsage batteryUsage = mAppRestrictionController .getUidBatteryUsage(uid); return result.first.mutate().add(batteryUsage).subtract(result.second).unmutate(); } return result.first; } Loading @@ -156,7 +161,7 @@ final class AppBatteryExemptionTracker * @param batteryUsage The background current drain since the system boots. * @param eventType One of EVENT_TYPE_* defined in the class BaseAppStateDurationsTracker. */ void addEvent(boolean start, long now, double batteryUsage, int eventType) { void addEvent(boolean start, long now, ImmutableBatteryUsage batteryUsage, int eventType) { if (start) { addEvent(start, new UidStateEventWithBattery(start, now, batteryUsage, null), eventType); Loading @@ -169,7 +174,8 @@ final class AppBatteryExemptionTracker return; } addEvent(start, new UidStateEventWithBattery(start, now, batteryUsage - last.getBatteryUsage(), last), eventType); batteryUsage.mutate().subtract(last.getBatteryUsage()).unmutate(), last), eventType); } } Loading @@ -183,34 +189,37 @@ final class AppBatteryExemptionTracker * the second value is the battery usage since the system boots, if there is * an open event(just start, no stop) at the end of the duration. */ Pair<Double, Double> getBatteryUsageSince(long since, long now, int eventType) { Pair<ImmutableBatteryUsage, ImmutableBatteryUsage> getBatteryUsageSince(long since, long now, int eventType) { return getBatteryUsageSince(since, now, mEvents[eventType]); } private Pair<Double, Double> getBatteryUsageSince(long since, long now, LinkedList<UidStateEventWithBattery> events) { private Pair<ImmutableBatteryUsage, ImmutableBatteryUsage> getBatteryUsageSince(long since, long now, LinkedList<UidStateEventWithBattery> events) { if (events == null || events.size() == 0) { return Pair.create(0.0d, 0.0d); return Pair.create(BATTERY_USAGE_NONE, BATTERY_USAGE_NONE); } double batteryUsage = 0.0d; final BatteryUsage batteryUsage = new BatteryUsage(); UidStateEventWithBattery lastEvent = null; for (UidStateEventWithBattery event : events) { lastEvent = event; if (event.getTimestamp() < since || event.isStart()) { continue; } batteryUsage += event.getBatteryUsage(since, Math.min(now, event.getTimestamp())); batteryUsage.add(event.getBatteryUsage(since, Math.min(now, event.getTimestamp()))); if (now <= event.getTimestamp()) { break; } } return Pair.create(batteryUsage, lastEvent.isStart() ? lastEvent.getBatteryUsage() : 0); return Pair.create(batteryUsage.unmutate(), lastEvent.isStart() ? lastEvent.getBatteryUsage() : BATTERY_USAGE_NONE); } /** * @return The aggregated battery usage amongst all the event types we're tracking. */ Pair<Double, Double> getBatteryUsageSince(long since, long now) { Pair<ImmutableBatteryUsage, ImmutableBatteryUsage> getBatteryUsageSince(long since, long now) { LinkedList<UidStateEventWithBattery> result = new LinkedList<>(); for (int i = 0; i < mEvents.length; i++) { result = add(result, mEvents[i]); Loading @@ -236,7 +245,7 @@ final class AppBatteryExemptionTracker UidStateEventWithBattery l = itl.next(), r = itr.next(); LinkedList<UidStateEventWithBattery> dest = new LinkedList<>(); boolean actl = false, actr = false, overlapping = false; double batteryUsage = 0.0d; final BatteryUsage batteryUsage = new BatteryUsage(); long recentActTs = 0, overlappingDuration = 0; for (long lts = l.getTimestamp(), rts = r.getTimestamp(); lts != Long.MAX_VALUE || rts != Long.MAX_VALUE;) { Loading @@ -245,8 +254,8 @@ final class AppBatteryExemptionTracker if (lts == rts) { earliest = l; // we'll deal with the double counting problem later. batteryUsage += actl ? l.getBatteryUsage() : 0.0d; batteryUsage += actr ? r.getBatteryUsage() : 0.0d; if (actl) batteryUsage.add(l.getBatteryUsage()); if (actr) batteryUsage.add(r.getBatteryUsage()); overlappingDuration += overlapping && (actl || actr) ? (lts - recentActTs) : 0; actl = !actl; Loading @@ -255,13 +264,13 @@ final class AppBatteryExemptionTracker rts = itr.hasNext() ? (r = itr.next()).getTimestamp() : Long.MAX_VALUE; } else if (lts < rts) { earliest = l; batteryUsage += actl ? l.getBatteryUsage() : 0.0d; if (actl) batteryUsage.add(l.getBatteryUsage()); overlappingDuration += overlapping && actl ? (lts - recentActTs) : 0; actl = !actl; lts = itl.hasNext() ? (l = itl.next()).getTimestamp() : Long.MAX_VALUE; } else { earliest = r; batteryUsage += actr ? r.getBatteryUsage() : 0.0d; if (actr) batteryUsage.add(r.getBatteryUsage()); overlappingDuration += overlapping && actr ? (rts - recentActTs) : 0; actr = !actr; rts = itr.hasNext() ? (r = itr.next()).getTimestamp() : Long.MAX_VALUE; Loading @@ -281,12 +290,12 @@ final class AppBatteryExemptionTracker final long durationWithOverlapping = duration + overlappingDuration; // Get the proportional batteryUsage. if (durationWithOverlapping != 0) { batteryUsage *= duration * 1.0d / durationWithOverlapping; batteryUsage.scale(duration * 1.0d / durationWithOverlapping); event.update(lastEvent, new ImmutableBatteryUsage(batteryUsage)); } else { batteryUsage = 0.0d; event.update(lastEvent, BATTERY_USAGE_NONE); } event.update(lastEvent, batteryUsage); batteryUsage = 0.0d; batteryUsage.setTo(BATTERY_USAGE_NONE); overlappingDuration = 0; } dest.add(event); Loading Loading @@ -322,14 +331,15 @@ final class AppBatteryExemptionTracker * the system boots if the {@link #mIsStart} is true, but will be the delta of the bg * battery usage since the start event if the {@link #mIsStart} is false. */ private double mBatteryUsage; private @NonNull ImmutableBatteryUsage mBatteryUsage; /** * The peer event of this pair (a pair of start/stop events). */ private @Nullable UidStateEventWithBattery mPeer; UidStateEventWithBattery(boolean isStart, long now, double batteryUsage, UidStateEventWithBattery(boolean isStart, long now, @NonNull ImmutableBatteryUsage batteryUsage, @Nullable UidStateEventWithBattery peer) { super(now); mIsStart = isStart; Loading @@ -355,15 +365,19 @@ final class AppBatteryExemptionTracker } if (mPeer != null) { // Reduce the bg battery usage proportionally. final double batteryUsage = mPeer.getBatteryUsage(); final ImmutableBatteryUsage batteryUsage = mPeer.getBatteryUsage(); mPeer.mBatteryUsage = mPeer.getBatteryUsage(timestamp, mPeer.mTimestamp); // Update the battery data of the start event too. mBatteryUsage += batteryUsage - mPeer.mBatteryUsage; mBatteryUsage = mBatteryUsage.mutate() .add(batteryUsage) .subtract(mPeer.mBatteryUsage) .unmutate(); } mTimestamp = timestamp; } void update(@NonNull UidStateEventWithBattery peer, double batteryUsage) { void update(@NonNull UidStateEventWithBattery peer, @NonNull ImmutableBatteryUsage batteryUsage) { mPeer = peer; peer.mPeer = this; mBatteryUsage = batteryUsage; Loading @@ -373,18 +387,19 @@ final class AppBatteryExemptionTracker return mIsStart; } double getBatteryUsage(long start, long end) { @NonNull ImmutableBatteryUsage getBatteryUsage(long start, long end) { if (mIsStart || start >= mTimestamp || end <= start) { return 0.0d; return BATTERY_USAGE_NONE; } start = Math.max(start, mPeer.mTimestamp); end = Math.min(end, mTimestamp); final long totalDur = mTimestamp - mPeer.mTimestamp; final long inputDur = end - start; return totalDur != 0 ? mBatteryUsage * (1.0d * inputDur) / totalDur : 0.0d; return totalDur != 0 ? (totalDur == inputDur ? mBatteryUsage : mBatteryUsage.mutate() .scale((1.0d * inputDur) / totalDur).unmutate()) : BATTERY_USAGE_NONE; } double getBatteryUsage() { @NonNull ImmutableBatteryUsage getBatteryUsage() { return mBatteryUsage; } Loading @@ -404,14 +419,20 @@ final class AppBatteryExemptionTracker final UidStateEventWithBattery otherEvent = (UidStateEventWithBattery) other; return otherEvent.mIsStart == mIsStart && otherEvent.mTimestamp == mTimestamp && Double.compare(otherEvent.mBatteryUsage, mBatteryUsage) == 0; && mBatteryUsage.equals(otherEvent.mBatteryUsage); } @Override public String toString() { return "UidStateEventWithBattery(" + mIsStart + ", " + mTimestamp + ", " + mBatteryUsage + ")"; } @Override public int hashCode() { return (Boolean.hashCode(mIsStart) * 31 + Long.hashCode(mTimestamp)) * 31 + Double.hashCode(mBatteryUsage); + mBatteryUsage.hashCode(); } } Loading services/core/java/com/android/server/am/AppBatteryTracker.java +495 −94 File changed.Preview size limit exceeded, changes collapsed. Show changes services/core/java/com/android/server/am/AppRestrictionController.java +4 −3 Original line number Diff line number Diff line Loading @@ -142,6 +142,7 @@ import com.android.internal.util.function.TriConsumer; import com.android.server.AppStateTracker; import com.android.server.LocalServices; import com.android.server.SystemConfig; import com.android.server.am.AppBatteryTracker.ImmutableBatteryUsage; import com.android.server.apphibernation.AppHibernationManagerInternal; import com.android.server.pm.UserManagerInternal; import com.android.server.usage.AppStandbyInternal; Loading Loading @@ -1076,7 +1077,7 @@ public final class AppRestrictionController { * @return The to-be-exempted battery usage of the given UID in the given duration; it could * be considered as "exempted" due to various use cases, i.e. media playback. */ double getUidBatteryExemptedUsageSince(int uid, long since, long now) { ImmutableBatteryUsage getUidBatteryExemptedUsageSince(int uid, long since, long now) { return mInjector.getAppBatteryExemptionTracker() .getUidBatteryExemptedUsageSince(uid, since, now); } Loading @@ -1084,7 +1085,7 @@ public final class AppRestrictionController { /** * @return The total battery usage of the given UID since the system boots. */ double getUidBatteryUsage(int uid) { @NonNull ImmutableBatteryUsage getUidBatteryUsage(int uid) { return mInjector.getUidBatteryUsageProvider().getUidBatteryUsage(uid); } Loading @@ -1092,7 +1093,7 @@ public final class AppRestrictionController { /** * @return The total battery usage of the given UID since the system boots. */ double getUidBatteryUsage(int uid); @NonNull ImmutableBatteryUsage getUidBatteryUsage(int uid); } void dump(PrintWriter pw, String prefix) { Loading services/tests/mockingservicestests/src/com/android/server/am/BackgroundRestrictionTest.java +15 −10 Original line number Diff line number Diff line Loading @@ -46,9 +46,10 @@ import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE; import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; import static com.android.internal.notification.SystemNotificationChannels.ABUSIVE_BACKGROUND_APPS; import static com.android.server.am.AppBatteryTracker.BATT_DIMEN_BG; import static com.android.server.am.AppBatteryTracker.BATT_DIMEN_FG; import static com.android.server.am.AppBatteryTracker.BATT_DIMEN_FGS; import static com.android.server.am.AppBatteryTracker.BatteryUsage.BATTERY_USAGE_INDEX_BACKGROUND; import static com.android.server.am.AppBatteryTracker.BatteryUsage.BATTERY_USAGE_INDEX_FOREGROUND; import static com.android.server.am.AppBatteryTracker.BatteryUsage.BATTERY_USAGE_INDEX_FOREGROUND_SERVICE; import static com.android.server.am.AppBatteryTracker.BatteryUsage.BATT_DIMENS; import static com.android.server.am.AppRestrictionController.STOCK_PM_FLAGS; import static org.junit.Assert.assertEquals; Loading Loading @@ -113,6 +114,7 @@ import com.android.server.am.AppBatteryExemptionTracker.AppBatteryExemptionPolic import com.android.server.am.AppBatteryExemptionTracker.UidBatteryStates; import com.android.server.am.AppBatteryExemptionTracker.UidStateEventWithBattery; import com.android.server.am.AppBatteryTracker.AppBatteryPolicy; import com.android.server.am.AppBatteryTracker.ImmutableBatteryUsage; import com.android.server.am.AppBindServiceEventsTracker.AppBindServiceEventsPolicy; import com.android.server.am.AppBroadcastEventsTracker.AppBroadcastEventsPolicy; import com.android.server.am.AppFGSTracker.AppFGSPolicy; Loading Loading @@ -566,7 +568,7 @@ public final class BackgroundRestrictionTest { DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_THRESHOLD_TO_RESTRICTED_BUCKET, DeviceConfig::getFloat, AppBatteryPolicy.DEFAULT_BG_CURRENT_DRAIN_BG_RESTRICTED_THRESHOLD); AppBatteryPolicy.DEFAULT_BG_CURRENT_DRAIN_RESTRICTED_BUCKET_THRESHOLD); bgCurrentDrainRestrictedBucketThreshold.set(restrictBucketThreshold); bgCurrentDrainBgRestrictedThreshold = new DeviceConfigSession<>( Loading Loading @@ -1294,7 +1296,7 @@ public final class BackgroundRestrictionTest { DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_THRESHOLD_TO_RESTRICTED_BUCKET, DeviceConfig::getFloat, AppBatteryPolicy.DEFAULT_BG_CURRENT_DRAIN_BG_RESTRICTED_THRESHOLD); AppBatteryPolicy.DEFAULT_BG_CURRENT_DRAIN_RESTRICTED_BUCKET_THRESHOLD); bgCurrentDrainRestrictedBucketThreshold.set(restrictBucketThreshold); bgCurrentDrainBgRestrictedThreshold = new DeviceConfigSession<>( Loading Loading @@ -1932,9 +1934,12 @@ public final class BackgroundRestrictionTest { private UidBatteryConsumer mockUidBatteryConsumer(int uid, double bg, double fgs, double fg) { UidBatteryConsumer uidConsumer = mock(UidBatteryConsumer.class); doReturn(uid).when(uidConsumer).getUid(); doReturn(bg).when(uidConsumer).getConsumedPower(eq(BATT_DIMEN_BG)); doReturn(fgs).when(uidConsumer).getConsumedPower(eq(BATT_DIMEN_FGS)); doReturn(fg).when(uidConsumer).getConsumedPower(eq(BATT_DIMEN_FG)); doReturn(bg).when(uidConsumer).getConsumedPower( eq(BATT_DIMENS[BATTERY_USAGE_INDEX_BACKGROUND])); doReturn(fgs).when(uidConsumer).getConsumedPower( eq(BATT_DIMENS[BATTERY_USAGE_INDEX_FOREGROUND_SERVICE])); doReturn(fg).when(uidConsumer).getConsumedPower( eq(BATT_DIMENS[BATTERY_USAGE_INDEX_FOREGROUND])); return uidConsumer; } Loading Loading @@ -2234,8 +2239,8 @@ public final class BackgroundRestrictionTest { boolean[] isStart, long[] timestamps, double[] batteryUsage) { final LinkedList<UidStateEventWithBattery> result = new LinkedList<>(); for (int i = 0; i < isStart.length; i++) { result.add(new UidStateEventWithBattery( isStart[i], timestamps[i], batteryUsage[i], null)); result.add(new UidStateEventWithBattery(isStart[i], timestamps[i], new ImmutableBatteryUsage(0.0d, 0.0d, batteryUsage[i], 0.0d), null)); } return result; } Loading Loading
services/core/java/com/android/server/am/ActivityManagerShellCommand.java +13 −7 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_MOD import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_NORMAL; import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.am.AppBatteryTracker.BatteryUsage.BATTERY_USAGE_COUNT; import static com.android.server.am.LowMemDetector.ADJ_MEM_FACTOR_NOTHING; import android.app.ActivityManager; Loading Loading @@ -3256,12 +3257,12 @@ final class ActivityManagerShellCommand extends ShellCommand { return -1; } if (arg == null) { batteryTracker.mDebugUidPercentages.clear(); batteryTracker.clearDebugUidPercentage(); return 0; } String[] pairs = arg.split(","); int[] uids = new int[pairs.length]; double[] values = new double[pairs.length]; double[][] values = new double[pairs.length][]; try { for (int i = 0; i < pairs.length; i++) { String[] pair = pairs[i].split("="); Loading @@ -3270,16 +3271,21 @@ final class ActivityManagerShellCommand extends ShellCommand { return -1; } uids[i] = Integer.parseInt(pair[0]); values[i] = Double.parseDouble(pair[1]); final String[] vals = pair[1].split(":"); if (vals.length != BATTERY_USAGE_COUNT) { getErrPrintWriter().println("Malformed input"); return -1; } values[i] = new double[vals.length]; for (int j = 0; j < vals.length; j++) { values[i][j] = Double.parseDouble(vals[j]); } } } catch (NumberFormatException e) { getErrPrintWriter().println("Malformed input"); return -1; } batteryTracker.mDebugUidPercentages.clear(); for (int i = 0; i < pairs.length; i++) { batteryTracker.mDebugUidPercentages.put(uids[i], values[i]); } batteryTracker.setDebugUidPercentage(uids, values); return 0; } Loading
services/core/java/com/android/server/am/AppBatteryExemptionTracker.java +59 −38 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.server.am; import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.am.AppBatteryTracker.BATTERY_USAGE_NONE; import static com.android.server.am.AppRestrictionController.DEVICE_CONFIG_SUBNAMESPACE_PREFIX; import static com.android.server.am.BaseAppStateDurationsTracker.EVENT_NUM; Loading @@ -32,6 +33,8 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.server.am.AppBatteryExemptionTracker.AppBatteryExemptionPolicy; import com.android.server.am.AppBatteryExemptionTracker.UidBatteryStates; import com.android.server.am.AppBatteryTracker.AppBatteryPolicy; import com.android.server.am.AppBatteryTracker.BatteryUsage; import com.android.server.am.AppBatteryTracker.ImmutableBatteryUsage; import com.android.server.am.BaseAppStateDurationsTracker.EventListener; import com.android.server.am.BaseAppStateTimeEvents.BaseTimeEvent; import com.android.server.am.BaseAppStateTracker.Injector; Loading Loading @@ -97,7 +100,8 @@ final class AppBatteryExemptionTracker if (!mInjector.getPolicy().isEnabled()) { return; } final double batteryUsage = mAppRestrictionController.getUidBatteryUsage(uid); final ImmutableBatteryUsage batteryUsage = mAppRestrictionController .getUidBatteryUsage(uid); synchronized (mLock) { UidBatteryStates pkg = mPkgEvents.get(uid, DEFAULT_NAME); if (pkg == null) { Loading @@ -120,22 +124,23 @@ final class AppBatteryExemptionTracker * @return The to-be-exempted battery usage of the given UID in the given duration; it could * be considered as "exempted" due to various use cases, i.e. media playback. */ double getUidBatteryExemptedUsageSince(int uid, long since, long now) { ImmutableBatteryUsage getUidBatteryExemptedUsageSince(int uid, long since, long now) { if (!mInjector.getPolicy().isEnabled()) { return 0.0d; return BATTERY_USAGE_NONE; } Pair<Double, Double> result; Pair<ImmutableBatteryUsage, ImmutableBatteryUsage> result; synchronized (mLock) { final UidBatteryStates pkg = mPkgEvents.get(uid, DEFAULT_NAME); if (pkg == null) { return 0.0d; return BATTERY_USAGE_NONE; } result = pkg.getBatteryUsageSince(since, now); } if (result.second > 0.0d) { if (!result.second.isEmpty()) { // We have an open event (just start, no stop), get the battery usage till now. final double batteryUsage = mAppRestrictionController.getUidBatteryUsage(uid); return result.first + batteryUsage - result.second; final ImmutableBatteryUsage batteryUsage = mAppRestrictionController .getUidBatteryUsage(uid); return result.first.mutate().add(batteryUsage).subtract(result.second).unmutate(); } return result.first; } Loading @@ -156,7 +161,7 @@ final class AppBatteryExemptionTracker * @param batteryUsage The background current drain since the system boots. * @param eventType One of EVENT_TYPE_* defined in the class BaseAppStateDurationsTracker. */ void addEvent(boolean start, long now, double batteryUsage, int eventType) { void addEvent(boolean start, long now, ImmutableBatteryUsage batteryUsage, int eventType) { if (start) { addEvent(start, new UidStateEventWithBattery(start, now, batteryUsage, null), eventType); Loading @@ -169,7 +174,8 @@ final class AppBatteryExemptionTracker return; } addEvent(start, new UidStateEventWithBattery(start, now, batteryUsage - last.getBatteryUsage(), last), eventType); batteryUsage.mutate().subtract(last.getBatteryUsage()).unmutate(), last), eventType); } } Loading @@ -183,34 +189,37 @@ final class AppBatteryExemptionTracker * the second value is the battery usage since the system boots, if there is * an open event(just start, no stop) at the end of the duration. */ Pair<Double, Double> getBatteryUsageSince(long since, long now, int eventType) { Pair<ImmutableBatteryUsage, ImmutableBatteryUsage> getBatteryUsageSince(long since, long now, int eventType) { return getBatteryUsageSince(since, now, mEvents[eventType]); } private Pair<Double, Double> getBatteryUsageSince(long since, long now, LinkedList<UidStateEventWithBattery> events) { private Pair<ImmutableBatteryUsage, ImmutableBatteryUsage> getBatteryUsageSince(long since, long now, LinkedList<UidStateEventWithBattery> events) { if (events == null || events.size() == 0) { return Pair.create(0.0d, 0.0d); return Pair.create(BATTERY_USAGE_NONE, BATTERY_USAGE_NONE); } double batteryUsage = 0.0d; final BatteryUsage batteryUsage = new BatteryUsage(); UidStateEventWithBattery lastEvent = null; for (UidStateEventWithBattery event : events) { lastEvent = event; if (event.getTimestamp() < since || event.isStart()) { continue; } batteryUsage += event.getBatteryUsage(since, Math.min(now, event.getTimestamp())); batteryUsage.add(event.getBatteryUsage(since, Math.min(now, event.getTimestamp()))); if (now <= event.getTimestamp()) { break; } } return Pair.create(batteryUsage, lastEvent.isStart() ? lastEvent.getBatteryUsage() : 0); return Pair.create(batteryUsage.unmutate(), lastEvent.isStart() ? lastEvent.getBatteryUsage() : BATTERY_USAGE_NONE); } /** * @return The aggregated battery usage amongst all the event types we're tracking. */ Pair<Double, Double> getBatteryUsageSince(long since, long now) { Pair<ImmutableBatteryUsage, ImmutableBatteryUsage> getBatteryUsageSince(long since, long now) { LinkedList<UidStateEventWithBattery> result = new LinkedList<>(); for (int i = 0; i < mEvents.length; i++) { result = add(result, mEvents[i]); Loading @@ -236,7 +245,7 @@ final class AppBatteryExemptionTracker UidStateEventWithBattery l = itl.next(), r = itr.next(); LinkedList<UidStateEventWithBattery> dest = new LinkedList<>(); boolean actl = false, actr = false, overlapping = false; double batteryUsage = 0.0d; final BatteryUsage batteryUsage = new BatteryUsage(); long recentActTs = 0, overlappingDuration = 0; for (long lts = l.getTimestamp(), rts = r.getTimestamp(); lts != Long.MAX_VALUE || rts != Long.MAX_VALUE;) { Loading @@ -245,8 +254,8 @@ final class AppBatteryExemptionTracker if (lts == rts) { earliest = l; // we'll deal with the double counting problem later. batteryUsage += actl ? l.getBatteryUsage() : 0.0d; batteryUsage += actr ? r.getBatteryUsage() : 0.0d; if (actl) batteryUsage.add(l.getBatteryUsage()); if (actr) batteryUsage.add(r.getBatteryUsage()); overlappingDuration += overlapping && (actl || actr) ? (lts - recentActTs) : 0; actl = !actl; Loading @@ -255,13 +264,13 @@ final class AppBatteryExemptionTracker rts = itr.hasNext() ? (r = itr.next()).getTimestamp() : Long.MAX_VALUE; } else if (lts < rts) { earliest = l; batteryUsage += actl ? l.getBatteryUsage() : 0.0d; if (actl) batteryUsage.add(l.getBatteryUsage()); overlappingDuration += overlapping && actl ? (lts - recentActTs) : 0; actl = !actl; lts = itl.hasNext() ? (l = itl.next()).getTimestamp() : Long.MAX_VALUE; } else { earliest = r; batteryUsage += actr ? r.getBatteryUsage() : 0.0d; if (actr) batteryUsage.add(r.getBatteryUsage()); overlappingDuration += overlapping && actr ? (rts - recentActTs) : 0; actr = !actr; rts = itr.hasNext() ? (r = itr.next()).getTimestamp() : Long.MAX_VALUE; Loading @@ -281,12 +290,12 @@ final class AppBatteryExemptionTracker final long durationWithOverlapping = duration + overlappingDuration; // Get the proportional batteryUsage. if (durationWithOverlapping != 0) { batteryUsage *= duration * 1.0d / durationWithOverlapping; batteryUsage.scale(duration * 1.0d / durationWithOverlapping); event.update(lastEvent, new ImmutableBatteryUsage(batteryUsage)); } else { batteryUsage = 0.0d; event.update(lastEvent, BATTERY_USAGE_NONE); } event.update(lastEvent, batteryUsage); batteryUsage = 0.0d; batteryUsage.setTo(BATTERY_USAGE_NONE); overlappingDuration = 0; } dest.add(event); Loading Loading @@ -322,14 +331,15 @@ final class AppBatteryExemptionTracker * the system boots if the {@link #mIsStart} is true, but will be the delta of the bg * battery usage since the start event if the {@link #mIsStart} is false. */ private double mBatteryUsage; private @NonNull ImmutableBatteryUsage mBatteryUsage; /** * The peer event of this pair (a pair of start/stop events). */ private @Nullable UidStateEventWithBattery mPeer; UidStateEventWithBattery(boolean isStart, long now, double batteryUsage, UidStateEventWithBattery(boolean isStart, long now, @NonNull ImmutableBatteryUsage batteryUsage, @Nullable UidStateEventWithBattery peer) { super(now); mIsStart = isStart; Loading @@ -355,15 +365,19 @@ final class AppBatteryExemptionTracker } if (mPeer != null) { // Reduce the bg battery usage proportionally. final double batteryUsage = mPeer.getBatteryUsage(); final ImmutableBatteryUsage batteryUsage = mPeer.getBatteryUsage(); mPeer.mBatteryUsage = mPeer.getBatteryUsage(timestamp, mPeer.mTimestamp); // Update the battery data of the start event too. mBatteryUsage += batteryUsage - mPeer.mBatteryUsage; mBatteryUsage = mBatteryUsage.mutate() .add(batteryUsage) .subtract(mPeer.mBatteryUsage) .unmutate(); } mTimestamp = timestamp; } void update(@NonNull UidStateEventWithBattery peer, double batteryUsage) { void update(@NonNull UidStateEventWithBattery peer, @NonNull ImmutableBatteryUsage batteryUsage) { mPeer = peer; peer.mPeer = this; mBatteryUsage = batteryUsage; Loading @@ -373,18 +387,19 @@ final class AppBatteryExemptionTracker return mIsStart; } double getBatteryUsage(long start, long end) { @NonNull ImmutableBatteryUsage getBatteryUsage(long start, long end) { if (mIsStart || start >= mTimestamp || end <= start) { return 0.0d; return BATTERY_USAGE_NONE; } start = Math.max(start, mPeer.mTimestamp); end = Math.min(end, mTimestamp); final long totalDur = mTimestamp - mPeer.mTimestamp; final long inputDur = end - start; return totalDur != 0 ? mBatteryUsage * (1.0d * inputDur) / totalDur : 0.0d; return totalDur != 0 ? (totalDur == inputDur ? mBatteryUsage : mBatteryUsage.mutate() .scale((1.0d * inputDur) / totalDur).unmutate()) : BATTERY_USAGE_NONE; } double getBatteryUsage() { @NonNull ImmutableBatteryUsage getBatteryUsage() { return mBatteryUsage; } Loading @@ -404,14 +419,20 @@ final class AppBatteryExemptionTracker final UidStateEventWithBattery otherEvent = (UidStateEventWithBattery) other; return otherEvent.mIsStart == mIsStart && otherEvent.mTimestamp == mTimestamp && Double.compare(otherEvent.mBatteryUsage, mBatteryUsage) == 0; && mBatteryUsage.equals(otherEvent.mBatteryUsage); } @Override public String toString() { return "UidStateEventWithBattery(" + mIsStart + ", " + mTimestamp + ", " + mBatteryUsage + ")"; } @Override public int hashCode() { return (Boolean.hashCode(mIsStart) * 31 + Long.hashCode(mTimestamp)) * 31 + Double.hashCode(mBatteryUsage); + mBatteryUsage.hashCode(); } } Loading
services/core/java/com/android/server/am/AppBatteryTracker.java +495 −94 File changed.Preview size limit exceeded, changes collapsed. Show changes
services/core/java/com/android/server/am/AppRestrictionController.java +4 −3 Original line number Diff line number Diff line Loading @@ -142,6 +142,7 @@ import com.android.internal.util.function.TriConsumer; import com.android.server.AppStateTracker; import com.android.server.LocalServices; import com.android.server.SystemConfig; import com.android.server.am.AppBatteryTracker.ImmutableBatteryUsage; import com.android.server.apphibernation.AppHibernationManagerInternal; import com.android.server.pm.UserManagerInternal; import com.android.server.usage.AppStandbyInternal; Loading Loading @@ -1076,7 +1077,7 @@ public final class AppRestrictionController { * @return The to-be-exempted battery usage of the given UID in the given duration; it could * be considered as "exempted" due to various use cases, i.e. media playback. */ double getUidBatteryExemptedUsageSince(int uid, long since, long now) { ImmutableBatteryUsage getUidBatteryExemptedUsageSince(int uid, long since, long now) { return mInjector.getAppBatteryExemptionTracker() .getUidBatteryExemptedUsageSince(uid, since, now); } Loading @@ -1084,7 +1085,7 @@ public final class AppRestrictionController { /** * @return The total battery usage of the given UID since the system boots. */ double getUidBatteryUsage(int uid) { @NonNull ImmutableBatteryUsage getUidBatteryUsage(int uid) { return mInjector.getUidBatteryUsageProvider().getUidBatteryUsage(uid); } Loading @@ -1092,7 +1093,7 @@ public final class AppRestrictionController { /** * @return The total battery usage of the given UID since the system boots. */ double getUidBatteryUsage(int uid); @NonNull ImmutableBatteryUsage getUidBatteryUsage(int uid); } void dump(PrintWriter pw, String prefix) { Loading
services/tests/mockingservicestests/src/com/android/server/am/BackgroundRestrictionTest.java +15 −10 Original line number Diff line number Diff line Loading @@ -46,9 +46,10 @@ import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE; import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; import static com.android.internal.notification.SystemNotificationChannels.ABUSIVE_BACKGROUND_APPS; import static com.android.server.am.AppBatteryTracker.BATT_DIMEN_BG; import static com.android.server.am.AppBatteryTracker.BATT_DIMEN_FG; import static com.android.server.am.AppBatteryTracker.BATT_DIMEN_FGS; import static com.android.server.am.AppBatteryTracker.BatteryUsage.BATTERY_USAGE_INDEX_BACKGROUND; import static com.android.server.am.AppBatteryTracker.BatteryUsage.BATTERY_USAGE_INDEX_FOREGROUND; import static com.android.server.am.AppBatteryTracker.BatteryUsage.BATTERY_USAGE_INDEX_FOREGROUND_SERVICE; import static com.android.server.am.AppBatteryTracker.BatteryUsage.BATT_DIMENS; import static com.android.server.am.AppRestrictionController.STOCK_PM_FLAGS; import static org.junit.Assert.assertEquals; Loading Loading @@ -113,6 +114,7 @@ import com.android.server.am.AppBatteryExemptionTracker.AppBatteryExemptionPolic import com.android.server.am.AppBatteryExemptionTracker.UidBatteryStates; import com.android.server.am.AppBatteryExemptionTracker.UidStateEventWithBattery; import com.android.server.am.AppBatteryTracker.AppBatteryPolicy; import com.android.server.am.AppBatteryTracker.ImmutableBatteryUsage; import com.android.server.am.AppBindServiceEventsTracker.AppBindServiceEventsPolicy; import com.android.server.am.AppBroadcastEventsTracker.AppBroadcastEventsPolicy; import com.android.server.am.AppFGSTracker.AppFGSPolicy; Loading Loading @@ -566,7 +568,7 @@ public final class BackgroundRestrictionTest { DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_THRESHOLD_TO_RESTRICTED_BUCKET, DeviceConfig::getFloat, AppBatteryPolicy.DEFAULT_BG_CURRENT_DRAIN_BG_RESTRICTED_THRESHOLD); AppBatteryPolicy.DEFAULT_BG_CURRENT_DRAIN_RESTRICTED_BUCKET_THRESHOLD); bgCurrentDrainRestrictedBucketThreshold.set(restrictBucketThreshold); bgCurrentDrainBgRestrictedThreshold = new DeviceConfigSession<>( Loading Loading @@ -1294,7 +1296,7 @@ public final class BackgroundRestrictionTest { DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_THRESHOLD_TO_RESTRICTED_BUCKET, DeviceConfig::getFloat, AppBatteryPolicy.DEFAULT_BG_CURRENT_DRAIN_BG_RESTRICTED_THRESHOLD); AppBatteryPolicy.DEFAULT_BG_CURRENT_DRAIN_RESTRICTED_BUCKET_THRESHOLD); bgCurrentDrainRestrictedBucketThreshold.set(restrictBucketThreshold); bgCurrentDrainBgRestrictedThreshold = new DeviceConfigSession<>( Loading Loading @@ -1932,9 +1934,12 @@ public final class BackgroundRestrictionTest { private UidBatteryConsumer mockUidBatteryConsumer(int uid, double bg, double fgs, double fg) { UidBatteryConsumer uidConsumer = mock(UidBatteryConsumer.class); doReturn(uid).when(uidConsumer).getUid(); doReturn(bg).when(uidConsumer).getConsumedPower(eq(BATT_DIMEN_BG)); doReturn(fgs).when(uidConsumer).getConsumedPower(eq(BATT_DIMEN_FGS)); doReturn(fg).when(uidConsumer).getConsumedPower(eq(BATT_DIMEN_FG)); doReturn(bg).when(uidConsumer).getConsumedPower( eq(BATT_DIMENS[BATTERY_USAGE_INDEX_BACKGROUND])); doReturn(fgs).when(uidConsumer).getConsumedPower( eq(BATT_DIMENS[BATTERY_USAGE_INDEX_FOREGROUND_SERVICE])); doReturn(fg).when(uidConsumer).getConsumedPower( eq(BATT_DIMENS[BATTERY_USAGE_INDEX_FOREGROUND])); return uidConsumer; } Loading Loading @@ -2234,8 +2239,8 @@ public final class BackgroundRestrictionTest { boolean[] isStart, long[] timestamps, double[] batteryUsage) { final LinkedList<UidStateEventWithBattery> result = new LinkedList<>(); for (int i = 0; i < isStart.length; i++) { result.add(new UidStateEventWithBattery( isStart[i], timestamps[i], batteryUsage[i], null)); result.add(new UidStateEventWithBattery(isStart[i], timestamps[i], new ImmutableBatteryUsage(0.0d, 0.0d, batteryUsage[i], 0.0d), null)); } return result; } Loading