BatteryStats.java revision c38c0f6b9869889fbb6743275e35f120a27f6361
1package android.os; 2 3import java.io.PrintWriter; 4import java.util.Formatter; 5import java.util.Map; 6 7import android.util.Log; 8import android.util.Printer; 9import android.util.SparseArray; 10 11/** 12 * A class providing access to battery usage statistics, including information on 13 * wakelocks, processes, packages, and services. All times are represented in microseconds 14 * except where indicated otherwise. 15 * @hide 16 */ 17public abstract class BatteryStats implements Parcelable { 18 19 private static final boolean LOCAL_LOGV = false; 20 21 /** 22 * A constant indicating a partial wake lock timer. 23 */ 24 public static final int WAKE_TYPE_PARTIAL = 0; 25 26 /** 27 * A constant indicating a full wake lock timer. 28 */ 29 public static final int WAKE_TYPE_FULL = 1; 30 31 /** 32 * A constant indicating a window wake lock timer. 33 */ 34 public static final int WAKE_TYPE_WINDOW = 2; 35 36 /** 37 * A constant indicating a sensor timer. 38 * 39 * {@hide} 40 */ 41 public static final int SENSOR = 3; 42 43 /** 44 * A constant indicating a full wifi lock timer 45 * 46 * {@hide} 47 */ 48 public static final int FULL_WIFI_LOCK = 4; 49 50 /** 51 * A constant indicating a scan wifi lock timer 52 * 53 * {@hide} 54 */ 55 public static final int SCAN_WIFI_LOCK = 5; 56 57 /** 58 * Include all of the data in the stats, including previously saved data. 59 */ 60 public static final int STATS_TOTAL = 0; 61 62 /** 63 * Include only the last run in the stats. 64 */ 65 public static final int STATS_LAST = 1; 66 67 /** 68 * Include only the current run in the stats. 69 */ 70 public static final int STATS_CURRENT = 2; 71 72 /** 73 * Include only the run since the last time the device was unplugged in the stats. 74 */ 75 public static final int STATS_UNPLUGGED = 3; 76 77 /** 78 * Bump the version on this if the checkin format changes. 79 */ 80 private static final int BATTERY_STATS_CHECKIN_VERSION = 2; 81 82 private static final long BYTES_PER_KB = 1024; 83 private static final long BYTES_PER_MB = 1048576; // 1024^2 84 private static final long BYTES_PER_GB = 1073741824; //1024^3 85 86 // TODO: Update this list if you add/change any stats above. 87 private static final String[] STAT_NAMES = { "total", "last", "current", "unplugged" }; 88 89 private static final String APK_DATA = "apk"; 90 private static final String PROCESS_DATA = "process"; 91 private static final String SENSOR_DATA = "sensor"; 92 private static final String WAKELOCK_DATA = "wakelock"; 93 private static final String NETWORK_DATA = "network"; 94 private static final String BATTERY_DATA = "battery"; 95 private static final String WIFI_LOCK_DATA = "wifilock"; 96 private static final String MISC_DATA = "misc"; 97 private static final String SIGNAL_STRENGTH_DATA = "signal"; 98 private static final String DATA_CONNECTION_DATA = "dataconn"; 99 100 private final StringBuilder mFormatBuilder = new StringBuilder(8); 101 private final Formatter mFormatter = new Formatter(mFormatBuilder); 102 103 /** 104 * State for keeping track of timing information. 105 */ 106 public static abstract class Timer { 107 108 /** 109 * Returns the count associated with this Timer for the 110 * selected type of statistics. 111 * 112 * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT 113 */ 114 public abstract int getCount(int which); 115 116 /** 117 * Returns the total time in microseconds associated with this Timer for the 118 * selected type of statistics. 119 * 120 * @param batteryRealtime system realtime on battery in microseconds 121 * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT 122 * @return a time in microseconds 123 */ 124 public abstract long getTotalTime(long batteryRealtime, int which); 125 126 /** 127 * Temporary for debugging. 128 */ 129 public abstract void logState(Printer pw, String prefix); 130 } 131 132 /** 133 * The statistics associated with a particular uid. 134 */ 135 public static abstract class Uid { 136 137 /** 138 * Returns a mapping containing wakelock statistics. 139 * 140 * @return a Map from Strings to Uid.Wakelock objects. 141 */ 142 public abstract Map<String, ? extends Wakelock> getWakelockStats(); 143 144 /** 145 * The statistics associated with a particular wake lock. 146 */ 147 public static abstract class Wakelock { 148 public abstract Timer getWakeTime(int type); 149 } 150 151 /** 152 * Returns a mapping containing sensor statistics. 153 * 154 * @return a Map from Integer sensor ids to Uid.Sensor objects. 155 */ 156 public abstract Map<Integer, ? extends Sensor> getSensorStats(); 157 158 /** 159 * Returns a mapping containing process statistics. 160 * 161 * @return a Map from Strings to Uid.Proc objects. 162 */ 163 public abstract Map<String, ? extends Proc> getProcessStats(); 164 165 /** 166 * Returns a mapping containing package statistics. 167 * 168 * @return a Map from Strings to Uid.Pkg objects. 169 */ 170 public abstract Map<String, ? extends Pkg> getPackageStats(); 171 172 /** 173 * {@hide} 174 */ 175 public abstract int getUid(); 176 177 /** 178 * {@hide} 179 */ 180 public abstract long getTcpBytesReceived(int which); 181 182 /** 183 * {@hide} 184 */ 185 public abstract long getTcpBytesSent(int which); 186 187 public abstract void noteFullWifiLockAcquiredLocked(); 188 public abstract void noteFullWifiLockReleasedLocked(); 189 public abstract void noteScanWifiLockAcquiredLocked(); 190 public abstract void noteScanWifiLockReleasedLocked(); 191 public abstract long getFullWifiLockTime(long batteryRealtime, int which); 192 public abstract long getScanWifiLockTime(long batteryRealtime, int which); 193 194 public static abstract class Sensor { 195 // Magic sensor number for the GPS. 196 public static final int GPS = -10000; 197 198 public abstract int getHandle(); 199 200 public abstract Timer getSensorTime(); 201 } 202 203 /** 204 * The statistics associated with a particular process. 205 */ 206 public static abstract class Proc { 207 208 /** 209 * Returns the total time (in 1/100 sec) spent executing in user code. 210 * 211 * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT. 212 */ 213 public abstract long getUserTime(int which); 214 215 /** 216 * Returns the total time (in 1/100 sec) spent executing in system code. 217 * 218 * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT. 219 */ 220 public abstract long getSystemTime(int which); 221 222 /** 223 * Returns the number of times the process has been started. 224 * 225 * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT. 226 */ 227 public abstract int getStarts(int which); 228 } 229 230 /** 231 * The statistics associated with a particular package. 232 */ 233 public static abstract class Pkg { 234 235 /** 236 * Returns the number of times this package has done something that could wake up the 237 * device from sleep. 238 * 239 * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT. 240 */ 241 public abstract int getWakeups(int which); 242 243 /** 244 * Returns a mapping containing service statistics. 245 */ 246 public abstract Map<String, ? extends Serv> getServiceStats(); 247 248 /** 249 * The statistics associated with a particular service. 250 */ 251 public abstract class Serv { 252 253 /** 254 * Returns the amount of time spent started. 255 * 256 * @param batteryUptime elapsed uptime on battery in microseconds. 257 * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT. 258 * @return 259 */ 260 public abstract long getStartTime(long batteryUptime, int which); 261 262 /** 263 * Returns the total number of times startService() has been called. 264 * 265 * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT. 266 */ 267 public abstract int getStarts(int which); 268 269 /** 270 * Returns the total number times the service has been launched. 271 * 272 * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT. 273 */ 274 public abstract int getLaunches(int which); 275 } 276 } 277 } 278 279 /** 280 * Returns the number of times the device has been started. 281 */ 282 public abstract int getStartCount(); 283 284 /** 285 * Returns the time in milliseconds that the screen has been on while the device was 286 * running on battery. 287 * 288 * {@hide} 289 */ 290 public abstract long getScreenOnTime(long batteryRealtime, int which); 291 292 /** 293 * Returns the time in milliseconds that the phone has been on while the device was 294 * running on battery. 295 * 296 * {@hide} 297 */ 298 public abstract long getPhoneOnTime(long batteryRealtime, int which); 299 300 public static final int SIGNAL_STRENGTH_NONE_OR_UNKNOWN = 0; 301 public static final int SIGNAL_STRENGTH_POOR = 1; 302 public static final int SIGNAL_STRENGTH_MODERATE = 2; 303 public static final int SIGNAL_STRENGTH_GOOD = 3; 304 public static final int SIGNAL_STRENGTH_GREAT = 4; 305 306 static final String[] SIGNAL_STRENGTH_NAMES = { 307 "none", "poor", "moderate", "good", "great" 308 }; 309 310 public static final int NUM_SIGNAL_STRENGTH_BINS = 5; 311 312 /** 313 * Returns the time in milliseconds that the phone has been running with 314 * the given signal strength. 315 * 316 * {@hide} 317 */ 318 public abstract long getPhoneSignalStrengthTime(int strengthBin, 319 long batteryRealtime, int which); 320 321 public static final int DATA_CONNECTION_NONE = 0; 322 public static final int DATA_CONNECTION_GPRS = 1; 323 public static final int DATA_CONNECTION_EDGE = 2; 324 public static final int DATA_CONNECTION_UMTS = 3; 325 public static final int DATA_CONNECTION_OTHER = 4; 326 327 static final String[] DATA_CONNECTION_NAMES = { 328 "none", "gprs", "edge", "umts", "other" 329 }; 330 331 public static final int NUM_DATA_CONNECTION_TYPES = 5; 332 333 /** 334 * Returns the time in milliseconds that the phone has been running with 335 * the given data connection. 336 * 337 * {@hide} 338 */ 339 public abstract long getPhoneDataConnectionTime(int dataType, 340 long batteryRealtime, int which); 341 342 /** 343 * Returns the time in milliseconds that wifi has been on while the device was 344 * running on battery. 345 * 346 * {@hide} 347 */ 348 public abstract long getWifiOnTime(long batteryRealtime, int which); 349 350 /** 351 * Returns the time in milliseconds that wifi has been on and the driver has 352 * been in the running state while the device was running on battery. 353 * 354 * {@hide} 355 */ 356 public abstract long getWifiRunningTime(long batteryRealtime, int which); 357 358 /** 359 * Returns the time in milliseconds that bluetooth has been on while the device was 360 * running on battery. 361 * 362 * {@hide} 363 */ 364 public abstract long getBluetoothOnTime(long batteryRealtime, int which); 365 366 /** 367 * Return whether we are currently running on battery. 368 */ 369 public abstract boolean getIsOnBattery(); 370 371 /** 372 * Returns a SparseArray containing the statistics for each uid. 373 */ 374 public abstract SparseArray<? extends Uid> getUidStats(); 375 376 /** 377 * Returns the current battery uptime in microseconds. 378 * 379 * @param curTime the amount of elapsed realtime in microseconds. 380 */ 381 public abstract long getBatteryUptime(long curTime); 382 383 /** 384 * Returns the current battery realtime in microseconds. 385 * 386 * @param curTime the amount of elapsed realtime in microseconds. 387 */ 388 public abstract long getBatteryRealtime(long curTime); 389 390 /** 391 * Returns the battery percentage level at the last time the device was unplugged from power, 392 * or the last time it was booted while unplugged. 393 */ 394 public abstract int getUnpluggedStartLevel(); 395 396 /** 397 * Returns the battery percentage level at the last time the device was plugged into power. 398 */ 399 public abstract int getPluggedStartLevel(); 400 401 /** 402 * Returns the total, last, or current battery uptime in microseconds. 403 * 404 * @param curTime the elapsed realtime in microseconds. 405 * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT. 406 */ 407 public abstract long computeBatteryUptime(long curTime, int which); 408 409 /** 410 * Returns the total, last, or current battery realtime in microseconds. 411 * 412 * @param curTime the current elapsed realtime in microseconds. 413 * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT. 414 */ 415 public abstract long computeBatteryRealtime(long curTime, int which); 416 417 /** 418 * Returns the total, last, or current uptime in microseconds. 419 * 420 * @param curTime the current elapsed realtime in microseconds. 421 * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT. 422 */ 423 public abstract long computeUptime(long curTime, int which); 424 425 /** 426 * Returns the total, last, or current realtime in microseconds. 427 * * 428 * @param curTime the current elapsed realtime in microseconds. 429 * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT. 430 */ 431 public abstract long computeRealtime(long curTime, int which); 432 433 private final static void formatTime(StringBuilder out, long seconds) { 434 long days = seconds / (60 * 60 * 24); 435 if (days != 0) { 436 out.append(days); 437 out.append("d "); 438 } 439 long used = days * 60 * 60 * 24; 440 441 long hours = (seconds - used) / (60 * 60); 442 if (hours != 0 || used != 0) { 443 out.append(hours); 444 out.append("h "); 445 } 446 used += hours * 60 * 60; 447 448 long mins = (seconds-used) / 60; 449 if (mins != 0 || used != 0) { 450 out.append(mins); 451 out.append("m "); 452 } 453 used += mins * 60; 454 455 if (seconds != 0 || used != 0) { 456 out.append(seconds-used); 457 out.append("s "); 458 } 459 } 460 461 private final static String formatTime(long time) { 462 long sec = time / 100; 463 StringBuilder sb = new StringBuilder(); 464 formatTime(sb, sec); 465 sb.append((time - (sec * 100)) * 10); 466 sb.append("ms "); 467 return sb.toString(); 468 } 469 470 private final static String formatTimeMs(long time) { 471 long sec = time / 1000; 472 StringBuilder sb = new StringBuilder(); 473 formatTime(sb, sec); 474 sb.append(time - (sec * 1000)); 475 sb.append("ms "); 476 return sb.toString(); 477 } 478 479 private final String formatRatioLocked(long num, long den) { 480 if (den == 0L) { 481 return "---%"; 482 } 483 float perc = ((float)num) / ((float)den) * 100; 484 mFormatBuilder.setLength(0); 485 mFormatter.format("%.1f%%", perc); 486 return mFormatBuilder.toString(); 487 } 488 489 private final String formatBytesLocked(long bytes) { 490 mFormatBuilder.setLength(0); 491 492 if (bytes < BYTES_PER_KB) { 493 return bytes + "B"; 494 } else if (bytes < BYTES_PER_MB) { 495 mFormatter.format("%.2fKB", bytes / (double) BYTES_PER_KB); 496 return mFormatBuilder.toString(); 497 } else if (bytes < BYTES_PER_GB){ 498 mFormatter.format("%.2fMB", bytes / (double) BYTES_PER_MB); 499 return mFormatBuilder.toString(); 500 } else { 501 mFormatter.format("%.2fGB", bytes / (double) BYTES_PER_GB); 502 return mFormatBuilder.toString(); 503 } 504 } 505 506 /** 507 * 508 * @param sb a StringBuilder object. 509 * @param timer a Timer object contining the wakelock times. 510 * @param batteryRealtime the current on-battery time in microseconds. 511 * @param name the name of the wakelock. 512 * @param which which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT. 513 * @param linePrefix a String to be prepended to each line of output. 514 * @return the line prefix 515 */ 516 private static final String printWakeLock(StringBuilder sb, Timer timer, 517 long batteryRealtime, String name, int which, String linePrefix) { 518 519 if (timer != null) { 520 // Convert from microseconds to milliseconds with rounding 521 long totalTimeMicros = timer.getTotalTime(batteryRealtime, which); 522 long totalTimeMillis = (totalTimeMicros + 500) / 1000; 523 524 int count = timer.getCount(which); 525 if (totalTimeMillis != 0) { 526 sb.append(linePrefix); 527 sb.append(formatTimeMs(totalTimeMillis)); 528 sb.append(name); 529 sb.append(' '); 530 sb.append('('); 531 sb.append(count); 532 sb.append(" times)"); 533 return ", "; 534 } 535 } 536 return linePrefix; 537 } 538 539 /** 540 * Checkin version of wakelock printer. Prints simple comma-separated list. 541 * 542 * @param sb a StringBuilder object. 543 * @param timer a Timer object contining the wakelock times. 544 * @param now the current time in microseconds. 545 * @param name the name of the wakelock. 546 * @param which which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT. 547 * @param linePrefix a String to be prepended to each line of output. 548 * @return the line prefix 549 */ 550 private static final String printWakeLockCheckin(StringBuilder sb, Timer timer, long now, 551 String name, int which, String linePrefix) { 552 long totalTimeMicros = 0; 553 int count = 0; 554 if (timer != null) { 555 totalTimeMicros = timer.getTotalTime(now, which); 556 count = timer.getCount(which); 557 } 558 sb.append(linePrefix); 559 sb.append((totalTimeMicros + 500) / 1000); // microseconds to milliseconds with rounding 560 sb.append(','); 561 sb.append(name); 562 sb.append(','); 563 sb.append(count); 564 return ","; 565 } 566 567 /** 568 * Dump a comma-separated line of values for terse checkin mode. 569 * 570 * @param pw the PageWriter to dump log to 571 * @param category category of data (e.g. "total", "last", "unplugged", "current" ) 572 * @param type type of data (e.g. "wakelock", "sensor", "process", "apk" , "process", "network") 573 * @param args type-dependent data arguments 574 */ 575 private static final void dumpLine(PrintWriter pw, int uid, String category, String type, 576 Object... args ) { 577 pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(','); 578 pw.print(uid); pw.print(','); 579 pw.print(category); pw.print(','); 580 pw.print(type); 581 582 for (Object arg : args) { 583 pw.print(','); 584 pw.print(arg); 585 } 586 pw.print('\n'); 587 } 588 589 /** 590 * Checkin server version of dump to produce more compact, computer-readable log. 591 * 592 * NOTE: all times are expressed in 'ms'. 593 * @param fd 594 * @param pw 595 * @param which 596 */ 597 private final void dumpCheckinLocked(PrintWriter pw, int which) { 598 final long rawUptime = SystemClock.uptimeMillis() * 1000; 599 final long rawRealtime = SystemClock.elapsedRealtime() * 1000; 600 final long batteryUptime = getBatteryUptime(rawUptime); 601 final long batteryRealtime = getBatteryRealtime(rawRealtime); 602 final long whichBatteryUptime = computeBatteryUptime(rawUptime, which); 603 final long whichBatteryRealtime = computeBatteryRealtime(rawRealtime, which); 604 final long totalRealtime = computeRealtime(rawRealtime, which); 605 final long totalUptime = computeUptime(rawUptime, which); 606 final long screenOnTime = getScreenOnTime(batteryRealtime, which); 607 final long phoneOnTime = getPhoneOnTime(batteryRealtime, which); 608 final long wifiOnTime = getWifiOnTime(batteryRealtime, which); 609 final long wifiRunningTime = getWifiRunningTime(batteryRealtime, which); 610 final long bluetoothOnTime = getBluetoothOnTime(batteryRealtime, which); 611 612 StringBuilder sb = new StringBuilder(128); 613 614 SparseArray<? extends Uid> uidStats = getUidStats(); 615 final int NU = uidStats.size(); 616 617 String category = STAT_NAMES[which]; 618 619 // Dump "battery" stat 620 dumpLine(pw, 0 /* uid */, category, BATTERY_DATA, 621 which == STATS_TOTAL ? getStartCount() : "N/A", 622 whichBatteryUptime / 1000, whichBatteryRealtime / 1000, 623 totalUptime / 1000, totalRealtime / 1000); 624 625 // Calculate total network and wakelock times across all uids. 626 long rxTotal = 0; 627 long txTotal = 0; 628 long fullWakeLockTimeTotal = 0; 629 long partialWakeLockTimeTotal = 0; 630 631 for (int iu = 0; iu < NU; iu++) { 632 Uid u = uidStats.valueAt(iu); 633 rxTotal += u.getTcpBytesReceived(which); 634 txTotal += u.getTcpBytesSent(which); 635 636 Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats(); 637 if (wakelocks.size() > 0) { 638 for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent 639 : wakelocks.entrySet()) { 640 Uid.Wakelock wl = ent.getValue(); 641 642 Timer fullWakeTimer = wl.getWakeTime(WAKE_TYPE_FULL); 643 if (fullWakeTimer != null) { 644 fullWakeLockTimeTotal += fullWakeTimer.getTotalTime(batteryRealtime, which); 645 } 646 647 Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL); 648 if (partialWakeTimer != null) { 649 partialWakeLockTimeTotal += partialWakeTimer.getTotalTime( 650 batteryRealtime, which); 651 } 652 } 653 } 654 } 655 656 // Dump misc stats 657 dumpLine(pw, 0 /* uid */, category, MISC_DATA, 658 screenOnTime / 1000, phoneOnTime / 1000, wifiOnTime / 1000, 659 wifiRunningTime / 1000, bluetoothOnTime / 1000, rxTotal, txTotal, 660 fullWakeLockTimeTotal, partialWakeLockTimeTotal); 661 662 // Dump signal strength stats 663 Object[] args = new Object[NUM_SIGNAL_STRENGTH_BINS]; 664 for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) { 665 args[i] = getPhoneSignalStrengthTime(i, batteryRealtime, which) / 1000; 666 } 667 dumpLine(pw, 0 /* uid */, category, SIGNAL_STRENGTH_DATA, args); 668 669 // Dump network type stats 670 args = new Object[NUM_DATA_CONNECTION_TYPES]; 671 for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { 672 args[i] = getPhoneDataConnectionTime(i, batteryRealtime, which) / 1000; 673 } 674 dumpLine(pw, 0 /* uid */, category, DATA_CONNECTION_DATA, args); 675 676 if (which == STATS_UNPLUGGED) { 677 dumpLine(pw, 0 /* uid */, category, BATTERY_DATA, getUnpluggedStartLevel(), 678 getPluggedStartLevel()); 679 } 680 681 for (int iu = 0; iu < NU; iu++) { 682 final int uid = uidStats.keyAt(iu); 683 Uid u = uidStats.valueAt(iu); 684 // Dump Network stats per uid, if any 685 long rx = u.getTcpBytesReceived(which); 686 long tx = u.getTcpBytesSent(which); 687 long fullWifiLockOnTime = u.getFullWifiLockTime(batteryRealtime, which); 688 long scanWifiLockOnTime = u.getScanWifiLockTime(batteryRealtime, which); 689 690 if (rx > 0 || tx > 0) dumpLine(pw, uid, category, NETWORK_DATA, rx, tx); 691 692 if (fullWifiLockOnTime != 0 || scanWifiLockOnTime != 0) { 693 dumpLine(pw, uid, category, WIFI_LOCK_DATA, 694 fullWifiLockOnTime, scanWifiLockOnTime); 695 } 696 697 Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats(); 698 if (wakelocks.size() > 0) { 699 for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent 700 : wakelocks.entrySet()) { 701 Uid.Wakelock wl = ent.getValue(); 702 String linePrefix = ""; 703 sb.setLength(0); 704 linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_FULL), batteryRealtime, 705 "full", which, linePrefix); 706 linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL), batteryRealtime, 707 "partial", which, linePrefix); 708 linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), batteryRealtime, 709 "window", which, linePrefix); 710 711 // Only log if we had at lease one wakelock... 712 if (sb.length() > 0) { 713 dumpLine(pw, uid, category, WAKELOCK_DATA, ent.getKey(), sb.toString()); 714 } 715 } 716 } 717 718 Map<Integer, ? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats(); 719 if (sensors.size() > 0) { 720 for (Map.Entry<Integer, ? extends BatteryStats.Uid.Sensor> ent 721 : sensors.entrySet()) { 722 Uid.Sensor se = ent.getValue(); 723 int sensorNumber = ent.getKey(); 724 Timer timer = se.getSensorTime(); 725 if (timer != null) { 726 // Convert from microseconds to milliseconds with rounding 727 long totalTime = (timer.getTotalTime(batteryRealtime, which) + 500) / 1000; 728 int count = timer.getCount(which); 729 if (totalTime != 0) { 730 dumpLine(pw, uid, category, SENSOR_DATA, sensorNumber, totalTime, count); 731 } 732 } 733 } 734 } 735 736 Map<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats(); 737 if (processStats.size() > 0) { 738 for (Map.Entry<String, ? extends BatteryStats.Uid.Proc> ent 739 : processStats.entrySet()) { 740 Uid.Proc ps = ent.getValue(); 741 742 long userTime = ps.getUserTime(which); 743 long systemTime = ps.getSystemTime(which); 744 int starts = ps.getStarts(which); 745 746 if (userTime != 0 || systemTime != 0 || starts != 0) { 747 dumpLine(pw, uid, category, PROCESS_DATA, 748 ent.getKey(), // proc 749 userTime * 10, // cpu time in ms 750 systemTime * 10, // user time in ms 751 starts); // process starts 752 } 753 } 754 } 755 756 Map<String, ? extends BatteryStats.Uid.Pkg> packageStats = u.getPackageStats(); 757 if (packageStats.size() > 0) { 758 for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg> ent 759 : packageStats.entrySet()) { 760 761 Uid.Pkg ps = ent.getValue(); 762 int wakeups = ps.getWakeups(which); 763 Map<String, ? extends Uid.Pkg.Serv> serviceStats = ps.getServiceStats(); 764 for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg.Serv> sent 765 : serviceStats.entrySet()) { 766 BatteryStats.Uid.Pkg.Serv ss = sent.getValue(); 767 long startTime = ss.getStartTime(batteryUptime, which); 768 int starts = ss.getStarts(which); 769 int launches = ss.getLaunches(which); 770 if (startTime != 0 || starts != 0 || launches != 0) { 771 dumpLine(pw, uid, category, APK_DATA, 772 wakeups, // wakeup alarms 773 ent.getKey(), // Apk 774 sent.getKey(), // service 775 startTime / 1000, // time spent started, in ms 776 starts, 777 launches); 778 } 779 } 780 } 781 } 782 } 783 } 784 785 @SuppressWarnings("unused") 786 private final void dumpLocked(Printer pw, String prefix, int which) { 787 final long rawUptime = SystemClock.uptimeMillis() * 1000; 788 final long rawRealtime = SystemClock.elapsedRealtime() * 1000; 789 final long batteryUptime = getBatteryUptime(rawUptime); 790 final long batteryRealtime = getBatteryRealtime(rawRealtime); 791 792 final long whichBatteryUptime = computeBatteryUptime(rawUptime, which); 793 final long whichBatteryRealtime = computeBatteryRealtime(rawRealtime, which); 794 final long totalRealtime = computeRealtime(rawRealtime, which); 795 final long totalUptime = computeUptime(rawUptime, which); 796 797 StringBuilder sb = new StringBuilder(128); 798 799 SparseArray<? extends Uid> uidStats = getUidStats(); 800 final int NU = uidStats.size(); 801 802 pw.println(prefix 803 + " Time on battery: " + formatTimeMs(whichBatteryUptime / 1000) 804 + "(" + formatRatioLocked(whichBatteryUptime, totalRealtime) 805 + ") uptime, " 806 + formatTimeMs(whichBatteryRealtime / 1000) + "(" 807 + formatRatioLocked(whichBatteryRealtime, totalRealtime) 808 + ") realtime"); 809 pw.println(prefix 810 + " Total: " 811 + formatTimeMs(totalUptime / 1000) 812 + "uptime, " 813 + formatTimeMs(totalRealtime / 1000) 814 + "realtime"); 815 816 final long screenOnTime = getScreenOnTime(batteryRealtime, which); 817 final long phoneOnTime = getPhoneOnTime(batteryRealtime, which); 818 final long wifiRunningTime = getWifiRunningTime(batteryRealtime, which); 819 final long wifiOnTime = getWifiOnTime(batteryRealtime, which); 820 final long bluetoothOnTime = getBluetoothOnTime(batteryRealtime, which); 821 pw.println(prefix 822 + " Screen on: " + formatTimeMs(screenOnTime / 1000) 823 + "(" + formatRatioLocked(screenOnTime, whichBatteryRealtime) 824 + "), Phone on: " + formatTimeMs(phoneOnTime / 1000) 825 + "(" + formatRatioLocked(phoneOnTime, whichBatteryRealtime)); 826 pw.println(prefix 827 + " Wifi on: " + formatTimeMs(wifiOnTime / 1000) 828 + "(" + formatRatioLocked(wifiOnTime, whichBatteryRealtime) 829 + "), Wifi running: " + formatTimeMs(wifiRunningTime / 1000) 830 + "(" + formatRatioLocked(wifiRunningTime, whichBatteryRealtime) 831 + "), Bluetooth on: " + formatTimeMs(bluetoothOnTime / 1000) 832 + "(" + formatRatioLocked(bluetoothOnTime, whichBatteryRealtime)+ ")"); 833 834 // Calculate total network and wakelock times across all uids. 835 long rxTotal = 0; 836 long txTotal = 0; 837 long fullWakeLockTimeTotalMicros = 0; 838 long partialWakeLockTimeTotalMicros = 0; 839 840 for (int iu = 0; iu < NU; iu++) { 841 Uid u = uidStats.valueAt(iu); 842 rxTotal += u.getTcpBytesReceived(which); 843 txTotal += u.getTcpBytesSent(which); 844 845 Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats(); 846 if (wakelocks.size() > 0) { 847 for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent 848 : wakelocks.entrySet()) { 849 Uid.Wakelock wl = ent.getValue(); 850 851 Timer fullWakeTimer = wl.getWakeTime(WAKE_TYPE_FULL); 852 if (fullWakeTimer != null) { 853 fullWakeLockTimeTotalMicros += fullWakeTimer.getTotalTime( 854 batteryRealtime, which); 855 } 856 857 Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL); 858 if (partialWakeTimer != null) { 859 partialWakeLockTimeTotalMicros += partialWakeTimer.getTotalTime( 860 batteryRealtime, which); 861 } 862 } 863 } 864 } 865 866 pw.println(prefix 867 + " Total received: " + formatBytesLocked(rxTotal) 868 + ", Total sent: " + formatBytesLocked(txTotal)); 869 pw.println(prefix 870 + " Total full wakelock time: " + formatTimeMs( 871 (fullWakeLockTimeTotalMicros + 500) / 1000) 872 + ", Total partial waklock time: " + formatTimeMs( 873 (partialWakeLockTimeTotalMicros + 500) / 1000)); 874 875 sb.setLength(0); 876 sb.append(" Signal strengths: "); 877 boolean didOne = false; 878 for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) { 879 final long time = getPhoneSignalStrengthTime(i, batteryRealtime, which); 880 if (time == 0) { 881 continue; 882 } 883 if (didOne) sb.append(", "); 884 didOne = true; 885 sb.append(SIGNAL_STRENGTH_NAMES[i]); 886 sb.append(" "); 887 sb.append(formatTimeMs(time/1000)); 888 sb.append("("); 889 sb.append(formatRatioLocked(time, whichBatteryRealtime)); 890 sb.append(")"); 891 } 892 if (!didOne) sb.append("No activity"); 893 pw.println(sb.toString()); 894 895 sb.setLength(0); 896 sb.append(" Data types: "); 897 didOne = false; 898 for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { 899 final long time = getPhoneDataConnectionTime(i, batteryRealtime, which); 900 if (time == 0) { 901 continue; 902 } 903 if (didOne) sb.append(", "); 904 didOne = true; 905 sb.append(DATA_CONNECTION_NAMES[i]); 906 sb.append(" "); 907 sb.append(formatTimeMs(time/1000)); 908 sb.append("("); 909 sb.append(formatRatioLocked(time, whichBatteryRealtime)); 910 sb.append(")"); 911 } 912 if (!didOne) sb.append("No activity"); 913 pw.println(sb.toString()); 914 915 pw.println(" "); 916 917 if (which == STATS_UNPLUGGED) { 918 if (getIsOnBattery()) { 919 pw.println(prefix + " Device is currently unplugged"); 920 pw.println(prefix + " Discharge cycle start level: " + 921 getUnpluggedStartLevel()); 922 } else { 923 pw.println(prefix + " Device is currently plugged into power"); 924 pw.println(prefix + " Last discharge cycle start level: " + 925 getUnpluggedStartLevel()); 926 pw.println(prefix + " Last discharge cycle end level: " + 927 getPluggedStartLevel()); 928 } 929 } 930 931 pw.println(" "); 932 933 934 for (int iu=0; iu<NU; iu++) { 935 final int uid = uidStats.keyAt(iu); 936 Uid u = uidStats.valueAt(iu); 937 pw.println(prefix + " #" + uid + ":"); 938 boolean uidActivity = false; 939 940 long tcpReceived = u.getTcpBytesReceived(which); 941 long tcpSent = u.getTcpBytesSent(which); 942 long fullWifiLockOnTime = u.getFullWifiLockTime(batteryRealtime, which); 943 long scanWifiLockOnTime = u.getScanWifiLockTime(batteryRealtime, which); 944 945 if (tcpReceived != 0 || tcpSent != 0) { 946 pw.println(prefix + " Network: " + formatBytesLocked(tcpReceived) + " received, " 947 + formatBytesLocked(tcpSent) + " sent"); 948 } 949 if (fullWifiLockOnTime != 0 || scanWifiLockOnTime != 0) { 950 pw.println(prefix + " Full Wifi Lock Time: " 951 + formatTimeMs(fullWifiLockOnTime / 1000) 952 + "(" + formatRatioLocked(fullWifiLockOnTime, 953 whichBatteryRealtime)+ ")"); 954 pw.println(prefix + " Scan Wifi Lock Time: " 955 + formatTimeMs(scanWifiLockOnTime / 1000) 956 + "(" + formatRatioLocked(scanWifiLockOnTime, 957 whichBatteryRealtime)+ ")"); 958 } 959 960 Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats(); 961 if (wakelocks.size() > 0) { 962 for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent 963 : wakelocks.entrySet()) { 964 Uid.Wakelock wl = ent.getValue(); 965 String linePrefix = ": "; 966 sb.setLength(0); 967 sb.append(prefix); 968 sb.append(" Wake lock "); 969 sb.append(ent.getKey()); 970 linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_FULL), batteryRealtime, 971 "full", which, linePrefix); 972 linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL), batteryRealtime, 973 "partial", which, linePrefix); 974 linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), batteryRealtime, 975 "window", which, linePrefix); 976 if (!linePrefix.equals(": ")) { 977 sb.append(" realtime"); 978 } else { 979 sb.append(": (nothing executed)"); 980 } 981 pw.println(sb.toString()); 982 uidActivity = true; 983 } 984 } 985 986 Map<Integer, ? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats(); 987 if (sensors.size() > 0) { 988 for (Map.Entry<Integer, ? extends BatteryStats.Uid.Sensor> ent 989 : sensors.entrySet()) { 990 Uid.Sensor se = ent.getValue(); 991 int sensorNumber = ent.getKey(); 992 sb.setLength(0); 993 sb.append(prefix); 994 sb.append(" Sensor "); 995 int handle = se.getHandle(); 996 if (handle == Uid.Sensor.GPS) { 997 sb.append("GPS"); 998 } else { 999 sb.append(handle); 1000 } 1001 sb.append(": "); 1002 1003 Timer timer = se.getSensorTime(); 1004 if (timer != null) { 1005 // Convert from microseconds to milliseconds with rounding 1006 long totalTime = (timer.getTotalTime(batteryRealtime, which) + 500) / 1000; 1007 int count = timer.getCount(which); 1008 //timer.logState(); 1009 if (totalTime != 0) { 1010 sb.append(formatTimeMs(totalTime)); 1011 sb.append("realtime ("); 1012 sb.append(count); 1013 sb.append(" times)"); 1014 } else { 1015 sb.append("(not used)"); 1016 } 1017 } else { 1018 sb.append("(not used)"); 1019 } 1020 1021 pw.println(sb.toString()); 1022 uidActivity = true; 1023 } 1024 } 1025 1026 Map<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats(); 1027 if (processStats.size() > 0) { 1028 for (Map.Entry<String, ? extends BatteryStats.Uid.Proc> ent 1029 : processStats.entrySet()) { 1030 Uid.Proc ps = ent.getValue(); 1031 long userTime; 1032 long systemTime; 1033 int starts; 1034 1035 userTime = ps.getUserTime(which); 1036 systemTime = ps.getSystemTime(which); 1037 starts = ps.getStarts(which); 1038 1039 if (userTime != 0 || systemTime != 0 || starts != 0) { 1040 pw.println(prefix + " Proc " + ent.getKey() + ":"); 1041 pw.println(prefix + " CPU: " + formatTime(userTime) + "user + " 1042 + formatTime(systemTime) + "kernel"); 1043 pw.println(prefix + " " + starts + " process starts"); 1044 uidActivity = true; 1045 } 1046 } 1047 } 1048 1049 Map<String, ? extends BatteryStats.Uid.Pkg> packageStats = u.getPackageStats(); 1050 if (packageStats.size() > 0) { 1051 for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg> ent 1052 : packageStats.entrySet()) { 1053 pw.println(prefix + " Apk " + ent.getKey() + ":"); 1054 boolean apkActivity = false; 1055 Uid.Pkg ps = ent.getValue(); 1056 int wakeups = ps.getWakeups(which); 1057 if (wakeups != 0) { 1058 pw.println(prefix + " " + wakeups + " wakeup alarms"); 1059 apkActivity = true; 1060 } 1061 Map<String, ? extends Uid.Pkg.Serv> serviceStats = ps.getServiceStats(); 1062 if (serviceStats.size() > 0) { 1063 for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg.Serv> sent 1064 : serviceStats.entrySet()) { 1065 BatteryStats.Uid.Pkg.Serv ss = sent.getValue(); 1066 long startTime = ss.getStartTime(batteryUptime, which); 1067 int starts = ss.getStarts(which); 1068 int launches = ss.getLaunches(which); 1069 if (startTime != 0 || starts != 0 || launches != 0) { 1070 pw.println(prefix + " Service " + sent.getKey() + ":"); 1071 pw.println(prefix + " Created for: " 1072 + formatTimeMs(startTime / 1000) 1073 + " uptime"); 1074 pw.println(prefix + " Starts: " + starts 1075 + ", launches: " + launches); 1076 apkActivity = true; 1077 } 1078 } 1079 } 1080 if (!apkActivity) { 1081 pw.println(prefix + " (nothing executed)"); 1082 } 1083 uidActivity = true; 1084 } 1085 } 1086 if (!uidActivity) { 1087 pw.println(prefix + " (nothing executed)"); 1088 } 1089 } 1090 } 1091 1092 /** 1093 * Dumps a human-readable summary of the battery statistics to the given PrintWriter. 1094 * 1095 * @param pw a Printer to receive the dump output. 1096 */ 1097 @SuppressWarnings("unused") 1098 public void dumpLocked(Printer pw) { 1099 pw.println("Total Statistics (Current and Historic):"); 1100 pw.println(" System starts: " + getStartCount() 1101 + ", currently on battery: " + getIsOnBattery()); 1102 dumpLocked(pw, "", STATS_TOTAL); 1103 pw.println(""); 1104 pw.println("Last Run Statistics (Previous run of system):"); 1105 dumpLocked(pw, "", STATS_LAST); 1106 pw.println(""); 1107 pw.println("Current Battery Statistics (Currently running system):"); 1108 dumpLocked(pw, "", STATS_CURRENT); 1109 pw.println(""); 1110 pw.println("Unplugged Statistics (Since last unplugged from power):"); 1111 dumpLocked(pw, "", STATS_UNPLUGGED); 1112 } 1113 1114 @SuppressWarnings("unused") 1115 public void dumpCheckinLocked(PrintWriter pw, String[] args) { 1116 boolean isUnpluggedOnly = false; 1117 1118 for (String arg : args) { 1119 if ("-u".equals(arg)) { 1120 if (LOCAL_LOGV) Log.v("BatteryStats", "Dumping unplugged data"); 1121 isUnpluggedOnly = true; 1122 } 1123 } 1124 1125 if (isUnpluggedOnly) { 1126 dumpCheckinLocked(pw, STATS_UNPLUGGED); 1127 } 1128 else { 1129 dumpCheckinLocked(pw, STATS_TOTAL); 1130 dumpCheckinLocked(pw, STATS_LAST); 1131 dumpCheckinLocked(pw, STATS_UNPLUGGED); 1132 dumpCheckinLocked(pw, STATS_CURRENT); 1133 } 1134 } 1135 1136} 1137