diff options
author | Jean-Baptiste Queru <jbq@google.com> | 2009-11-12 18:45:53 -0800 |
---|---|---|
committer | Jean-Baptiste Queru <jbq@google.com> | 2009-11-13 13:53:39 -0800 |
commit | 9db3d07b9620b4269ab33f78604a36327e536ce1 (patch) | |
tree | 41e294f34b9695187af098cd42167489fb0c8fb0 /core/java/android/os | |
parent | 6c63ee4fc4acae4bbbbd2a49e0a68206221f0de0 (diff) | |
download | frameworks_base-9db3d07b9620b4269ab33f78604a36327e536ce1.zip frameworks_base-9db3d07b9620b4269ab33f78604a36327e536ce1.tar.gz frameworks_base-9db3d07b9620b4269ab33f78604a36327e536ce1.tar.bz2 |
eclair snapshot
Diffstat (limited to 'core/java/android/os')
23 files changed, 1272 insertions, 170 deletions
diff --git a/core/java/android/os/AsyncTask.java b/core/java/android/os/AsyncTask.java index abfb274..7d2c698 100644 --- a/core/java/android/os/AsyncTask.java +++ b/core/java/android/os/AsyncTask.java @@ -413,6 +413,7 @@ public abstract class AsyncTask<Params, Progress, Result> { } private void finish(Result result) { + if (isCancelled()) result = null; onPostExecute(result); mStatus = Status.FINISHED; } diff --git a/core/java/android/os/BatteryManager.java b/core/java/android/os/BatteryManager.java index 8f1a756..44b73c5 100644 --- a/core/java/android/os/BatteryManager.java +++ b/core/java/android/os/BatteryManager.java @@ -18,10 +18,73 @@ package android.os; /** * The BatteryManager class contains strings and constants used for values - * in the ACTION_BATTERY_CHANGED Intent. + * in the {@link android.content.Intent#ACTION_BATTERY_CHANGED} Intent. */ public class BatteryManager { - + /** + * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}: + * integer containing the current status constant. + */ + public static final String EXTRA_STATUS = "status"; + + /** + * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}: + * integer containing the current health constant. + */ + public static final String EXTRA_HEALTH = "health"; + + /** + * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}: + * boolean indicating whether a battery is present. + */ + public static final String EXTRA_PRESENT = "present"; + + /** + * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}: + * integer field containing the current battery level, from 0 to + * {@link #EXTRA_SCALE}. + */ + public static final String EXTRA_LEVEL = "level"; + + /** + * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}: + * integer containing the maximum battery level. + */ + public static final String EXTRA_SCALE = "scale"; + + /** + * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}: + * integer containing the resource ID of a small status bar icon + * indicating the current battery state. + */ + public static final String EXTRA_ICON_SMALL = "icon-small"; + + /** + * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}: + * integer indicating whether the device is plugged in to a power + * source; 0 means it is on battery, other constants are different + * types of power sources. + */ + public static final String EXTRA_PLUGGED = "plugged"; + + /** + * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}: + * integer containing the current battery voltage level. + */ + public static final String EXTRA_VOLTAGE = "voltage"; + + /** + * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}: + * integer containing the current battery temperature. + */ + public static final String EXTRA_TEMPERATURE = "temperature"; + + /** + * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}: + * String describing the technology of the current battery. + */ + public static final String EXTRA_TECHNOLOGY = "technology"; + // values for "status" field in the ACTION_BATTERY_CHANGED Intent public static final int BATTERY_STATUS_UNKNOWN = 1; public static final int BATTERY_STATUS_CHARGING = 2; diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index e203fd5..b706c5c 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -130,6 +130,7 @@ public abstract class BatteryStats implements Parcelable { 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_SCANNING_TIME_DATA = "sst"; 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"; @@ -314,6 +315,15 @@ public abstract class BatteryStats implements Parcelable { * @return foreground cpu time in microseconds */ public abstract long getForegroundTime(int which); + + /** + * Returns the approximate cpu time spent in microseconds, at a certain CPU speed. + * @param speedStep the index of the CPU speed. This is not the actual speed of the + * CPU. + * @param which one of STATS_TOTAL, STATS_LAST, STATS_CURRENT or STATS_UNPLUGGED + * @see BatteryStats#getCpuSpeedSteps() + */ + public abstract long getTimeAtCpuSpeedStep(int speedStep, int which); } /** @@ -431,6 +441,15 @@ public abstract class BatteryStats implements Parcelable { long batteryRealtime, int which); /** + * Returns the time in microseconds that the phone has been trying to + * acquire a signal. + * + * {@hide} + */ + public abstract long getPhoneSignalScanningTime( + long batteryRealtime, int which); + + /** * Returns the number of times the phone has entered the given signal strength. * * {@hide} @@ -573,6 +592,9 @@ public abstract class BatteryStats implements Parcelable { public abstract Map<String, ? extends Timer> getKernelWakelockStats(); + /** Returns the number of different speeds that the CPU can run at */ + public abstract int getCpuSpeedSteps(); + private final static void formatTimeRaw(StringBuilder out, long seconds) { long days = seconds / (60 * 60 * 24); if (days != 0) { @@ -811,6 +833,8 @@ public abstract class BatteryStats implements Parcelable { args[i] = getPhoneSignalStrengthTime(i, batteryRealtime, which) / 1000; } dumpLine(pw, 0 /* uid */, category, SIGNAL_STRENGTH_TIME_DATA, args); + dumpLine(pw, 0 /* uid */, category, SIGNAL_SCANNING_TIME_DATA, + getPhoneSignalScanningTime(batteryRealtime, which) / 1000); for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) { args[i] = getPhoneSignalStrengthCount(i, which); } @@ -1118,7 +1142,13 @@ public abstract class BatteryStats implements Parcelable { } if (!didOne) sb.append("No activity"); pw.println(sb.toString()); - + + sb.setLength(0); + sb.append(prefix); + sb.append(" Signal scanning time: "); + formatTimeMs(sb, getPhoneSignalScanningTime(batteryRealtime, which) / 1000); + pw.println(sb.toString()); + sb.setLength(0); sb.append(prefix); sb.append(" Radio types: "); diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java index 1775a4b..d4aaba3 100644 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -70,6 +70,7 @@ public class Build { * * @deprecated Use {@link #SDK_INT} to easily get this as an integer. */ + @Deprecated public static final String SDK = getString("ro.build.version.sdk"); /** @@ -102,16 +103,19 @@ public class Build { * 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; + /** - * Current work on "Donut" development branch. + * September 2009: Android 1.6. * * <p>Applications targeting this or a later release will get these * new changes in behavior:</p> @@ -132,6 +136,31 @@ public class Build { * </ul> */ public static final int DONUT = 4; + + /** + * November 2009: Android 2.0 + * + * <p>Applications targeting this or a later release will get these + * new changes in behavior:</p> + * <ul> + * <li> The {@link android.app.Service#onStartCommand + * Service.onStartCommand} function will return the new + * {@link android.app.Service#START_STICKY} behavior instead of the + * old compatibility {@link android.app.Service#START_STICKY_COMPATIBILITY}. + * <li> The {@link android.app.Activity} class will now execute back + * key presses on the key up instead of key down, to be able to detect + * canceled presses from virtual keys. + * <li> The {@link android.widget.TabWidget} class will use a new color scheme + * for tabs. In the new scheme, the foreground tab has a medium gray background + * the background tabs have a dark gray background. + * </ul> + */ + public static final int ECLAIR = 5; + + /** + * Current work on Eclair MR1. + */ + public static final int ECLAIR_MR1 = 6; } /** The type of build, like "user" or "eng". */ diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java index d40ea6b..b4f64b6 100644 --- a/core/java/android/os/Debug.java +++ b/core/java/android/os/Debug.java @@ -104,7 +104,7 @@ public final class Debug * This class is used to retrieved various statistics about the memory mappings for this * process. The returns info broken down by dalvik, native, and other. All results are in kB. */ - public static class MemoryInfo { + public static class MemoryInfo implements Parcelable { /** The proportional set size for dalvik. */ public int dalvikPss; /** The private dirty pages used by dalvik. */ @@ -125,6 +125,71 @@ public final class Debug public int otherPrivateDirty; /** The shared dirty pages used by everything else. */ public int otherSharedDirty; + + public MemoryInfo() { + } + + /** + * Return total PSS memory usage in kB. + */ + public int getTotalPss() { + return dalvikPss + nativePss + otherPss; + } + + /** + * Return total private dirty memory usage in kB. + */ + public int getTotalPrivateDirty() { + return dalvikPrivateDirty + nativePrivateDirty + otherPrivateDirty; + } + + /** + * Return total shared dirty memory usage in kB. + */ + public int getTotalSharedDirty() { + return dalvikSharedDirty + nativeSharedDirty + otherSharedDirty; + } + + public int describeContents() { + return 0; + } + + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(dalvikPss); + dest.writeInt(dalvikPrivateDirty); + dest.writeInt(dalvikSharedDirty); + dest.writeInt(nativePss); + dest.writeInt(nativePrivateDirty); + dest.writeInt(nativeSharedDirty); + dest.writeInt(otherPss); + dest.writeInt(otherPrivateDirty); + dest.writeInt(otherSharedDirty); + } + + public void readFromParcel(Parcel source) { + dalvikPss = source.readInt(); + dalvikPrivateDirty = source.readInt(); + dalvikSharedDirty = source.readInt(); + nativePss = source.readInt(); + nativePrivateDirty = source.readInt(); + nativeSharedDirty = source.readInt(); + otherPss = source.readInt(); + otherPrivateDirty = source.readInt(); + otherSharedDirty = source.readInt(); + } + + public static final Creator<MemoryInfo> CREATOR = new Creator<MemoryInfo>() { + public MemoryInfo createFromParcel(Parcel source) { + return new MemoryInfo(source); + } + public MemoryInfo[] newArray(int size) { + return new MemoryInfo[size]; + } + }; + + private MemoryInfo(Parcel source) { + readFromParcel(source); + } } @@ -556,6 +621,13 @@ href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Lo public static native void getMemoryInfo(MemoryInfo memoryInfo); /** + * Note: currently only works when the requested pid has the same UID + * as the caller. + * @hide + */ + public static native void getMemoryInfo(int pid, MemoryInfo memoryInfo); + + /** * Establish an object allocation limit in the current thread. Useful * for catching regressions in code that is expected to operate * without causing any allocations. @@ -662,6 +734,25 @@ href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Lo public static final native int getBinderDeathObjectCount(); /** + * Primes the register map cache. + * + * Only works for classes in the bootstrap class loader. Does not + * cause classes to be loaded if they're not already present. + * + * The classAndMethodDesc argument is a concatentation of the VM-internal + * class descriptor, method name, and method descriptor. Examples: + * Landroid/os/Looper;.loop:()V + * Landroid/app/ActivityThread;.main:([Ljava/lang/String;)V + * + * @param classAndMethodDesc the method to prepare + * + * @hide + */ + public static final boolean cacheRegisterMap(String classAndMethodDesc) { + return VMDebug.cacheRegisterMap(classAndMethodDesc); + } + + /** * API for gathering and querying instruction counts. * * Example usage: diff --git a/core/java/android/os/Exec.java b/core/java/android/os/Exec.java deleted file mode 100644 index a50d5fe..0000000 --- a/core/java/android/os/Exec.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 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; - -import java.io.FileDescriptor; - -/** - * @hide - * Tools for executing commands. Not for public consumption. - */ - -public class Exec -{ - /** - * @param cmd The command to execute - * @param arg0 The first argument to the command, may be null - * @param arg1 the second argument to the command, may be null - * @return the file descriptor of the started process. - * - */ - public static FileDescriptor createSubprocess( - String cmd, String arg0, String arg1) { - return createSubprocess(cmd, arg0, arg1, null); - } - - /** - * @param cmd The command to execute - * @param arg0 The first argument to the command, may be null - * @param arg1 the second argument to the command, may be null - * @param processId A one-element array to which the process ID of the - * started process will be written. - * @return the file descriptor of the started process. - * - */ - public static native FileDescriptor createSubprocess( - String cmd, String arg0, String arg1, int[] processId); - - public static native void setPtyWindowSize(FileDescriptor fd, - int row, int col, int xpixel, int ypixel); - /** - * Causes the calling thread to wait for the process associated with the - * receiver to finish executing. - * - * @return The exit value of the Process being waited on - * - */ - public static native int waitFor(int processId); -} - diff --git a/core/java/android/os/FileObserver.java b/core/java/android/os/FileObserver.java index d9804ea..38d252e 100644 --- a/core/java/android/os/FileObserver.java +++ b/core/java/android/os/FileObserver.java @@ -25,22 +25,35 @@ import java.util.ArrayList; import java.util.HashMap; public abstract class FileObserver { - public static final int ACCESS = 0x00000001; /* File was accessed */ - public static final int MODIFY = 0x00000002; /* File was modified */ - public static final int ATTRIB = 0x00000004; /* Metadata changed */ - public static final int CLOSE_WRITE = 0x00000008; /* Writtable file was closed */ - public static final int CLOSE_NOWRITE = 0x00000010; /* Unwrittable file closed */ - public static final int OPEN = 0x00000020; /* File was opened */ - public static final int MOVED_FROM = 0x00000040; /* File was moved from X */ - public static final int MOVED_TO = 0x00000080; /* File was moved to Y */ - public static final int CREATE = 0x00000100; /* Subfile was created */ - public static final int DELETE = 0x00000200; /* Subfile was deleted */ - public static final int DELETE_SELF = 0x00000400; /* Self was deleted */ - public static final int MOVE_SELF = 0x00000800; /* Self was moved */ + /** File was accessed */ + public static final int ACCESS = 0x00000001; + /** File was modified */ + public static final int MODIFY = 0x00000002; + /** Metadata changed */ + public static final int ATTRIB = 0x00000004; + /** Writable file was closed */ + public static final int CLOSE_WRITE = 0x00000008; + /** Unwrittable file closed */ + public static final int CLOSE_NOWRITE = 0x00000010; + /** File was opened */ + public static final int OPEN = 0x00000020; + /** File was moved from X */ + public static final int MOVED_FROM = 0x00000040; + /** File was moved to Y */ + public static final int MOVED_TO = 0x00000080; + /** Subfile was created */ + public static final int CREATE = 0x00000100; + /** Subfile was deleted */ + public static final int DELETE = 0x00000200; + /** Self was deleted */ + public static final int DELETE_SELF = 0x00000400; + /** Self was moved */ + public static final int MOVE_SELF = 0x00000800; + public static final int ALL_EVENTS = ACCESS | MODIFY | ATTRIB | CLOSE_WRITE | CLOSE_NOWRITE | OPEN | MOVED_FROM | MOVED_TO | DELETE | CREATE | DELETE_SELF | MOVE_SELF; - + private static final String LOG_TAG = "FileObserver"; private static class ObserverThread extends Thread { diff --git a/core/java/android/os/HandlerStateMachine.java b/core/java/android/os/HandlerStateMachine.java index d004a25..9e7902b 100644 --- a/core/java/android/os/HandlerStateMachine.java +++ b/core/java/android/os/HandlerStateMachine.java @@ -56,22 +56,22 @@ import android.util.LogPrinter; } class S1 extends HandlerState { - @Override public void enter(Message message) { + &#064;Override public void enter(Message message) { } - @Override public void processMessage(Message message) { + &#064;Override public void processMessage(Message message) { deferMessage(message); if (message.what == TEST_WHAT_2) { transitionTo(mS2); } } - @Override public void exit(Message message) { + &#064;Override public void exit(Message message) { } } class S2 extends HandlerState { - @Override public void processMessage(Message message) { + &#064;Override public void processMessage(Message message) { // Do some processing if (message.what == TEST_WHAT_2) { transtionTo(mS1); diff --git a/core/java/android/os/HandlerThread.java b/core/java/android/os/HandlerThread.java index 0ce86db..65301e4 100644 --- a/core/java/android/os/HandlerThread.java +++ b/core/java/android/os/HandlerThread.java @@ -64,7 +64,7 @@ public class HandlerThread extends Thread { /** * This method returns the Looper associated with this thread. If this thread not been started * or for any reason is isAlive() returns false, this method will return null. If this thread - * has been started, this method will blocked until the looper has been initialized. + * has been started, this method will block until the looper has been initialized. * @return The looper. */ public Looper getLooper() { @@ -85,6 +85,21 @@ public class HandlerThread extends Thread { } /** + * Ask the currently running looper to quit. If the thread has not + * been started or has finished (that is if {@link #getLooper} returns + * null), then false is returned. Otherwise the looper is asked to + * quit and true is returned. + */ + public boolean quit() { + Looper looper = getLooper(); + if (looper != null) { + looper.quit(); + return true; + } + return false; + } + + /** * Returns the identifier of this thread. See Process.myTid(). */ public int getThreadId() { diff --git a/core/java/android/os/IHardwareService.aidl b/core/java/android/os/IHardwareService.aidl index fb121bb..34f30a7 100755 --- a/core/java/android/os/IHardwareService.aidl +++ b/core/java/android/os/IHardwareService.aidl @@ -1,16 +1,16 @@ /** * Copyright (c) 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 + * 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 + * 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 + * 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. */ @@ -20,19 +20,16 @@ package android.os; interface IHardwareService { // Vibrator support - void vibrate(long milliseconds); + void vibrate(long milliseconds, IBinder token); void vibratePattern(in long[] pattern, int repeat, IBinder token); - void cancelVibrate(); - + void cancelVibrate(IBinder token); + // flashlight support boolean getFlashlightEnabled(); void setFlashlightEnabled(boolean on); void enableCameraFlash(int milliseconds); - - // sets the brightness of the backlights (screen, keyboard, button) 0-255 - void setBacklights(int brightness); // for the phone - void setAttentionLight(boolean on); + void setAttentionLight(boolean on, int color); } diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl index 5486920..bcf769d 100644 --- a/core/java/android/os/IPowerManager.aidl +++ b/core/java/android/os/IPowerManager.aidl @@ -26,8 +26,13 @@ interface IPowerManager void userActivity(long when, boolean noChangeLights); void userActivityWithForce(long when, boolean noChangeLights, boolean force); void setPokeLock(int pokey, IBinder lock, String tag); + int getSupportedWakeLockFlags(); void setStayOnSetting(int val); long getScreenOnTime(); void preventScreenOn(boolean prevent); void setScreenBrightnessOverride(int brightness); + boolean isScreenOn(); + + // sets the brightness of the backlights (screen, keyboard, button) 0-255 + void setBacklightBrightness(int brightness); } diff --git a/core/java/android/os/LatencyTimer.java b/core/java/android/os/LatencyTimer.java new file mode 100644 index 0000000..ed2f0f9e --- /dev/null +++ b/core/java/android/os/LatencyTimer.java @@ -0,0 +1,94 @@ +/* + * 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 android.util.Log; + +import java.util.HashMap; + +/** + * A class to help with measuring latency in your code. + * + * Suggested usage: + * 1) Instanciate a LatencyTimer as a class field. + * private [static] LatencyTimer mLt = new LatencyTimer(100, 1000); + * 2) At various points in the code call sample with a string and the time delta to some fixed time. + * The string should be unique at each point of the code you are measuring. + * mLt.sample("before processing event", System.nanoTime() - event.getEventTimeNano()); + * processEvent(event); + * mLt.sample("after processing event ", System.nanoTime() - event.getEventTimeNano()); + * + * @hide + */ +public final class LatencyTimer +{ + final String TAG = "LatencyTimer"; + final int mSampleSize; + final int mScaleFactor; + volatile HashMap<String, long[]> store = new HashMap<String, long[]>(); + + /** + * Creates a LatencyTimer object + * @param sampleSize number of samples to collect before printing out the average + * @param scaleFactor divisor used to make each sample smaller to prevent overflow when + * (sampleSize * average sample value)/scaleFactor > Long.MAX_VALUE + */ + public LatencyTimer(int sampleSize, int scaleFactor) { + if (scaleFactor == 0) { + scaleFactor = 1; + } + mScaleFactor = scaleFactor; + mSampleSize = sampleSize; + } + + /** + * Add a sample delay for averaging. + * @param tag string used for printing out the result. This should be unique at each point of + * this called. + * @param delta time difference from an unique point of reference for a particular iteration + */ + public void sample(String tag, long delta) { + long[] array = getArray(tag); + + // array[mSampleSize] holds the number of used entries + final int index = (int) array[mSampleSize]++; + array[index] = delta; + if (array[mSampleSize] == mSampleSize) { + long totalDelta = 0; + for (long d : array) { + totalDelta += d/mScaleFactor; + } + array[mSampleSize] = 0; + Log.i(TAG, tag + " average = " + totalDelta / mSampleSize); + } + } + + private long[] getArray(String tag) { + long[] data = store.get(tag); + if (data == null) { + synchronized(store) { + data = store.get(tag); + if (data == null) { + data = new long[mSampleSize + 1]; + store.put(tag, data); + data[mSampleSize] = 0; + } + } + } + return data; + } +} diff --git a/core/java/android/os/MemoryFile.java b/core/java/android/os/MemoryFile.java index c14925c..03542dd 100644 --- a/core/java/android/os/MemoryFile.java +++ b/core/java/android/os/MemoryFile.java @@ -52,7 +52,7 @@ public class MemoryFile private static native void native_write(FileDescriptor fd, int address, byte[] buffer, int srcOffset, int destOffset, int count, boolean isUnpinned) throws IOException; private static native void native_pin(FileDescriptor fd, boolean pin) throws IOException; - private static native boolean native_is_ashmem_region(FileDescriptor fd) throws IOException; + private static native int native_get_mapped_size(FileDescriptor fd) throws IOException; private FileDescriptor mFD; // ashmem file descriptor private int mAddress; // address of ashmem memory @@ -300,7 +300,20 @@ public class MemoryFile * @hide */ public static boolean isMemoryFile(FileDescriptor fd) throws IOException { - return native_is_ashmem_region(fd); + return (native_get_mapped_size(fd) >= 0); + } + + /** + * Returns the size of the memory file, rounded up to a page boundary, that + * the file descriptor refers to, or -1 if the file descriptor does not + * refer to a memory file. + * + * @throws IOException If <code>fd</code> is not a valid file descriptor. + * + * @hide + */ + public static int getMappedSize(FileDescriptor fd) throws IOException { + return native_get_mapped_size(fd); } /** diff --git a/core/java/android/os/ParcelUuid.aidl b/core/java/android/os/ParcelUuid.aidl new file mode 100644 index 0000000..f7e080a --- /dev/null +++ b/core/java/android/os/ParcelUuid.aidl @@ -0,0 +1,19 @@ +/* +** Copyright 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; + +parcelable ParcelUuid; diff --git a/core/java/android/os/ParcelUuid.java b/core/java/android/os/ParcelUuid.java new file mode 100644 index 0000000..88fcfc5 --- /dev/null +++ b/core/java/android/os/ParcelUuid.java @@ -0,0 +1,132 @@ +/* + * 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 java.util.UUID; + +/** + * This class is a Parcelable wrapper around {@link UUID} which is an + * immutable representation of a 128-bit universally unique + * identifier. + */ +public final class ParcelUuid implements Parcelable { + + private final UUID mUuid; + + /** + * Constructor creates a ParcelUuid instance from the + * given {@link UUID}. + * + * @param uuid UUID + */ + public ParcelUuid(UUID uuid) { + mUuid = uuid; + } + + /** + * Creates a new ParcelUuid from a string representation of {@link UUID}. + * + * @param uuid + * the UUID string to parse. + * @return an ParcelUuid instance. + * @throws NullPointerException + * if {@code uuid} is {@code null}. + * @throws IllegalArgumentException + * if {@code uuid} is not formatted correctly. + */ + public static ParcelUuid fromString(String uuid) { + return new ParcelUuid(UUID.fromString(uuid)); + } + + /** + * Get the {@link UUID} represented by the ParcelUuid. + * + * @return UUID contained in the ParcelUuid. + */ + public UUID getUuid() { + return mUuid; + } + + /** + * Returns a string representation of the ParcelUuid + * For example: 0000110B-0000-1000-8000-00805F9B34FB will be the return value. + * + * @return a String instance. + */ + @Override + public String toString() { + return mUuid.toString(); + } + + + @Override + public int hashCode() { + return mUuid.hashCode(); + } + + /** + * Compares this ParcelUuid to another object for equality. If {@code object} + * is not {@code null}, is a ParcelUuid instance, and all bits are equal, then + * {@code true} is returned. + * + * @param object + * the {@code Object} to compare to. + * @return {@code true} if this ParcelUuid is equal to {@code object} + * or {@code false} if not. + */ + @Override + public boolean equals(Object object) { + if (object == null) { + return false; + } + + if (this == object) { + return true; + } + + if (!(object instanceof ParcelUuid)) { + return false; + } + + ParcelUuid that = (ParcelUuid) object; + + return (this.mUuid.equals(that.mUuid)); + } + + public static final Parcelable.Creator<ParcelUuid> CREATOR = + new Parcelable.Creator<ParcelUuid>() { + public ParcelUuid createFromParcel(Parcel source) { + long mostSigBits = source.readLong(); + long leastSigBits = source.readLong(); + UUID uuid = new UUID(mostSigBits, leastSigBits); + return new ParcelUuid(uuid); + } + + public ParcelUuid[] newArray(int size) { + return new ParcelUuid[size]; + } + }; + + public int describeContents() { + return 0; + } + + public void writeToParcel(Parcel dest, int flags) { + dest.writeLong(mUuid.getMostSignificantBits()); + dest.writeLong(mUuid.getLeastSignificantBits()); + } +} diff --git a/core/java/android/os/Parcelable.java b/core/java/android/os/Parcelable.java index aee1e0b..0a4b60f 100644 --- a/core/java/android/os/Parcelable.java +++ b/core/java/android/os/Parcelable.java @@ -28,13 +28,17 @@ package android.os; * <pre> * public class MyParcelable implements Parcelable { * private int mData; - * + * + * public int describeContents() { + * return 0; + * } + * * public void writeToParcel(Parcel out, int flags) { * out.writeInt(mData); * } * - * public static final Parcelable.Creator<MyParcelable> CREATOR - * = new Parcelable.Creator<MyParcelable>() { + * public static final Parcelable.Creator<MyParcelable> CREATOR + * = new Parcelable.Creator<MyParcelable>() { * public MyParcelable createFromParcel(Parcel in) { * return new MyParcelable(in); * } @@ -42,7 +46,7 @@ package android.os; * public MyParcelable[] newArray(int size) { * return new MyParcelable[size]; * } - * } + * }; * * private MyParcelable(Parcel in) { * mData = in.readInt(); diff --git a/core/java/android/os/PerformanceCollector.java b/core/java/android/os/PerformanceCollector.java new file mode 100644 index 0000000..be1cf6d --- /dev/null +++ b/core/java/android/os/PerformanceCollector.java @@ -0,0 +1,587 @@ +/* + * 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 java.util.ArrayList; + +/** + * Collects performance data between two function calls in Bundle objects and + * outputs the results using writer of type {@link PerformanceResultsWriter}. + * <p> + * {@link #beginSnapshot(String)} and {@link #endSnapshot()} functions collect + * memory usage information and measure runtime between calls to begin and end. + * These functions logically wrap around an entire test, and should be called + * with name of test as the label, e.g. EmailPerformanceTest. + * <p> + * {@link #startTiming(String)} and {@link #stopTiming(String)} functions + * measure runtime between calls to start and stop. These functions logically + * wrap around a single test case or a small block of code, and should be called + * with the name of test case as the label, e.g. testSimpleSendMailSequence. + * <p> + * {@link #addIteration(String)} inserts intermediate measurement point which + * can be labeled with a String, e.g. Launch email app, compose, send, etc. + * <p> + * Snapshot and timing functions do not interfere with each other, and thus can + * be called in any order. The intended structure is to wrap begin/endSnapshot + * around calls to start/stopTiming, for example: + * <p> + * <code>beginSnapshot("EmailPerformanceTest"); + * startTiming("testSimpleSendSequence"); + * addIteration("Launch email app"); + * addIteration("Compose"); + * stopTiming("Send"); + * startTiming("testComplexSendSequence"); + * stopTiming(""); + * startTiming("testAddLabel"); + * stopTiming(""); + * endSnapshot();</code> + * <p> + * Structure of results output is up to implementor of + * {@link PerformanceResultsWriter }. + * + * {@hide} Pending approval for public API. + */ +public class PerformanceCollector { + + /** + * Interface for reporting performance data. + */ + public interface PerformanceResultsWriter { + + /** + * Callback invoked as first action in + * PerformanceCollector#beginSnapshot(String) for reporting the start of + * a performance snapshot. + * + * @param label description of code block between beginSnapshot and + * PerformanceCollector#endSnapshot() + * @see PerformanceCollector#beginSnapshot(String) + */ + public void writeBeginSnapshot(String label); + + /** + * Callback invoked as last action in PerformanceCollector#endSnapshot() + * for reporting performance data collected in the snapshot. + * + * @param results memory and runtime metrics stored as key/value pairs, + * in the same structure as returned by + * PerformanceCollector#endSnapshot() + * @see PerformanceCollector#endSnapshot() + */ + public void writeEndSnapshot(Bundle results); + + /** + * Callback invoked as first action in + * PerformanceCollector#startTiming(String) for reporting the start of + * a timing measurement. + * + * @param label description of code block between startTiming and + * PerformanceCollector#stopTiming(String) + * @see PerformanceCollector#startTiming(String) + */ + public void writeStartTiming(String label); + + /** + * Callback invoked as last action in + * {@link PerformanceCollector#stopTiming(String)} for reporting the + * sequence of timings measured. + * + * @param results runtime metrics of code block between calls to + * startTiming and stopTiming, in the same structure as + * returned by PerformanceCollector#stopTiming(String) + * @see PerformanceCollector#stopTiming(String) + */ + public void writeStopTiming(Bundle results); + + /** + * Callback invoked as last action in + * {@link PerformanceCollector#addMeasurement(String, long)} for + * reporting an integer type measurement. + * + * @param label short description of the metric that was measured + * @param value long value of the measurement + */ + public void writeMeasurement(String label, long value); + + /** + * Callback invoked as last action in + * {@link PerformanceCollector#addMeasurement(String, float)} for + * reporting a float type measurement. + * + * @param label short description of the metric that was measured + * @param value float value of the measurement + */ + public void writeMeasurement(String label, float value); + + /** + * Callback invoked as last action in + * {@link PerformanceCollector#addMeasurement(String, String)} for + * reporting a string field. + * + * @param label short description of the metric that was measured + * @param value string summary of the measurement + */ + public void writeMeasurement(String label, String value); + } + + /** + * In a results Bundle, this key references a List of iteration Bundles. + */ + public static final String METRIC_KEY_ITERATIONS = "iterations"; + /** + * In an iteration Bundle, this key describes the iteration. + */ + public static final String METRIC_KEY_LABEL = "label"; + /** + * In a results Bundle, this key reports the cpu time of the code block + * under measurement. + */ + public static final String METRIC_KEY_CPU_TIME = "cpu_time"; + /** + * In a results Bundle, this key reports the execution time of the code + * block under measurement. + */ + public static final String METRIC_KEY_EXECUTION_TIME = "execution_time"; + /** + * In a snapshot Bundle, this key reports the number of received + * transactions from the binder driver before collection started. + */ + public static final String METRIC_KEY_PRE_RECEIVED_TRANSACTIONS = "pre_received_transactions"; + /** + * In a snapshot Bundle, this key reports the number of transactions sent by + * the running program before collection started. + */ + public static final String METRIC_KEY_PRE_SENT_TRANSACTIONS = "pre_sent_transactions"; + /** + * In a snapshot Bundle, this key reports the number of received + * transactions from the binder driver. + */ + public static final String METRIC_KEY_RECEIVED_TRANSACTIONS = "received_transactions"; + /** + * In a snapshot Bundle, this key reports the number of transactions sent by + * the running program. + */ + public static final String METRIC_KEY_SENT_TRANSACTIONS = "sent_transactions"; + /** + * In a snapshot Bundle, this key reports the number of garbage collection + * invocations. + */ + public static final String METRIC_KEY_GC_INVOCATION_COUNT = "gc_invocation_count"; + /** + * In a snapshot Bundle, this key reports the amount of allocated memory + * used by the running program. + */ + public static final String METRIC_KEY_JAVA_ALLOCATED = "java_allocated"; + /** + * In a snapshot Bundle, this key reports the amount of free memory + * available to the running program. + */ + public static final String METRIC_KEY_JAVA_FREE = "java_free"; + /** + * In a snapshot Bundle, this key reports the number of private dirty pages + * used by dalvik. + */ + public static final String METRIC_KEY_JAVA_PRIVATE_DIRTY = "java_private_dirty"; + /** + * In a snapshot Bundle, this key reports the proportional set size for + * dalvik. + */ + public static final String METRIC_KEY_JAVA_PSS = "java_pss"; + /** + * In a snapshot Bundle, this key reports the number of shared dirty pages + * used by dalvik. + */ + public static final String METRIC_KEY_JAVA_SHARED_DIRTY = "java_shared_dirty"; + /** + * In a snapshot Bundle, this key reports the total amount of memory + * available to the running program. + */ + public static final String METRIC_KEY_JAVA_SIZE = "java_size"; + /** + * In a snapshot Bundle, this key reports the amount of allocated memory in + * the native heap. + */ + public static final String METRIC_KEY_NATIVE_ALLOCATED = "native_allocated"; + /** + * In a snapshot Bundle, this key reports the amount of free memory in the + * native heap. + */ + public static final String METRIC_KEY_NATIVE_FREE = "native_free"; + /** + * In a snapshot Bundle, this key reports the number of private dirty pages + * used by the native heap. + */ + public static final String METRIC_KEY_NATIVE_PRIVATE_DIRTY = "native_private_dirty"; + /** + * In a snapshot Bundle, this key reports the proportional set size for the + * native heap. + */ + public static final String METRIC_KEY_NATIVE_PSS = "native_pss"; + /** + * In a snapshot Bundle, this key reports the number of shared dirty pages + * used by the native heap. + */ + public static final String METRIC_KEY_NATIVE_SHARED_DIRTY = "native_shared_dirty"; + /** + * In a snapshot Bundle, this key reports the size of the native heap. + */ + public static final String METRIC_KEY_NATIVE_SIZE = "native_size"; + /** + * In a snapshot Bundle, this key reports the number of objects allocated + * globally. + */ + public static final String METRIC_KEY_GLOBAL_ALLOC_COUNT = "global_alloc_count"; + /** + * In a snapshot Bundle, this key reports the size of all objects allocated + * globally. + */ + public static final String METRIC_KEY_GLOBAL_ALLOC_SIZE = "global_alloc_size"; + /** + * In a snapshot Bundle, this key reports the number of objects freed + * globally. + */ + public static final String METRIC_KEY_GLOBAL_FREED_COUNT = "global_freed_count"; + /** + * In a snapshot Bundle, this key reports the size of all objects freed + * globally. + */ + public static final String METRIC_KEY_GLOBAL_FREED_SIZE = "global_freed_size"; + /** + * In a snapshot Bundle, this key reports the number of private dirty pages + * used by everything else. + */ + public static final String METRIC_KEY_OTHER_PRIVATE_DIRTY = "other_private_dirty"; + /** + * In a snapshot Bundle, this key reports the proportional set size for + * everything else. + */ + public static final String METRIC_KEY_OTHER_PSS = "other_pss"; + /** + * In a snapshot Bundle, this key reports the number of shared dirty pages + * used by everything else. + */ + public static final String METRIC_KEY_OTHER_SHARED_DIRTY = "other_shared_dirty"; + + private PerformanceResultsWriter mPerfWriter; + private Bundle mPerfSnapshot; + private Bundle mPerfMeasurement; + private long mSnapshotCpuTime; + private long mSnapshotExecTime; + private long mCpuTime; + private long mExecTime; + + public PerformanceCollector() { + } + + public PerformanceCollector(PerformanceResultsWriter writer) { + setPerformanceResultsWriter(writer); + } + + public void setPerformanceResultsWriter(PerformanceResultsWriter writer) { + mPerfWriter = writer; + } + + /** + * Begin collection of memory usage information. + * + * @param label description of code block between beginSnapshot and + * endSnapshot, used to label output + */ + public void beginSnapshot(String label) { + if (mPerfWriter != null) + mPerfWriter.writeBeginSnapshot(label); + startPerformanceSnapshot(); + } + + /** + * End collection of memory usage information. Returns collected data in a + * Bundle object. + * + * @return Memory and runtime metrics stored as key/value pairs. Values are + * of type long, and keys include: + * <ul> + * <li>{@link #METRIC_KEY_CPU_TIME cpu_time} + * <li>{@link #METRIC_KEY_EXECUTION_TIME execution_time} + * <li>{@link #METRIC_KEY_PRE_RECEIVED_TRANSACTIONS + * pre_received_transactions} + * <li>{@link #METRIC_KEY_PRE_SENT_TRANSACTIONS + * pre_sent_transactions} + * <li>{@link #METRIC_KEY_RECEIVED_TRANSACTIONS + * received_transactions} + * <li>{@link #METRIC_KEY_SENT_TRANSACTIONS sent_transactions} + * <li>{@link #METRIC_KEY_GC_INVOCATION_COUNT gc_invocation_count} + * <li>{@link #METRIC_KEY_JAVA_ALLOCATED java_allocated} + * <li>{@link #METRIC_KEY_JAVA_FREE java_free} + * <li>{@link #METRIC_KEY_JAVA_PRIVATE_DIRTY java_private_dirty} + * <li>{@link #METRIC_KEY_JAVA_PSS java_pss} + * <li>{@link #METRIC_KEY_JAVA_SHARED_DIRTY java_shared_dirty} + * <li>{@link #METRIC_KEY_JAVA_SIZE java_size} + * <li>{@link #METRIC_KEY_NATIVE_ALLOCATED native_allocated} + * <li>{@link #METRIC_KEY_NATIVE_FREE native_free} + * <li>{@link #METRIC_KEY_NATIVE_PRIVATE_DIRTY native_private_dirty} + * <li>{@link #METRIC_KEY_NATIVE_PSS native_pss} + * <li>{@link #METRIC_KEY_NATIVE_SHARED_DIRTY native_shared_dirty} + * <li>{@link #METRIC_KEY_NATIVE_SIZE native_size} + * <li>{@link #METRIC_KEY_GLOBAL_ALLOC_COUNT global_alloc_count} + * <li>{@link #METRIC_KEY_GLOBAL_ALLOC_SIZE global_alloc_size} + * <li>{@link #METRIC_KEY_GLOBAL_FREED_COUNT global_freed_count} + * <li>{@link #METRIC_KEY_GLOBAL_FREED_SIZE global_freed_size} + * <li>{@link #METRIC_KEY_OTHER_PRIVATE_DIRTY other_private_dirty} + * <li>{@link #METRIC_KEY_OTHER_PSS other_pss} + * <li>{@link #METRIC_KEY_OTHER_SHARED_DIRTY other_shared_dirty} + * </ul> + */ + public Bundle endSnapshot() { + endPerformanceSnapshot(); + if (mPerfWriter != null) + mPerfWriter.writeEndSnapshot(mPerfSnapshot); + return mPerfSnapshot; + } + + /** + * Start measurement of user and cpu time. + * + * @param label description of code block between startTiming and + * stopTiming, used to label output + */ + public void startTiming(String label) { + if (mPerfWriter != null) + mPerfWriter.writeStartTiming(label); + mPerfMeasurement = new Bundle(); + mPerfMeasurement.putParcelableArrayList( + METRIC_KEY_ITERATIONS, new ArrayList<Parcelable>()); + mExecTime = SystemClock.uptimeMillis(); + mCpuTime = Process.getElapsedCpuTime(); + } + + /** + * Add a measured segment, and start measuring the next segment. Returns + * collected data in a Bundle object. + * + * @param label description of code block between startTiming and + * addIteration, and between two calls to addIteration, used + * to label output + * @return Runtime metrics stored as key/value pairs. Values are of type + * long, and keys include: + * <ul> + * <li>{@link #METRIC_KEY_LABEL label} + * <li>{@link #METRIC_KEY_CPU_TIME cpu_time} + * <li>{@link #METRIC_KEY_EXECUTION_TIME execution_time} + * </ul> + */ + public Bundle addIteration(String label) { + mCpuTime = Process.getElapsedCpuTime() - mCpuTime; + mExecTime = SystemClock.uptimeMillis() - mExecTime; + + Bundle iteration = new Bundle(); + iteration.putString(METRIC_KEY_LABEL, label); + iteration.putLong(METRIC_KEY_EXECUTION_TIME, mExecTime); + iteration.putLong(METRIC_KEY_CPU_TIME, mCpuTime); + mPerfMeasurement.getParcelableArrayList(METRIC_KEY_ITERATIONS).add(iteration); + + mExecTime = SystemClock.uptimeMillis(); + mCpuTime = Process.getElapsedCpuTime(); + return iteration; + } + + /** + * Stop measurement of user and cpu time. + * + * @param label description of code block between addIteration or + * startTiming and stopTiming, used to label output + * @return Runtime metrics stored in a bundle, including all iterations + * between calls to startTiming and stopTiming. List of iterations + * is keyed by {@link #METRIC_KEY_ITERATIONS iterations}. + */ + public Bundle stopTiming(String label) { + addIteration(label); + if (mPerfWriter != null) + mPerfWriter.writeStopTiming(mPerfMeasurement); + return mPerfMeasurement; + } + + /** + * Add an integer type measurement to the collector. + * + * @param label short description of the metric that was measured + * @param value long value of the measurement + */ + public void addMeasurement(String label, long value) { + if (mPerfWriter != null) + mPerfWriter.writeMeasurement(label, value); + } + + /** + * Add a float type measurement to the collector. + * + * @param label short description of the metric that was measured + * @param value float value of the measurement + */ + public void addMeasurement(String label, float value) { + if (mPerfWriter != null) + mPerfWriter.writeMeasurement(label, value); + } + + /** + * Add a string field to the collector. + * + * @param label short description of the metric that was measured + * @param value string summary of the measurement + */ + public void addMeasurement(String label, String value) { + if (mPerfWriter != null) + mPerfWriter.writeMeasurement(label, value); + } + + /* + * Starts tracking memory usage, binder transactions, and real & cpu timing. + */ + private void startPerformanceSnapshot() { + // Create new snapshot + mPerfSnapshot = new Bundle(); + + // Add initial binder counts + Bundle binderCounts = getBinderCounts(); + for (String key : binderCounts.keySet()) { + mPerfSnapshot.putLong("pre_" + key, binderCounts.getLong(key)); + } + + // Force a GC and zero out the performance counters. Do this + // before reading initial CPU/wall-clock times so we don't include + // the cost of this setup in our final metrics. + startAllocCounting(); + + // Record CPU time up to this point, and start timing. Note: this + // must happen at the end of this method, otherwise the timing will + // include noise. + mSnapshotExecTime = SystemClock.uptimeMillis(); + mSnapshotCpuTime = Process.getElapsedCpuTime(); + } + + /* + * Stops tracking memory usage, binder transactions, and real & cpu timing. + * Stores collected data as type long into Bundle object for reporting. + */ + private void endPerformanceSnapshot() { + // Stop the timing. This must be done first before any other counting is + // stopped. + mSnapshotCpuTime = Process.getElapsedCpuTime() - mSnapshotCpuTime; + mSnapshotExecTime = SystemClock.uptimeMillis() - mSnapshotExecTime; + + stopAllocCounting(); + + long nativeMax = Debug.getNativeHeapSize() / 1024; + long nativeAllocated = Debug.getNativeHeapAllocatedSize() / 1024; + long nativeFree = Debug.getNativeHeapFreeSize() / 1024; + + Debug.MemoryInfo memInfo = new Debug.MemoryInfo(); + Debug.getMemoryInfo(memInfo); + + Runtime runtime = Runtime.getRuntime(); + + long dalvikMax = runtime.totalMemory() / 1024; + long dalvikFree = runtime.freeMemory() / 1024; + long dalvikAllocated = dalvikMax - dalvikFree; + + // Add final binder counts + Bundle binderCounts = getBinderCounts(); + for (String key : binderCounts.keySet()) { + mPerfSnapshot.putLong(key, binderCounts.getLong(key)); + } + + // Add alloc counts + Bundle allocCounts = getAllocCounts(); + for (String key : allocCounts.keySet()) { + mPerfSnapshot.putLong(key, allocCounts.getLong(key)); + } + + mPerfSnapshot.putLong(METRIC_KEY_EXECUTION_TIME, mSnapshotExecTime); + mPerfSnapshot.putLong(METRIC_KEY_CPU_TIME, mSnapshotCpuTime); + + mPerfSnapshot.putLong(METRIC_KEY_NATIVE_SIZE, nativeMax); + mPerfSnapshot.putLong(METRIC_KEY_NATIVE_ALLOCATED, nativeAllocated); + mPerfSnapshot.putLong(METRIC_KEY_NATIVE_FREE, nativeFree); + mPerfSnapshot.putLong(METRIC_KEY_NATIVE_PSS, memInfo.nativePss); + mPerfSnapshot.putLong(METRIC_KEY_NATIVE_PRIVATE_DIRTY, memInfo.nativePrivateDirty); + mPerfSnapshot.putLong(METRIC_KEY_NATIVE_SHARED_DIRTY, memInfo.nativeSharedDirty); + + mPerfSnapshot.putLong(METRIC_KEY_JAVA_SIZE, dalvikMax); + mPerfSnapshot.putLong(METRIC_KEY_JAVA_ALLOCATED, dalvikAllocated); + mPerfSnapshot.putLong(METRIC_KEY_JAVA_FREE, dalvikFree); + mPerfSnapshot.putLong(METRIC_KEY_JAVA_PSS, memInfo.dalvikPss); + mPerfSnapshot.putLong(METRIC_KEY_JAVA_PRIVATE_DIRTY, memInfo.dalvikPrivateDirty); + mPerfSnapshot.putLong(METRIC_KEY_JAVA_SHARED_DIRTY, memInfo.dalvikSharedDirty); + + mPerfSnapshot.putLong(METRIC_KEY_OTHER_PSS, memInfo.otherPss); + mPerfSnapshot.putLong(METRIC_KEY_OTHER_PRIVATE_DIRTY, memInfo.otherPrivateDirty); + mPerfSnapshot.putLong(METRIC_KEY_OTHER_SHARED_DIRTY, memInfo.otherSharedDirty); + } + + /* + * Starts allocation counting. This triggers a gc and resets the counts. + */ + private static void startAllocCounting() { + // Before we start trigger a GC and reset the debug counts. Run the + // finalizers and another GC before starting and stopping the alloc + // counts. This will free up any objects that were just sitting around + // waiting for their finalizers to be run. + Runtime.getRuntime().gc(); + Runtime.getRuntime().runFinalization(); + Runtime.getRuntime().gc(); + + Debug.resetAllCounts(); + + // start the counts + Debug.startAllocCounting(); + } + + /* + * Stops allocation counting. + */ + private static void stopAllocCounting() { + Runtime.getRuntime().gc(); + Runtime.getRuntime().runFinalization(); + Runtime.getRuntime().gc(); + Debug.stopAllocCounting(); + } + + /* + * Returns a bundle with the current results from the allocation counting. + */ + private static Bundle getAllocCounts() { + Bundle results = new Bundle(); + results.putLong(METRIC_KEY_GLOBAL_ALLOC_COUNT, Debug.getGlobalAllocCount()); + results.putLong(METRIC_KEY_GLOBAL_ALLOC_SIZE, Debug.getGlobalAllocSize()); + results.putLong(METRIC_KEY_GLOBAL_FREED_COUNT, Debug.getGlobalFreedCount()); + results.putLong(METRIC_KEY_GLOBAL_FREED_SIZE, Debug.getGlobalFreedSize()); + results.putLong(METRIC_KEY_GC_INVOCATION_COUNT, Debug.getGlobalGcInvocationCount()); + return results; + } + + /* + * Returns a bundle with the counts for various binder counts for this + * process. Currently the only two that are reported are the number of send + * and the number of received transactions. + */ + private static Bundle getBinderCounts() { + Bundle results = new Bundle(); + results.putLong(METRIC_KEY_SENT_TRANSACTIONS, Debug.getBinderSentTransactions()); + results.putLong(METRIC_KEY_RECEIVED_TRANSACTIONS, Debug.getBinderReceivedTransactions()); + return results; + } +} diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java index bfcf2fc..2efc230 100644 --- a/core/java/android/os/PowerManager.java +++ b/core/java/android/os/PowerManager.java @@ -114,12 +114,14 @@ public class PowerManager private static final int WAKE_BIT_SCREEN_DIM = 4; private static final int WAKE_BIT_SCREEN_BRIGHT = 8; private static final int WAKE_BIT_KEYBOARD_BRIGHT = 16; + private static final int WAKE_BIT_PROXIMITY_SCREEN_OFF = 32; private static final int LOCK_MASK = WAKE_BIT_CPU_STRONG | WAKE_BIT_CPU_WEAK | WAKE_BIT_SCREEN_DIM | WAKE_BIT_SCREEN_BRIGHT - | WAKE_BIT_KEYBOARD_BRIGHT; + | WAKE_BIT_KEYBOARD_BRIGHT + | WAKE_BIT_PROXIMITY_SCREEN_OFF; /** * Wake lock that ensures that the CPU is running. The screen might @@ -147,6 +149,16 @@ public class PowerManager public static final int SCREEN_DIM_WAKE_LOCK = WAKE_BIT_CPU_WEAK | WAKE_BIT_SCREEN_DIM; /** + * Wake lock that turns the screen off when the proximity sensor activates. + * Since not all devices have proximity sensors, use + * {@link #getSupportedWakeLockFlags() getSupportedWakeLockFlags()} to determine if + * this wake lock mode is supported. + * + * {@hide} + */ + public static final int PROXIMITY_SCREEN_OFF_WAKE_LOCK = WAKE_BIT_PROXIMITY_SCREEN_OFF; + + /** * Normally wake locks don't actually wake the device, they just cause * it to remain on once it's already on. Think of the video player * app as the normal behavior. Notifications that pop up and want @@ -196,6 +208,7 @@ public class PowerManager case SCREEN_DIM_WAKE_LOCK: case SCREEN_BRIGHT_WAKE_LOCK: case FULL_WAKE_LOCK: + case PROXIMITY_SCREEN_OFF_WAKE_LOCK: break; default: throw new IllegalArgumentException(); @@ -365,7 +378,68 @@ public class PowerManager } catch (RemoteException e) { } } - + + /** + * sets the brightness of the backlights (screen, keyboard, button). + * + * @param brightness value from 0 to 255 + * + * {@hide} + */ + public void setBacklightBrightness(int brightness) + { + try { + mService.setBacklightBrightness(brightness); + } catch (RemoteException e) { + } + } + + /** + * Returns the set of flags for {@link #newWakeLock(int, String) newWakeLock()} + * that are supported on the device. + * For example, to test to see if the {@link #PROXIMITY_SCREEN_OFF_WAKE_LOCK} + * is supported: + * + * {@samplecode + * PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); + * int supportedFlags = pm.getSupportedWakeLockFlags(); + * boolean proximitySupported = ((supportedFlags & PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK) + * == PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK); + * } + * + * @return the set of supported WakeLock flags. + * + * {@hide} + */ + public int getSupportedWakeLockFlags() + { + try { + return mService.getSupportedWakeLockFlags(); + } catch (RemoteException e) { + return 0; + } + } + + /** + * Returns whether the screen is currently on. The screen could be bright + * or dim. + * + * {@samplecode + * PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); + * boolean isScreenOn = pm.isScreenOn(); + * } + * + * @return whether the screen is on (bright or dim). + */ + public boolean isScreenOn() + { + try { + return mService.isScreenOn(); + } catch (RemoteException e) { + return false; + } + } + private PowerManager() { } diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java index 4805193..699ddb2 100644 --- a/core/java/android/os/Process.java +++ b/core/java/android/os/Process.java @@ -74,6 +74,12 @@ public class Process { public static final int SHELL_UID = 2000; /** + * Defines the UID/GID for the log group. + * @hide + */ + public static final int LOG_UID = 1007; + + /** * Defines the UID/GID for the WIFI supplicant process. * @hide */ @@ -739,7 +745,7 @@ public class Process { public static final native void sendSignal(int pid, int signal); /** @hide */ - public static final native int getFreeMemory(); + public static final native long getFreeMemory(); /** @hide */ public static final native void readProcLines(String path, diff --git a/core/java/android/os/RemoteCallbackList.java b/core/java/android/os/RemoteCallbackList.java index 584224f..b74af16 100644 --- a/core/java/android/os/RemoteCallbackList.java +++ b/core/java/android/os/RemoteCallbackList.java @@ -22,7 +22,7 @@ import java.util.HashMap; * Takes care of the grunt work of maintaining a list of remote interfaces, * typically for the use of performing callbacks from a * {@link android.app.Service} to its clients. In particular, this: - * + * * <ul> * <li> Keeps track of a set of registered {@link IInterface} callbacks, * taking care to identify them through their underlying unique {@link IBinder} @@ -34,13 +34,13 @@ import java.util.HashMap; * multithreaded incoming calls, and a thread-safe way to iterate over a * snapshot of the list without holding its lock. * </ul> - * + * * <p>To use this class, simply create a single instance along with your * service, and call its {@link #register} and {@link #unregister} methods * as client register and unregister with your service. To call back on to * the registered clients, use {@link #beginBroadcast}, * {@link #getBroadcastItem}, and {@link #finishBroadcast}. - * + * * <p>If a registered callback's process goes away, this class will take * care of automatically removing it from the list. If you want to do * additional work in this situation, you can create a subclass that @@ -52,7 +52,7 @@ public class RemoteCallbackList<E extends IInterface> { private Object[] mActiveBroadcast; private int mBroadcastCount = -1; private boolean mKilled = false; - + private final class Callback implements IBinder.DeathRecipient { final E mCallback; final Object mCookie; @@ -61,7 +61,7 @@ public class RemoteCallbackList<E extends IInterface> { mCallback = callback; mCookie = cookie; } - + public void binderDied() { synchronized (mCallbacks) { mCallbacks.remove(mCallback.asBinder()); @@ -69,7 +69,7 @@ public class RemoteCallbackList<E extends IInterface> { onCallbackDied(mCallback, mCookie); } } - + /** * Simple version of {@link RemoteCallbackList#register(E, Object)} * that does not take a cookie object. @@ -86,19 +86,20 @@ public class RemoteCallbackList<E extends IInterface> { * object is already in the list), then it will be left as-is. * Registrations are not counted; a single call to {@link #unregister} * will remove a callback after any number calls to register it. - * + * * @param callback The callback interface to be added to the list. Must * not be null -- passing null here will cause a NullPointerException. * 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 * previously been called or the callback's process has gone away. - * + * * @see #unregister * @see #kill * @see #onCallbackDied @@ -119,7 +120,7 @@ public class RemoteCallbackList<E extends IInterface> { } } } - + /** * Remove from the list a callback that was previously added with * {@link #register}. This uses the @@ -127,14 +128,14 @@ public class RemoteCallbackList<E extends IInterface> { * find the previous registration. * Registrations are not counted; a single unregister call will remove * a callback after any number calls to {@link #register} for it. - * + * * @param callback The callback to be removed from the list. Passing * null here will cause a NullPointerException, so you will generally want * to check for null before calling. - * + * * @return Returns true if the callback was found and unregistered. Returns * false if the given callback was not found on the list. - * + * * @see #register */ public boolean unregister(E callback) { @@ -147,13 +148,13 @@ public class RemoteCallbackList<E extends IInterface> { return false; } } - + /** * Disable this callback list. All registered callbacks are unregistered, * and the list is disabled so that future calls to {@link #register} will * fail. This should be used when a Service is stopping, to prevent clients * from registering callbacks after it is stopped. - * + * * @see #register */ public void kill() { @@ -165,7 +166,7 @@ public class RemoteCallbackList<E extends IInterface> { mKilled = true; } } - + /** * Old version of {@link #onCallbackDied(E, Object)} that * does not provide a cookie. @@ -190,7 +191,7 @@ public class RemoteCallbackList<E extends IInterface> { public void onCallbackDied(E callback, Object cookie) { onCallbackDied(callback); } - + /** * Prepare to start making calls to the currently registered callbacks. * This creates a copy of the callback list, which you can retrieve items @@ -199,12 +200,12 @@ public class RemoteCallbackList<E extends IInterface> { * same thread (usually by scheduling with {@link Handler}) or * do your own synchronization. You must call {@link #finishBroadcast} * when done. - * + * * <p>A typical loop delivering a broadcast looks like this: - * + * * <pre> * int i = callbacks.beginBroadcast(); - * while (i > 0) { + * while (i > 0) { * i--; * try { * callbacks.getBroadcastItem(i).somethingHappened(); @@ -214,11 +215,11 @@ public class RemoteCallbackList<E extends IInterface> { * } * } * callbacks.finishBroadcast();</pre> - * + * * @return Returns the number of callbacks in the broadcast, to be used * with {@link #getBroadcastItem} to determine the range of indices you * can supply. - * + * * @see #getBroadcastItem * @see #finishBroadcast */ @@ -244,26 +245,26 @@ public class RemoteCallbackList<E extends IInterface> { return i; } } - + /** * Retrieve an item in the active broadcast that was previously started * with {@link #beginBroadcast}. This can <em>only</em> be called after * the broadcast is started, and its data is no longer valid after * calling {@link #finishBroadcast}. - * + * * <p>Note that it is possible for the process of one of the returned * callbacks to go away before you call it, so you will need to catch * {@link RemoteException} when calling on to the returned object. * The callback list itself, however, will take care of unregistering * these objects once it detects that it is no longer valid, so you can * handle such an exception by simply ignoring it. - * + * * @param index Which of the registered callbacks you would like to * retrieve. Ranges from 0 to 1-{@link #beginBroadcast}. - * + * * @return Returns the callback interface that you can call. This will * always be non-null. - * + * * @see #beginBroadcast */ public E getBroadcastItem(int index) { @@ -279,12 +280,12 @@ public class RemoteCallbackList<E extends IInterface> { public Object getBroadcastCookie(int index) { return ((Callback)mActiveBroadcast[index]).mCookie; } - + /** * Clean up the state of a broadcast previously initiated by calling * {@link #beginBroadcast}. This must always be called when you are done * with a broadcast. - * + * * @see #beginBroadcast */ public void finishBroadcast() { diff --git a/core/java/android/os/SystemClock.java b/core/java/android/os/SystemClock.java index 2b57b39..2dd6749 100644 --- a/core/java/android/os/SystemClock.java +++ b/core/java/android/os/SystemClock.java @@ -30,7 +30,13 @@ package android.os; * backwards or forwards unpredictably. This clock should only be used * when correspondence with real-world dates and times is important, such * as in a calendar or alarm clock application. Interval or elapsed - * time measurements should use a different clock. + * time measurements should use a different clock. If you are using + * System.currentTimeMillis(), consider listening to the + * {@link android.content.Intent#ACTION_TIME_TICK ACTION_TIME_TICK}, + * {@link android.content.Intent#ACTION_TIME_CHANGED ACTION_TIME_CHANGED} + * and {@link android.content.Intent#ACTION_TIMEZONE_CHANGED + * ACTION_TIMEZONE_CHANGED} {@link android.content.Intent Intent} + * broadcasts to find out when the time changes. * * <li> <p> {@link #uptimeMillis} is counted in milliseconds since the * system was booted. This clock stops when the system enters deep diff --git a/core/java/android/os/SystemProperties.java b/core/java/android/os/SystemProperties.java index c3ae3c2..4a036ec 100644 --- a/core/java/android/os/SystemProperties.java +++ b/core/java/android/os/SystemProperties.java @@ -30,6 +30,9 @@ public class SystemProperties private static native String native_get(String key); private static native String native_get(String key, String def); + private static native int native_get_int(String key, int def); + private static native long native_get_long(String key, long def); + private static native boolean native_get_boolean(String key, boolean def); private static native void native_set(String key, String def); /** @@ -65,11 +68,10 @@ public class SystemProperties * @throws IllegalArgumentException if the key exceeds 32 characters */ public static int getInt(String key, int def) { - try { - return Integer.parseInt(get(key)); - } catch (NumberFormatException e) { - return def; + if (key.length() > PROP_NAME_MAX) { + throw new IllegalArgumentException("key.length > " + PROP_NAME_MAX); } + return native_get_int(key, def); } /** @@ -81,11 +83,10 @@ public class SystemProperties * @throws IllegalArgumentException if the key exceeds 32 characters */ public static long getLong(String key, long def) { - try { - return Long.parseLong(get(key)); - } catch (NumberFormatException e) { - return def; + if (key.length() > PROP_NAME_MAX) { + throw new IllegalArgumentException("key.length > " + PROP_NAME_MAX); } + return native_get_long(key, def); } /** @@ -102,27 +103,10 @@ public class SystemProperties * @throws IllegalArgumentException if the key exceeds 32 characters */ public static boolean getBoolean(String key, boolean def) { - String value = get(key); - // Deal with these quick cases first: not found, 0 and 1 - if (value.equals("")) { - return def; - } else if (value.equals("0")) { - return false; - } else if (value.equals("1")) { - return true; - // now for slower (and hopefully less common) cases - } else if (value.equalsIgnoreCase("n") || - value.equalsIgnoreCase("no") || - value.equalsIgnoreCase("false") || - value.equalsIgnoreCase("off")) { - return false; - } else if (value.equalsIgnoreCase("y") || - value.equalsIgnoreCase("yes") || - value.equalsIgnoreCase("true") || - value.equalsIgnoreCase("on")) { - return true; + if (key.length() > PROP_NAME_MAX) { + throw new IllegalArgumentException("key.length > " + PROP_NAME_MAX); } - return def; + return native_get_boolean(key, def); } /** diff --git a/core/java/android/os/Vibrator.java b/core/java/android/os/Vibrator.java index 0f75289..51dcff1 100644 --- a/core/java/android/os/Vibrator.java +++ b/core/java/android/os/Vibrator.java @@ -24,6 +24,7 @@ package android.os; public class Vibrator { IHardwareService mService; + private final Binder mToken = new Binder(); /** @hide */ public Vibrator() @@ -40,7 +41,7 @@ public class Vibrator public void vibrate(long milliseconds) { try { - mService.vibrate(milliseconds); + mService.vibrate(milliseconds, mToken); } catch (RemoteException e) { } } @@ -65,7 +66,7 @@ public class Vibrator // anyway if (repeat < pattern.length) { try { - mService.vibratePattern(pattern, repeat, new Binder()); + mService.vibratePattern(pattern, repeat, mToken); } catch (RemoteException e) { } } else { @@ -79,7 +80,7 @@ public class Vibrator public void cancel() { try { - mService.cancelVibrate(); + mService.cancelVibrate(mToken); } catch (RemoteException e) { } } |