summaryrefslogtreecommitdiffstats
path: root/core/java/android/os
diff options
context:
space:
mode:
authorJean-Baptiste Queru <jbq@google.com>2009-05-20 11:28:04 -0700
committerJean-Baptiste Queru <jbq@google.com>2009-05-20 11:28:04 -0700
commit843ef36f7b96cc19ea7d2996b7c8661b41ec3452 (patch)
tree560e1648c99a93986f8b7deef851ef8bb8029db7 /core/java/android/os
parent358d23017d0d6c4636eb7599ae7a9b48108899a3 (diff)
downloadframeworks_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.java4
-rw-r--r--core/java/android/os/BatteryStats.java350
-rw-r--r--core/java/android/os/Build.java38
-rw-r--r--core/java/android/os/Debug.java251
-rw-r--r--core/java/android/os/Power.java7
-rw-r--r--core/java/android/os/Process.java41
-rw-r--r--core/java/android/os/RemoteCallbackList.java57
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&lt;Void, Void, Void&gt; { ... }
* </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++) {