Merge "Add JavaDoc for SyncResult http://b/2420252" into froyo
diff --git a/api/8.xml b/api/8.xml
index 8cffff1b..e757db2 100644
--- a/api/8.xml
+++ b/api/8.xml
@@ -27144,7 +27144,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="fd" type="android.os.ParcelFileDescriptor">
+<parameter name="newState" type="android.os.ParcelFileDescriptor">
 </parameter>
 </method>
 </interface>
@@ -37923,6 +37923,28 @@
  visibility="public"
 >
 </field>
+<field name="ACTION_EXTERNAL_APPLICATIONS_AVAILABLE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.intent.action.EXTERNAL_APPLICATIONS_AVAILABLE&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.intent.action.EXTERNAL_APPLICATIONS_UNAVAILABLE&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="ACTION_FACTORY_TEST"
  type="java.lang.String"
  transient="false"
@@ -38890,6 +38912,28 @@
  visibility="public"
 >
 </field>
+<field name="EXTRA_CHANGED_PACKAGE_LIST"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.intent.extra.changed_package_list&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EXTRA_CHANGED_UID_LIST"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.intent.extra.changed_uid_list&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="EXTRA_DATA_REMOVED"
  type="java.lang.String"
  transient="false"
@@ -42658,6 +42702,17 @@
  visibility="public"
 >
 </field>
+<field name="FLAG_EXTERNAL_STORAGE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="262144"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="FLAG_FACTORY_TEST"
  type="int"
  transient="false"
diff --git a/api/current.xml b/api/current.xml
index db28cba..e757db2 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -42702,6 +42702,17 @@
  visibility="public"
 >
 </field>
+<field name="FLAG_EXTERNAL_STORAGE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="262144"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="FLAG_FACTORY_TEST"
  type="int"
  transient="false"
diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c
index e8b5eaf..082e704 100644
--- a/cmds/dumpstate/dumpstate.c
+++ b/cmds/dumpstate/dumpstate.c
@@ -138,6 +138,8 @@
     dump_file("LAST PANIC CONSOLE", "/data/dontpanic/apanic_console");
     dump_file("LAST PANIC THREADS", "/data/dontpanic/apanic_threads");
 
+    for_each_pid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
+
     printf("------ BACKLIGHTS ------\n");
     printf("LCD brightness=");
     dump_file(NULL, "/sys/class/leds/lcd-backlight/brightness");
@@ -161,7 +163,6 @@
     run_command("DUMPSYS", 60, "dumpsys", NULL);
 }
 
-
 static void usage() {
     fprintf(stderr, "usage: dumpstate [-d] [-o file] [-s] [-z]\n"
             "  -d: append date to filename (requires -o)\n"
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index 6d48a85..682eafd 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -38,4 +38,10 @@
 /* dump Dalvik stack traces, return the trace file location (NULL if none) */
 const char *dump_vm_traces();
 
+/* for each process in the system, run the specified function */
+void for_each_pid(void (*func)(int, const char *), const char *header);
+
+/* Displays a blocked processes in-kernel wait channel */
+void show_wchan(int pid, const char *name);
+
 #endif /* _DUMPSTATE_H_ */
diff --git a/cmds/dumpstate/utils.c b/cmds/dumpstate/utils.c
index c21dace..c7a78cc 100644
--- a/cmds/dumpstate/utils.c
+++ b/cmds/dumpstate/utils.c
@@ -37,6 +37,64 @@
 
 #include "dumpstate.h"
 
+void for_each_pid(void (*func)(int, const char *), const char *header) {
+    DIR *d;
+    struct dirent *de;
+
+    if (!(d = opendir("/proc"))) {
+        printf("Failed to open /proc (%s)\n", strerror(errno));
+        return;
+    }
+
+    printf("\n------ %s ------\n", header);
+    while ((de = readdir(d))) {
+        int pid;
+        int fd;
+        char cmdpath[255];
+        char cmdline[255];
+
+        if (!(pid = atoi(de->d_name))) {
+            continue;
+        }
+
+        sprintf(cmdpath,"/proc/%d/cmdline", pid);
+        memset(cmdline, 0, sizeof(cmdline));
+        if ((fd = open(cmdpath, O_RDONLY)) < 0) {
+            strcpy(cmdline, "N/A");
+        } else {
+            read(fd, cmdline, sizeof(cmdline));
+            close(fd);
+        }
+        func(pid, cmdline);
+    }
+
+    closedir(d);
+}
+
+void show_wchan(int pid, const char *name) {
+    char path[255];
+    char buffer[255];
+    int fd;
+
+    memset(buffer, 0, sizeof(buffer));
+
+    sprintf(path, "/proc/%d/wchan", pid);
+    if ((fd = open(path, O_RDONLY)) < 0) {
+        printf("Failed to open '%s' (%s)\n", path, strerror(errno));
+        return;
+    }
+
+    if (read(fd, buffer, sizeof(buffer)) < 0) {
+        printf("Failed to read '%s' (%s)\n", path, strerror(errno));
+        goto out_close;
+    }
+
+    printf("%-7d %-32s %s\n", pid, name, buffer);
+
+out_close:
+    close(fd);
+    return;
+}
 
 /* prints the contents of a file */
 int dump_file(const char *title, const char* path) {
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 0a04e5b..1577f9e 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -252,20 +252,22 @@
     public static final int FLAG_RESTORE_ANY_VERSION = 1<<17;
 
     /**
+     * Value for {@link #flags}: Set to true if the application is
+     * currently installed on external/removable/unprotected storage.  Such
+     * applications may not be available if their storage is not currently
+     * mounted.  When the storage it is on is not available, it will look like
+     * the application has been uninstalled (its .apk is no longer available)
+     * but its persistent data is not removed.
+     */
+    public static final int FLAG_EXTERNAL_STORAGE = 1<<18;
+
+    /**
      * Value for {@link #flags}: Set to true if the application has been
      * installed using the forward lock option.
      *
      * {@hide}
      */
-    public static final int FLAG_FORWARD_LOCK = 1<<19;
-
-    /**
-     * Value for {@link #flags}: Set to true if the application is
-     * currently installed on the sdcard.
-     *
-     * {@hide}
-     */
-    public static final int FLAG_EXTERNAL_STORAGE = 1<<20;
+    public static final int FLAG_FORWARD_LOCK = 1<<20;
 
     /**
      * Value for {@link #flags}: Set to true if the application is
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index 6a9218a..83ef8ba 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -147,6 +147,7 @@
     private int mSaveCount;
     @SuppressWarnings("unused")
     private Canvas mCanvas;
+    private String mName;
 
     // The display metrics used to provide the pseudo canvas size for applications
     // running in compatibility mode. This is set to null for non compatibility mode.
@@ -204,6 +205,7 @@
         }
         mCanvas = new CompatibleCanvas();
         init(s,pid,name,display,w,h,format,flags);
+        mName = name;
     }
 
     /**
@@ -386,7 +388,7 @@
 
     @Override
     public String toString() {
-        return "Surface(native-token=" + mSurface + ")";
+        return "Surface(name=" + mName + ", identity=" + getIdentity() + ")";
     }
 
     private Surface(Parcel source) throws OutOfResourcesException {
@@ -437,4 +439,6 @@
             throws OutOfResourcesException;
 
     private native void init(Parcel source);
+
+    private native int getIdentity();
 }
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index ed26cbe..788374b 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -229,6 +229,15 @@
     setSurface(env, clazz, rhs);
 }
 
+static jint Surface_getIdentity(JNIEnv* env, jobject clazz)
+{
+    const sp<SurfaceControl>& control(getSurfaceControl(env, clazz));
+    if (control != 0) return (jint) control->getIdentity();
+    const sp<Surface>& surface(getSurface(env, clazz));
+    if (surface != 0) return (jint) surface->getIdentity();
+    return -1;
+}
+
 static void Surface_destroy(JNIEnv* env, jobject clazz, uintptr_t *ostack)
 {
     const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
@@ -261,14 +270,14 @@
         we can map to SkBitmap::kARGB_8888_Config, and optionally call
         bitmap.setIsOpaque(true) on the resulting SkBitmap (as an accelerator)
     */
-	switch (format) {
-	case PIXEL_FORMAT_RGBX_8888:    return SkBitmap::kARGB_8888_Config;
+    switch (format) {
+    case PIXEL_FORMAT_RGBX_8888:    return SkBitmap::kARGB_8888_Config;
     case PIXEL_FORMAT_RGBA_8888:    return SkBitmap::kARGB_8888_Config;
     case PIXEL_FORMAT_RGBA_4444:    return SkBitmap::kARGB_4444_Config;
-	case PIXEL_FORMAT_RGB_565:		return SkBitmap::kRGB_565_Config;
-	case PIXEL_FORMAT_A_8:          return SkBitmap::kA8_Config;
-	default:                        return SkBitmap::kNo_Config;
-	}
+    case PIXEL_FORMAT_RGB_565:      return SkBitmap::kRGB_565_Config;
+    case PIXEL_FORMAT_A_8:          return SkBitmap::kA8_Config;
+    default:                        return SkBitmap::kNo_Config;
+    }
 }
 
 static jobject Surface_lockCanvas(JNIEnv* env, jobject clazz, jobject dirtyRect)
@@ -347,7 +356,7 @@
         env->SetIntField(dirtyRect, ro.b, bounds.bottom);
     }
     
-	return canvas;
+    return canvas;
 }
 
 static void Surface_unlockCanvasAndPost(
@@ -631,8 +640,8 @@
 static void nativeClassInit(JNIEnv* env, jclass clazz);
 
 static JNINativeMethod gSurfaceSessionMethods[] = {
-	{"init",     "()V",  (void*)SurfaceSession_init },
-	{"destroy",  "()V",  (void*)SurfaceSession_destroy },
+    {"init",     "()V",  (void*)SurfaceSession_init },
+    {"destroy",  "()V",  (void*)SurfaceSession_destroy },
     {"kill",     "()V",  (void*)SurfaceSession_kill },
 };
 
@@ -640,43 +649,44 @@
     {"nativeClassInit",     "()V",  (void*)nativeClassInit },
     {"init",                "(Landroid/view/SurfaceSession;ILjava/lang/String;IIIII)V",  (void*)Surface_init },
     {"init",                "(Landroid/os/Parcel;)V",  (void*)Surface_initParcel },
+    {"getIdentity",         "()I",  (void*)Surface_getIdentity },
     {"destroy",             "()V",  (void*)Surface_destroy },
     {"release",             "()V",  (void*)Surface_release },
-	{"copyFrom",            "(Landroid/view/Surface;)V",  (void*)Surface_copyFrom },
-	{"isValid",             "()Z",  (void*)Surface_isValid },
-	{"lockCanvasNative",    "(Landroid/graphics/Rect;)Landroid/graphics/Canvas;",  (void*)Surface_lockCanvas },
-	{"unlockCanvasAndPost", "(Landroid/graphics/Canvas;)V", (void*)Surface_unlockCanvasAndPost },
-	{"unlockCanvas",        "(Landroid/graphics/Canvas;)V", (void*)Surface_unlockCanvas },
-	{"openTransaction",     "()V",  (void*)Surface_openTransaction },
+    {"copyFrom",            "(Landroid/view/Surface;)V",  (void*)Surface_copyFrom },
+    {"isValid",             "()Z",  (void*)Surface_isValid },
+    {"lockCanvasNative",    "(Landroid/graphics/Rect;)Landroid/graphics/Canvas;",  (void*)Surface_lockCanvas },
+    {"unlockCanvasAndPost", "(Landroid/graphics/Canvas;)V", (void*)Surface_unlockCanvasAndPost },
+    {"unlockCanvas",        "(Landroid/graphics/Canvas;)V", (void*)Surface_unlockCanvas },
+    {"openTransaction",     "()V",  (void*)Surface_openTransaction },
     {"closeTransaction",    "()V",  (void*)Surface_closeTransaction },
     {"setOrientation",      "(III)V", (void*)Surface_setOrientation },
     {"freezeDisplay",       "(I)V", (void*)Surface_freezeDisplay },
     {"unfreezeDisplay",     "(I)V", (void*)Surface_unfreezeDisplay },
     {"setLayer",            "(I)V", (void*)Surface_setLayer },
-	{"setPosition",         "(II)V",(void*)Surface_setPosition },
-	{"setSize",             "(II)V",(void*)Surface_setSize },
-	{"hide",                "()V",  (void*)Surface_hide },
-	{"show",                "()V",  (void*)Surface_show },
-	{"freeze",              "()V",  (void*)Surface_freeze },
-	{"unfreeze",            "()V",  (void*)Surface_unfreeze },
-	{"setFlags",            "(II)V",(void*)Surface_setFlags },
-	{"setTransparentRegionHint","(Landroid/graphics/Region;)V", (void*)Surface_setTransparentRegion },
-	{"setAlpha",            "(F)V", (void*)Surface_setAlpha },
-	{"setMatrix",           "(FFFF)V",  (void*)Surface_setMatrix },
-	{"setFreezeTint",       "(I)V",  (void*)Surface_setFreezeTint },
-	{"readFromParcel",      "(Landroid/os/Parcel;)V", (void*)Surface_readFromParcel },
-	{"writeToParcel",       "(Landroid/os/Parcel;I)V", (void*)Surface_writeToParcel },
+    {"setPosition",         "(II)V",(void*)Surface_setPosition },
+    {"setSize",             "(II)V",(void*)Surface_setSize },
+    {"hide",                "()V",  (void*)Surface_hide },
+    {"show",                "()V",  (void*)Surface_show },
+    {"freeze",              "()V",  (void*)Surface_freeze },
+    {"unfreeze",            "()V",  (void*)Surface_unfreeze },
+    {"setFlags",            "(II)V",(void*)Surface_setFlags },
+    {"setTransparentRegionHint","(Landroid/graphics/Region;)V", (void*)Surface_setTransparentRegion },
+    {"setAlpha",            "(F)V", (void*)Surface_setAlpha },
+    {"setMatrix",           "(FFFF)V",  (void*)Surface_setMatrix },
+    {"setFreezeTint",       "(I)V",  (void*)Surface_setFreezeTint },
+    {"readFromParcel",      "(Landroid/os/Parcel;)V", (void*)Surface_readFromParcel },
+    {"writeToParcel",       "(Landroid/os/Parcel;I)V", (void*)Surface_writeToParcel },
 };
 
 void nativeClassInit(JNIEnv* env, jclass clazz)
 {
     so.surface = env->GetFieldID(clazz, "mSurface", "I");
     so.surfaceControl = env->GetFieldID(clazz, "mSurfaceControl", "I");
-	so.saveCount = env->GetFieldID(clazz, "mSaveCount", "I");
-	so.canvas    = env->GetFieldID(clazz, "mCanvas", "Landroid/graphics/Canvas;");
+    so.saveCount = env->GetFieldID(clazz, "mSaveCount", "I");
+    so.canvas    = env->GetFieldID(clazz, "mCanvas", "Landroid/graphics/Canvas;");
 
     jclass surfaceSession = env->FindClass("android/view/SurfaceSession");
- 	sso.client = env->GetFieldID(surfaceSession, "mClient", "I");
+    sso.client = env->GetFieldID(surfaceSession, "mClient", "I");
 
     jclass canvas = env->FindClass("android/graphics/Canvas");
     no.native_canvas = env->GetFieldID(canvas, "mNativeCanvas", "I");
diff --git a/services/java/com/android/server/NotificationPlayer.java b/services/java/com/android/server/NotificationPlayer.java
index acc4c85..0b1a03b 100644
--- a/services/java/com/android/server/NotificationPlayer.java
+++ b/services/java/com/android/server/NotificationPlayer.java
@@ -69,9 +69,9 @@
      * OnCompletionListener, to be called at the end of the playback, the MediaPlayer needs to
      * be created with a looper running so its event handler is not null.
      */
-    private final class PlayerCreationThread extends Thread {
+    private final class CreationAndCompletionThread extends Thread {
         public Command mCmd;
-        public PlayerCreationThread(Command cmd) {
+        public CreationAndCompletionThread(Command cmd) {
             super();
             mCmd = cmd;
         }
@@ -121,10 +121,19 @@
             //-----------------------------------
             // This is were we deviate from the AsyncPlayer implementation and create the
             // MediaPlayer in a new thread with which we're synchronized
-            PlayerCreationThread t = new PlayerCreationThread(cmd);
-            synchronized(t) {
-                t.start();
-                t.wait();
+            synchronized(mCompletionHandlingLock) {
+                // if another sound was already playing, it doesn't matter we won't get notified
+                // of the completion, since only the completion notification of the last sound
+                // matters
+                if((mLooper != null)
+                        && (mLooper.getThread().getState() != Thread.State.TERMINATED)) {
+                    mLooper.quit();
+                }
+                mCompletionThread = new CreationAndCompletionThread(cmd);
+                synchronized(mCompletionThread) {
+                    mCompletionThread.start();
+                    mCompletionThread.wait();
+                }
             }
             //-----------------------------------
 
@@ -169,7 +178,10 @@
                         mPlayer = null;
                         mAudioManager.abandonAudioFocus(null);
                         mAudioManager = null;
-                        mLooper.quit();
+                        if((mLooper != null)
+                                && (mLooper.getThread().getState() != Thread.State.TERMINATED)) {
+                            mLooper.quit();
+                        }
                     } else {
                         Log.w(mTag, "STOP command without a player");
                     }
@@ -195,10 +207,23 @@
         if (mAudioManager != null) {
             mAudioManager.abandonAudioFocus(null);
         }
+        // if there are no more sounds to play, end the Looper to listen for media completion
+        synchronized (mCmdQueue) {
+            if (mCmdQueue.size() == 0) {
+                synchronized(mCompletionHandlingLock) {
+                    if(mLooper != null) {
+                        mLooper.quit();
+                    }
+                    mCompletionThread = null;
+                }
+            }
+        }
     }
 
     private String mTag;
     private CmdThread mThread;
+    private CreationAndCompletionThread mCompletionThread;
+    private final Object mCompletionHandlingLock = new Object();
     private MediaPlayer mPlayer;
     private PowerManager.WakeLock mWakeLock;
     private AudioManager mAudioManager;
diff --git a/services/java/com/android/server/ThrottleService.java b/services/java/com/android/server/ThrottleService.java
index a1aa555..6a5bbd2 100644
--- a/services/java/com/android/server/ThrottleService.java
+++ b/services/java/com/android/server/ThrottleService.java
@@ -732,23 +732,25 @@
             checkForSubscriberId();
             boolean startNewPeriod = true;
 
-            // if we rolled back in time, toss out
-            // if we rolled foward, advance to the next
-            if (end.before(mPeriodStart)) {
+            if (start.equals(mPeriodStart) && end.equals(mPeriodEnd)) {
+                // same endpoints - keep collecting
                 if (DBG) {
-                    Slog.d(TAG, "next period (" + start.getTimeInMillis() + "," +
-                        end.getTimeInMillis() + ") - old start was " +
-                        mPeriodStart.getTimeInMillis() + ", wiping");
+                    Slog.d(TAG, "same period (" + start.getTimeInMillis() + "," +
+                            end.getTimeInMillis() +") - ammending data");
                 }
-                synchronized (mParent) {
-                    mPeriodRxData[mCurrentPeriod] = 0;
-                    mPeriodTxData[mCurrentPeriod] = 0;
-                }
-            } else if(start.after(mPeriodEnd)) {
+                startNewPeriod = false;
+            } else {
                 if (DBG) {
-                    Slog.d(TAG, "next period (" + start.getTimeInMillis() + "," +
-                            end.getTimeInMillis() + ") - old end was " +
-                            mPeriodEnd.getTimeInMillis() + ", following");
+                    if(start.equals(mPeriodEnd) || start.after(mPeriodEnd)) {
+                        Slog.d(TAG, "next period (" + start.getTimeInMillis() + "," +
+                                end.getTimeInMillis() + ") - old end was " +
+                                mPeriodEnd.getTimeInMillis() + ", following");
+                    } else {
+                        Slog.d(TAG, "new period (" + start.getTimeInMillis() + "," +
+                                end.getTimeInMillis() + ") replacing old (" +
+                                mPeriodStart.getTimeInMillis() + "," +
+                                mPeriodEnd.getTimeInMillis() + ")");
+                    }
                 }
                 synchronized (mParent) {
                     ++mCurrentPeriod;
@@ -756,12 +758,6 @@
                     mPeriodRxData[mCurrentPeriod] = 0;
                     mPeriodTxData[mCurrentPeriod] = 0;
                 }
-            } else {
-                startNewPeriod = false;
-                if (DBG) {
-                    Slog.d(TAG, "next period (" + start.getTimeInMillis() + "," +
-                            end.getTimeInMillis() + ") - we fit - ammending to last period");
-                }
             }
             setPeriodStart(start);
             setPeriodEnd(end);