diff options
| author | Dmitri Plotnikov <dplotnikov@google.com> | 2022-02-09 06:26:02 +0000 |
|---|---|---|
| committer | Android (Google) Code Review <android-gerrit@google.com> | 2022-02-09 06:26:02 +0000 |
| commit | 24e45284df7dcb8f715d502ca979bd8568266d70 (patch) | |
| tree | 92ca8f558274a825c4e259c192e5cc26450f3517 /core/java/android | |
| parent | 898058eb428f11a4e57fc82b0fe86c00f43281f7 (diff) | |
| parent | 706703d665e86c1f26ca79883be6966db9b316b1 (diff) | |
Merge "Convert dumpsys batterystats --checkin and --proto to BatteryUsageStats API"
Diffstat (limited to 'core/java/android')
| -rw-r--r-- | core/java/android/os/BatteryStats.java | 397 |
1 files changed, 235 insertions, 162 deletions
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index 6dfa99506c61..f1d4ba0029bd 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -27,6 +27,8 @@ import android.app.job.JobParameters; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.content.res.Resources; import android.location.GnssSignalQuality; import android.os.BatteryStatsManager.WifiState; import android.os.BatteryStatsManager.WifiSupplState; @@ -43,6 +45,7 @@ import android.util.MutableBoolean; import android.util.Pair; import android.util.Printer; import android.util.SparseArray; +import android.util.SparseDoubleArray; import android.util.SparseIntArray; import android.util.TimeUtils; import android.util.proto.ProtoOutputStream; @@ -65,6 +68,7 @@ import java.util.Collections; import java.util.Comparator; import java.util.Formatter; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; @@ -4126,7 +4130,28 @@ public abstract class BatteryStats implements Parcelable { * Temporary for settings. */ public final void dumpCheckinLocked(Context context, PrintWriter pw, int which, int reqUid) { - dumpCheckinLocked(context, pw, which, reqUid, BatteryStatsHelper.checkWifiOnly(context)); + dumpCheckinLocked(context, pw, which, reqUid, checkWifiOnly(context)); + } + + private static final String[] CHECKIN_POWER_COMPONENT_LABELS = + new String[BatteryConsumer.POWER_COMPONENT_COUNT]; + static { + // Assign individually to avoid future mismatch of indices + CHECKIN_POWER_COMPONENT_LABELS[BatteryConsumer.POWER_COMPONENT_SCREEN] = "scrn"; + CHECKIN_POWER_COMPONENT_LABELS[BatteryConsumer.POWER_COMPONENT_CPU] = "cpu"; + CHECKIN_POWER_COMPONENT_LABELS[BatteryConsumer.POWER_COMPONENT_BLUETOOTH] = "blue"; + CHECKIN_POWER_COMPONENT_LABELS[BatteryConsumer.POWER_COMPONENT_CAMERA] = "camera"; + CHECKIN_POWER_COMPONENT_LABELS[BatteryConsumer.POWER_COMPONENT_AUDIO] = "audio"; + CHECKIN_POWER_COMPONENT_LABELS[BatteryConsumer.POWER_COMPONENT_VIDEO] = "video"; + CHECKIN_POWER_COMPONENT_LABELS[BatteryConsumer.POWER_COMPONENT_FLASHLIGHT] = "flashlight"; + CHECKIN_POWER_COMPONENT_LABELS[BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO] = "cell"; + CHECKIN_POWER_COMPONENT_LABELS[BatteryConsumer.POWER_COMPONENT_SENSORS] = "sensors"; + CHECKIN_POWER_COMPONENT_LABELS[BatteryConsumer.POWER_COMPONENT_GNSS] = "gnss"; + CHECKIN_POWER_COMPONENT_LABELS[BatteryConsumer.POWER_COMPONENT_WIFI] = "wifi"; + CHECKIN_POWER_COMPONENT_LABELS[BatteryConsumer.POWER_COMPONENT_MEMORY] = "memory"; + CHECKIN_POWER_COMPONENT_LABELS[BatteryConsumer.POWER_COMPONENT_PHONE] = "phone"; + CHECKIN_POWER_COMPONENT_LABELS[BatteryConsumer.POWER_COMPONENT_AMBIENT_DISPLAY] = "ambi"; + CHECKIN_POWER_COMPONENT_LABELS[BatteryConsumer.POWER_COMPONENT_IDLE] = "idle"; } /** @@ -4397,74 +4422,37 @@ public abstract class BatteryStats implements Parcelable { } } - final BatteryStatsHelper helper = new BatteryStatsHelper(context, false, wifiOnly); - helper.create(this); - helper.refreshStats(which, UserHandle.USER_ALL); - final List<BatterySipper> sippers = helper.getUsageList(); - if (sippers != null && sippers.size() > 0) { - dumpLine(pw, 0 /* uid */, category, POWER_USE_SUMMARY_DATA, - PowerCalculator.formatCharge(helper.getPowerProfile().getBatteryCapacity()), - PowerCalculator.formatCharge(helper.getComputedPower()), - PowerCalculator.formatCharge(helper.getMinDrainedPower()), - PowerCalculator.formatCharge(helper.getMaxDrainedPower())); - int uid = 0; - for (int i=0; i<sippers.size(); i++) { - final BatterySipper bs = sippers.get(i); - String label; - switch (bs.drainType) { - case AMBIENT_DISPLAY: - label = "ambi"; - break; - case IDLE: - label="idle"; - break; - case CELL: - label="cell"; - break; - case PHONE: - label="phone"; - break; - case WIFI: - label="wifi"; - break; - case BLUETOOTH: - label="blue"; - break; - case SCREEN: - label="scrn"; - break; - case FLASHLIGHT: - label="flashlight"; - break; - case APP: - uid = bs.uidObj.getUid(); - label = "uid"; - break; - case USER: - uid = UserHandle.getUid(bs.userId, 0); - label = "user"; - break; - case UNACCOUNTED: - label = "unacc"; - break; - case OVERCOUNTED: - label = "over"; - break; - case CAMERA: - label = "camera"; - break; - case MEMORY: - label = "memory"; - break; - default: - label = "???"; - } - dumpLine(pw, uid, category, POWER_USE_ITEM_DATA, label, - PowerCalculator.formatCharge(bs.totalPowerMah), - bs.shouldHide ? 1 : 0, - PowerCalculator.formatCharge(bs.screenPowerMah), - PowerCalculator.formatCharge(bs.proportionalSmearMah)); + final BatteryUsageStats stats = getBatteryUsageStats(context); + dumpLine(pw, 0 /* uid */, category, POWER_USE_SUMMARY_DATA, + PowerCalculator.formatCharge(stats.getBatteryCapacity()), + PowerCalculator.formatCharge(stats.getConsumedPower()), + PowerCalculator.formatCharge(stats.getDischargedPowerRange().getLower()), + PowerCalculator.formatCharge(stats.getDischargedPowerRange().getUpper())); + final BatteryConsumer deviceConsumer = stats.getAggregateBatteryConsumer( + BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE); + for (@BatteryConsumer.PowerComponent int powerComponent = 0; + powerComponent < BatteryConsumer.POWER_COMPONENT_COUNT; powerComponent++) { + String label = CHECKIN_POWER_COMPONENT_LABELS[powerComponent]; + if (label == null) { + label = "???"; } + dumpLine(pw, 0 /* uid */, category, POWER_USE_ITEM_DATA, label, + PowerCalculator.formatCharge(deviceConsumer.getConsumedPower(powerComponent)), + shouldHidePowerComponent(powerComponent) ? 1 : 0, "0", "0"); + } + + final ProportionalAttributionCalculator proportionalAttributionCalculator = + new ProportionalAttributionCalculator(context, stats); + final List<UidBatteryConsumer> uidBatteryConsumers = stats.getUidBatteryConsumers(); + for (int i = 0; i < uidBatteryConsumers.size(); i++) { + UidBatteryConsumer consumer = uidBatteryConsumers.get(i); + dumpLine(pw, consumer.getUid(), category, POWER_USE_ITEM_DATA, "uid", + PowerCalculator.formatCharge(consumer.getConsumedPower()), + proportionalAttributionCalculator.isSystemBatteryConsumer(consumer) ? 1 : 0, + PowerCalculator.formatCharge( + consumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_SCREEN)), + PowerCalculator.formatCharge( + proportionalAttributionCalculator.getProportionalPowerMah(consumer))); } final long[] cpuFreqs = getCpuFreqs(); @@ -4909,7 +4897,7 @@ public abstract class BatteryStats implements Parcelable { */ public final void dumpLocked(Context context, PrintWriter pw, String prefix, int which, int reqUid) { - dumpLocked(context, pw, prefix, which, reqUid, BatteryStatsHelper.checkWifiOnly(context)); + dumpLocked(context, pw, prefix, which, reqUid, checkWifiOnly(context)); } @SuppressWarnings("unused") @@ -7625,21 +7613,20 @@ public abstract class BatteryStats implements Parcelable { proto.write(BatteryStatsProto.END_PLATFORM_VERSION, getEndPlatformVersion()); if ((flags & DUMP_DAILY_ONLY) == 0) { - final BatteryStatsHelper helper = new BatteryStatsHelper(context, false, - (flags & DUMP_DEVICE_WIFI_ONLY) != 0); - helper.create(this); - helper.refreshStats(STATS_SINCE_CHARGED, UserHandle.USER_ALL); - - dumpProtoAppsLocked(proto, helper, apps); - dumpProtoSystemLocked(proto, helper); + final BatteryUsageStats stats = getBatteryUsageStats(context); + ProportionalAttributionCalculator proportionalAttributionCalculator = + new ProportionalAttributionCalculator(context, stats); + dumpProtoAppsLocked(proto, stats, apps, proportionalAttributionCalculator); + dumpProtoSystemLocked(proto, stats); } proto.end(bToken); proto.flush(); } - private void dumpProtoAppsLocked(ProtoOutputStream proto, BatteryStatsHelper helper, - List<ApplicationInfo> apps) { + private void dumpProtoAppsLocked(ProtoOutputStream proto, BatteryUsageStats stats, + List<ApplicationInfo> apps, + ProportionalAttributionCalculator proportionalAttributionCalculator) { final int which = STATS_SINCE_CHARGED; final long rawUptimeUs = SystemClock.uptimeMillis() * 1000; final long rawRealtimeMs = SystemClock.elapsedRealtime(); @@ -7660,17 +7647,11 @@ public abstract class BatteryStats implements Parcelable { } } - SparseArray<BatterySipper> uidToSipper = new SparseArray<>(); - final List<BatterySipper> sippers = helper.getUsageList(); - if (sippers != null) { - for (int i = 0; i < sippers.size(); ++i) { - final BatterySipper bs = sippers.get(i); - if (bs.drainType != BatterySipper.DrainType.APP) { - // Others are handled by dumpProtoSystemLocked() - continue; - } - uidToSipper.put(bs.uidObj.getUid(), bs); - } + SparseArray<UidBatteryConsumer> uidToConsumer = new SparseArray<>(); + final List<UidBatteryConsumer> consumers = stats.getUidBatteryConsumers(); + for (int i = consumers.size() - 1; i >= 0; --i) { + final UidBatteryConsumer bs = consumers.get(i); + uidToConsumer.put(bs.getUid(), bs); } SparseArray<? extends Uid> uidStats = getUidStats(); @@ -7936,14 +7917,16 @@ public abstract class BatteryStats implements Parcelable { proto.end(nToken); // Power use item (POWER_USE_ITEM_DATA) - BatterySipper bs = uidToSipper.get(uid); - if (bs != null) { + UidBatteryConsumer consumer = uidToConsumer.get(uid); + if (consumer != null) { final long bsToken = proto.start(UidProto.POWER_USE_ITEM); - proto.write(UidProto.PowerUseItem.COMPUTED_POWER_MAH, bs.totalPowerMah); - proto.write(UidProto.PowerUseItem.SHOULD_HIDE, bs.shouldHide); - proto.write(UidProto.PowerUseItem.SCREEN_POWER_MAH, bs.screenPowerMah); + proto.write(UidProto.PowerUseItem.COMPUTED_POWER_MAH, consumer.getConsumedPower()); + proto.write(UidProto.PowerUseItem.SHOULD_HIDE, + proportionalAttributionCalculator.isSystemBatteryConsumer(consumer)); + proto.write(UidProto.PowerUseItem.SCREEN_POWER_MAH, + consumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_SCREEN)); proto.write(UidProto.PowerUseItem.PROPORTIONAL_SMEAR_MAH, - bs.proportionalSmearMah); + proportionalAttributionCalculator.getProportionalPowerMah(consumer)); proto.end(bsToken); } @@ -8189,7 +8172,7 @@ public abstract class BatteryStats implements Parcelable { } } - private void dumpProtoSystemLocked(ProtoOutputStream proto, BatteryStatsHelper helper) { + private void dumpProtoSystemLocked(ProtoOutputStream proto, BatteryUsageStats stats) { final long sToken = proto.start(BatteryStatsProto.SYSTEM); final long rawUptimeUs = SystemClock.uptimeMillis() * 1000; final long rawRealtimeMs = SystemClock.elapsedRealtime(); @@ -8433,77 +8416,65 @@ public abstract class BatteryStats implements Parcelable { multicastWakeLockCountTotal); proto.end(wmctToken); - // Power use item (POWER_USE_ITEM_DATA) - final List<BatterySipper> sippers = helper.getUsageList(); - if (sippers != null) { - for (int i = 0; i < sippers.size(); ++i) { - final BatterySipper bs = sippers.get(i); - int n = SystemProto.PowerUseItem.UNKNOWN_SIPPER; - int uid = 0; - switch (bs.drainType) { - case AMBIENT_DISPLAY: - n = SystemProto.PowerUseItem.AMBIENT_DISPLAY; - break; - case IDLE: - n = SystemProto.PowerUseItem.IDLE; - break; - case CELL: - n = SystemProto.PowerUseItem.CELL; - break; - case PHONE: - n = SystemProto.PowerUseItem.PHONE; - break; - case WIFI: - n = SystemProto.PowerUseItem.WIFI; - break; - case BLUETOOTH: - n = SystemProto.PowerUseItem.BLUETOOTH; - break; - case SCREEN: - n = SystemProto.PowerUseItem.SCREEN; - break; - case FLASHLIGHT: - n = SystemProto.PowerUseItem.FLASHLIGHT; - break; - case APP: - // dumpProtoAppsLocked will handle this. - continue; - case USER: - n = SystemProto.PowerUseItem.USER; - uid = UserHandle.getUid(bs.userId, 0); - break; - case UNACCOUNTED: - n = SystemProto.PowerUseItem.UNACCOUNTED; - break; - case OVERCOUNTED: - n = SystemProto.PowerUseItem.OVERCOUNTED; - break; - case CAMERA: - n = SystemProto.PowerUseItem.CAMERA; - break; - case MEMORY: - n = SystemProto.PowerUseItem.MEMORY; - break; - } - final long puiToken = proto.start(SystemProto.POWER_USE_ITEM); - proto.write(SystemProto.PowerUseItem.NAME, n); - proto.write(SystemProto.PowerUseItem.UID, uid); - proto.write(SystemProto.PowerUseItem.COMPUTED_POWER_MAH, bs.totalPowerMah); - proto.write(SystemProto.PowerUseItem.SHOULD_HIDE, bs.shouldHide); - proto.write(SystemProto.PowerUseItem.SCREEN_POWER_MAH, bs.screenPowerMah); - proto.write(SystemProto.PowerUseItem.PROPORTIONAL_SMEAR_MAH, - bs.proportionalSmearMah); - proto.end(puiToken); - } + final BatteryConsumer deviceConsumer = stats.getAggregateBatteryConsumer( + BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE); + + for (int powerComponent = 0; powerComponent < BatteryConsumer.POWER_COMPONENT_COUNT; + powerComponent++) { + int n = SystemProto.PowerUseItem.UNKNOWN_SIPPER; + switch (powerComponent) { + case BatteryConsumer.POWER_COMPONENT_AMBIENT_DISPLAY: + n = SystemProto.PowerUseItem.AMBIENT_DISPLAY; + break; + case BatteryConsumer.POWER_COMPONENT_IDLE: + n = SystemProto.PowerUseItem.IDLE; + break; + case BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO: + n = SystemProto.PowerUseItem.CELL; + break; + case BatteryConsumer.POWER_COMPONENT_PHONE: + n = SystemProto.PowerUseItem.PHONE; + break; + case BatteryConsumer.POWER_COMPONENT_WIFI: + n = SystemProto.PowerUseItem.WIFI; + break; + case BatteryConsumer.POWER_COMPONENT_BLUETOOTH: + n = SystemProto.PowerUseItem.BLUETOOTH; + break; + case BatteryConsumer.POWER_COMPONENT_SCREEN: + n = SystemProto.PowerUseItem.SCREEN; + break; + case BatteryConsumer.POWER_COMPONENT_FLASHLIGHT: + n = SystemProto.PowerUseItem.FLASHLIGHT; + break; + case BatteryConsumer.POWER_COMPONENT_CAMERA: + n = SystemProto.PowerUseItem.CAMERA; + break; + case BatteryConsumer.POWER_COMPONENT_MEMORY: + n = SystemProto.PowerUseItem.MEMORY; + break; + } + final long puiToken = proto.start(SystemProto.POWER_USE_ITEM); + proto.write(SystemProto.PowerUseItem.NAME, n); + proto.write(SystemProto.PowerUseItem.UID, 0); + proto.write(SystemProto.PowerUseItem.COMPUTED_POWER_MAH, + deviceConsumer.getConsumedPower(powerComponent)); + proto.write(SystemProto.PowerUseItem.SHOULD_HIDE, + shouldHidePowerComponent(powerComponent)); + proto.write(SystemProto.PowerUseItem.SCREEN_POWER_MAH, 0); + proto.write(SystemProto.PowerUseItem.PROPORTIONAL_SMEAR_MAH, 0); + proto.end(puiToken); } // Power use summary (POWER_USE_SUMMARY_DATA) final long pusToken = proto.start(SystemProto.POWER_USE_SUMMARY); proto.write(SystemProto.PowerUseSummary.BATTERY_CAPACITY_MAH, - helper.getPowerProfile().getBatteryCapacity()); - proto.write(SystemProto.PowerUseSummary.COMPUTED_POWER_MAH, helper.getComputedPower()); - proto.write(SystemProto.PowerUseSummary.MIN_DRAINED_POWER_MAH, helper.getMinDrainedPower()); - proto.write(SystemProto.PowerUseSummary.MAX_DRAINED_POWER_MAH, helper.getMaxDrainedPower()); + stats.getBatteryCapacity()); + proto.write(SystemProto.PowerUseSummary.COMPUTED_POWER_MAH, stats.getConsumedPower()); + proto.write(SystemProto.PowerUseSummary.MIN_DRAINED_POWER_MAH, + stats.getDischargedPowerRange().getLower()); + proto.write(SystemProto.PowerUseSummary.MAX_DRAINED_POWER_MAH, + stats.getDischargedPowerRange().getUpper()); proto.end(pusToken); // RPM stats (RESOURCE_POWER_MANAGER_DATA) @@ -8579,4 +8550,106 @@ public abstract class BatteryStats implements Parcelable { proto.end(sToken); } + + private static boolean checkWifiOnly(Context context) { + final TelephonyManager tm = context.getSystemService(TelephonyManager.class); + if (tm == null) { + return false; + } + return !tm.isDataCapable(); + } + + private BatteryUsageStats getBatteryUsageStats(Context context) { + final BatteryUsageStatsProvider provider = new BatteryUsageStatsProvider(context, this); + final BatteryUsageStatsQuery query = + new BatteryUsageStatsQuery.Builder().setMaxStatsAgeMs(0).build(); + return provider.getBatteryUsageStats(query); + } + + private boolean shouldHidePowerComponent(int powerComponent) { + return powerComponent == BatteryConsumer.POWER_COMPONENT_IDLE + || powerComponent == BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO + || powerComponent == BatteryConsumer.POWER_COMPONENT_SCREEN + || powerComponent == BatteryConsumer.POWER_COMPONENT_AMBIENT_DISPLAY; + } + + private static class ProportionalAttributionCalculator { + private static final double SYSTEM_BATTERY_CONSUMER = -1; + private final PackageManager mPackageManager; + private final HashSet<String> mSystemAndServicePackages; + private final SparseDoubleArray mProportionalPowerMah; + + ProportionalAttributionCalculator(Context context, BatteryUsageStats stats) { + mPackageManager = context.getPackageManager(); + final Resources resources = context.getResources(); + final String[] systemPackageArray = resources.getStringArray( + com.android.internal.R.array.config_batteryPackageTypeSystem); + final String[] servicePackageArray = resources.getStringArray( + com.android.internal.R.array.config_batteryPackageTypeService); + mSystemAndServicePackages = + new HashSet<>(systemPackageArray.length + servicePackageArray.length); + for (String packageName : systemPackageArray) { + mSystemAndServicePackages.add(packageName); + } + for (String packageName : servicePackageArray) { + mSystemAndServicePackages.add(packageName); + } + + final List<UidBatteryConsumer> uidBatteryConsumers = stats.getUidBatteryConsumers(); + mProportionalPowerMah = new SparseDoubleArray(uidBatteryConsumers.size()); + double systemPowerMah = 0; + for (int i = uidBatteryConsumers.size() - 1; i >= 0; i--) { + UidBatteryConsumer consumer = uidBatteryConsumers.get(i); + final int uid = consumer.getUid(); + if (isSystemUid(uid)) { + mProportionalPowerMah.put(uid, SYSTEM_BATTERY_CONSUMER); + systemPowerMah += consumer.getConsumedPower(); + } + } + + final double totalRemainingPower = stats.getConsumedPower() - systemPowerMah; + if (Math.abs(totalRemainingPower) > 1e-3) { + for (int i = uidBatteryConsumers.size() - 1; i >= 0; i--) { + UidBatteryConsumer consumer = uidBatteryConsumers.get(i); + final int uid = consumer.getUid(); + if (mProportionalPowerMah.get(uid) != SYSTEM_BATTERY_CONSUMER) { + final double power = consumer.getConsumedPower(); + mProportionalPowerMah.put(uid, + power + systemPowerMah * power / totalRemainingPower); + } + } + } + } + + boolean isSystemBatteryConsumer(UidBatteryConsumer consumer) { + return mProportionalPowerMah.get(consumer.getUid()) < 0; + } + + double getProportionalPowerMah(UidBatteryConsumer consumer) { + final double powerMah = mProportionalPowerMah.get(consumer.getUid()); + return powerMah >= 0 ? powerMah : 0; + } + + /** + * Check whether the UID is one of the system UIDs or a service UID + */ + private boolean isSystemUid(int uid) { + if (uid >= Process.ROOT_UID && uid < Process.FIRST_APPLICATION_UID) { + return true; + } + + final String[] packages = mPackageManager.getPackagesForUid(uid); + if (packages == null) { + return false; + } + + for (String packageName : packages) { + if (mSystemAndServicePackages.contains(packageName)) { + return true; + } + } + + return false; + } + } } |
