in android/os/BatteryStats.java [7110:7564]
private void dumpProtoAppsLocked(ProtoOutputStream proto, BatteryStatsHelper helper,
List<ApplicationInfo> apps) {
final int which = STATS_SINCE_CHARGED;
final long rawUptimeUs = SystemClock.uptimeMillis() * 1000;
final long rawRealtimeMs = SystemClock.elapsedRealtime();
final long rawRealtimeUs = rawRealtimeMs * 1000;
final long batteryUptimeUs = getBatteryUptime(rawUptimeUs);
SparseArray<ArrayList<String>> aidToPackages = new SparseArray<>();
if (apps != null) {
for (int i = 0; i < apps.size(); ++i) {
ApplicationInfo ai = apps.get(i);
int aid = UserHandle.getAppId(ai.uid);
ArrayList<String> pkgs = aidToPackages.get(aid);
if (pkgs == null) {
pkgs = new ArrayList<String>();
aidToPackages.put(aid, pkgs);
}
pkgs.add(ai.packageName);
}
}
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<? extends Uid> uidStats = getUidStats();
final int n = uidStats.size();
for (int iu = 0; iu < n; ++iu) {
final long uTkn = proto.start(BatteryStatsProto.UIDS);
final Uid u = uidStats.valueAt(iu);
final int uid = uidStats.keyAt(iu);
proto.write(UidProto.UID, uid);
// Print packages and apk stats (UID_DATA & APK_DATA)
ArrayList<String> pkgs = aidToPackages.get(UserHandle.getAppId(uid));
if (pkgs == null) {
pkgs = new ArrayList<String>();
}
final ArrayMap<String, ? extends BatteryStats.Uid.Pkg> packageStats =
u.getPackageStats();
for (int ipkg = packageStats.size() - 1; ipkg >= 0; --ipkg) {
String pkg = packageStats.keyAt(ipkg);
final ArrayMap<String, ? extends Uid.Pkg.Serv> serviceStats =
packageStats.valueAt(ipkg).getServiceStats();
if (serviceStats.size() == 0) {
// Due to the way ActivityManagerService logs wakeup alarms, some packages (for
// example, "android") may be included in the packageStats that aren't part of
// the UID. If they don't have any services, then they shouldn't be listed here.
// These packages won't be a part in the pkgs List.
continue;
}
final long pToken = proto.start(UidProto.PACKAGES);
proto.write(UidProto.Package.NAME, pkg);
// Remove from the packages list since we're logging it here.
pkgs.remove(pkg);
for (int isvc = serviceStats.size() - 1; isvc >= 0; --isvc) {
final BatteryStats.Uid.Pkg.Serv ss = serviceStats.valueAt(isvc);
final long startTimeMs = roundUsToMs(ss.getStartTime(batteryUptimeUs, which));
final int starts = ss.getStarts(which);
final int launches = ss.getLaunches(which);
if (startTimeMs == 0 && starts == 0 && launches == 0) {
continue;
}
long sToken = proto.start(UidProto.Package.SERVICES);
proto.write(UidProto.Package.Service.NAME, serviceStats.keyAt(isvc));
proto.write(UidProto.Package.Service.START_DURATION_MS, startTimeMs);
proto.write(UidProto.Package.Service.START_COUNT, starts);
proto.write(UidProto.Package.Service.LAUNCH_COUNT, launches);
proto.end(sToken);
}
proto.end(pToken);
}
// Print any remaining packages that weren't in the packageStats map. pkgs is pulled
// from PackageManager data. Packages are only included in packageStats if there was
// specific data tracked for them (services and wakeup alarms, etc.).
for (String p : pkgs) {
final long pToken = proto.start(UidProto.PACKAGES);
proto.write(UidProto.Package.NAME, p);
proto.end(pToken);
}
// Total wakelock data (AGGREGATED_WAKELOCK_DATA)
if (u.getAggregatedPartialWakelockTimer() != null) {
final Timer timer = u.getAggregatedPartialWakelockTimer();
// Times are since reset (regardless of 'which')
final long totTimeMs = timer.getTotalDurationMsLocked(rawRealtimeMs);
final Timer bgTimer = timer.getSubTimer();
final long bgTimeMs = bgTimer != null
? bgTimer.getTotalDurationMsLocked(rawRealtimeMs) : 0;
final long awToken = proto.start(UidProto.AGGREGATED_WAKELOCK);
proto.write(UidProto.AggregatedWakelock.PARTIAL_DURATION_MS, totTimeMs);
proto.write(UidProto.AggregatedWakelock.BACKGROUND_PARTIAL_DURATION_MS, bgTimeMs);
proto.end(awToken);
}
// Audio (AUDIO_DATA)
dumpTimer(proto, UidProto.AUDIO, u.getAudioTurnedOnTimer(), rawRealtimeUs, which);
// Bluetooth Controller (BLUETOOTH_CONTROLLER_DATA)
dumpControllerActivityProto(proto, UidProto.BLUETOOTH_CONTROLLER,
u.getBluetoothControllerActivity(), which);
// BLE scans (BLUETOOTH_MISC_DATA) (uses totalDurationMsLocked and MaxDurationMsLocked)
final Timer bleTimer = u.getBluetoothScanTimer();
if (bleTimer != null) {
final long bmToken = proto.start(UidProto.BLUETOOTH_MISC);
dumpTimer(proto, UidProto.BluetoothMisc.APPORTIONED_BLE_SCAN, bleTimer,
rawRealtimeUs, which);
dumpTimer(proto, UidProto.BluetoothMisc.BACKGROUND_BLE_SCAN,
u.getBluetoothScanBackgroundTimer(), rawRealtimeUs, which);
// Unoptimized scan timer. Unpooled and since reset (regardless of 'which').
dumpTimer(proto, UidProto.BluetoothMisc.UNOPTIMIZED_BLE_SCAN,
u.getBluetoothUnoptimizedScanTimer(), rawRealtimeUs, which);
// Unoptimized bg scan timer. Unpooled and since reset (regardless of 'which').
dumpTimer(proto, UidProto.BluetoothMisc.BACKGROUND_UNOPTIMIZED_BLE_SCAN,
u.getBluetoothUnoptimizedScanBackgroundTimer(), rawRealtimeUs, which);
// Result counters
proto.write(UidProto.BluetoothMisc.BLE_SCAN_RESULT_COUNT,
u.getBluetoothScanResultCounter() != null
? u.getBluetoothScanResultCounter().getCountLocked(which) : 0);
proto.write(UidProto.BluetoothMisc.BACKGROUND_BLE_SCAN_RESULT_COUNT,
u.getBluetoothScanResultBgCounter() != null
? u.getBluetoothScanResultBgCounter().getCountLocked(which) : 0);
proto.end(bmToken);
}
// Camera (CAMERA_DATA)
dumpTimer(proto, UidProto.CAMERA, u.getCameraTurnedOnTimer(), rawRealtimeUs, which);
// CPU stats (CPU_DATA & CPU_TIMES_AT_FREQ_DATA)
final long cpuToken = proto.start(UidProto.CPU);
proto.write(UidProto.Cpu.USER_DURATION_MS, roundUsToMs(u.getUserCpuTimeUs(which)));
proto.write(UidProto.Cpu.SYSTEM_DURATION_MS, roundUsToMs(u.getSystemCpuTimeUs(which)));
final long[] cpuFreqs = getCpuFreqs();
if (cpuFreqs != null) {
final long[] cpuFreqTimeMs = u.getCpuFreqTimes(which);
// If total cpuFreqTimes is null, then we don't need to check for
// screenOffCpuFreqTimes.
if (cpuFreqTimeMs != null && cpuFreqTimeMs.length == cpuFreqs.length) {
long[] screenOffCpuFreqTimeMs = u.getScreenOffCpuFreqTimes(which);
if (screenOffCpuFreqTimeMs == null) {
screenOffCpuFreqTimeMs = new long[cpuFreqTimeMs.length];
}
for (int ic = 0; ic < cpuFreqTimeMs.length; ++ic) {
long cToken = proto.start(UidProto.Cpu.BY_FREQUENCY);
proto.write(UidProto.Cpu.ByFrequency.FREQUENCY_INDEX, ic + 1);
proto.write(UidProto.Cpu.ByFrequency.TOTAL_DURATION_MS,
cpuFreqTimeMs[ic]);
proto.write(UidProto.Cpu.ByFrequency.SCREEN_OFF_DURATION_MS,
screenOffCpuFreqTimeMs[ic]);
proto.end(cToken);
}
}
}
for (int procState = 0; procState < Uid.NUM_PROCESS_STATE; ++procState) {
final long[] timesMs = u.getCpuFreqTimes(which, procState);
if (timesMs != null && timesMs.length == cpuFreqs.length) {
long[] screenOffTimesMs = u.getScreenOffCpuFreqTimes(which, procState);
if (screenOffTimesMs == null) {
screenOffTimesMs = new long[timesMs.length];
}
final long procToken = proto.start(UidProto.Cpu.BY_PROCESS_STATE);
proto.write(UidProto.Cpu.ByProcessState.PROCESS_STATE, procState);
for (int ic = 0; ic < timesMs.length; ++ic) {
long cToken = proto.start(UidProto.Cpu.ByProcessState.BY_FREQUENCY);
proto.write(UidProto.Cpu.ByFrequency.FREQUENCY_INDEX, ic + 1);
proto.write(UidProto.Cpu.ByFrequency.TOTAL_DURATION_MS,
timesMs[ic]);
proto.write(UidProto.Cpu.ByFrequency.SCREEN_OFF_DURATION_MS,
screenOffTimesMs[ic]);
proto.end(cToken);
}
proto.end(procToken);
}
}
proto.end(cpuToken);
// Flashlight (FLASHLIGHT_DATA)
dumpTimer(proto, UidProto.FLASHLIGHT, u.getFlashlightTurnedOnTimer(),
rawRealtimeUs, which);
// Foreground activity (FOREGROUND_ACTIVITY_DATA)
dumpTimer(proto, UidProto.FOREGROUND_ACTIVITY, u.getForegroundActivityTimer(),
rawRealtimeUs, which);
// Foreground service (FOREGROUND_SERVICE_DATA)
dumpTimer(proto, UidProto.FOREGROUND_SERVICE, u.getForegroundServiceTimer(),
rawRealtimeUs, which);
// Job completion (JOB_COMPLETION_DATA)
final ArrayMap<String, SparseIntArray> completions = u.getJobCompletionStats();
final int[] reasons = new int[]{
JobParameters.REASON_CANCELED,
JobParameters.REASON_CONSTRAINTS_NOT_SATISFIED,
JobParameters.REASON_PREEMPT,
JobParameters.REASON_TIMEOUT,
JobParameters.REASON_DEVICE_IDLE,
};
for (int ic = 0; ic < completions.size(); ++ic) {
SparseIntArray types = completions.valueAt(ic);
if (types != null) {
final long jcToken = proto.start(UidProto.JOB_COMPLETION);
proto.write(UidProto.JobCompletion.NAME, completions.keyAt(ic));
for (int r : reasons) {
long rToken = proto.start(UidProto.JobCompletion.REASON_COUNT);
proto.write(UidProto.JobCompletion.ReasonCount.NAME, r);
proto.write(UidProto.JobCompletion.ReasonCount.COUNT, types.get(r, 0));
proto.end(rToken);
}
proto.end(jcToken);
}
}
// Scheduled jobs (JOB_DATA)
final ArrayMap<String, ? extends Timer> jobs = u.getJobStats();
for (int ij = jobs.size() - 1; ij >= 0; --ij) {
final Timer timer = jobs.valueAt(ij);
final Timer bgTimer = timer.getSubTimer();
final long jToken = proto.start(UidProto.JOBS);
proto.write(UidProto.Job.NAME, jobs.keyAt(ij));
// Background uses totalDurationMsLocked, while total uses totalTimeLocked
dumpTimer(proto, UidProto.Job.TOTAL, timer, rawRealtimeUs, which);
dumpTimer(proto, UidProto.Job.BACKGROUND, bgTimer, rawRealtimeUs, which);
proto.end(jToken);
}
// Modem Controller (MODEM_CONTROLLER_DATA)
dumpControllerActivityProto(proto, UidProto.MODEM_CONTROLLER,
u.getModemControllerActivity(), which);
// Network stats (NETWORK_DATA)
final long nToken = proto.start(UidProto.NETWORK);
proto.write(UidProto.Network.MOBILE_BYTES_RX,
u.getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which));
proto.write(UidProto.Network.MOBILE_BYTES_TX,
u.getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which));
proto.write(UidProto.Network.WIFI_BYTES_RX,
u.getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which));
proto.write(UidProto.Network.WIFI_BYTES_TX,
u.getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which));
proto.write(UidProto.Network.BT_BYTES_RX,
u.getNetworkActivityBytes(NETWORK_BT_RX_DATA, which));
proto.write(UidProto.Network.BT_BYTES_TX,
u.getNetworkActivityBytes(NETWORK_BT_TX_DATA, which));
proto.write(UidProto.Network.MOBILE_PACKETS_RX,
u.getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which));
proto.write(UidProto.Network.MOBILE_PACKETS_TX,
u.getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which));
proto.write(UidProto.Network.WIFI_PACKETS_RX,
u.getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which));
proto.write(UidProto.Network.WIFI_PACKETS_TX,
u.getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which));
proto.write(UidProto.Network.MOBILE_ACTIVE_DURATION_MS,
roundUsToMs(u.getMobileRadioActiveTime(which)));
proto.write(UidProto.Network.MOBILE_ACTIVE_COUNT,
u.getMobileRadioActiveCount(which));
proto.write(UidProto.Network.MOBILE_WAKEUP_COUNT,
u.getMobileRadioApWakeupCount(which));
proto.write(UidProto.Network.WIFI_WAKEUP_COUNT,
u.getWifiRadioApWakeupCount(which));
proto.write(UidProto.Network.MOBILE_BYTES_BG_RX,
u.getNetworkActivityBytes(NETWORK_MOBILE_BG_RX_DATA, which));
proto.write(UidProto.Network.MOBILE_BYTES_BG_TX,
u.getNetworkActivityBytes(NETWORK_MOBILE_BG_TX_DATA, which));
proto.write(UidProto.Network.WIFI_BYTES_BG_RX,
u.getNetworkActivityBytes(NETWORK_WIFI_BG_RX_DATA, which));
proto.write(UidProto.Network.WIFI_BYTES_BG_TX,
u.getNetworkActivityBytes(NETWORK_WIFI_BG_TX_DATA, which));
proto.write(UidProto.Network.MOBILE_PACKETS_BG_RX,
u.getNetworkActivityPackets(NETWORK_MOBILE_BG_RX_DATA, which));
proto.write(UidProto.Network.MOBILE_PACKETS_BG_TX,
u.getNetworkActivityPackets(NETWORK_MOBILE_BG_TX_DATA, which));
proto.write(UidProto.Network.WIFI_PACKETS_BG_RX,
u.getNetworkActivityPackets(NETWORK_WIFI_BG_RX_DATA, which));
proto.write(UidProto.Network.WIFI_PACKETS_BG_TX,
u.getNetworkActivityPackets(NETWORK_WIFI_BG_TX_DATA, which));
proto.end(nToken);
// Power use item (POWER_USE_ITEM_DATA)
BatterySipper bs = uidToSipper.get(uid);
if (bs != 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.PROPORTIONAL_SMEAR_MAH,
bs.proportionalSmearMah);
proto.end(bsToken);
}
// Processes (PROCESS_DATA)
final ArrayMap<String, ? extends BatteryStats.Uid.Proc> processStats =
u.getProcessStats();
for (int ipr = processStats.size() - 1; ipr >= 0; --ipr) {
final Uid.Proc ps = processStats.valueAt(ipr);
final long prToken = proto.start(UidProto.PROCESS);
proto.write(UidProto.Process.NAME, processStats.keyAt(ipr));
proto.write(UidProto.Process.USER_DURATION_MS, ps.getUserTime(which));
proto.write(UidProto.Process.SYSTEM_DURATION_MS, ps.getSystemTime(which));
proto.write(UidProto.Process.FOREGROUND_DURATION_MS, ps.getForegroundTime(which));
proto.write(UidProto.Process.START_COUNT, ps.getStarts(which));
proto.write(UidProto.Process.ANR_COUNT, ps.getNumAnrs(which));
proto.write(UidProto.Process.CRASH_COUNT, ps.getNumCrashes(which));
proto.end(prToken);
}
// Sensors (SENSOR_DATA)
final SparseArray<? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats();
for (int ise = 0; ise < sensors.size(); ++ise) {
final Uid.Sensor se = sensors.valueAt(ise);
final Timer timer = se.getSensorTime();
if (timer == null) {
continue;
}
final Timer bgTimer = se.getSensorBackgroundTime();
final int sensorNumber = sensors.keyAt(ise);
final long seToken = proto.start(UidProto.SENSORS);
proto.write(UidProto.Sensor.ID, sensorNumber);
// Background uses totalDurationMsLocked, while total uses totalTimeLocked
dumpTimer(proto, UidProto.Sensor.APPORTIONED, timer, rawRealtimeUs, which);
dumpTimer(proto, UidProto.Sensor.BACKGROUND, bgTimer, rawRealtimeUs, which);
proto.end(seToken);
}
// State times (STATE_TIME_DATA)
for (int ips = 0; ips < Uid.NUM_PROCESS_STATE; ++ips) {
long durMs = roundUsToMs(u.getProcessStateTime(ips, rawRealtimeUs, which));
if (durMs == 0) {
continue;
}
final long stToken = proto.start(UidProto.STATES);
proto.write(UidProto.StateTime.STATE, ips);
proto.write(UidProto.StateTime.DURATION_MS, durMs);
proto.end(stToken);
}
// Syncs (SYNC_DATA)
final ArrayMap<String, ? extends Timer> syncs = u.getSyncStats();
for (int isy = syncs.size() - 1; isy >= 0; --isy) {
final Timer timer = syncs.valueAt(isy);
final Timer bgTimer = timer.getSubTimer();
final long syToken = proto.start(UidProto.SYNCS);
proto.write(UidProto.Sync.NAME, syncs.keyAt(isy));
// Background uses totalDurationMsLocked, while total uses totalTimeLocked
dumpTimer(proto, UidProto.Sync.TOTAL, timer, rawRealtimeUs, which);
dumpTimer(proto, UidProto.Sync.BACKGROUND, bgTimer, rawRealtimeUs, which);
proto.end(syToken);
}
// User activity (USER_ACTIVITY_DATA)
if (u.hasUserActivity()) {
for (int i = 0; i < Uid.NUM_USER_ACTIVITY_TYPES; ++i) {
int val = u.getUserActivityCount(i, which);
if (val != 0) {
final long uaToken = proto.start(UidProto.USER_ACTIVITY);
proto.write(UidProto.UserActivity.NAME, i);
proto.write(UidProto.UserActivity.COUNT, val);
proto.end(uaToken);
}
}
}
// Vibrator (VIBRATOR_DATA)
dumpTimer(proto, UidProto.VIBRATOR, u.getVibratorOnTimer(), rawRealtimeUs, which);
// Video (VIDEO_DATA)
dumpTimer(proto, UidProto.VIDEO, u.getVideoTurnedOnTimer(), rawRealtimeUs, which);
// Wakelocks (WAKELOCK_DATA)
final ArrayMap<String, ? extends Uid.Wakelock> wakelocks = u.getWakelockStats();
for (int iw = wakelocks.size() - 1; iw >= 0; --iw) {
final Uid.Wakelock wl = wakelocks.valueAt(iw);
final long wToken = proto.start(UidProto.WAKELOCKS);
proto.write(UidProto.Wakelock.NAME, wakelocks.keyAt(iw));
dumpTimer(proto, UidProto.Wakelock.FULL, wl.getWakeTime(WAKE_TYPE_FULL),
rawRealtimeUs, which);
final Timer pTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL);
if (pTimer != null) {
dumpTimer(proto, UidProto.Wakelock.PARTIAL, pTimer, rawRealtimeUs, which);
dumpTimer(proto, UidProto.Wakelock.BACKGROUND_PARTIAL, pTimer.getSubTimer(),
rawRealtimeUs, which);
}
dumpTimer(proto, UidProto.Wakelock.WINDOW, wl.getWakeTime(WAKE_TYPE_WINDOW),
rawRealtimeUs, which);
proto.end(wToken);
}
// Wifi Multicast Wakelock (WIFI_MULTICAST_WAKELOCK_DATA)
dumpTimer(proto, UidProto.WIFI_MULTICAST_WAKELOCK, u.getMulticastWakelockStats(),
rawRealtimeUs, which);
// Wakeup alarms (WAKEUP_ALARM_DATA)
for (int ipkg = packageStats.size() - 1; ipkg >= 0; --ipkg) {
final Uid.Pkg ps = packageStats.valueAt(ipkg);
final ArrayMap<String, ? extends Counter> alarms = ps.getWakeupAlarmStats();
for (int iwa = alarms.size() - 1; iwa >= 0; --iwa) {
final long waToken = proto.start(UidProto.WAKEUP_ALARM);
proto.write(UidProto.WakeupAlarm.NAME, alarms.keyAt(iwa));
proto.write(UidProto.WakeupAlarm.COUNT,
alarms.valueAt(iwa).getCountLocked(which));
proto.end(waToken);
}
}
// Wifi Controller (WIFI_CONTROLLER_DATA)
dumpControllerActivityProto(proto, UidProto.WIFI_CONTROLLER,
u.getWifiControllerActivity(), which);
// Wifi data (WIFI_DATA)
final long wToken = proto.start(UidProto.WIFI);
proto.write(UidProto.Wifi.FULL_WIFI_LOCK_DURATION_MS,
roundUsToMs(u.getFullWifiLockTime(rawRealtimeUs, which)));
dumpTimer(proto, UidProto.Wifi.APPORTIONED_SCAN, u.getWifiScanTimer(),
rawRealtimeUs, which);
proto.write(UidProto.Wifi.RUNNING_DURATION_MS,
roundUsToMs(u.getWifiRunningTime(rawRealtimeUs, which)));
dumpTimer(proto, UidProto.Wifi.BACKGROUND_SCAN, u.getWifiScanBackgroundTimer(),
rawRealtimeUs, which);
proto.end(wToken);
proto.end(uTkn);
}
}