diff options
Diffstat (limited to 'core/java/android/os')
-rw-r--r-- | core/java/android/os/BatteryStats.java | 425 | ||||
-rw-r--r-- | core/java/android/os/Binder.java | 44 | ||||
-rw-r--r-- | core/java/android/os/Build.java | 3 | ||||
-rw-r--r-- | core/java/android/os/Debug.java | 26 | ||||
-rw-r--r-- | core/java/android/os/Environment.java | 12 | ||||
-rw-r--r-- | core/java/android/os/HandlerInterface.java | 27 | ||||
-rw-r--r-- | core/java/android/os/IBinder.java | 11 | ||||
-rw-r--r-- | core/java/android/os/ICheckinService.aidl | 9 | ||||
-rw-r--r-- | core/java/android/os/IMountService.aidl | 27 | ||||
-rw-r--r-- | core/java/android/os/INetStatService.aidl | 15 | ||||
-rw-r--r-- | core/java/android/os/IPowerManager.aidl | 1 | ||||
-rw-r--r-- | core/java/android/os/NetStat.java | 224 | ||||
-rw-r--r-- | core/java/android/os/ParcelFileDescriptor.java | 18 | ||||
-rw-r--r-- | core/java/android/os/ResultReceiver.aidl | 20 | ||||
-rw-r--r-- | core/java/android/os/ResultReceiver.java | 130 |
15 files changed, 869 insertions, 123 deletions
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index ed7c366..7590bfe 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -1,33 +1,44 @@ package android.os; -import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.Formatter; import java.util.Map; +import android.util.Log; +import android.util.Printer; import android.util.SparseArray; /** * A class providing access to battery usage statistics, including information on * wakelocks, processes, packages, and services. All times are represented in microseconds * except where indicated otherwise. + * @hide */ -public abstract class BatteryStats { +public abstract class BatteryStats implements Parcelable { + private static final boolean LOCAL_LOGV = false; + /** - * A constant indicating a partial wake lock. + * A constant indicating a partial wake lock timer. */ public static final int WAKE_TYPE_PARTIAL = 0; /** - * A constant indicating a full wake lock. + * A constant indicating a full wake lock timer. */ public static final int WAKE_TYPE_FULL = 1; /** - * A constant indicating a window wake lock. + * A constant indicating a window wake lock timer. */ public static final int WAKE_TYPE_WINDOW = 2; + + /** + * A constant indicating a sensor timer. + * + * {@hide} + */ + public static final int SENSOR = 3; /** * Include all of the data in the stats, including previously saved data. @@ -48,6 +59,22 @@ public abstract class BatteryStats { * Include only the run since the last time the device was unplugged in the stats. */ public static final int STATS_UNPLUGGED = 3; + + /** + * Bump the version on this if the checkin format changes. + */ + private static final int BATTERY_STATS_CHECKIN_VERSION = 1; + + // 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 BATTERY_DATA = "battery"; + private static final String MISC_DATA = "misc"; private final StringBuilder mFormatBuilder = new StringBuilder(8); private final Formatter mFormatter = new Formatter(mFormatBuilder); @@ -69,11 +96,16 @@ public abstract class BatteryStats { * Returns the total time in microseconds associated with this Timer for the * selected type of statistics. * - * @param now system uptime time in microseconds + * @param batteryRealtime system realtime on battery in microseconds * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT * @return a time in microseconds */ - public abstract long getTotalTime(long now, int which); + public abstract long getTotalTime(long batteryRealtime, int which); + + /** + * Temporary for debugging. + */ + public abstract void logState(); } /** @@ -115,8 +147,28 @@ public abstract class BatteryStats { * @return a Map from Strings to Uid.Pkg objects. */ public abstract Map<String, ? extends Pkg> getPackageStats(); + + /** + * {@hide} + */ + public abstract int getUid(); + + /** + * {@hide} + */ + public abstract long getTcpBytesReceived(int which); + + /** + * {@hide} + */ + public abstract long getTcpBytesSent(int which); public static abstract class Sensor { + // Magic sensor number for the GPS. + public static final int GPS = -10000; + + public abstract int getHandle(); + public abstract Timer getSensorTime(); } @@ -173,11 +225,11 @@ public abstract class BatteryStats { /** * Returns the amount of time spent started. * - * @param now elapsed realtime in microseconds. + * @param batteryUptime elapsed uptime on battery in microseconds. * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT. * @return */ - public abstract long getStartTime(long now, int which); + public abstract long getStartTime(long batteryUptime, int which); /** * Returns the total number of times startService() has been called. @@ -200,7 +252,28 @@ public abstract class BatteryStats { * Returns the number of times the device has been started. */ public abstract int getStartCount(); - + + /** + * Returns the time in milliseconds that the screen has been on while the device was + * running on battery. + * + * {@hide} + */ + public abstract long getScreenOnTime(long batteryRealtime, int which); + + /** + * Returns the time in milliseconds that the phone has been on while the device was + * running on battery. + * + * {@hide} + */ + public abstract long getPhoneOnTime(long batteryRealtime, int which); + + /** + * Return whether we are currently running on battery. + */ + public abstract boolean getIsOnBattery(); + /** * Returns a SparseArray containing the statistics for each uid. */ @@ -312,17 +385,20 @@ public abstract class BatteryStats { * * @param sb a StringBuilder object. * @param timer a Timer object contining the wakelock times. - * @param now the current time in microseconds. + * @param batteryRealtime the current on-battery time in microseconds. * @param name the name of the wakelock. * @param which which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT. * @param linePrefix a String to be prepended to each line of output. * @return the line prefix */ - private final String printWakeLock(StringBuilder sb, Timer timer, long now, - String name, int which, String linePrefix) { + private static final String printWakeLock(StringBuilder sb, Timer timer, + long batteryRealtime, String name, int which, String linePrefix) { + if (timer != null) { // Convert from microseconds to milliseconds with rounding - long totalTimeMillis = (timer.getTotalTime(now, which) + 500) / 1000; + long totalTimeMicros = timer.getTotalTime(batteryRealtime, which); + long totalTimeMillis = (totalTimeMicros + 500) / 1000; + int count = timer.getCount(which); if (totalTimeMillis != 0) { sb.append(linePrefix); @@ -337,40 +413,225 @@ public abstract class BatteryStats { } return linePrefix; } + + /** + * Checkin version of wakelock printer. Prints simple comma-separated list. + * + * @param sb a StringBuilder object. + * @param timer a Timer object contining the wakelock times. + * @param now the current time in microseconds. + * @param name the name of the wakelock. + * @param which which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT. + * @param linePrefix a String to be prepended to each line of output. + * @return the line prefix + */ + private static final String printWakeLockCheckin(StringBuilder sb, Timer timer, long now, + String name, int which, String linePrefix) { + long totalTimeMicros = 0; + int count = 0; + if (timer != null) { + totalTimeMicros = timer.getTotalTime(now, which); + count = timer.getCount(which); + } + sb.append(linePrefix); + sb.append((totalTimeMicros + 500) / 1000); // microseconds to milliseconds with rounding + sb.append(','); + sb.append(name); + sb.append(','); + sb.append(count); + return ","; + } + + /** + * Dump a comma-separated line of values for terse checkin mode. + * + * @param pw the PageWriter to dump log to + * @param category category of data (e.g. "total", "last", "unplugged", "current" ) + * @param type type of data (e.g. "wakelock", "sensor", "process", "apk" , "process", "network") + * @param args type-dependent data arguments + */ + private static final void dumpLine(PrintWriter pw, int uid, String category, String type, + Object... args ) { + pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(','); + pw.print(uid); pw.print(','); + pw.print(category); pw.print(','); + pw.print(type); + + for (Object arg : args) { + pw.print(','); + pw.print(arg); + } + pw.print('\n'); + } + + /** + * Checkin server version of dump to produce more compact, computer-readable log. + * + * NOTE: all times are expressed in 'ms'. + * @param fd + * @param pw + * @param which + */ + private final void dumpCheckinLocked(PrintWriter pw, int which) { + final long rawUptime = SystemClock.uptimeMillis() * 1000; + final long rawRealtime = SystemClock.elapsedRealtime() * 1000; + final long batteryUptime = getBatteryUptime(rawUptime); + final long batteryRealtime = getBatteryRealtime(rawRealtime); + final long whichBatteryUptime = computeBatteryUptime(rawUptime, which); + final long whichBatteryRealtime = computeBatteryRealtime(rawRealtime, which); + final long totalRealtime = computeRealtime(rawRealtime, which); + final long totalUptime = computeUptime(rawUptime, which); + final long screenOnTime = getScreenOnTime(batteryRealtime, which); + final long phoneOnTime = getPhoneOnTime(batteryRealtime, which); + + StringBuilder sb = new StringBuilder(128); + + String category = STAT_NAMES[which]; + + // Dump "battery" stat + dumpLine(pw, 0 /* uid */, category, BATTERY_DATA, + which == STATS_TOTAL ? getStartCount() : "N/A", + whichBatteryUptime / 1000, whichBatteryRealtime / 1000, + totalUptime / 1000, totalRealtime / 1000); + + // Dump misc stats + dumpLine(pw, 0 /* uid */, category, MISC_DATA, + screenOnTime / 1000, phoneOnTime / 1000); + + SparseArray<? extends Uid> uidStats = getUidStats(); + final int NU = uidStats.size(); + for (int iu = 0; iu < NU; iu++) { + final int uid = uidStats.keyAt(iu); + Uid u = uidStats.valueAt(iu); + // Dump Network stats per uid, if any + long rx = u.getTcpBytesReceived(which); + long tx = u.getTcpBytesSent(which); + if (rx > 0 || tx > 0) dumpLine(pw, uid, category, NETWORK_DATA, rx, tx); - @SuppressWarnings("unused") - private final void dumpLocked(FileDescriptor fd, PrintWriter pw, String prefix, int which) { - long uSecTime = SystemClock.elapsedRealtime() * 1000; - final long uSecNow = getBatteryUptime(uSecTime); + Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats(); + if (wakelocks.size() > 0) { + for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent + : wakelocks.entrySet()) { + Uid.Wakelock wl = ent.getValue(); + String linePrefix = ""; + sb.setLength(0); + linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_FULL), batteryRealtime, + "full", which, linePrefix); + linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL), batteryRealtime, + "partial", which, linePrefix); + linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), batteryRealtime, + "window", which, linePrefix); + + // Only log if we had at lease one wakelock... + if (sb.length() > 0) { + dumpLine(pw, uid, category, WAKELOCK_DATA, ent.getKey(), sb.toString()); + } + } + } + + Map<Integer, ? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats(); + if (sensors.size() > 0) { + for (Map.Entry<Integer, ? extends BatteryStats.Uid.Sensor> ent + : sensors.entrySet()) { + Uid.Sensor se = ent.getValue(); + int sensorNumber = ent.getKey(); + Timer timer = se.getSensorTime(); + if (timer != null) { + // Convert from microseconds to milliseconds with rounding + long totalTime = (timer.getTotalTime(batteryRealtime, which) + 500) / 1000; + int count = timer.getCount(which); + if (totalTime != 0) { + dumpLine(pw, uid, category, SENSOR_DATA, sensorNumber, totalTime, count); + } + } + } + } - StringBuilder sb = new StringBuilder(128); - if (which == STATS_TOTAL) { - pw.println(prefix + "Current and Historic Battery Usage Statistics:"); - pw.println(prefix + " System starts: " + getStartCount()); - } else if (which == STATS_LAST) { - pw.println(prefix + "Last Battery Usage Statistics:"); - } else { - pw.println(prefix + "Current Battery Usage Statistics:"); + Map<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats(); + if (processStats.size() > 0) { + for (Map.Entry<String, ? extends BatteryStats.Uid.Proc> ent + : processStats.entrySet()) { + Uid.Proc ps = ent.getValue(); + + long userTime = ps.getUserTime(which); + long systemTime = ps.getSystemTime(which); + int starts = ps.getStarts(which); + + if (userTime != 0 || systemTime != 0 || starts != 0) { + dumpLine(pw, uid, category, PROCESS_DATA, + ent.getKey(), // proc + userTime * 10, // cpu time in ms + systemTime * 10, // user time in ms + starts); // process starts + } + } + } + + Map<String, ? extends BatteryStats.Uid.Pkg> packageStats = u.getPackageStats(); + if (packageStats.size() > 0) { + for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg> ent + : packageStats.entrySet()) { + + Uid.Pkg ps = ent.getValue(); + int wakeups = ps.getWakeups(which); + Map<String, ? extends Uid.Pkg.Serv> serviceStats = ps.getServiceStats(); + for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg.Serv> sent + : serviceStats.entrySet()) { + BatteryStats.Uid.Pkg.Serv ss = sent.getValue(); + long startTime = ss.getStartTime(batteryUptime, which); + int starts = ss.getStarts(which); + int launches = ss.getLaunches(which); + if (startTime != 0 || starts != 0 || launches != 0) { + dumpLine(pw, uid, category, APK_DATA, + wakeups, // wakeup alarms + ent.getKey(), // Apk + sent.getKey(), // service + startTime / 1000, // time spent started, in ms + starts, + launches); + } + } + } + } } - long batteryUptime = computeBatteryUptime(uSecNow, which); - long batteryRealtime = computeBatteryRealtime(getBatteryRealtime(uSecTime), which); - long elapsedRealtime = computeRealtime(uSecTime, which); - long uptime = computeUptime(SystemClock.uptimeMillis() * 1000, which); + } + + @SuppressWarnings("unused") + private final void dumpLocked(Printer pw, String prefix, int which) { + final long rawUptime = SystemClock.uptimeMillis() * 1000; + final long rawRealtime = SystemClock.elapsedRealtime() * 1000; + final long batteryUptime = getBatteryUptime(rawUptime); + final long batteryRealtime = getBatteryUptime(rawRealtime); + + final long whichBatteryUptime = computeBatteryUptime(rawUptime, which); + final long whichBatteryRealtime = computeBatteryRealtime(rawRealtime, which); + final long totalRealtime = computeRealtime(rawRealtime, which); + final long totalUptime = computeUptime(rawUptime, which); + + StringBuilder sb = new StringBuilder(128); pw.println(prefix - + " On battery: " + formatTimeMs(batteryUptime / 1000) + "(" - + formatRatioLocked(batteryUptime, batteryRealtime) + + " Time on battery: " + formatTimeMs(whichBatteryUptime / 1000) + + "(" + formatRatioLocked(whichBatteryUptime, totalRealtime) + ") uptime, " - + formatTimeMs(batteryRealtime / 1000) + "(" - + formatRatioLocked(batteryRealtime, elapsedRealtime) + + formatTimeMs(whichBatteryRealtime / 1000) + "(" + + formatRatioLocked(whichBatteryRealtime, totalRealtime) + ") realtime"); pw.println(prefix + " Total: " - + formatTimeMs(uptime / 1000) + + formatTimeMs(totalUptime / 1000) + "uptime, " - + formatTimeMs(elapsedRealtime / 1000) + + formatTimeMs(totalRealtime / 1000) + "realtime"); - + + long screenOnTime = getScreenOnTime(batteryRealtime, which); + long phoneOnTime = getPhoneOnTime(batteryRealtime, which); + pw.println(prefix + + " Time with screen on: " + formatTimeMs(screenOnTime / 1000) + + "(" + formatRatioLocked(screenOnTime, whichBatteryRealtime) + + "), time with phone on: " + formatTimeMs(phoneOnTime / 1000) + + "(" + formatRatioLocked(phoneOnTime, whichBatteryRealtime) + ")"); + pw.println(" "); SparseArray<? extends Uid> uidStats = getUidStats(); @@ -380,6 +641,13 @@ public abstract class BatteryStats { Uid u = uidStats.valueAt(iu); pw.println(prefix + " #" + uid + ":"); boolean uidActivity = false; + + long tcpReceived = u.getTcpBytesReceived(which); + long tcpSent = u.getTcpBytesSent(which); + if (tcpReceived != 0 || tcpSent != 0) { + pw.println(prefix + " Network: " + tcpReceived + " bytes received, " + + tcpSent + " bytes sent"); + } Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats(); if (wakelocks.size() > 0) { @@ -391,13 +659,15 @@ public abstract class BatteryStats { sb.append(prefix); sb.append(" Wake lock "); sb.append(ent.getKey()); - linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_FULL), uSecNow, + linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_FULL), batteryRealtime, "full", which, linePrefix); - linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL), uSecNow, + linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL), batteryRealtime, "partial", which, linePrefix); - linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), uSecNow, + linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), batteryRealtime, "window", which, linePrefix); - if (linePrefix.equals(": ")) { + if (!linePrefix.equals(": ")) { + sb.append(" realtime"); + } else { sb.append(": (nothing executed)"); } pw.println(sb.toString()); @@ -414,23 +684,30 @@ public abstract class BatteryStats { sb.setLength(0); sb.append(prefix); sb.append(" Sensor "); - sb.append(sensorNumber); + int handle = se.getHandle(); + if (handle == Uid.Sensor.GPS) { + sb.append("GPS"); + } else { + sb.append(handle); + } + sb.append(": "); Timer timer = se.getSensorTime(); if (timer != null) { // Convert from microseconds to milliseconds with rounding - long totalTime = (timer.getTotalTime(uSecNow, which) + 500) / 1000; + long totalTime = (timer.getTotalTime(batteryRealtime, which) + 500) / 1000; int count = timer.getCount(which); + //timer.logState(); if (totalTime != 0) { - sb.append(": "); sb.append(formatTimeMs(totalTime)); - sb.append(' '); - sb.append('('); + sb.append("realtime ("); sb.append(count); sb.append(" times)"); + } else { + sb.append("(not used)"); } } else { - sb.append(": (none used)"); + sb.append("(not used)"); } pw.println(sb.toString()); @@ -478,13 +755,14 @@ public abstract class BatteryStats { for (Map.Entry<String, ? extends BatteryStats.Uid.Pkg.Serv> sent : serviceStats.entrySet()) { BatteryStats.Uid.Pkg.Serv ss = sent.getValue(); - long startTime = ss.getStartTime(uSecNow, which); + long startTime = ss.getStartTime(batteryUptime, which); int starts = ss.getStarts(which); int launches = ss.getLaunches(which); if (startTime != 0 || starts != 0 || launches != 0) { pw.println(prefix + " Service " + sent.getKey() + ":"); - pw.println(prefix + " Time spent started: " - + formatTimeMs(startTime / 1000)); + pw.println(prefix + " Created for: " + + formatTimeMs(startTime / 1000) + + " uptime"); pw.println(prefix + " Starts: " + starts + ", launches: " + launches); apkActivity = true; @@ -506,18 +784,45 @@ public abstract class BatteryStats { /** * Dumps a human-readable summary of the battery statistics to the given PrintWriter. * - * @param fd a FileDescriptor, currently unused. - * @param pw a PrintWriter to receive the dump output. - * @param args an array of Strings, currently unused. + * @param pw a Printer to receive the dump output. */ @SuppressWarnings("unused") - public void dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args) { - synchronized (this) { - dumpLocked(fd, pw, "", STATS_TOTAL); - pw.println(""); - dumpLocked(fd, pw, "", STATS_LAST); - pw.println(""); - dumpLocked(fd, pw, "", STATS_CURRENT); + public void dumpLocked(Printer pw) { + pw.println("Total Statistics (Current and Historic):"); + pw.println(" System starts: " + getStartCount() + + ", currently on battery: " + getIsOnBattery()); + dumpLocked(pw, "", STATS_TOTAL); + pw.println(""); + pw.println("Last Run Statistics (Previous run of system):"); + dumpLocked(pw, "", STATS_LAST); + pw.println(""); + pw.println("Current Battery Statistics (Currently running system):"); + dumpLocked(pw, "", STATS_CURRENT); + pw.println(""); + pw.println("Unplugged Statistics (Since last unplugged from power):"); + dumpLocked(pw, "", STATS_UNPLUGGED); + } + + @SuppressWarnings("unused") + public void dumpCheckinLocked(PrintWriter pw, String[] args) { + boolean isUnpluggedOnly = false; + + for (String arg : args) { + if ("-u".equals(arg)) { + if (LOCAL_LOGV) Log.v("BatteryStats", "Dumping unplugged data"); + isUnpluggedOnly = true; + } + } + + if (isUnpluggedOnly) { + dumpCheckinLocked(pw, STATS_UNPLUGGED); + } + else { + dumpCheckinLocked(pw, STATS_TOTAL); + dumpCheckinLocked(pw, STATS_LAST); + dumpCheckinLocked(pw, STATS_UNPLUGGED); + dumpCheckinLocked(pw, STATS_CURRENT); } } + } diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java index 528e6bd..df10c6a 100644 --- a/core/java/android/os/Binder.java +++ b/core/java/android/os/Binder.java @@ -33,7 +33,7 @@ import java.lang.reflect.Modifier; * the standard support creating a local implementation of such an object. * * <p>Most developers will not implement this class directly, instead using the - * <a href="{@docRoot}reference/aidl.html">aidl</a> tool to describe the desired + * <a href="{@docRoot}guide/developing/tools/aidl.html">aidl</a> tool to describe the desired * interface, having it generate the appropriate Binder subclass. You can, * however, derive directly from Binder to implement your own custom RPC * protocol or simply instantiate a raw Binder object directly to use as a @@ -194,18 +194,15 @@ public class Binder implements IBinder { return true; } else if (code == DUMP_TRANSACTION) { ParcelFileDescriptor fd = data.readFileDescriptor(); - FileOutputStream fout = fd != null - ? new FileOutputStream(fd.getFileDescriptor()) : null; - PrintWriter pw = fout != null ? new PrintWriter(fout) : null; - if (pw != null) { - String[] args = data.readStringArray(); - dump(fd.getFileDescriptor(), pw, args); - pw.flush(); - } + String[] args = data.readStringArray(); if (fd != null) { try { - fd.close(); - } catch (IOException e) { + dump(fd.getFileDescriptor(), args); + } finally { + try { + fd.close(); + } catch (IOException e) { + } } } return true; @@ -214,6 +211,20 @@ public class Binder implements IBinder { } /** + * Implemented to call the more convenient version + * {@link #dump(FileDescriptor, PrintWriter, String[])}. + */ + public void dump(FileDescriptor fd, String[] args) { + FileOutputStream fout = new FileOutputStream(fd); + PrintWriter pw = new PrintWriter(fout); + try { + dump(fd, pw, args); + } finally { + pw.flush(); + } + } + + /** * Print the object's state into the given stream. * * @param fd The raw file descriptor that the dump is being sent to. @@ -302,6 +313,17 @@ final class BinderProxy implements IBinder { throws RemoteException; public native boolean unlinkToDeath(DeathRecipient recipient, int flags); + public void dump(FileDescriptor fd, String[] args) throws RemoteException { + Parcel data = Parcel.obtain(); + data.writeFileDescriptor(fd); + data.writeStringArray(args); + try { + transact(DUMP_TRANSACTION, data, null, 0); + } finally { + data.recycle(); + } + } + BinderProxy() { mSelf = new WeakReference(this); } diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java index cdf907b..467c17f 100644 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -26,6 +26,9 @@ public class Build { /** Either a changelist number, or a label like "M4-rc20". */ public static final String ID = getString("ro.build.id"); + /** A build ID string meant for displaying to the user */ + public static final String DISPLAY = getString("ro.build.display.id"); + /** The name of the overall product. */ public static final String PRODUCT = getString("ro.product.name"); diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java index 5f7f91f..950bb09 100644 --- a/core/java/android/os/Debug.java +++ b/core/java/android/os/Debug.java @@ -17,6 +17,7 @@ package android.os; import java.io.FileOutputStream; +import java.io.IOException; import java.io.OutputStreamWriter; import java.io.PrintWriter; @@ -28,12 +29,13 @@ import dalvik.bytecode.Opcodes; import dalvik.system.VMDebug; -/** Provides various debugging functions for Android applications, including +/** + * Provides various debugging functions for Android applications, including * tracing and allocation counts. * <p><strong>Logging Trace Files</strong></p> * <p>Debug can create log files that give details about an application, such as * a call stack and start/stop times for any running methods. See <a -href="{@docRoot}reference/traceview.html">Running the Traceview Debugging Program</a> for +href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for * information about reading trace files. To start logging trace files, call one * of the startMethodTracing() methods. To stop tracing, call * {@link #stopMethodTracing()}. @@ -285,7 +287,7 @@ public final class Debug /** * Start method tracing with default log name and buffer size. See <a -href="{@docRoot}reference/traceview.html">Running the Traceview Debugging Program</a> for +href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for * information about reading these files. Call stopMethodTracing() to stop * tracing. */ @@ -297,7 +299,7 @@ href="{@docRoot}reference/traceview.html">Running the Traceview Debugging Progra * Start method tracing, specifying the trace log file name. The trace * file will be put under "/sdcard" unless an absolute path is given. * See <a - href="{@docRoot}reference/traceview.html">Running the Traceview Debugging Program</a> for + href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for * information about reading trace files. * * @param traceName Name for the trace log file to create. @@ -313,7 +315,7 @@ href="{@docRoot}reference/traceview.html">Running the Traceview Debugging Progra * Start method tracing, specifying the trace log file name and the * buffer size. The trace files will be put under "/sdcard" unless an * absolute path is given. See <a - href="{@docRoot}reference/traceview.html">Running the Traceview Debugging Program</a> for + href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for * information about reading trace files. * @param traceName Name for the trace log file to create. * If no name argument is given, this value defaults to "/sdcard/dmtrace.trace". @@ -330,7 +332,7 @@ href="{@docRoot}reference/traceview.html">Running the Traceview Debugging Progra * Start method tracing, specifying the trace log file name and the * buffer size. The trace files will be put under "/sdcard" unless an * absolute path is given. See <a - href="{@docRoot}reference/traceview.html">Running the Traceview Debugging Program</a> for + href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for * information about reading trace files. * * <p> @@ -581,6 +583,18 @@ href="{@docRoot}reference/traceview.html">Running the Traceview Debugging Progra } /** + * Dump "hprof" data to the specified file. This will cause a GC. + * + * @param fileName Full pathname of output file (e.g. "/sdcard/dump.hprof"). + * @throws UnsupportedOperationException if the VM was built without + * HPROF support. + * @throws IOException if an error occurs while opening or writing files. + */ + public static void dumpHprofData(String fileName) throws IOException { + VMDebug.dumpHprofData(fileName); + } + + /** * Returns the number of sent transactions from this process. * @return The number of sent transactions or -1 if it could not read t. */ diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java index e37b551..f761e8e 100644 --- a/core/java/android/os/Environment.java +++ b/core/java/android/os/Environment.java @@ -75,6 +75,18 @@ public class Environment { public static final String MEDIA_UNMOUNTED = "unmounted"; /** + * getExternalStorageState() returns MEDIA_CHECKING if the media is present + * and being disk-checked + */ + public static final String MEDIA_CHECKING = "checking"; + + /** + * getExternalStorageState() returns MEDIA_NOFS if the media is present + * but is blank or is using an unsupported filesystem + */ + public static final String MEDIA_NOFS = "nofs"; + + /** * getExternalStorageState() returns MEDIA_MOUNTED if the media is present * and mounted at its mount point with read/write access. */ diff --git a/core/java/android/os/HandlerInterface.java b/core/java/android/os/HandlerInterface.java deleted file mode 100644 index 62dc273..0000000 --- a/core/java/android/os/HandlerInterface.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.os; - -/** - * @hide - * @deprecated - */ -public interface HandlerInterface -{ - void handleMessage(Message msg); -} - diff --git a/core/java/android/os/IBinder.java b/core/java/android/os/IBinder.java index 3ec0e9b..5c40c9a0 100644 --- a/core/java/android/os/IBinder.java +++ b/core/java/android/os/IBinder.java @@ -16,6 +16,9 @@ package android.os; +import java.io.FileDescriptor; +import java.io.PrintWriter; + /** * Base interface for a remotable object, the core part of a lightweight * remote procedure call mechanism designed for high performance when @@ -145,6 +148,14 @@ public interface IBinder { public IInterface queryLocalInterface(String descriptor); /** + * Print the object's state into the given stream. + * + * @param fd The raw file descriptor that the dump is being sent to. + * @param args additional arguments to the dump request. + */ + public void dump(FileDescriptor fd, String[] args) throws RemoteException; + + /** * Perform a generic operation with the object. * * @param code The action to perform. This should diff --git a/core/java/android/os/ICheckinService.aidl b/core/java/android/os/ICheckinService.aidl index 70ad28e..e56b55d 100644 --- a/core/java/android/os/ICheckinService.aidl +++ b/core/java/android/os/ICheckinService.aidl @@ -26,6 +26,15 @@ import android.os.IParentalControlCallback; * {@hide} */ interface ICheckinService { + /** Synchronously attempt a checkin with the server, return true + * on success. + * @throws IllegalStateException whenever an error occurs. The + * cause of the exception will be the real exception: + * IOException for network errors, JSONException for invalid + * server responses, etc. + */ + boolean checkin(); + /** Direct submission of crash data; returns after writing the crash. */ void reportCrashSync(in byte[] crashData); diff --git a/core/java/android/os/IMountService.aidl b/core/java/android/os/IMountService.aidl index 0397446..96d44b6 100644 --- a/core/java/android/os/IMountService.aidl +++ b/core/java/android/os/IMountService.aidl @@ -48,4 +48,31 @@ interface IMountService * Safely unmount external storage at given mount point. */ void unmountMedia(String mountPoint); + + /** + * Format external storage given a mount point. + */ + void formatMedia(String mountPoint); + + /** + * Returns true if media notification sounds are enabled. + */ + boolean getPlayNotificationSounds(); + + /** + * Sets whether or not media notification sounds are played. + */ + void setPlayNotificationSounds(boolean value); + + /** + * Returns true if USB Mass Storage is automatically started + * when a UMS host is detected. + */ + boolean getAutoStartUms(); + + /** + * Sets whether or not USB Mass Storage is automatically started + * when a UMS host is detected. + */ + void setAutoStartUms(boolean value); } diff --git a/core/java/android/os/INetStatService.aidl b/core/java/android/os/INetStatService.aidl index fb840d8..a8f3de0 100644 --- a/core/java/android/os/INetStatService.aidl +++ b/core/java/android/os/INetStatService.aidl @@ -17,14 +17,19 @@ package android.os; /** - * Retrieves packet and byte counts for the phone data interface. + * Retrieves packet and byte counts for the phone data interface, + * and for all interfaces. * Used for the data activity icon and the phone status in Settings. * * {@hide} */ interface INetStatService { - int getTxPackets(); - int getRxPackets(); - int getTxBytes(); - int getRxBytes(); + long getMobileTxPackets(); + long getMobileRxPackets(); + long getMobileTxBytes(); + long getMobileRxBytes(); + long getTotalTxPackets(); + long getTotalRxPackets(); + long getTotalTxBytes(); + long getTotalRxBytes(); } diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl index e48f152..5486920 100644 --- a/core/java/android/os/IPowerManager.aidl +++ b/core/java/android/os/IPowerManager.aidl @@ -29,4 +29,5 @@ interface IPowerManager void setStayOnSetting(int val); long getScreenOnTime(); void preventScreenOn(boolean prevent); + void setScreenBrightnessOverride(int brightness); } diff --git a/core/java/android/os/NetStat.java b/core/java/android/os/NetStat.java index 7312236..e294cdf 100644 --- a/core/java/android/os/NetStat.java +++ b/core/java/android/os/NetStat.java @@ -16,36 +16,232 @@ package android.os; +import android.util.Log; + +import java.io.File; +import java.io.RandomAccessFile; +import java.io.IOException; + /** @hide */ -public class NetStat{ +public class NetStat { + + // Logging tag. + private final static String TAG = "netstat"; + + // We pre-create all the File objects so we don't spend a lot of + // CPU at runtime converting from Java Strings to byte[] for the + // kernel calls. + private final static File[] MOBILE_TX_PACKETS = mobileFiles("tx_packets"); + private final static File[] MOBILE_RX_PACKETS = mobileFiles("rx_packets"); + private final static File[] MOBILE_TX_BYTES = mobileFiles("tx_bytes"); + private final static File[] MOBILE_RX_BYTES = mobileFiles("rx_bytes"); + private final static File SYS_CLASS_NET_DIR = new File("/sys/class/net"); /** - * Get total number of tx packets sent through ppp0 + * Get total number of tx packets sent through rmnet0 or ppp0 * - * @return number of Tx packets through ppp0 + * @return number of Tx packets through rmnet0 or ppp0 */ + public static long getMobileTxPkts() { + return getMobileStat(MOBILE_TX_PACKETS); + } - public native static int netStatGetTxPkts(); + /** + * Get total number of rx packets received through rmnet0 or ppp0 + * + * @return number of Rx packets through rmnet0 or ppp0 + */ + public static long getMobileRxPkts() { + return getMobileStat(MOBILE_RX_PACKETS); + } /** - * Get total number of rx packets received through ppp0 + * Get total number of tx bytes received through rmnet0 or ppp0 * - * @return number of Rx packets through ppp0 + * @return number of Tx bytes through rmnet0 or ppp0 */ - public native static int netStatGetRxPkts(); + public static long getMobileTxBytes() { + return getMobileStat(MOBILE_TX_BYTES); + } - /** - * Get total number of tx bytes received through ppp0 + /** + * Get total number of rx bytes received through rmnet0 or ppp0 * - * @return number of Tx bytes through ppp0 + * @return number of Rx bytes through rmnet0 or ppp0 */ - public native static int netStatGetTxBytes(); + public static long getMobileRxBytes() { + return getMobileStat(MOBILE_RX_BYTES); + } /** - * Get total number of rx bytes received through ppp0 + * Get the total number of packets sent through all network interfaces. * - * @return number of Rx bytes through ppp0 + * @return the number of packets sent through all network interfaces */ - public native static int netStatGetRxBytes(); + public static long getTotalTxPkts() { + return getTotalStat("tx_packets"); + } + + /** + * Get the total number of packets received through all network interfaces. + * + * @return the number of packets received through all network interfaces + */ + public static long getTotalRxPkts() { + return getTotalStat("rx_packets"); + } + + /** + * Get the total number of bytes sent through all network interfaces. + * + * @return the number of bytes sent through all network interfaces + */ + public static long getTotalTxBytes() { + return getTotalStat("tx_bytes"); + } + + /** + * Get the total number of bytes received through all network interfaces. + * + * @return the number of bytes received through all network interfaces + */ + public static long getTotalRxBytes() { + return getTotalStat("rx_bytes"); + } + + /** + * Gets network bytes sent for this UID. + * The statistics are across all interfaces. + * The statistics come from /proc/uid_stat. + * + * {@see android.os.Process#myUid()}. + * + * @param uid + * @return byte count + */ + public static long getUidTxBytes(int uid) { + return getNumberFromFilePath("/proc/uid_stat/" + uid + "/tcp_snd"); + } + + /** + * Gets network bytes received for this UID. + * The statistics are across all interfaces. + * The statistics come from /proc/uid_stat. + * + * {@see android.os.Process#myUid()}. + * + * @param uid + * @return byte count + */ + public static long getUidRxBytes(int uid) { + return getNumberFromFilePath("/proc/uid_stat/" + uid + "/tcp_rcv"); + } + + /** + * Returns the array of two possible File locations for a given + * statistic. + */ + private static File[] mobileFiles(String whatStat) { + // Note that we stat them at runtime to see which is + // available, rather than here, to guard against the files + // coming & going later as modules shut down (e.g. airplane + // mode) and whatnot. The runtime stat() isn't expensive compared + // to the previous charset conversion that happened before we + // were reusing File instances. + File[] files = new File[2]; + files[0] = new File("/sys/class/net/rmnet0/statistics/" + whatStat); + files[1] = new File("/sys/class/net/ppp0/statistics/" + whatStat); + return files; + } + + private static long getTotalStat(String whatStat) { + File netdir = new File("/sys/class/net"); + + File[] nets = SYS_CLASS_NET_DIR.listFiles(); + if (nets == null) { + return 0; + } + long total = 0; + StringBuffer strbuf = new StringBuffer(); + for (File net : nets) { + strbuf.append(net.getPath()).append(File.separator).append("statistics") + .append(File.separator).append(whatStat); + total += getNumberFromFilePath(strbuf.toString()); + strbuf.setLength(0); + } + return total; + } + + private static long getMobileStat(File[] files) { + for (int i = 0; i < files.length; i++) { + File file = files[i]; + if (!file.exists()) { + continue; + } + try { + RandomAccessFile raf = new RandomAccessFile(file, "r"); + return getNumberFromFile(raf, file.getAbsolutePath()); + } catch (IOException e) { + Log.w(TAG, + "Exception opening TCP statistics file " + file.getAbsolutePath(), + e); + } + } + return 0L; + } + + // File will have format <number><newline> + private static long getNumberFromFilePath(String filename) { + RandomAccessFile raf = getFile(filename); + if (raf == null) { + return 0L; + } + return getNumberFromFile(raf, filename); + } + + // Private buffer for getNumberFromFile. Safe for re-use because + // getNumberFromFile is synchronized. + private final static byte[] buf = new byte[16]; + + private static synchronized long getNumberFromFile(RandomAccessFile raf, String filename) { + try { + raf.read(buf); + raf.close(); + } catch (IOException e) { + Log.w(TAG, "Exception getting TCP bytes from " + filename, e); + return 0L; + } finally { + if (raf != null) { + try { + raf.close(); + } catch (IOException e) { + Log.w(TAG, "Exception closing " + filename, e); + } + } + } + + long num = 0L; + for (int i = 0; i < buf.length; i++) { + if (buf[i] < '0' || buf[i] > '9') { + break; + } + num *= 10; + num += buf[i] - '0'; + } + return num; + } + + private static RandomAccessFile getFile(String filename) { + File f = new File(filename); + if (!f.canRead()) { + return null; + } + try { + return new RandomAccessFile(f, "r"); + } catch (IOException e) { + Log.w(TAG, "Exception opening TCP statistics file " + filename, e); + return null; + } + } } diff --git a/core/java/android/os/ParcelFileDescriptor.java b/core/java/android/os/ParcelFileDescriptor.java index ed138cb..3fcb18e 100644 --- a/core/java/android/os/ParcelFileDescriptor.java +++ b/core/java/android/os/ParcelFileDescriptor.java @@ -76,6 +76,11 @@ public class ParcelFileDescriptor implements Parcelable { public static final int MODE_TRUNCATE = 0x04000000; /** + * For use with {@link #open}: append to end of file while writing. + */ + public static final int MODE_APPEND = 0x02000000; + + /** * Create a new ParcelFileDescriptor accessing a given file. * * @param file The file to be opened. @@ -138,6 +143,19 @@ public class ParcelFileDescriptor implements Parcelable { } /** + * Return the total size of the file representing this fd, as determined + * by stat(). Returns -1 if the fd is not a file. + */ + public native long getStatSize(); + + /** + * This is needed for implementing AssetFileDescriptor.AutoCloseOutputStream, + * and I really don't think we want it to be public. + * @hide + */ + public native long seekTo(long pos); + + /** * Close the ParcelFileDescriptor. This implementation closes the underlying * OS resources allocated to represent this stream. * diff --git a/core/java/android/os/ResultReceiver.aidl b/core/java/android/os/ResultReceiver.aidl new file mode 100644 index 0000000..28ce6d5 --- /dev/null +++ b/core/java/android/os/ResultReceiver.aidl @@ -0,0 +1,20 @@ +/* //device/java/android/android/os/ParcelFileDescriptor.aidl +** +** Copyright 2007, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +package android.os; + +parcelable ResultReceiver; diff --git a/core/java/android/os/ResultReceiver.java b/core/java/android/os/ResultReceiver.java new file mode 100644 index 0000000..711d4d9 --- /dev/null +++ b/core/java/android/os/ResultReceiver.java @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.os; + +import com.android.internal.os.IResultReceiver; + +/** + * Generic interface for receiving a callback result from someone. Use this + * by creating a subclass and implement {@link #onReceiveResult}, which you can + * then pass to others and send through IPC, and receive results they + * supply with {@link #send}. + */ +public class ResultReceiver implements Parcelable { + final boolean mLocal; + final Handler mHandler; + + IResultReceiver mReceiver; + + class MyRunnable implements Runnable { + final int mResultCode; + final Bundle mResultData; + + MyRunnable(int resultCode, Bundle resultData) { + mResultCode = resultCode; + mResultData = resultData; + } + + public void run() { + onReceiveResult(mResultCode, mResultData); + } + } + + class MyResultReceiver extends IResultReceiver.Stub { + public void send(int resultCode, Bundle resultData) { + if (mHandler != null) { + mHandler.post(new MyRunnable(resultCode, resultData)); + } else { + onReceiveResult(resultCode, resultData); + } + } + } + + /** + * Create a new ResultReceive to receive results. Your + * {@link #onReceiveResult} method will be called from the thread running + * <var>handler</var> if given, or from an arbitrary thread if null. + */ + public ResultReceiver(Handler handler) { + mLocal = true; + mHandler = handler; + } + + /** + * Deliver a result to this receiver. Will call {@link #onReceiveResult}, + * always asynchronously if the receiver has supplied a Handler in which + * to dispatch the result. + * @param resultCode Arbitrary result code to deliver, as defined by you. + * @param resultData Any additional data provided by you. + */ + public void send(int resultCode, Bundle resultData) { + if (mLocal) { + if (mHandler != null) { + mHandler.post(new MyRunnable(resultCode, resultData)); + } else { + onReceiveResult(resultCode, resultData); + } + return; + } + + if (mReceiver != null) { + try { + mReceiver.send(resultCode, resultData); + } catch (RemoteException e) { + } + } + } + + /** + * Override to receive results delivered to this object. + * + * @param resultCode Arbitrary result code delivered by the sender, as + * defined by the sender. + * @param resultData Any additional data provided by the sender. + */ + protected void onReceiveResult(int resultCode, Bundle resultData) { + } + + public int describeContents() { + return 0; + } + + public void writeToParcel(Parcel out, int flags) { + synchronized (this) { + if (mReceiver == null) { + mReceiver = new MyResultReceiver(); + } + out.writeStrongBinder(mReceiver.asBinder()); + } + } + + ResultReceiver(Parcel in) { + mLocal = false; + mHandler = null; + mReceiver = IResultReceiver.Stub.asInterface(in.readStrongBinder()); + } + + public static final Parcelable.Creator<ResultReceiver> CREATOR + = new Parcelable.Creator<ResultReceiver>() { + public ResultReceiver createFromParcel(Parcel in) { + return new ResultReceiver(in); + } + public ResultReceiver[] newArray(int size) { + return new ResultReceiver[size]; + } + }; +} |