blob: 17594d410d701c23f989a52c6009fbdd352c5924 [file] [log] [blame]
package android.os;
import java.io.PrintWriter;
import java.util.Formatter;
import java.util.Map;
import android.util.Log;
import android.util.Printer;
import android.util.SparseArray;
/**
* A class providing access to battery usage statistics, including information on
* wakelocks, processes, packages, and services. All times are represented in microseconds
* except where indicated otherwise.
* @hide
*/
public abstract class BatteryStats implements Parcelable {
private static final boolean LOCAL_LOGV = false;
/**
* A constant indicating a partial wake lock timer.
*/
public static final int WAKE_TYPE_PARTIAL = 0;
/**
* A constant indicating a full wake lock timer.
*/
public static final int WAKE_TYPE_FULL = 1;
/**
* A constant indicating a window wake lock timer.
*/
public static final int WAKE_TYPE_WINDOW = 2;
/**
* A constant indicating a sensor timer.
*
* {@hide}
*/
public static final int SENSOR = 3;
/**
* A constant indicating a a wifi turn on timer
*
* {@hide}
*/
public static final int WIFI_TURNED_ON = 4;
/**
* A constant indicating a full wifi lock timer
*
* {@hide}
*/
public static final int FULL_WIFI_LOCK = 5;
/**
* A constant indicating a scan wifi lock timer
*
* {@hide}
*/
public static final int SCAN_WIFI_LOCK = 6;
/**
* Include all of the data in the stats, including previously saved data.
*/
public static final int STATS_TOTAL = 0;
/**
* Include only the last run in the stats.
*/
public static final int STATS_LAST = 1;
/**
* Include only the current run in the stats.
*/
public static final int STATS_CURRENT = 2;
/**
* Include only the run since the last time the device was unplugged in the stats.
*/
public static final int STATS_UNPLUGGED = 3;
/**
* Bump the version on this if the checkin format changes.
*/
private static final int BATTERY_STATS_CHECKIN_VERSION = 3;
private static final long BYTES_PER_KB = 1024;
private static final long BYTES_PER_MB = 1048576; // 1024^2
private static final long BYTES_PER_GB = 1073741824; //1024^3
// TODO: Update this list if you add/change any stats above.
private static final String[] STAT_NAMES = { "total", "last", "current", "unplugged" };
private static final String APK_DATA = "apk";
private static final String PROCESS_DATA = "process";
private static final String SENSOR_DATA = "sensor";
private static final String WAKELOCK_DATA = "wakelock";
private static final String NETWORK_DATA = "network";
private static final String USER_ACTIVITY_DATA = "useract";
private static final String BATTERY_DATA = "battery";
private static final String WIFI_LOCK_DATA = "wifilock";
private static final String MISC_DATA = "misc";
private static final String SCREEN_BRIGHTNESS_DATA = "brightness";
private static final String SIGNAL_STRENGTH_TIME_DATA = "sigtime";
private static final String SIGNAL_STRENGTH_COUNT_DATA = "sigcnt";
private static final String DATA_CONNECTION_TIME_DATA = "dconntime";
private static final String DATA_CONNECTION_COUNT_DATA = "dconncnt";
private final StringBuilder mFormatBuilder = new StringBuilder(8);
private final Formatter mFormatter = new Formatter(mFormatBuilder);
/**
* State for keeping track of counting information.
*/
public static abstract class Counter {
/**
* Returns the count associated with this Counter for the
* selected type of statistics.
*
* @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT
*/
public abstract int getCount(int which);
/**
* Temporary for debugging.
*/
public abstract void logState(Printer pw, String prefix);
}
/**
* State for keeping track of timing information.
*/
public static abstract class Timer {
/**
* Returns the count associated with this Timer for the
* selected type of statistics.
*
* @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT
*/
public abstract int getCount(int which);
/**
* Returns the total time in microseconds associated with this Timer for the
* selected type of statistics.
*
* @param batteryRealtime system realtime on battery in microseconds
* @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT
* @return a time in microseconds
*/
public abstract long getTotalTime(long batteryRealtime, int which);
/**
* Temporary for debugging.
*/
public abstract void logState(Printer pw, String prefix);
}
/**
* The statistics associated with a particular uid.
*/
public static abstract class Uid {
/**
* Returns a mapping containing wakelock statistics.
*
* @return a Map from Strings to Uid.Wakelock objects.
*/
public abstract Map<String, ? extends Wakelock> getWakelockStats();
/**
* The statistics associated with a particular wake lock.
*/
public static abstract class Wakelock {
public abstract Timer getWakeTime(int type);
}
/**
* Returns a mapping containing sensor statistics.
*
* @return a Map from Integer sensor ids to Uid.Sensor objects.
*/
public abstract Map<Integer, ? extends Sensor> getSensorStats();
/**
* Returns a mapping containing process statistics.
*
* @return a Map from Strings to Uid.Proc objects.
*/
public abstract Map<String, ? extends Proc> getProcessStats();
/**
* Returns a mapping containing package statistics.
*
* @return a Map from Strings to Uid.Pkg objects.
*/
public abstract Map<String, ? extends Pkg> getPackageStats();
/**
* {@hide}
*/
public abstract int getUid();
/**
* {@hide}
*/
public abstract long getTcpBytesReceived(int which);
/**
* {@hide}
*/
public abstract long getTcpBytesSent(int which);
public abstract void noteWifiTurnedOnLocked();
public abstract void noteWifiTurnedOffLocked();
public abstract void noteFullWifiLockAcquiredLocked();
public abstract void noteFullWifiLockReleasedLocked();
public abstract void noteScanWifiLockAcquiredLocked();
public abstract void noteScanWifiLockReleasedLocked();
public abstract long getWifiTurnedOnTime(long batteryRealtime, int which);
public abstract long getFullWifiLockTime(long batteryRealtime, int which);
public abstract long getScanWifiLockTime(long batteryRealtime, int which);
/**
* Note that these must match the constants in android.os.LocalPowerManager.
*/
static final String[] USER_ACTIVITY_TYPES = {
"other", "cheek", "touch", "long_touch", "touch_up", "button", "unknown"
};
public static final int NUM_USER_ACTIVITY_TYPES = 7;
public abstract void noteUserActivityLocked(int type);
public abstract boolean hasUserActivity();
public abstract int getUserActivityCount(int type, int which);
public static abstract class Sensor {
// Magic sensor number for the GPS.
public static final int GPS = -10000;
public abstract int getHandle();
public abstract Timer getSensorTime();
}
/**
* The statistics associated with a particular process.
*/
public static abstract class Proc {
/**
* Returns the total time (in 1/100 sec) spent executing in user code.
*
* @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
*/
public abstract long getUserTime(int which);
/**
* Returns the total time (in 1/100 sec) spent executing in system code.
*
* @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
*/
public abstract long getSystemTime(int which);
/**
* Returns the number of times the process has been started.
*
* @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
*/
public abstract int getStarts(int which);
}
/**
* The statistics associated with a particular package.
*/
public static abstract class Pkg {
/**
* Returns the number of times this package has done something that could wake up the
* device from sleep.
*
* @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
*/
public abstract int getWakeups(int which);
/**
* Returns a mapping containing service statistics.
*/
public abstract Map<String, ? extends Serv> getServiceStats();
/**
* The statistics associated with a particular service.
*/
public abstract class Serv {
/**
* Returns the amount of time spent started.
*
* @param batteryUptime elapsed uptime on battery in microseconds.
* @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
* @return
*/
public abstract long getStartTime(long batteryUptime, int which);
/**
* Returns the total number of times startService() has been called.
*
* @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
*/
public abstract int getStarts(int which);
/**
* Returns the total number times the service has been launched.
*
* @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
*/
public abstract int getLaunches(int which);
}
}
}
/**
* Returns the number of times the device has been started.
*/
public abstract int getStartCount();
/**
* Returns the time in milliseconds that the screen has been on while the device was
* running on battery.
*
* {@hide}
*/
public abstract long getScreenOnTime(long batteryRealtime, int which);
public static final int SCREEN_BRIGHTNESS_DARK = 0;
public static final int SCREEN_BRIGHTNESS_DIM = 1;
public static final int SCREEN_BRIGHTNESS_MEDIUM = 2;
public static final int SCREEN_BRIGHTNESS_LIGHT = 3;
public static final int SCREEN_BRIGHTNESS_BRIGHT = 4;
static final String[] SCREEN_BRIGHTNESS_NAMES = {
"dark", "dim", "medium", "light", "bright"
};
public static final int NUM_SCREEN_BRIGHTNESS_BINS = 5;
/**
* Returns the time in milliseconds that the screen has been on with
* the given brightness
*
* {@hide}
*/
public abstract long getScreenBrightnessTime(int brightnessBin,
long batteryRealtime, int which);
public abstract int getInputEventCount(int which);
/**
* Returns the time in milliseconds that the phone has been on while the device was
* running on battery.
*
* {@hide}
*/
public abstract long getPhoneOnTime(long batteryRealtime, int which);
public static final int SIGNAL_STRENGTH_NONE_OR_UNKNOWN = 0;
public static final int SIGNAL_STRENGTH_POOR = 1;
public static final int SIGNAL_STRENGTH_MODERATE = 2;
public static final int SIGNAL_STRENGTH_GOOD = 3;
public static final int SIGNAL_STRENGTH_GREAT = 4;
static final String[] SIGNAL_STRENGTH_NAMES = {
"none", "poor", "moderate", "good", "great"
};
public static final int NUM_SIGNAL_STRENGTH_BINS = 5;
/**
* Returns the time in milliseconds that the phone has been running with
* the given signal strength.
*
* {@hide}
*/
public abstract long getPhoneSignalStrengthTime(int strengthBin,
long batteryRealtime, int which);
/**
* Returns the number of times the phone has entered the given signal strength.
*
* {@hide}
*/
public abstract int getPhoneSignalStrengthCount(int strengthBin, int which);
public static final int DATA_CONNECTION_NONE = 0;
public static final int DATA_CONNECTION_GPRS = 1;
public static final int DATA_CONNECTION_EDGE = 2;
public static final int DATA_CONNECTION_UMTS = 3;
public static final int DATA_CONNECTION_OTHER = 4;
static final String[] DATA_CONNECTION_NAMES = {
"none", "gprs", "edge", "umts", "other"
};
public static final int NUM_DATA_CONNECTION_TYPES = 5;
/**
* Returns the time in milliseconds that the phone has been running with
* the given data connection.
*
* {@hide}
*/
public abstract long getPhoneDataConnectionTime(int dataType,
long batteryRealtime, int which);
/**
* Returns the number of times the phone has entered the given data
* connection type.
*
* {@hide}
*/
public abstract int getPhoneDataConnectionCount(int dataType, int which);
/**
* Returns the time in milliseconds that wifi has been on while the device was
* running on battery.
*
* {@hide}
*/
public abstract long getWifiOnTime(long batteryRealtime, int which);
/**
* Returns the time in milliseconds that wifi has been on and the driver has
* been in the running state while the device was running on battery.
*
* {@hide}
*/
public abstract long getWifiRunningTime(long batteryRealtime, int which);
/**
* Returns the time in milliseconds that bluetooth has been on while the device was
* running on battery.
*
* {@hide}
*/
public abstract long getBluetoothOnTime(long batteryRealtime, int which);
/**
* Return whether we are currently running on battery.
*/
public abstract boolean getIsOnBattery();
/**
* Returns a SparseArray containing the statistics for each uid.
*/
public abstract SparseArray<? extends Uid> getUidStats();
/**
* Returns the current battery uptime in microseconds.
*
* @param curTime the amount of elapsed realtime in microseconds.
*/
public abstract long getBatteryUptime(long curTime);
/**
* Returns the current battery realtime in microseconds.
*
* @param curTime the amount of elapsed realtime in microseconds.
*/
public abstract long getBatteryRealtime(long curTime);
/**
* Returns the battery percentage level at the last time the device was unplugged from power,
* or the last time it was booted while unplugged.
*/
public abstract int getUnpluggedStartLevel();
/**
* Returns the battery percentage level at the last time the device was plugged into power.
*/
public abstract int getPluggedStartLevel();
/**
* Returns the total, last, or current battery uptime in microseconds.
*
* @param curTime the elapsed realtime in microseconds.
* @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
*/
public abstract long computeBatteryUptime(long curTime, int which);
/**
* Returns the total, last, or current battery realtime in microseconds.
*
* @param curTime the current elapsed realtime in microseconds.
* @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
*/
public abstract long computeBatteryRealtime(long curTime, int which);
/**
* Returns the total, last, or current uptime in microseconds.
*
* @param curTime the current elapsed realtime in microseconds.
* @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
*/
public abstract long computeUptime(long curTime, int which);
/**
* Returns the total, last, or current realtime in microseconds.
* *
* @param curTime the current elapsed realtime in microseconds.
* @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
*/
public abstract long computeRealtime(long curTime, int which);
private final static void formatTime(StringBuilder out, long seconds) {
long days = seconds / (60 * 60 * 24);
if (days != 0) {
out.append(days);
out.append("d ");
}
long used = days * 60 * 60 * 24;
long hours = (seconds - used) / (60 * 60);
if (hours != 0 || used != 0) {
out.append(hours);
out.append("h ");
}
used += hours * 60 * 60;
long mins = (seconds-used) / 60;
if (mins != 0 || used != 0) {
out.append(mins);
out.append("m ");
}
used += mins * 60;
if (seconds != 0 || used != 0) {
out.append(seconds-used);
out.append("s ");
}
}
private final static String formatTime(long time) {
long sec = time / 100;
StringBuilder sb = new StringBuilder();
formatTime(sb, sec);
sb.append((time - (sec * 100)) * 10);
sb.append("ms ");
return sb.toString();
}
private final static String formatTimeMs(long time) {
long sec = time / 1000;
StringBuilder sb = new StringBuilder();
formatTime(sb, sec);
sb.append(time - (sec * 1000));
sb.append("ms ");
return sb.toString();
}
private final String formatRatioLocked(long num, long den) {
if (den == 0L) {
return "---%";
}
float perc = ((float)num) / ((float)den) * 100;
mFormatBuilder.setLength(0);
mFormatter.format("%.1f%%", perc);
return mFormatBuilder.toString();
}
private final String formatBytesLocked(long bytes) {
mFormatBuilder.setLength(0);
if (bytes < BYTES_PER_KB) {
return bytes + "B";
} else if (bytes < BYTES_PER_MB) {
mFormatter.format("%.2fKB", bytes / (double) BYTES_PER_KB);
return mFormatBuilder.toString();
} else if (bytes < BYTES_PER_GB){
mFormatter.format("%.2fMB", bytes / (double) BYTES_PER_MB);
return mFormatBuilder.toString();
} else {
mFormatter.format("%.2fGB", bytes / (double) BYTES_PER_GB);
return mFormatBuilder.toString();
}
}
/**
*
* @param sb a StringBuilder object.
* @param timer a Timer object contining the wakelock times.
* @param batteryRealtime the current on-battery time in microseconds.
* @param name the name of the wakelock.
* @param which which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
* @param linePrefix a String to be prepended to each line of output.
* @return the line prefix
*/
private static final String printWakeLock(StringBuilder sb, Timer timer,
long batteryRealtime, String name, int which, String linePrefix) {
if (timer != null) {
// Convert from microseconds to milliseconds with rounding
long totalTimeMicros = timer.getTotalTime(batteryRealtime, which);
long totalTimeMillis = (totalTimeMicros + 500) / 1000;
int count = timer.getCount(which);
if (totalTimeMillis != 0) {
sb.append(linePrefix);
sb.append(formatTimeMs(totalTimeMillis));
sb.append(name);
sb.append(' ');
sb.append('(');
sb.append(count);
sb.append(" times)");
return ", ";
}
}
return linePrefix;
}
/**
* Checkin version of wakelock printer. Prints simple comma-separated list.
*
* @param sb a StringBuilder object.
* @param timer a Timer object contining the wakelock times.
* @param now the current time in microseconds.
* @param name the name of the wakelock.
* @param which which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
* @param linePrefix a String to be prepended to each line of output.
* @return the line prefix
*/
private static final String printWakeLockCheckin(StringBuilder sb, Timer timer, long now,
String name, int which, String linePrefix) {
long totalTimeMicros = 0;
int count = 0;
if (timer != null) {
totalTimeMicros = timer.getTotalTime(now, which);
count = timer.getCount(which);
}
sb.append(linePrefix);
sb.append((totalTimeMicros + 500) / 1000); // microseconds to milliseconds with rounding
sb.append(',');
sb.append(name);
sb.append(',');
sb.append(count);
return ",";
}
/**
* Dump a comma-separated line of values for terse checkin mode.
*
* @param pw the PageWriter to dump log to
* @param category category of data (e.g. "total", "last", "unplugged", "current" )
* @param type type of data (e.g. "wakelock", "sensor", "process", "apk" , "process", "network")
* @param args type-dependent data arguments
*/
private static final void dumpLine(PrintWriter pw, int uid, String category, String type,
Object... args ) {
pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
pw.print(uid); pw.print(',');
pw.print(category); pw.print(',');
pw.print(type);
for (Object arg : args) {
pw.print(',');
pw.print(arg);
}
pw.print('\n');
}
/**
* Checkin server version of dump to produce more compact, computer-readable log.
*
* NOTE: all times are expressed in 'ms'.
* @param fd
* @param pw
* @param which
*/
private final void dumpCheckinLocked(PrintWriter pw, int which) {
final long rawUptime = SystemClock.uptimeMillis() * 1000;
final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
final long batteryUptime = getBatteryUptime(rawUptime);
final long batteryRealtime = getBatteryRealtime(rawRealtime);
final long whichBatteryUptime = computeBatteryUptime(rawUptime, which);
final long whichBatteryRealtime = computeBatteryRealtime(rawRealtime, which);
final long totalRealtime = computeRealtime(rawRealtime, which);
final long totalUptime = computeUptime(rawUptime, which);
final long screenOnTime = getScreenOnTime(batteryRealtime, which);
final long phoneOnTime = getPhoneOnTime(batteryRealtime, which);
final long wifiOnTime = getWifiOnTime(batteryRealtime, which);
final long wifiRunningTime = getWifiRunningTime(batteryRealtime, which);
final long bluetoothOnTime = getBluetoothOnTime(batteryRealtime, which);
StringBuilder sb = new StringBuilder(128);
SparseArray<? extends Uid> uidStats = getUidStats();
final int NU = uidStats.size();
String category = STAT_NAMES[which];
// Dump "battery" stat
dumpLine(pw, 0 /* uid */, category, BATTERY_DATA,
which == STATS_TOTAL ? getStartCount() : "N/A",
whichBatteryRealtime / 1000, whichBatteryUptime / 1000,
totalRealtime / 1000, totalUptime / 1000);
// Calculate total network and wakelock times across all uids.
long rxTotal = 0;
long txTotal = 0;
long fullWakeLockTimeTotal = 0;
long partialWakeLockTimeTotal = 0;
for (int iu = 0; iu < NU; iu++) {
Uid u = uidStats.valueAt(iu);
rxTotal += u.getTcpBytesReceived(which);
txTotal += u.getTcpBytesSent(which);
Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
if (wakelocks.size() > 0) {
for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
: wakelocks.entrySet()) {
Uid.Wakelock wl = ent.getValue();
Timer fullWakeTimer = wl.getWakeTime(WAKE_TYPE_FULL);
if (fullWakeTimer != null) {
fullWakeLockTimeTotal += fullWakeTimer.getTotalTime(batteryRealtime, which);
}
Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL);
if (partialWakeTimer != null) {
partialWakeLockTimeTotal += partialWakeTimer.getTotalTime(
batteryRealtime, which);
}
}
}
}
// Dump misc stats
dumpLine(pw, 0 /* uid */, category, MISC_DATA,
screenOnTime / 1000, phoneOnTime / 1000, wifiOnTime / 1000,
wifiRunningTime / 1000, bluetoothOnTime / 1000, rxTotal, txTotal,
fullWakeLockTimeTotal, partialWakeLockTimeTotal,
getInputEventCount(which));
// Dump screen brightness stats
Object[] args = new Object[NUM_SCREEN_BRIGHTNESS_BINS];
for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
args[i] = getScreenBrightnessTime(i, batteryRealtime, which) / 1000;
}
dumpLine(pw, 0 /* uid */, category, SCREEN_BRIGHTNESS_DATA, args);
// Dump signal strength stats
args = new Object[NUM_SIGNAL_STRENGTH_BINS];
for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) {
args[i] = getPhoneSignalStrengthTime(i, batteryRealtime, which) / 1000;
}
dumpLine(pw, 0 /* uid */, category, SIGNAL_STRENGTH_TIME_DATA, args);
for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) {
args[i] = getPhoneSignalStrengthCount(i, which);
}
dumpLine(pw, 0 /* uid */, category, SIGNAL_STRENGTH_COUNT_DATA, args);
// Dump network type stats
args = new Object[NUM_DATA_CONNECTION_TYPES];
for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
args[i] = getPhoneDataConnectionTime(i, batteryRealtime, which) / 1000;
}
dumpLine(pw, 0 /* uid */, category, DATA_CONNECTION_TIME_DATA, args);
for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
args[i] = getPhoneDataConnectionCount(i, which);
}
dumpLine(pw, 0 /* uid */, category, DATA_CONNECTION_COUNT_DATA, args);
if (which == STATS_UNPLUGGED) {
dumpLine(pw, 0 /* uid */, category, BATTERY_DATA, getUnpluggedStartLevel(),
getPluggedStartLevel());
}
for (int iu = 0; iu < NU; iu++) {
final int uid = uidStats.keyAt(iu);
Uid u = uidStats.valueAt(iu);
// Dump Network stats per uid, if any
long rx = u.getTcpBytesReceived(which);
long tx = u.getTcpBytesSent(which);
long fullWifiLockOnTime = u.getFullWifiLockTime(batteryRealtime, which);
long scanWifiLockOnTime = u.getScanWifiLockTime(batteryRealtime, which);
long wifiTurnedOnTime = u.getWifiTurnedOnTime(batteryRealtime, which);
if (rx > 0 || tx > 0) dumpLine(pw, uid, category, NETWORK_DATA, rx, tx);
if (fullWifiLockOnTime != 0 || scanWifiLockOnTime != 0
|| wifiTurnedOnTime != 0) {
dumpLine(pw, uid, category, WIFI_LOCK_DATA,
fullWifiLockOnTime, scanWifiLockOnTime, wifiTurnedOnTime);
}
if (u.hasUserActivity()) {
args = new Object[Uid.NUM_USER_ACTIVITY_TYPES];
boolean hasData = false;
for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
int val = u.getUserActivityCount(i, which);
args[i] = val;
if (val != 0) hasData = true;
}
if (hasData) {
dumpLine(pw, 0 /* uid */, category, USER_ACTIVITY_DATA, args);
}
}
Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
if (wakelocks.size() > 0) {
for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
: wakelocks.entrySet()) {
Uid.Wakelock wl = ent.getValue();
String linePrefix = "";
sb.setLength(0);
linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_FULL), batteryRealtime,
"full", which, linePrefix);
linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL), batteryRealtime,
"partial", which, linePrefix);
linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), batteryRealtime,
"window", which, linePrefix);
// Only log if we had at lease one wakelock...
if (sb.length() > 0) {
dumpLine(pw, uid, category, WAKELOCK_DATA, ent.getKey(), sb.toString());
}
}
}
Map<Integer, ? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats();
if (sensors.size() > 0) {
for (Map.Entry<Integer, ? extends BatteryStats.Uid.Sensor> ent
: sensors.entrySet()) {
Uid.Sensor se = ent.getValue();
int sensorNumber = ent.getKey();
Timer timer = se.getSensorTime();
if (timer != null) {
// Convert from microseconds to milliseconds with rounding
long totalTime = (timer.getTotalTime(batteryRealtime, which) + 500) / 1000;
int count = timer.getCount(which);
if (totalTime != 0) {
dumpLine(pw, uid, category, SENSOR_DATA, sensorNumber, totalTime, count);
}
}
}
}
Map<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats();
if (processStats.size() > 0) {
for (Map.Entry<String, ? extends BatteryStats.Uid.Proc> ent
: processStats.entrySet()) {
Uid.Proc ps = ent.getValue();
long userTime = ps.getUserTime(which);
long systemTime = ps.getSystemTime(which);
int starts = ps.getStarts(which);
if (userTime != 0 || systemTime != 0 || starts != 0) {
dumpLine(pw, uid, category, PROCESS_DATA,
ent.getKey(), // proc
userTime * 10, // cpu time in ms
systemTime * 10, // user time in ms
starts); // process starts
}
}
}
Map<String, ? extends BatteryStats.Uid.Pkg> packageStats = u.getPackageStats();
if (packageStats.size() > 0) {
for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg> ent
: packageStats.entrySet()) {
Uid.Pkg ps = ent.getValue();
int wakeups = ps.getWakeups(which);
Map<String, ? extends Uid.Pkg.Serv> serviceStats = ps.getServiceStats();
for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg.Serv> sent
: serviceStats.entrySet()) {
BatteryStats.Uid.Pkg.Serv ss = sent.getValue();
long startTime = ss.getStartTime(batteryUptime, which);
int starts = ss.getStarts(which);
int launches = ss.getLaunches(which);
if (startTime != 0 || starts != 0 || launches != 0) {
dumpLine(pw, uid, category, APK_DATA,
wakeups, // wakeup alarms
ent.getKey(), // Apk
sent.getKey(), // service
startTime / 1000, // time spent started, in ms
starts,
launches);
}
}
}
}
}
}
@SuppressWarnings("unused")
private final void dumpLocked(Printer pw, String prefix, int which) {
final long rawUptime = SystemClock.uptimeMillis() * 1000;
final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
final long batteryUptime = getBatteryUptime(rawUptime);
final long batteryRealtime = getBatteryRealtime(rawRealtime);
final long whichBatteryUptime = computeBatteryUptime(rawUptime, which);
final long whichBatteryRealtime = computeBatteryRealtime(rawRealtime, which);
final long totalRealtime = computeRealtime(rawRealtime, which);
final long totalUptime = computeUptime(rawUptime, which);
StringBuilder sb = new StringBuilder(128);
SparseArray<? extends Uid> uidStats = getUidStats();
final int NU = uidStats.size();
pw.println(prefix
+ " Time on battery: "
+ formatTimeMs(whichBatteryRealtime / 1000) + "("
+ formatRatioLocked(whichBatteryRealtime, totalRealtime)
+ ") realtime, "
+ formatTimeMs(whichBatteryUptime / 1000)
+ "(" + formatRatioLocked(whichBatteryUptime, totalRealtime)
+ ") uptime");
pw.println(prefix
+ " Total run time: "
+ formatTimeMs(totalRealtime / 1000)
+ "realtime, "
+ formatTimeMs(totalUptime / 1000)
+ "uptime, ");
final long screenOnTime = getScreenOnTime(batteryRealtime, which);
final long phoneOnTime = getPhoneOnTime(batteryRealtime, which);
final long wifiRunningTime = getWifiRunningTime(batteryRealtime, which);
final long wifiOnTime = getWifiOnTime(batteryRealtime, which);
final long bluetoothOnTime = getBluetoothOnTime(batteryRealtime, which);
pw.println(prefix
+ " Screen on: " + formatTimeMs(screenOnTime / 1000)
+ "(" + formatRatioLocked(screenOnTime, whichBatteryRealtime)
+ "), Input events: " + getInputEventCount(which)
+ ", Active phone call: " + formatTimeMs(phoneOnTime / 1000)
+ "(" + formatRatioLocked(phoneOnTime, whichBatteryRealtime) + ")");
sb.setLength(0);
sb.append(" Screen brightnesses: ");
boolean didOne = false;
for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
final long time = getScreenBrightnessTime(i, batteryRealtime, which);
if (time == 0) {
continue;
}
if (didOne) sb.append(", ");
didOne = true;
sb.append(SCREEN_BRIGHTNESS_NAMES[i]);
sb.append(" ");
sb.append(formatTimeMs(time/1000));
sb.append("(");
sb.append(formatRatioLocked(time, screenOnTime));
sb.append(")");
}
if (!didOne) sb.append("No activity");
pw.println(sb.toString());
// Calculate total network and wakelock times across all uids.
long rxTotal = 0;
long txTotal = 0;
long fullWakeLockTimeTotalMicros = 0;
long partialWakeLockTimeTotalMicros = 0;
for (int iu = 0; iu < NU; iu++) {
Uid u = uidStats.valueAt(iu);
rxTotal += u.getTcpBytesReceived(which);
txTotal += u.getTcpBytesSent(which);
Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
if (wakelocks.size() > 0) {
for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
: wakelocks.entrySet()) {
Uid.Wakelock wl = ent.getValue();
Timer fullWakeTimer = wl.getWakeTime(WAKE_TYPE_FULL);
if (fullWakeTimer != null) {
fullWakeLockTimeTotalMicros += fullWakeTimer.getTotalTime(
batteryRealtime, which);
}
Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL);
if (partialWakeTimer != null) {
partialWakeLockTimeTotalMicros += partialWakeTimer.getTotalTime(
batteryRealtime, which);
}
}
}
}
pw.println(prefix
+ " Total received: " + formatBytesLocked(rxTotal)
+ ", Total sent: " + formatBytesLocked(txTotal));
pw.println(prefix
+ " Total full wakelock time: " + formatTimeMs(
(fullWakeLockTimeTotalMicros + 500) / 1000)
+ ", Total partial waklock time: " + formatTimeMs(
(partialWakeLockTimeTotalMicros + 500) / 1000));
sb.setLength(0);
sb.append(" Signal levels: ");
didOne = false;
for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) {
final long time = getPhoneSignalStrengthTime(i, batteryRealtime, which);
if (time == 0) {
continue;
}
if (didOne) sb.append(", ");
didOne = true;
sb.append(SIGNAL_STRENGTH_NAMES[i]);
sb.append(" ");
sb.append(formatTimeMs(time/1000));
sb.append("(");
sb.append(formatRatioLocked(time, whichBatteryRealtime));
sb.append(") ");
sb.append(getPhoneSignalStrengthCount(i, which));
sb.append("x");
}
if (!didOne) sb.append("No activity");
pw.println(sb.toString());
sb.setLength(0);
sb.append(" Radio types: ");
didOne = false;
for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
final long time = getPhoneDataConnectionTime(i, batteryRealtime, which);
if (time == 0) {
continue;
}
if (didOne) sb.append(", ");
didOne = true;
sb.append(DATA_CONNECTION_NAMES[i]);
sb.append(" ");
sb.append(formatTimeMs(time/1000));
sb.append("(");
sb.append(formatRatioLocked(time, whichBatteryRealtime));
sb.append(") ");
sb.append(getPhoneDataConnectionCount(i, which));
sb.append("x");
}
if (!didOne) sb.append("No activity");
pw.println(sb.toString());
pw.println(prefix
+ " Wifi on: " + formatTimeMs(wifiOnTime / 1000)
+ "(" + formatRatioLocked(wifiOnTime, whichBatteryRealtime)
+ "), Wifi running: " + formatTimeMs(wifiRunningTime / 1000)
+ "(" + formatRatioLocked(wifiRunningTime, whichBatteryRealtime)
+ "), Bluetooth on: " + formatTimeMs(bluetoothOnTime / 1000)
+ "(" + formatRatioLocked(bluetoothOnTime, whichBatteryRealtime)+ ")");
pw.println(" ");
if (which == STATS_UNPLUGGED) {
if (getIsOnBattery()) {
pw.println(prefix + " Device is currently unplugged");
pw.println(prefix + " Discharge cycle start level: " +
getUnpluggedStartLevel());
} else {
pw.println(prefix + " Device is currently plugged into power");
pw.println(prefix + " Last discharge cycle start level: " +
getUnpluggedStartLevel());
pw.println(prefix + " Last discharge cycle end level: " +
getPluggedStartLevel());
}
pw.println(" ");
}
for (int iu=0; iu<NU; iu++) {
final int uid = uidStats.keyAt(iu);
Uid u = uidStats.valueAt(iu);
pw.println(prefix + " #" + uid + ":");
boolean uidActivity = false;
long tcpReceived = u.getTcpBytesReceived(which);
long tcpSent = u.getTcpBytesSent(which);
long fullWifiLockOnTime = u.getFullWifiLockTime(batteryRealtime, which);
long scanWifiLockOnTime = u.getScanWifiLockTime(batteryRealtime, which);
long wifiTurnedOnTime = u.getWifiTurnedOnTime(batteryRealtime, which);
if (tcpReceived != 0 || tcpSent != 0) {
pw.println(prefix + " Network: " + formatBytesLocked(tcpReceived) + " received, "
+ formatBytesLocked(tcpSent) + " sent");
}
if (u.hasUserActivity()) {
boolean hasData = false;
for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
int val = u.getUserActivityCount(i, which);
if (val != 0) {
if (!hasData) {
sb.setLength(0);
sb.append(" User activity: ");
hasData = true;
} else {
sb.append(", ");
}
sb.append(val);
sb.append(" ");
sb.append(Uid.USER_ACTIVITY_TYPES[i]);
}
}
if (hasData) {
pw.println(sb.toString());
}
}
if (fullWifiLockOnTime != 0 || scanWifiLockOnTime != 0
|| wifiTurnedOnTime != 0) {
pw.println(prefix + " Turned Wifi On Time: "
+ formatTimeMs(wifiTurnedOnTime / 1000)
+ "(" + formatRatioLocked(wifiTurnedOnTime,
whichBatteryRealtime)+ ")");
pw.println(prefix + " Full Wifi Lock Time: "
+ formatTimeMs(fullWifiLockOnTime / 1000)
+ "(" + formatRatioLocked(fullWifiLockOnTime,
whichBatteryRealtime)+ ")");
pw.println(prefix + " Scan Wifi Lock Time: "
+ formatTimeMs(scanWifiLockOnTime / 1000)
+ "(" + formatRatioLocked(scanWifiLockOnTime,
whichBatteryRealtime)+ ")");
}
Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
if (wakelocks.size() > 0) {
for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
: wakelocks.entrySet()) {
Uid.Wakelock wl = ent.getValue();
String linePrefix = ": ";
sb.setLength(0);
sb.append(prefix);
sb.append(" Wake lock ");
sb.append(ent.getKey());
linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_FULL), batteryRealtime,
"full", which, linePrefix);
linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL), batteryRealtime,
"partial", which, linePrefix);
linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), batteryRealtime,
"window", which, linePrefix);
if (!linePrefix.equals(": ")) {
sb.append(" realtime");
} else {
sb.append(": (nothing executed)");
}
pw.println(sb.toString());
uidActivity = true;
}
}
Map<Integer, ? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats();
if (sensors.size() > 0) {
for (Map.Entry<Integer, ? extends BatteryStats.Uid.Sensor> ent
: sensors.entrySet()) {
Uid.Sensor se = ent.getValue();
int sensorNumber = ent.getKey();
sb.setLength(0);
sb.append(prefix);
sb.append(" Sensor ");
int handle = se.getHandle();
if (handle == Uid.Sensor.GPS) {
sb.append("GPS");
} else {
sb.append(handle);
}
sb.append(": ");
Timer timer = se.getSensorTime();
if (timer != null) {
// Convert from microseconds to milliseconds with rounding
long totalTime = (timer.getTotalTime(batteryRealtime, which) + 500) / 1000;
int count = timer.getCount(which);
//timer.logState();
if (totalTime != 0) {
sb.append(formatTimeMs(totalTime));
sb.append("realtime (");
sb.append(count);
sb.append(" times)");
} else {
sb.append("(not used)");
}
} else {
sb.append("(not used)");
}
pw.println(sb.toString());
uidActivity = true;
}
}
Map<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats();
if (processStats.size() > 0) {
for (Map.Entry<String, ? extends BatteryStats.Uid.Proc> ent
: processStats.entrySet()) {
Uid.Proc ps = ent.getValue();
long userTime;
long systemTime;
int starts;
userTime = ps.getUserTime(which);
systemTime = ps.getSystemTime(which);
starts = ps.getStarts(which);
if (userTime != 0 || systemTime != 0 || starts != 0) {
pw.println(prefix + " Proc " + ent.getKey() + ":");
pw.println(prefix + " CPU: " + formatTime(userTime) + "user + "
+ formatTime(systemTime) + "kernel");
pw.println(prefix + " " + starts + " process starts");
uidActivity = true;
}
}
}
Map<String, ? extends BatteryStats.Uid.Pkg> packageStats = u.getPackageStats();
if (packageStats.size() > 0) {
for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg> ent
: packageStats.entrySet()) {
pw.println(prefix + " Apk " + ent.getKey() + ":");
boolean apkActivity = false;
Uid.Pkg ps = ent.getValue();
int wakeups = ps.getWakeups(which);
if (wakeups != 0) {
pw.println(prefix + " " + wakeups + " wakeup alarms");
apkActivity = true;
}
Map<String, ? extends Uid.Pkg.Serv> serviceStats = ps.getServiceStats();
if (serviceStats.size() > 0) {
for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg.Serv> sent
: serviceStats.entrySet()) {
BatteryStats.Uid.Pkg.Serv ss = sent.getValue();
long startTime = ss.getStartTime(batteryUptime, which);
int starts = ss.getStarts(which);
int launches = ss.getLaunches(which);
if (startTime != 0 || starts != 0 || launches != 0) {
pw.println(prefix + " Service " + sent.getKey() + ":");
pw.println(prefix + " Created for: "
+ formatTimeMs(startTime / 1000)
+ " uptime");
pw.println(prefix + " Starts: " + starts
+ ", launches: " + launches);
apkActivity = true;
}
}
}
if (!apkActivity) {
pw.println(prefix + " (nothing executed)");
}
uidActivity = true;
}
}
if (!uidActivity) {
pw.println(prefix + " (nothing executed)");
}
}
}
/**
* Dumps a human-readable summary of the battery statistics to the given PrintWriter.
*
* @param pw a Printer to receive the dump output.
*/
@SuppressWarnings("unused")
public void dumpLocked(Printer pw) {
pw.println("Total Statistics (Current and Historic):");
pw.println(" System starts: " + getStartCount()
+ ", currently on battery: " + getIsOnBattery());
dumpLocked(pw, "", STATS_TOTAL);
pw.println("");
pw.println("Last Run Statistics (Previous run of system):");
dumpLocked(pw, "", STATS_LAST);
pw.println("");
pw.println("Current Battery Statistics (Currently running system):");
dumpLocked(pw, "", STATS_CURRENT);
pw.println("");
pw.println("Unplugged Statistics (Since last unplugged from power):");
dumpLocked(pw, "", STATS_UNPLUGGED);
}
@SuppressWarnings("unused")
public void dumpCheckinLocked(PrintWriter pw, String[] args) {
boolean isUnpluggedOnly = false;
for (String arg : args) {
if ("-u".equals(arg)) {
if (LOCAL_LOGV) Log.v("BatteryStats", "Dumping unplugged data");
isUnpluggedOnly = true;
}
}
if (isUnpluggedOnly) {
dumpCheckinLocked(pw, STATS_UNPLUGGED);
}
else {
dumpCheckinLocked(pw, STATS_TOTAL);
dumpCheckinLocked(pw, STATS_LAST);
dumpCheckinLocked(pw, STATS_UNPLUGGED);
dumpCheckinLocked(pw, STATS_CURRENT);
}
}
}