diff options
author | Jean-Baptiste Queru <jbq@google.com> | 2009-05-20 11:28:04 -0700 |
---|---|---|
committer | Jean-Baptiste Queru <jbq@google.com> | 2009-05-20 11:28:04 -0700 |
commit | 843ef36f7b96cc19ea7d2996b7c8661b41ec3452 (patch) | |
tree | 560e1648c99a93986f8b7deef851ef8bb8029db7 /core/java/android/os | |
parent | 358d23017d0d6c4636eb7599ae7a9b48108899a3 (diff) | |
download | frameworks_base-843ef36f7b96cc19ea7d2996b7c8661b41ec3452.zip frameworks_base-843ef36f7b96cc19ea7d2996b7c8661b41ec3452.tar.gz frameworks_base-843ef36f7b96cc19ea7d2996b7c8661b41ec3452.tar.bz2 |
donut snapshot
Diffstat (limited to 'core/java/android/os')
-rw-r--r-- | core/java/android/os/AsyncTask.java | 4 | ||||
-rw-r--r-- | core/java/android/os/BatteryStats.java | 350 | ||||
-rw-r--r-- | core/java/android/os/Build.java | 38 | ||||
-rw-r--r-- | core/java/android/os/Debug.java | 251 | ||||
-rw-r--r-- | core/java/android/os/Power.java | 7 | ||||
-rw-r--r-- | core/java/android/os/Process.java | 41 | ||||
-rw-r--r-- | core/java/android/os/RemoteCallbackList.java | 57 |
7 files changed, 591 insertions, 157 deletions
diff --git a/core/java/android/os/AsyncTask.java b/core/java/android/os/AsyncTask.java index ee4e897..6c13582 100644 --- a/core/java/android/os/AsyncTask.java +++ b/core/java/android/os/AsyncTask.java @@ -37,7 +37,7 @@ import java.util.concurrent.atomic.AtomicInteger; * whose result is published on the UI thread. An asynchronous task is defined by 3 generic * types, called <code>Params</code>, <code>Progress</code> and <code>Result</code>, * and 4 steps, called <code>begin</code>, <code>doInBackground</code>, - * <code>processProgress<code> and <code>end</code>.</p> + * <code>processProgress</code> and <code>end</code>.</p> * * <h2>Usage</h2> * <p>AsyncTask must be subclassed to be used. The subclass will override at least @@ -85,7 +85,7 @@ import java.util.concurrent.atomic.AtomicInteger; * <p>Not all types are always used by am asynchronous task. To mark a type as unused, * simply use the type {@link Void}:</p> * <pre> - * private class MyTask extends AsyncTask<Void, Void, Void) { ... } + * private class MyTask extends AsyncTask<Void, Void, Void> { ... } * </pre> * * <h2>The 4 steps</h2> diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index 17594d4..8a0fd58 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -61,6 +61,13 @@ public abstract class BatteryStats implements Parcelable { */ public static final int SCAN_WIFI_LOCK = 6; + /** + * A constant indicating a wifi multicast timer + * + * {@hide} + */ + public static final int WIFI_MULTICAST_ENABLED = 7; + /** * Include all of the data in the stats, including previously saved data. */ @@ -80,35 +87,40 @@ public abstract class BatteryStats implements Parcelable { * Include only the run since the last time the device was unplugged in the stats. */ public static final int STATS_UNPLUGGED = 3; + + // NOTE: Update this list if you add/change any stats above. + // These characters are supposed to represent "total", "last", "current", + // and "unplugged". They were shortened for effeciency sake. + private static final String[] STAT_NAMES = { "t", "l", "c", "u" }; /** * Bump the version on this if the checkin format changes. */ - private static final int BATTERY_STATS_CHECKIN_VERSION = 3; + private static final int BATTERY_STATS_CHECKIN_VERSION = 5; 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 static final String PROCESS_DATA = "pr"; + private static final String SENSOR_DATA = "sr"; + private static final String WAKELOCK_DATA = "wl"; + private static final String KERNEL_WAKELOCK_DATA = "kwl"; + private static final String NETWORK_DATA = "nt"; + private static final String USER_ACTIVITY_DATA = "ua"; + private static final String BATTERY_DATA = "bt"; + private static final String BATTERY_LEVEL_DATA = "lv"; + private static final String WIFI_LOCK_DATA = "wfl"; + private static final String MISC_DATA = "m"; + private static final String SCREEN_BRIGHTNESS_DATA = "br"; + private static final String SIGNAL_STRENGTH_TIME_DATA = "sgt"; + private static final String SIGNAL_STRENGTH_COUNT_DATA = "sgc"; + private static final String DATA_CONNECTION_TIME_DATA = "dct"; + private static final String DATA_CONNECTION_COUNT_DATA = "dcc"; + + private final StringBuilder mFormatBuilder = new StringBuilder(32); private final Formatter mFormatter = new Formatter(mFormatBuilder); /** @@ -122,7 +134,7 @@ public abstract class BatteryStats implements Parcelable { * * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT */ - public abstract int getCount(int which); + public abstract int getCountLocked(int which); /** * Temporary for debugging. @@ -141,7 +153,7 @@ public abstract class BatteryStats implements Parcelable { * * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT */ - public abstract int getCount(int which); + public abstract int getCountLocked(int which); /** * Returns the total time in microseconds associated with this Timer for the @@ -151,7 +163,7 @@ public abstract class BatteryStats implements Parcelable { * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT * @return a time in microseconds */ - public abstract long getTotalTime(long batteryRealtime, int which); + public abstract long getTotalTimeLocked(long batteryRealtime, int which); /** * Temporary for debugging. @@ -220,9 +232,13 @@ public abstract class BatteryStats implements Parcelable { public abstract void noteFullWifiLockReleasedLocked(); public abstract void noteScanWifiLockAcquiredLocked(); public abstract void noteScanWifiLockReleasedLocked(); + public abstract void noteWifiMulticastEnabledLocked(); + public abstract void noteWifiMulticastDisabledLocked(); public abstract long getWifiTurnedOnTime(long batteryRealtime, int which); public abstract long getFullWifiLockTime(long batteryRealtime, int which); public abstract long getScanWifiLockTime(long batteryRealtime, int which); + public abstract long getWifiMulticastTime(long batteryRealtime, + int which); /** * Note that these must match the constants in android.os.LocalPowerManager. @@ -472,15 +488,16 @@ public abstract class BatteryStats implements Parcelable { 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. + * Returns the battery percentage level at the last time the device was unplugged from power, or + * the last time it booted on battery power. */ - public abstract int getUnpluggedStartLevel(); + public abstract int getDischargeStartLevel(); /** - * Returns the battery percentage level at the last time the device was plugged into power. + * Returns the current battery percentage level if we are in a discharge cycle, otherwise + * returns the level at the last plug event. */ - public abstract int getPluggedStartLevel(); + public abstract int getDischargeCurrentLevel(); /** * Returns the total, last, or current battery uptime in microseconds. @@ -513,8 +530,10 @@ public abstract class BatteryStats implements Parcelable { * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT. */ public abstract long computeRealtime(long curTime, int which); + + public abstract Map<String, ? extends Timer> getKernelWakelockStats(); - private final static void formatTime(StringBuilder out, long seconds) { + private final static void formatTimeRaw(StringBuilder out, long seconds) { long days = seconds / (60 * 60 * 24); if (days != 0) { out.append(days); @@ -542,22 +561,18 @@ public abstract class BatteryStats implements Parcelable { } } - private final static String formatTime(long time) { + private final static void formatTime(StringBuilder sb, long time) { long sec = time / 100; - StringBuilder sb = new StringBuilder(); - formatTime(sb, sec); + formatTimeRaw(sb, sec); sb.append((time - (sec * 100)) * 10); sb.append("ms "); - return sb.toString(); } - private final static String formatTimeMs(long time) { + private final static void formatTimeMs(StringBuilder sb, long time) { long sec = time / 1000; - StringBuilder sb = new StringBuilder(); - formatTime(sb, sec); + formatTimeRaw(sb, sec); sb.append(time - (sec * 1000)); sb.append("ms "); - return sb.toString(); } private final String formatRatioLocked(long num, long den) { @@ -602,14 +617,14 @@ public abstract class BatteryStats implements Parcelable { if (timer != null) { // Convert from microseconds to milliseconds with rounding - long totalTimeMicros = timer.getTotalTime(batteryRealtime, which); + long totalTimeMicros = timer.getTotalTimeLocked(batteryRealtime, which); long totalTimeMillis = (totalTimeMicros + 500) / 1000; - int count = timer.getCount(which); + int count = timer.getCountLocked(which); if (totalTimeMillis != 0) { sb.append(linePrefix); - sb.append(formatTimeMs(totalTimeMillis)); - sb.append(name); + formatTimeMs(sb, totalTimeMillis); + if (name != null) sb.append(name); sb.append(' '); sb.append('('); sb.append(count); @@ -632,18 +647,17 @@ public abstract class BatteryStats implements Parcelable { * @return the line prefix */ private static final String printWakeLockCheckin(StringBuilder sb, Timer timer, long now, - String name, int which, String linePrefix) { + String name, int which, String linePrefix) { long totalTimeMicros = 0; int count = 0; if (timer != null) { - totalTimeMicros = timer.getTotalTime(now, which); - count = timer.getCount(which); + totalTimeMicros = timer.getTotalTimeLocked(now, which); + count = timer.getCountLocked(which); } sb.append(linePrefix); sb.append((totalTimeMicros + 500) / 1000); // microseconds to milliseconds with rounding sb.append(','); - sb.append(name); - sb.append(','); + sb.append(name != null ? name + "," : ""); sb.append(count); return ","; } @@ -725,12 +739,12 @@ public abstract class BatteryStats implements Parcelable { Timer fullWakeTimer = wl.getWakeTime(WAKE_TYPE_FULL); if (fullWakeTimer != null) { - fullWakeLockTimeTotal += fullWakeTimer.getTotalTime(batteryRealtime, which); + fullWakeLockTimeTotal += fullWakeTimer.getTotalTimeLocked(batteryRealtime, which); } Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL); if (partialWakeTimer != null) { - partialWakeLockTimeTotal += partialWakeTimer.getTotalTime( + partialWakeLockTimeTotal += partialWakeTimer.getTotalTimeLocked( batteryRealtime, which); } } @@ -774,8 +788,19 @@ public abstract class BatteryStats implements Parcelable { dumpLine(pw, 0 /* uid */, category, DATA_CONNECTION_COUNT_DATA, args); if (which == STATS_UNPLUGGED) { - dumpLine(pw, 0 /* uid */, category, BATTERY_DATA, getUnpluggedStartLevel(), - getPluggedStartLevel()); + dumpLine(pw, 0 /* uid */, category, BATTERY_LEVEL_DATA, getDischargeStartLevel(), + getDischargeCurrentLevel()); + } + + Map<String, ? extends BatteryStats.Timer> kernelWakelocks = getKernelWakelockStats(); + if (kernelWakelocks.size() > 0) { + for (Map.Entry<String, ? extends BatteryStats.Timer> ent : kernelWakelocks.entrySet()) { + sb.setLength(0); + printWakeLockCheckin(sb, ent.getValue(), batteryRealtime, null, which, ""); + + dumpLine(pw, 0 /* uid */, category, KERNEL_WAKELOCK_DATA, ent.getKey(), + sb.toString()); + } } for (int iu = 0; iu < NU; iu++) { @@ -816,12 +841,12 @@ public abstract class BatteryStats implements Parcelable { 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); + linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_FULL), + batteryRealtime, "f", which, linePrefix); + linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL), + batteryRealtime, "p", which, linePrefix); + linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), + batteryRealtime, "w", which, linePrefix); // Only log if we had at lease one wakelock... if (sb.length() > 0) { @@ -839,8 +864,8 @@ public abstract class BatteryStats implements Parcelable { 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); + long totalTime = (timer.getTotalTimeLocked(batteryRealtime, which) + 500) / 1000; + int count = timer.getCountLocked(which); if (totalTime != 0) { dumpLine(pw, uid, category, SENSOR_DATA, sensorNumber, totalTime, count); } @@ -898,7 +923,7 @@ public abstract class BatteryStats implements Parcelable { } @SuppressWarnings("unused") - private final void dumpLocked(Printer pw, String prefix, int which) { + private final void dumpLocked(PrintWriter pw, String prefix, int which) { final long rawUptime = SystemClock.uptimeMillis() * 1000; final long rawRealtime = SystemClock.elapsedRealtime() * 1000; final long batteryUptime = getBatteryUptime(rawUptime); @@ -914,33 +939,41 @@ public abstract class BatteryStats implements Parcelable { 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, "); + sb.setLength(0); + sb.append(prefix); + sb.append(" Time on battery: "); + formatTimeMs(sb, whichBatteryRealtime / 1000); sb.append("("); + sb.append(formatRatioLocked(whichBatteryRealtime, totalRealtime)); + sb.append(") realtime, "); + formatTimeMs(sb, whichBatteryUptime / 1000); + sb.append("("); sb.append(formatRatioLocked(whichBatteryUptime, totalRealtime)); + sb.append(") uptime"); + pw.println(sb.toString()); + sb.setLength(0); + sb.append(prefix); + sb.append(" Total run time: "); + formatTimeMs(sb, totalRealtime / 1000); + sb.append("realtime, "); + formatTimeMs(sb, totalUptime / 1000); + sb.append("uptime, "); + pw.println(sb.toString()); 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(prefix); + sb.append(" Screen on: "); formatTimeMs(sb, screenOnTime / 1000); + sb.append("("); sb.append(formatRatioLocked(screenOnTime, whichBatteryRealtime)); + sb.append("), Input events: "); sb.append(getInputEventCount(which)); + sb.append(", Active phone call: "); formatTimeMs(sb, phoneOnTime / 1000); + sb.append("("); sb.append(formatRatioLocked(phoneOnTime, whichBatteryRealtime)); + sb.append(")"); + pw.println(sb.toString()); + sb.setLength(0); + sb.append(prefix); sb.append(" Screen brightnesses: "); boolean didOne = false; for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) { @@ -952,7 +985,7 @@ public abstract class BatteryStats implements Parcelable { didOne = true; sb.append(SCREEN_BRIGHTNESS_NAMES[i]); sb.append(" "); - sb.append(formatTimeMs(time/1000)); + formatTimeMs(sb, time/1000); sb.append("("); sb.append(formatRatioLocked(time, screenOnTime)); sb.append(")"); @@ -966,6 +999,26 @@ public abstract class BatteryStats implements Parcelable { long fullWakeLockTimeTotalMicros = 0; long partialWakeLockTimeTotalMicros = 0; + Map<String, ? extends BatteryStats.Timer> kernelWakelocks = getKernelWakelockStats(); + if (kernelWakelocks.size() > 0) { + for (Map.Entry<String, ? extends BatteryStats.Timer> ent : kernelWakelocks.entrySet()) { + + String linePrefix = ": "; + sb.setLength(0); + sb.append(prefix); + sb.append(" Kernel Wake lock "); + sb.append(ent.getKey()); + linePrefix = printWakeLock(sb, ent.getValue(), batteryRealtime, null, which, + linePrefix); + if (!linePrefix.equals(": ")) { + sb.append(" realtime"); + } else { + sb.append(": (nothing executed)"); + } + pw.println(sb.toString()); + } + } + for (int iu = 0; iu < NU; iu++) { Uid u = uidStats.valueAt(iu); rxTotal += u.getTcpBytesReceived(which); @@ -979,29 +1032,32 @@ public abstract class BatteryStats implements Parcelable { Timer fullWakeTimer = wl.getWakeTime(WAKE_TYPE_FULL); if (fullWakeTimer != null) { - fullWakeLockTimeTotalMicros += fullWakeTimer.getTotalTime( + fullWakeLockTimeTotalMicros += fullWakeTimer.getTotalTimeLocked( batteryRealtime, which); } Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL); if (partialWakeTimer != null) { - partialWakeLockTimeTotalMicros += partialWakeTimer.getTotalTime( + partialWakeLockTimeTotalMicros += partialWakeTimer.getTotalTimeLocked( 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)); + pw.print(prefix); + pw.print(" Total received: "); pw.print(formatBytesLocked(rxTotal)); + pw.print(", Total sent: "); pw.println(formatBytesLocked(txTotal)); + sb.setLength(0); + sb.append(prefix); + sb.append(" Total full wakelock time: "); formatTimeMs(sb, + (fullWakeLockTimeTotalMicros + 500) / 1000); + sb.append(", Total partial waklock time: "); formatTimeMs(sb, + (partialWakeLockTimeTotalMicros + 500) / 1000); + pw.println(sb.toString()); sb.setLength(0); + sb.append(prefix); sb.append(" Signal levels: "); didOne = false; for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) { @@ -1013,7 +1069,7 @@ public abstract class BatteryStats implements Parcelable { didOne = true; sb.append(SIGNAL_STRENGTH_NAMES[i]); sb.append(" "); - sb.append(formatTimeMs(time/1000)); + formatTimeMs(sb, time/1000); sb.append("("); sb.append(formatRatioLocked(time, whichBatteryRealtime)); sb.append(") "); @@ -1024,6 +1080,7 @@ public abstract class BatteryStats implements Parcelable { pw.println(sb.toString()); sb.setLength(0); + sb.append(prefix); sb.append(" Radio types: "); didOne = false; for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { @@ -1035,7 +1092,7 @@ public abstract class BatteryStats implements Parcelable { didOne = true; sb.append(DATA_CONNECTION_NAMES[i]); sb.append(" "); - sb.append(formatTimeMs(time/1000)); + formatTimeMs(sb, time/1000); sb.append("("); sb.append(formatRatioLocked(time, whichBatteryRealtime)); sb.append(") "); @@ -1045,27 +1102,32 @@ public abstract class BatteryStats implements Parcelable { 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)+ ")"); + sb.setLength(0); + sb.append(prefix); + sb.append(" Wifi on: "); formatTimeMs(sb, wifiOnTime / 1000); + sb.append("("); sb.append(formatRatioLocked(wifiOnTime, whichBatteryRealtime)); + sb.append("), Wifi running: "); formatTimeMs(sb, wifiRunningTime / 1000); + sb.append("("); sb.append(formatRatioLocked(wifiRunningTime, whichBatteryRealtime)); + sb.append("), Bluetooth on: "); formatTimeMs(sb, bluetoothOnTime / 1000); + sb.append("("); sb.append(formatRatioLocked(bluetoothOnTime, whichBatteryRealtime)); + sb.append(")"); + pw.println(sb.toString()); pw.println(" "); if (which == STATS_UNPLUGGED) { if (getIsOnBattery()) { - pw.println(prefix + " Device is currently unplugged"); - pw.println(prefix + " Discharge cycle start level: " + - getUnpluggedStartLevel()); + pw.print(prefix); pw.println(" Device is currently unplugged"); + pw.print(prefix); pw.print(" Discharge cycle start level: "); + pw.println(getDischargeStartLevel()); + pw.print(prefix); pw.print(" Discharge cycle current level: "); + pw.println(getDischargeCurrentLevel()); } 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.print(prefix); pw.println(" Device is currently plugged into power"); + pw.print(prefix); pw.print(" Last discharge cycle start level: "); + pw.println(getDischargeStartLevel()); + pw.print(prefix); pw.print(" Last discharge cycle end level: "); + pw.println(getDischargeCurrentLevel()); } pw.println(" "); } @@ -1084,8 +1146,9 @@ public abstract class BatteryStats implements Parcelable { long wifiTurnedOnTime = u.getWifiTurnedOnTime(batteryRealtime, which); if (tcpReceived != 0 || tcpSent != 0) { - pw.println(prefix + " Network: " + formatBytesLocked(tcpReceived) + " received, " - + formatBytesLocked(tcpSent) + " sent"); + pw.print(prefix); pw.print(" Network: "); + pw.print(formatBytesLocked(tcpReceived)); pw.print(" received, "); + pw.print(formatBytesLocked(tcpSent)); pw.println(" sent"); } if (u.hasUserActivity()) { @@ -1112,18 +1175,20 @@ public abstract class BatteryStats implements Parcelable { 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)+ ")"); + sb.setLength(0); + sb.append(prefix); sb.append(" Turned Wifi On: "); + formatTimeMs(sb, wifiTurnedOnTime / 1000); + sb.append("("); sb.append(formatRatioLocked(wifiTurnedOnTime, + whichBatteryRealtime)); sb.append(")\n"); + sb.append(prefix); sb.append(" Full Wifi Lock: "); + formatTimeMs(sb, fullWifiLockOnTime / 1000); + sb.append("("); sb.append(formatRatioLocked(fullWifiLockOnTime, + whichBatteryRealtime)); sb.append(")\n"); + sb.append(prefix); sb.append(" Scan Wifi Lock: "); + formatTimeMs(sb, scanWifiLockOnTime / 1000); + sb.append("("); sb.append(formatRatioLocked(scanWifiLockOnTime, + whichBatteryRealtime)); sb.append(")"); + pw.println(sb.toString()); } Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats(); @@ -1172,11 +1237,12 @@ public abstract class BatteryStats implements Parcelable { 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); + long totalTime = (timer.getTotalTimeLocked( + batteryRealtime, which) + 500) / 1000; + int count = timer.getCountLocked(which); //timer.logState(); if (totalTime != 0) { - sb.append(formatTimeMs(totalTime)); + formatTimeMs(sb, totalTime); sb.append("realtime ("); sb.append(count); sb.append(" times)"); @@ -1206,10 +1272,15 @@ public abstract class BatteryStats implements Parcelable { 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"); + sb.setLength(0); + sb.append(prefix); sb.append(" Proc "); + sb.append(ent.getKey()); sb.append(":\n"); + sb.append(prefix); sb.append(" CPU: "); + formatTime(sb, userTime); sb.append("usr + "); + formatTime(sb, systemTime); sb.append("krn\n"); + sb.append(prefix); sb.append(" "); sb.append(starts); + sb.append(" proc starts"); + pw.println(sb.toString()); uidActivity = true; } } @@ -1219,12 +1290,13 @@ public abstract class BatteryStats implements Parcelable { if (packageStats.size() > 0) { for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg> ent : packageStats.entrySet()) { - pw.println(prefix + " Apk " + ent.getKey() + ":"); + pw.print(prefix); pw.print(" Apk "); pw.print(ent.getKey()); pw.println(":"); boolean apkActivity = false; Uid.Pkg ps = ent.getValue(); int wakeups = ps.getWakeups(which); if (wakeups != 0) { - pw.println(prefix + " " + wakeups + " wakeup alarms"); + pw.print(prefix); pw.print(" "); + pw.print(wakeups); pw.println(" wakeup alarms"); apkActivity = true; } Map<String, ? extends Uid.Pkg.Serv> serviceStats = ps.getServiceStats(); @@ -1236,24 +1308,28 @@ public abstract class BatteryStats implements Parcelable { 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); + sb.setLength(0); + sb.append(prefix); sb.append(" Service "); + sb.append(sent.getKey()); sb.append(":\n"); + sb.append(prefix); sb.append(" Created for: "); + formatTimeMs(sb, startTime / 1000); + sb.append(" uptime\n"); + sb.append(prefix); sb.append(" Starts: "); + sb.append(starts); + sb.append(", launches: "); sb.append(launches); + pw.println(sb.toString()); apkActivity = true; } } } if (!apkActivity) { - pw.println(prefix + " (nothing executed)"); + pw.print(prefix); pw.println(" (nothing executed)"); } uidActivity = true; } } if (!uidActivity) { - pw.println(prefix + " (nothing executed)"); + pw.print(prefix); pw.println(" (nothing executed)"); } } } @@ -1264,7 +1340,7 @@ public abstract class BatteryStats implements Parcelable { * @param pw a Printer to receive the dump output. */ @SuppressWarnings("unused") - public void dumpLocked(Printer pw) { + public void dumpLocked(PrintWriter pw) { pw.println("Total Statistics (Current and Historic):"); pw.println(" System starts: " + getStartCount() + ", currently on battery: " + getIsOnBattery()); diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java index 467c17f..5487c54 100644 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -59,11 +59,47 @@ public class Build { public static final String RELEASE = getString("ro.build.version.release"); /** - * The user-visible SDK version of the framework. It is an integer starting at 1. + * The user-visible SDK version of the framework in its raw String + * representation; use {@link #SDK_INT} instead. + * + * @deprecated Use {@link #SDK_INT} to easily get this as an integer. */ public static final String SDK = getString("ro.build.version.sdk"); + + /** + * The user-visible SDK version of the framework; its possible + * values are defined in {@link Build.VERSION_CODES}. + */ + public static final int SDK_INT = SystemProperties.getInt( + "ro.build.version.sdk", 0); + + /** + * The current development codename, or the string "REL" if this is + * a release build. + */ + public static final String CODENAME = getString("ro.build.version.codename"); } + /** + * Enumeration of the currently known SDK version codes. These are the + * values that can be found in {@link VERSION#SDK}. Version numbers + * increment monotonically with each official platform release. + */ + public static class VERSION_CODES { + /** + * October 2008: The original, first, version of Android. Yay! + */ + public static final int BASE = 1; + /** + * February 2009: First Android update, officially called 1.1. + */ + public static final int BASE_1_1 = 2; + /** + * May 2009: Android 1.5. + */ + public static final int CUPCAKE = 3; + } + /** The type of build, like "user" or "eng". */ public static final String TYPE = getString("ro.build.type"); diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java index 950bb09..8fcb4d7 100644 --- a/core/java/android/os/Debug.java +++ b/core/java/android/os/Debug.java @@ -16,10 +16,24 @@ package android.os; +import com.android.internal.util.TypedProperties; + +import android.util.Config; +import android.util.Log; + +import java.io.FileNotFoundException; import java.io.FileOutputStream; +import java.io.FileReader; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.PrintWriter; +import java.io.Reader; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import org.apache.harmony.dalvik.ddmc.Chunk; import org.apache.harmony.dalvik.ddmc.ChunkHandler; @@ -364,6 +378,14 @@ href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Lo } /** + * Determine whether method tracing is currently active. + * @hide + */ + public static boolean isMethodTracingActive() { + return VMDebug.isMethodTracingActive(); + } + + /** * Stop method tracing. */ public static void stopMethodTracing() { @@ -713,5 +735,232 @@ href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Lo count += mCounts[Opcodes.OP_INVOKE_SUPER_QUICK_RANGE]; return count; } - }; + } + + + /** + * A Map of typed debug properties. + */ + private static final TypedProperties debugProperties; + + /* + * Load the debug properties from the standard files into debugProperties. + */ + static { + if (Config.DEBUG) { + final String TAG = "DebugProperties"; + final String[] files = { "/system/debug.prop", "/debug.prop", "/data/debug.prop" }; + final TypedProperties tp = new TypedProperties(); + + // Read the properties from each of the files, if present. + for (String file : files) { + Reader r; + try { + r = new FileReader(file); + } catch (FileNotFoundException ex) { + // It's ok if a file is missing. + continue; + } + + try { + tp.load(r); + } catch (Exception ex) { + throw new RuntimeException("Problem loading " + file, ex); + } finally { + try { + r.close(); + } catch (IOException ex) { + // Ignore this error. + } + } + } + + debugProperties = tp.isEmpty() ? null : tp; + } else { + debugProperties = null; + } + } + + + /** + * Returns true if the type of the field matches the specified class. + * Handles the case where the class is, e.g., java.lang.Boolean, but + * the field is of the primitive "boolean" type. Also handles all of + * the java.lang.Number subclasses. + */ + private static boolean fieldTypeMatches(Field field, Class<?> cl) { + Class<?> fieldClass = field.getType(); + if (fieldClass == cl) { + return true; + } + Field primitiveTypeField; + try { + /* All of the classes we care about (Boolean, Integer, etc.) + * have a Class field called "TYPE" that points to the corresponding + * primitive class. + */ + primitiveTypeField = cl.getField("TYPE"); + } catch (NoSuchFieldException ex) { + return false; + } + try { + return fieldClass == (Class<?>) primitiveTypeField.get(null); + } catch (IllegalAccessException ex) { + return false; + } + } + + + /** + * Looks up the property that corresponds to the field, and sets the field's value + * if the types match. + */ + private static void modifyFieldIfSet(final Field field, final TypedProperties properties, + final String propertyName) { + if (field.getType() == java.lang.String.class) { + int stringInfo = properties.getStringInfo(propertyName); + switch (stringInfo) { + case TypedProperties.STRING_SET: + // Handle as usual below. + break; + case TypedProperties.STRING_NULL: + try { + field.set(null, null); // null object for static fields; null string + } catch (IllegalAccessException ex) { + throw new IllegalArgumentException( + "Cannot set field for " + propertyName, ex); + } + return; + case TypedProperties.STRING_NOT_SET: + return; + case TypedProperties.STRING_TYPE_MISMATCH: + throw new IllegalArgumentException( + "Type of " + propertyName + " " + + " does not match field type (" + field.getType() + ")"); + default: + throw new IllegalStateException( + "Unexpected getStringInfo(" + propertyName + ") return value " + + stringInfo); + } + } + Object value = properties.get(propertyName); + if (value != null) { + if (!fieldTypeMatches(field, value.getClass())) { + throw new IllegalArgumentException( + "Type of " + propertyName + " (" + value.getClass() + ") " + + " does not match field type (" + field.getType() + ")"); + } + try { + field.set(null, value); // null object for static fields + } catch (IllegalAccessException ex) { + throw new IllegalArgumentException( + "Cannot set field for " + propertyName, ex); + } + } + } + + + /** + * Equivalent to <code>setFieldsOn(cl, false)</code>. + * + * @see #setFieldsOn(Class, boolean) + * + * @hide + */ + public static void setFieldsOn(Class<?> cl) { + setFieldsOn(cl, false); + } + + /** + * Reflectively sets static fields of a class based on internal debugging + * properties. This method is a no-op if android.util.Config.DEBUG is + * false. + * <p> + * <strong>NOTE TO APPLICATION DEVELOPERS</strong>: Config.DEBUG will + * always be false in release builds. This API is typically only useful + * for platform developers. + * </p> + * Class setup: define a class whose only fields are non-final, static + * primitive types (except for "char") or Strings. In a static block + * after the field definitions/initializations, pass the class to + * this method, Debug.setFieldsOn(). Example: + * <pre> + * package com.example; + * + * import android.os.Debug; + * + * public class MyDebugVars { + * public static String s = "a string"; + * public static String s2 = "second string"; + * public static String ns = null; + * public static boolean b = false; + * public static int i = 5; + * @Debug.DebugProperty + * public static float f = 0.1f; + * @@Debug.DebugProperty + * public static double d = 0.5d; + * + * // This MUST appear AFTER all fields are defined and initialized! + * static { + * // Sets all the fields + * Debug.setFieldsOn(MyDebugVars.class); + * + * // Sets only the fields annotated with @Debug.DebugProperty + * // Debug.setFieldsOn(MyDebugVars.class, true); + * } + * } + * </pre> + * setFieldsOn() may override the value of any field in the class based + * on internal properties that are fixed at boot time. + * <p> + * These properties are only set during platform debugging, and are not + * meant to be used as a general-purpose properties store. + * + * {@hide} + * + * @param cl The class to (possibly) modify + * @param partial If false, sets all static fields, otherwise, only set + * fields with the {@link android.os.Debug.DebugProperty} + * annotation + * @throws IllegalArgumentException if any fields are final or non-static, + * or if the type of the field does not match the type of + * the internal debugging property value. + */ + public static void setFieldsOn(Class<?> cl, boolean partial) { + if (Config.DEBUG) { + if (debugProperties != null) { + /* Only look for fields declared directly by the class, + * so we don't mysteriously change static fields in superclasses. + */ + for (Field field : cl.getDeclaredFields()) { + if (!partial || field.getAnnotation(DebugProperty.class) != null) { + final String propertyName = cl.getName() + "." + field.getName(); + boolean isStatic = Modifier.isStatic(field.getModifiers()); + boolean isFinal = Modifier.isFinal(field.getModifiers()); + + if (!isStatic || isFinal) { + throw new IllegalArgumentException(propertyName + + " must be static and non-final"); + } + modifyFieldIfSet(field, debugProperties, propertyName); + } + } + } + } else { + Log.w("android.os.Debug", + "setFieldsOn(" + (cl == null ? "null" : cl.getName()) + + ") called in non-DEBUG build"); + } + } + + /** + * Annotation to put on fields you want to set with + * {@link Debug#setFieldsOn(Class, boolean)}. + * + * @hide + */ + @Target({ ElementType.FIELD }) + @Retention(RetentionPolicy.RUNTIME) + public @interface DebugProperty { + } } diff --git a/core/java/android/os/Power.java b/core/java/android/os/Power.java index 47497e5..3679e47 100644 --- a/core/java/android/os/Power.java +++ b/core/java/android/os/Power.java @@ -80,10 +80,9 @@ public class Power public static native int setLastUserActivityTimeout(long ms); /** - * Turn the device off. - * - * This method is considered deprecated in favor of - * {@link android.policy.ShutdownThread.shutdownAfterDisablingRadio()}. + * Low-level function turn the device off immediately, without trying + * to be clean. Most people should use + * {@link android.internal.app.ShutdownThread} for a clean shutdown. * * @deprecated * @hide diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java index cd86fbe..30acef9 100644 --- a/core/java/android/os/Process.java +++ b/core/java/android/os/Process.java @@ -176,6 +176,26 @@ public class Process { */ public static final int THREAD_PRIORITY_LESS_FAVORABLE = +1; + /** + * Default thread group - gets a 'normal' share of the CPU + * @hide + */ + public static final int THREAD_GROUP_DEFAULT = 0; + + /** + * Background non-interactive thread group - All threads in + * this group are scheduled with a reduced share of the CPU. + * @hide + */ + public static final int THREAD_GROUP_BG_NONINTERACTIVE = 1; + + /** + * Foreground 'boost' thread group - All threads in + * this group are scheduled with an increased share of the CPU + * @hide + **/ + public static final int THREAD_GROUP_FG_BOOST = 2; + public static final int SIGNAL_QUIT = 3; public static final int SIGNAL_KILL = 9; public static final int SIGNAL_USR1 = 10; @@ -569,6 +589,21 @@ public class Process { */ public static final native void setThreadPriority(int tid, int priority) throws IllegalArgumentException, SecurityException; + + /** + * Sets the scheduling group for a thread. + * @hide + * @param tid The indentifier of the thread/process to change. + * @param group The target group for this thread/process. + * + * @throws IllegalArgumentException Throws IllegalArgumentException if + * <var>tid</var> does not exist. + * @throws SecurityException Throws SecurityException if your process does + * not have permission to modify the given thread, or to use the given + * priority. + */ + public static final native void setThreadGroup(int tid, int group) + throws IllegalArgumentException, SecurityException; /** * Set the priority of the calling thread, based on Linux priorities. See @@ -680,6 +715,8 @@ public class Process { /** @hide */ public static final int PROC_SPACE_TERM = (int)' '; /** @hide */ + public static final int PROC_TAB_TERM = (int)'\t'; + /** @hide */ public static final int PROC_COMBINE = 0x100; /** @hide */ public static final int PROC_PARENS = 0x200; @@ -693,6 +730,10 @@ public class Process { /** @hide */ public static final native boolean readProcFile(String file, int[] format, String[] outStrings, long[] outLongs, float[] outFloats); + + /** @hide */ + public static final native boolean parseProcLine(byte[] buffer, int startIndex, + int endIndex, int[] format, String[] outStrings, long[] outLongs, float[] outFloats); /** * Gets the total Pss value for a given process, in bytes. diff --git a/core/java/android/os/RemoteCallbackList.java b/core/java/android/os/RemoteCallbackList.java index 63f6dff..23c0a7b 100644 --- a/core/java/android/os/RemoteCallbackList.java +++ b/core/java/android/os/RemoteCallbackList.java @@ -49,25 +49,35 @@ import java.util.HashMap; public class RemoteCallbackList<E extends IInterface> { /*package*/ HashMap<IBinder, Callback> mCallbacks = new HashMap<IBinder, Callback>(); - private IInterface[] mActiveBroadcast; + private Object[] mActiveBroadcast; private boolean mKilled = false; private final class Callback implements IBinder.DeathRecipient { final E mCallback; + final Object mCookie; - Callback(E callback) { + Callback(E callback, Object cookie) { mCallback = callback; + mCookie = cookie; } public void binderDied() { synchronized (mCallbacks) { mCallbacks.remove(mCallback.asBinder()); } - onCallbackDied(mCallback); + onCallbackDied(mCallback, mCookie); } } /** + * Simple version of {@link RemoteCallbackList#register(E, Object)} + * that does not take a cookie object. + */ + public boolean register(E callback) { + return register(callback, null); + } + + /** * Add a new callback to the list. This callback will remain in the list * until a corresponding call to {@link #unregister} or its hosting process * goes away. If the callback was already registered (determined by @@ -81,6 +91,8 @@ public class RemoteCallbackList<E extends IInterface> { * Most services will want to check for null before calling this with * an object given from a client, so that clients can't crash the * service with bad data. + * @param cookie Optional additional data to be associated with this + * callback. * * @return Returns true if the callback was successfully added to the list. * Returns false if it was not added, either because {@link #kill} had @@ -90,14 +102,14 @@ public class RemoteCallbackList<E extends IInterface> { * @see #kill * @see #onCallbackDied */ - public boolean register(E callback) { + public boolean register(E callback, Object cookie) { synchronized (mCallbacks) { if (mKilled) { return false; } IBinder binder = callback.asBinder(); try { - Callback cb = new Callback(callback); + Callback cb = new Callback(callback, cookie); binder.linkToDeath(cb, 0); mCallbacks.put(binder, cb); return true; @@ -154,17 +166,28 @@ public class RemoteCallbackList<E extends IInterface> { } /** + * Old version of {@link #onCallbackDied(E, Object)} that + * does not provide a cookie. + */ + public void onCallbackDied(E callback) { + } + + /** * Called when the process hosting a callback in the list has gone away. - * The default implementation does nothing. + * The default implementation calls {@link #onCallbackDied(E)} + * for backwards compatibility. * * @param callback The callback whose process has died. Note that, since * its process has died, you can not make any calls on to this interface. * You can, however, retrieve its IBinder and compare it with another * IBinder to see if it is the same object. + * @param cookie The cookie object original provided to + * {@link #register(E, Object)}. * * @see #register */ - public void onCallbackDied(E callback) { + public void onCallbackDied(E callback, Object cookie) { + onCallbackDied(callback); } /** @@ -203,13 +226,13 @@ public class RemoteCallbackList<E extends IInterface> { if (N <= 0) { return 0; } - IInterface[] active = mActiveBroadcast; + Object[] active = mActiveBroadcast; if (active == null || active.length < N) { - mActiveBroadcast = active = new IInterface[N]; + mActiveBroadcast = active = new Object[N]; } int i=0; for (Callback cb : mCallbacks.values()) { - active[i++] = cb.mCallback; + active[i++] = cb; } return i; } @@ -237,7 +260,17 @@ public class RemoteCallbackList<E extends IInterface> { * @see #beginBroadcast */ public E getBroadcastItem(int index) { - return (E)mActiveBroadcast[index]; + return ((Callback)mActiveBroadcast[index]).mCallback; + } + + /** + * Retrieve the cookie associated with the item + * returned by {@link #getBroadcastItem(int)}. + * + * @see #getBroadcastItem + */ + public Object getBroadcastCookie(int index) { + return ((Callback)mActiveBroadcast[index]).mCookie; } /** @@ -248,7 +281,7 @@ public class RemoteCallbackList<E extends IInterface> { * @see #beginBroadcast */ public void finishBroadcast() { - IInterface[] active = mActiveBroadcast; + Object[] active = mActiveBroadcast; if (active != null) { final int N = active.length; for (int i=0; i<N; i++) { |