Merge "Fix issue #4554429: API REVIEW: deprecate Live Folders"
diff --git a/api/current.txt b/api/current.txt
index 084f16a..f380cf9 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -709,6 +709,7 @@
     field public static final int overScrollFooter = 16843459; // 0x10102c3
     field public static final int overScrollHeader = 16843458; // 0x10102c2
     field public static final int overScrollMode = 16843457; // 0x10102c1
+    field public static final int overridesImplicitlyEnabledSubtype = 16843696; // 0x10103b0
     field public static final int packageNames = 16843649; // 0x1010381
     field public static final int padding = 16842965; // 0x10100d5
     field public static final int paddingBottom = 16842969; // 0x10100d9
@@ -10668,7 +10669,7 @@
     method public void setAuxEffectSendLevel(float);
     method public void setDataSource(android.content.Context, android.net.Uri) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.SecurityException;
     method public void setDataSource(android.content.Context, android.net.Uri, java.util.Map<java.lang.String, java.lang.String>) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.SecurityException;
-    method public void setDataSource(java.lang.String) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
+    method public void setDataSource(java.lang.String) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.SecurityException;
     method public void setDataSource(java.io.FileDescriptor) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
     method public void setDataSource(java.io.FileDescriptor, long, long) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
     method public void setDisplay(android.view.SurfaceHolder);
@@ -18463,7 +18464,7 @@
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.textservice.SpellCheckerService";
   }
 
-  public abstract class SpellCheckerService.Session {
+  public static abstract class SpellCheckerService.Session {
     ctor public SpellCheckerService.Session();
     method public android.os.Bundle getBundle();
     method public java.lang.String getLocale();
@@ -24486,7 +24487,7 @@
     method public boolean isWatchingCursor(android.view.View);
     method public void restartInput(android.view.View);
     method public void sendAppPrivateCommand(android.view.View, java.lang.String, android.os.Bundle);
-    method public boolean setAdditionalInputMethodSubtypes(java.lang.String, android.view.inputmethod.InputMethodSubtype[]);
+    method public void setAdditionalInputMethodSubtypes(java.lang.String, android.view.inputmethod.InputMethodSubtype[]);
     method public boolean setCurrentInputMethodSubtype(android.view.inputmethod.InputMethodSubtype);
     method public void setInputMethod(android.os.IBinder, java.lang.String);
     method public void setInputMethodAndSubtype(android.os.IBinder, java.lang.String, android.view.inputmethod.InputMethodSubtype);
@@ -24531,8 +24532,7 @@
   }
 
   public final class InputMethodSubtype implements android.os.Parcelable {
-    ctor public InputMethodSubtype(int, int, java.lang.String, java.lang.String, java.lang.String);
-    ctor public InputMethodSubtype(int, int, java.lang.String, java.lang.String, java.lang.String, boolean);
+    ctor public InputMethodSubtype(int, int, java.lang.String, java.lang.String, java.lang.String, boolean, boolean);
     method public boolean containsExtraValueKey(java.lang.String);
     method public int describeContents();
     method public java.lang.CharSequence getDisplayName(android.content.Context, java.lang.String, android.content.pm.ApplicationInfo);
@@ -24543,6 +24543,7 @@
     method public java.lang.String getMode();
     method public int getNameResId();
     method public boolean isAuxiliary();
+    method public boolean overridesImplicitlyEnabledSubtype();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator CREATOR;
   }
diff --git a/cmds/stagefright/stream.cpp b/cmds/stagefright/stream.cpp
index aa3bc03..b13236a 100644
--- a/cmds/stagefright/stream.cpp
+++ b/cmds/stagefright/stream.cpp
@@ -357,9 +357,9 @@
     }
 
     sp<IMediaPlayer> player =
-        service->create(getpid(), client, source, 0);
+        service->create(getpid(), client, 0);
 
-    if (player != NULL) {
+    if (player != NULL && player->setDataSource(source) == NO_ERROR) {
         player->setVideoSurface(surface);
         player->start();
 
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index e5f3273..3918cfd 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -320,15 +320,36 @@
      * checking if a {@link #subtract(NetworkStats)} delta passes a threshold.
      */
     public long getTotalBytes() {
-        long totalBytes = 0;
+        final Entry entry = getTotal(null);
+        return entry.rxBytes + entry.txBytes;
+    }
+
+    /**
+     * Return total of all fields represented by this snapshot object.
+     */
+    public Entry getTotal(Entry recycle) {
+        final Entry entry = recycle != null ? recycle : new Entry();
+
+        entry.iface = IFACE_ALL;
+        entry.uid = UID_ALL;
+        entry.set = SET_ALL;
+        entry.tag = TAG_NONE;
+        entry.rxBytes = 0;
+        entry.rxPackets = 0;
+        entry.txBytes = 0;
+        entry.txPackets = 0;
+
         for (int i = 0; i < size; i++) {
             // skip specific tags, since already counted in TAG_NONE
             if (tag[i] != TAG_NONE) continue;
 
-            totalBytes += rxBytes[i];
-            totalBytes += txBytes[i];
+            entry.rxBytes += rxBytes[i];
+            entry.rxPackets += rxPackets[i];
+            entry.txBytes += txBytes[i];
+            entry.txPackets += txPackets[i];
+            entry.operations += operations[i];
         }
-        return totalBytes;
+        return entry;
     }
 
     /**
diff --git a/core/java/android/service/textservice/SpellCheckerService.java b/core/java/android/service/textservice/SpellCheckerService.java
index 3e2e38e..b96099e 100644
--- a/core/java/android/service/textservice/SpellCheckerService.java
+++ b/core/java/android/service/textservice/SpellCheckerService.java
@@ -66,7 +66,7 @@
     /**
      * This abstract class should be overridden by a concrete implementation of a spell checker.
      */
-    public abstract class Session {
+    public static abstract class Session {
         private InternalISpellCheckerSession mInternalSession;
 
         /**
diff --git a/core/java/android/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java
index 4ec4ff9..0119d03 100644
--- a/core/java/android/view/inputmethod/InputMethodInfo.java
+++ b/core/java/android/view/inputmethod/InputMethodInfo.java
@@ -164,7 +164,9 @@
                             a.getString(com.android.internal.R.styleable
                                     .InputMethod_Subtype_imeSubtypeExtraValue),
                             a.getBoolean(com.android.internal.R.styleable
-                                    .InputMethod_Subtype_isAuxiliary, false));
+                                    .InputMethod_Subtype_isAuxiliary, false),
+                            a.getBoolean(com.android.internal.R.styleable
+                                    .InputMethod_Subtype_overridesImplicitlyEnabledSubtype, false));
                     mSubtypes.add(subtype);
                 }
             }
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 302be57..3ead9df 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -1593,15 +1593,13 @@
      * to the current implementation.)
      * @param imiId Id of InputMethodInfo which additional input method subtypes will be added to.
      * @param subtypes subtypes will be added as additional subtypes of the current input method.
-     * @return true if the additional input method subtypes are successfully added.
      */
-    public boolean setAdditionalInputMethodSubtypes(String imiId, InputMethodSubtype[] subtypes) {
+    public void setAdditionalInputMethodSubtypes(String imiId, InputMethodSubtype[] subtypes) {
         synchronized (mH) {
             try {
-                return mService.setAdditionalInputMethodSubtypes(imiId, subtypes);
+                mService.setAdditionalInputMethodSubtypes(imiId, subtypes);
             } catch (RemoteException e) {
                 Log.w(TAG, "IME died: " + mCurId, e);
-                return false;
             }
         }
     }
diff --git a/core/java/android/view/inputmethod/InputMethodSubtype.java b/core/java/android/view/inputmethod/InputMethodSubtype.java
index 4a98336..5670432 100644
--- a/core/java/android/view/inputmethod/InputMethodSubtype.java
+++ b/core/java/android/view/inputmethod/InputMethodSubtype.java
@@ -42,6 +42,7 @@
     private static final String EXTRA_VALUE_KEY_VALUE_SEPARATOR = "=";
 
     private final boolean mIsAuxiliary;
+    private final boolean mOverridesImplicitlyEnabledSubtype;
     private final int mSubtypeHashCode;
     private final int mSubtypeIconResId;
     private final int mSubtypeNameResId;
@@ -57,10 +58,12 @@
      * @param locale The locale supported by the subtype
      * @param mode The mode supported by the subtype
      * @param extraValue The extra value of the subtype
+     * @param isAuxiliary true when this subtype is one shot subtype.
+     * @hide
      */
-    public InputMethodSubtype(
-            int nameId, int iconId, String locale, String mode, String extraValue) {
-        this(nameId, iconId, locale, mode, extraValue, false);
+    public InputMethodSubtype(int nameId, int iconId, String locale, String mode, String extraValue,
+            boolean isAuxiliary) {
+        this(nameId, iconId, locale, mode, extraValue, false, false);
     }
 
     /**
@@ -71,17 +74,21 @@
      * @param mode The mode supported by the subtype
      * @param extraValue The extra value of the subtype
      * @param isAuxiliary true when this subtype is one shot subtype.
+     * @param overridesImplicitlyEnabledSubtype true when this subtype should be selected by default
+     * if no other subtypes are selected explicitly. Note that a subtype with this parameter being
+     * true will not be shown in the subtypes list.
      */
     public InputMethodSubtype(int nameId, int iconId, String locale, String mode, String extraValue,
-            boolean isAuxiliary) {
+            boolean isAuxiliary, boolean overridesImplicitlyEnabledSubtype) {
         mSubtypeNameResId = nameId;
         mSubtypeIconResId = iconId;
         mSubtypeLocale = locale != null ? locale : "";
         mSubtypeMode = mode != null ? mode : "";
         mSubtypeExtraValue = extraValue != null ? extraValue : "";
         mIsAuxiliary = isAuxiliary;
+        mOverridesImplicitlyEnabledSubtype = overridesImplicitlyEnabledSubtype;
         mSubtypeHashCode = hashCodeInternal(mSubtypeLocale, mSubtypeMode, mSubtypeExtraValue,
-                mIsAuxiliary);
+                mIsAuxiliary, mOverridesImplicitlyEnabledSubtype);
     }
 
     InputMethodSubtype(Parcel source) {
@@ -95,8 +102,9 @@
         s = source.readString();
         mSubtypeExtraValue = s != null ? s : "";
         mIsAuxiliary = (source.readInt() == 1);
+        mOverridesImplicitlyEnabledSubtype = (source.readInt() == 1);
         mSubtypeHashCode = hashCodeInternal(mSubtypeLocale, mSubtypeMode, mSubtypeExtraValue,
-                mIsAuxiliary);
+                mIsAuxiliary, mOverridesImplicitlyEnabledSubtype);
     }
 
     /**
@@ -144,6 +152,14 @@
     }
 
     /**
+     * @return true when this subtype is selected by default if no other subtypes are selected
+     * explicitly. Note that a subtype that returns true will not be shown in the subtypes list.
+     */
+    public boolean overridesImplicitlyEnabledSubtype() {
+        return mOverridesImplicitlyEnabledSubtype;
+    }
+
+    /**
      * @param context Context will be used for getting Locale and PackageManager.
      * @param packageName The package name of the IME
      * @param appInfo The application info of the IME
@@ -242,6 +258,7 @@
         dest.writeString(mSubtypeMode);
         dest.writeString(mSubtypeExtraValue);
         dest.writeInt(mIsAuxiliary ? 1 : 0);
+        dest.writeInt(mOverridesImplicitlyEnabledSubtype ? 1 : 0);
     }
 
     public static final Parcelable.Creator<InputMethodSubtype> CREATOR
@@ -274,8 +291,9 @@
     }
 
     private static int hashCodeInternal(String locale, String mode, String extraValue,
-            boolean isAuxiliary) {
-        return Arrays.hashCode(new Object[] {locale, mode, extraValue, isAuxiliary});
+            boolean isAuxiliary, boolean overridesImplicitlyEnabledSubtype) {
+        return Arrays.hashCode(new Object[] {locale, mode, extraValue, isAuxiliary,
+                overridesImplicitlyEnabledSubtype});
     }
 
     /**
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 73a30c4..c895b84 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -538,6 +538,8 @@
 
     private native void nativeSendListBoxChoice(int choice);
 
+    private native void nativeCloseIdleConnections();
+
     /*  Tell webkit what its width and height are, for the purposes
         of layout/line-breaking. These coordinates are in document space,
         which is the same as View coords unless we have zoomed the document
@@ -1262,6 +1264,8 @@
                             if (!JniUtil.useChromiumHttpStack()) {
                                 WebViewWorker.getHandler().sendEmptyMessage(
                                         WebViewWorker.MSG_PAUSE_CACHE_TRANSACTION);
+                            } else {
+                                nativeCloseIdleConnections();
                             }
                             break;
 
diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl
index ce0299c..683aca5 100644
--- a/core/java/com/android/internal/view/IInputMethodManager.aidl
+++ b/core/java/com/android/internal/view/IInputMethodManager.aidl
@@ -68,5 +68,5 @@
     boolean setCurrentInputMethodSubtype(in InputMethodSubtype subtype);
     boolean switchToLastInputMethod(in IBinder token);
     boolean setInputMethodEnabled(String id, boolean enabled);
-    boolean setAdditionalInputMethodSubtypes(String id, in InputMethodSubtype[] subtypes);
+    oneway void setAdditionalInputMethodSubtypes(String id, in InputMethodSubtype[] subtypes);
 }
diff --git a/core/res/res/layout-sw600dp/status_bar_latest_event_ticker.xml b/core/res/res/layout-sw600dp/status_bar_latest_event_ticker.xml
index 7631781..269e086 100644
--- a/core/res/res/layout-sw600dp/status_bar_latest_event_ticker.xml
+++ b/core/res/res/layout-sw600dp/status_bar_latest_event_ticker.xml
@@ -38,8 +38,8 @@
         android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Info"
         android:layout_width="wrap_content"
         android:layout_height="match_parent"
-        android:layout_marginTop="-10dp"
+        android:layout_marginBottom="6dip"
+        android:gravity="bottom"
         android:singleLine="true"
         />
 </LinearLayout>
-
diff --git a/core/res/res/layout-sw600dp/status_bar_latest_event_ticker_large_icon.xml b/core/res/res/layout-sw600dp/status_bar_latest_event_ticker_large_icon.xml
index ff0f7d4..69eac92 100644
--- a/core/res/res/layout-sw600dp/status_bar_latest_event_ticker_large_icon.xml
+++ b/core/res/res/layout-sw600dp/status_bar_latest_event_ticker_large_icon.xml
@@ -33,8 +33,9 @@
         android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Info"
         android:layout_width="wrap_content"
         android:layout_height="match_parent"
+        android:layout_marginBottom="6dip"
+        android:gravity="bottom"
         android:singleLine="true"
-        android:layout_marginTop="-10dp"
         />
     <ImageView android:id="@+id/icon"
         android:layout_width="wrap_content"
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index b50c063..0bf5b0a 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2237,6 +2237,10 @@
              InputMethodManager#switchToLastInputMethod will ignore auxiliary subtypes when it
              chooses a target subtype. -->
         <attr name="isAuxiliary" format="boolean" />
+        <!-- Set true when this subtype should be selected by default if no other subtypes are
+             selected explicitly. Note that a subtype with this parameter being true will
+             not be shown in the subtypes list. -->
+        <attr name="overridesImplicitlyEnabledSubtype" format="boolean" />
         <!-- The extra value of the subtype. This string can be any string and will be passed to
              the IME when the framework calls the IME with the subtype.  -->
         <attr name="imeSubtypeExtraValue" format="string" />
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 6988f6b..bc2b907 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2010,4 +2010,5 @@
   <public type="attr" name="targetDescriptions" />
   <public type="attr" name="directionDescriptions" />
 
+  <public type="attr" name="overridesImplicitlyEnabledSubtype" />
 </resources>
diff --git a/include/media/IMediaPlayer.h b/include/media/IMediaPlayer.h
index d552b2e..0e2cdf7 100644
--- a/include/media/IMediaPlayer.h
+++ b/include/media/IMediaPlayer.h
@@ -20,11 +20,13 @@
 #include <utils/RefBase.h>
 #include <binder/IInterface.h>
 #include <binder/Parcel.h>
+#include <utils/KeyedVector.h>
 
 namespace android {
 
 class Parcel;
 class Surface;
+class IStreamSource;
 class ISurfaceTexture;
 
 class IMediaPlayer: public IInterface
@@ -34,6 +36,10 @@
 
     virtual void            disconnect() = 0;
 
+    virtual status_t        setDataSource(const char *url,
+                                    const KeyedVector<String8, String8>* headers) = 0;
+    virtual status_t        setDataSource(int fd, int64_t offset, int64_t length) = 0;
+    virtual status_t        setDataSource(const sp<IStreamSource>& source) = 0;
     virtual status_t        setVideoSurface(const sp<Surface>& surface) = 0;
     virtual status_t        setVideoSurfaceTexture(
                                     const sp<ISurfaceTexture>& surfaceTexture) = 0;
diff --git a/include/media/IMediaPlayerService.h b/include/media/IMediaPlayerService.h
index 7956788..93bbe13 100644
--- a/include/media/IMediaPlayerService.h
+++ b/include/media/IMediaPlayerService.h
@@ -39,17 +39,9 @@
 public:
     DECLARE_META_INTERFACE(MediaPlayerService);
 
-    virtual sp<IMediaRecorder>  createMediaRecorder(pid_t pid) = 0;
+    virtual sp<IMediaRecorder> createMediaRecorder(pid_t pid) = 0;
     virtual sp<IMediaMetadataRetriever> createMetadataRetriever(pid_t pid) = 0;
-    virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client,
-            const char* url, const KeyedVector<String8, String8> *headers = NULL,
-            int audioSessionId = 0) = 0;
-    virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client,
-            int fd, int64_t offset, int64_t length, int audioSessionId) = 0;
-
-    virtual sp<IMediaPlayer> create(
-            pid_t pid, const sp<IMediaPlayerClient> &client,
-            const sp<IStreamSource> &source, int audioSessionId) = 0;
+    virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client, int audioSessionId = 0) = 0;
 
     virtual sp<IMemory>         decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) = 0;
     virtual sp<IMemory>         decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) = 0;
diff --git a/include/media/mediaplayer.h b/include/media/mediaplayer.h
index 1a67671..e98d55c 100644
--- a/include/media/mediaplayer.h
+++ b/include/media/mediaplayer.h
@@ -21,6 +21,7 @@
 #include <media/IMediaPlayerClient.h>
 #include <media/IMediaPlayer.h>
 #include <media/IMediaDeathNotifier.h>
+#include <media/IStreamSource.h>
 
 #include <utils/KeyedVector.h>
 #include <utils/String8.h>
@@ -168,6 +169,7 @@
                     const KeyedVector<String8, String8> *headers);
 
             status_t        setDataSource(int fd, int64_t offset, int64_t length);
+            status_t        setDataSource(const sp<IStreamSource> &source);
             status_t        setVideoSurface(const sp<Surface>& surface);
             status_t        setVideoSurfaceTexture(
                                     const sp<ISurfaceTexture>& surfaceTexture);
@@ -206,7 +208,7 @@
             status_t        seekTo_l(int msec);
             status_t        prepareAsync_l();
             status_t        getDuration_l(int *msec);
-            status_t        setDataSource(const sp<IMediaPlayer>& player);
+            status_t        attachNewPlayer(const sp<IMediaPlayer>& player);
             void            disconnectNativeWindow();
             status_t        reset_l();
 
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 1ee9a1f..e25f654 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -459,6 +459,9 @@
  * android.R.styleable#AndroidManifestUsesPermission &lt;uses-permission&gt;}
  * element.
  *
+ * <p>This class requires the {@link android.Manifest.permission#INTERNET} permission
+ * when used with network-based content.
+ *
  * <a name="Callbacks"></a>
  * <h3>Callbacks</h3>
  * <p>Applications may want to register for informational and error
@@ -828,6 +831,7 @@
                 fd.close();
             }
         }
+
         Log.d(TAG, "Couldn't open file on client side, trying server side");
         setDataSource(uri.toString(), headers);
         return;
@@ -839,7 +843,8 @@
      * @param path the path of the file, or the http/rtsp URL of the stream you want to play
      * @throws IllegalStateException if it is called in an invalid state
      */
-    public native void setDataSource(String path) throws IOException, IllegalArgumentException, IllegalStateException;
+    public native void setDataSource(String path)
+            throws IOException, IllegalArgumentException, SecurityException, IllegalStateException;
 
     /**
      * Sets the data source (file-path or http/rtsp URL) to use.
@@ -850,7 +855,7 @@
      * @hide pending API council
      */
     public void setDataSource(String path, Map<String, String> headers)
-            throws IOException, IllegalArgumentException, IllegalStateException
+            throws IOException, IllegalArgumentException, SecurityException, IllegalStateException
     {
         String[] keys = null;
         String[] values = null;
@@ -871,7 +876,7 @@
 
     private native void _setDataSource(
         String path, String[] keys, String[] values)
-        throws IOException, IllegalArgumentException, IllegalStateException;
+        throws IOException, IllegalArgumentException, SecurityException, IllegalStateException;
 
     /**
      * Sets the data source (FileDescriptor) to use. It is the caller's responsibility
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index 354f2c9..5dfbe01 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -155,6 +155,8 @@
     } else {  // Throw exception!
         if ( opStatus == (status_t) INVALID_OPERATION ) {
             jniThrowException(env, "java/lang/IllegalStateException", NULL);
+        } else if ( opStatus == (status_t) PERMISSION_DENIED ) {
+            jniThrowException(env, "java/lang/SecurityException", NULL);
         } else if ( opStatus != (status_t) OK ) {
             if (strlen(message) > 230) {
                // if the message is too long, don't bother displaying the status code
diff --git a/media/libmedia/IMediaPlayer.cpp b/media/libmedia/IMediaPlayer.cpp
index 52885d2..bd89ad8 100644
--- a/media/libmedia/IMediaPlayer.cpp
+++ b/media/libmedia/IMediaPlayer.cpp
@@ -21,14 +21,20 @@
 #include <binder/Parcel.h>
 
 #include <media/IMediaPlayer.h>
+#include <media/IStreamSource.h>
+
 #include <surfaceflinger/ISurface.h>
 #include <surfaceflinger/Surface.h>
 #include <gui/ISurfaceTexture.h>
+#include <utils/String8.h>
 
 namespace android {
 
 enum {
     DISCONNECT = IBinder::FIRST_CALL_TRANSACTION,
+    SET_DATA_SOURCE_URL,
+    SET_DATA_SOURCE_FD,
+    SET_DATA_SOURCE_STREAM,
     SET_VIDEO_SURFACE,
     PREPARE_ASYNC,
     START,
@@ -68,6 +74,43 @@
         remote()->transact(DISCONNECT, data, &reply);
     }
 
+    status_t setDataSource(const char* url,
+            const KeyedVector<String8, String8>* headers)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+        data.writeCString(url);
+        if (headers == NULL) {
+            data.writeInt32(0);
+        } else {
+            // serialize the headers
+            data.writeInt32(headers->size());
+            for (size_t i = 0; i < headers->size(); ++i) {
+                data.writeString8(headers->keyAt(i));
+                data.writeString8(headers->valueAt(i));
+            }
+        }
+        remote()->transact(SET_DATA_SOURCE_URL, data, &reply);
+        return reply.readInt32();
+    }
+
+    status_t setDataSource(int fd, int64_t offset, int64_t length) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+        data.writeFileDescriptor(fd);
+        data.writeInt64(offset);
+        data.writeInt64(length);
+        remote()->transact(SET_DATA_SOURCE_FD, data, &reply);
+        return reply.readInt32();
+    }
+
+    status_t setDataSource(const sp<IStreamSource> &source) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+        data.writeStrongBinder(source->asBinder());
+        return reply.readInt32();
+    }
+
     // pass the buffered Surface to the media player service
     status_t setVideoSurface(const sp<Surface>& surface)
     {
@@ -273,6 +316,34 @@
             disconnect();
             return NO_ERROR;
         } break;
+        case SET_DATA_SOURCE_URL: {
+            CHECK_INTERFACE(IMediaPlayer, data, reply);
+            const char* url = data.readCString();
+            KeyedVector<String8, String8> headers;
+            int32_t numHeaders = data.readInt32();
+            for (int i = 0; i < numHeaders; ++i) {
+                String8 key = data.readString8();
+                String8 value = data.readString8();
+                headers.add(key, value);
+            }
+            reply->writeInt32(setDataSource(url, numHeaders > 0 ? &headers : NULL));
+            return NO_ERROR;
+        } break;
+        case SET_DATA_SOURCE_FD: {
+            CHECK_INTERFACE(IMediaPlayer, data, reply);
+            int fd = data.readFileDescriptor();
+            int64_t offset = data.readInt64();
+            int64_t length = data.readInt64();
+            reply->writeInt32(setDataSource(fd, offset, length));
+            return NO_ERROR;
+        }
+        case SET_DATA_SOURCE_STREAM: {
+            CHECK_INTERFACE(IMediaPlayer, data, reply);
+            sp<IStreamSource> source =
+                interface_cast<IStreamSource>(data.readStrongBinder());
+            reply->writeInt32(setDataSource(source));
+            return NO_ERROR;
+        }
         case SET_VIDEO_SURFACE: {
             CHECK_INTERFACE(IMediaPlayer, data, reply);
             sp<Surface> surface = Surface::readFromParcel(data);
diff --git a/media/libmedia/IMediaPlayerService.cpp b/media/libmedia/IMediaPlayerService.cpp
index 17a0362..8e4dd04 100644
--- a/media/libmedia/IMediaPlayerService.cpp
+++ b/media/libmedia/IMediaPlayerService.cpp
@@ -30,9 +30,7 @@
 namespace android {
 
 enum {
-    CREATE_URL = IBinder::FIRST_CALL_TRANSACTION,
-    CREATE_FD,
-    CREATE_STREAM,
+    CREATE = IBinder::FIRST_CALL_TRANSACTION,
     DECODE_URL,
     DECODE_FD,
     CREATE_MEDIA_RECORDER,
@@ -60,28 +58,14 @@
     }
 
     virtual sp<IMediaPlayer> create(
-            pid_t pid, const sp<IMediaPlayerClient>& client,
-            const char* url, const KeyedVector<String8, String8> *headers, int audioSessionId) {
+            pid_t pid, const sp<IMediaPlayerClient>& client, int audioSessionId) {
         Parcel data, reply;
         data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
         data.writeInt32(pid);
         data.writeStrongBinder(client->asBinder());
-        data.writeCString(url);
-
-        if (headers == NULL) {
-            data.writeInt32(0);
-        } else {
-            // serialize the headers
-            data.writeInt32(headers->size());
-            for (size_t i = 0; i < headers->size(); ++i) {
-                data.writeString8(headers->keyAt(i));
-                data.writeString8(headers->valueAt(i));
-            }
-        }
         data.writeInt32(audioSessionId);
 
-        remote()->transact(CREATE_URL, data, &reply);
-
+        remote()->transact(CREATE, data, &reply);
         return interface_cast<IMediaPlayer>(reply.readStrongBinder());
     }
 
@@ -94,38 +78,6 @@
         return interface_cast<IMediaRecorder>(reply.readStrongBinder());
     }
 
-    virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client, int fd,
-            int64_t offset, int64_t length, int audioSessionId)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
-        data.writeInt32(pid);
-        data.writeStrongBinder(client->asBinder());
-        data.writeFileDescriptor(fd);
-        data.writeInt64(offset);
-        data.writeInt64(length);
-        data.writeInt32(audioSessionId);
-
-        remote()->transact(CREATE_FD, data, &reply);
-
-        return interface_cast<IMediaPlayer>(reply.readStrongBinder());;
-    }
-
-    virtual sp<IMediaPlayer> create(
-            pid_t pid, const sp<IMediaPlayerClient> &client,
-            const sp<IStreamSource> &source, int audioSessionId) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
-        data.writeInt32(static_cast<int32_t>(pid));
-        data.writeStrongBinder(client->asBinder());
-        data.writeStrongBinder(source->asBinder());
-        data.writeInt32(static_cast<int32_t>(audioSessionId));
-
-        remote()->transact(CREATE_STREAM, data, &reply);
-
-        return interface_cast<IMediaPlayer>(reply.readStrongBinder());;
-    }
-
     virtual sp<IMemory> decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat)
     {
         Parcel data, reply;
@@ -181,62 +133,16 @@
     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
 {
     switch(code) {
-        case CREATE_URL: {
+        case CREATE: {
             CHECK_INTERFACE(IMediaPlayerService, data, reply);
             pid_t pid = data.readInt32();
             sp<IMediaPlayerClient> client =
                 interface_cast<IMediaPlayerClient>(data.readStrongBinder());
-            const char* url = data.readCString();
-
-            KeyedVector<String8, String8> headers;
-            int32_t numHeaders = data.readInt32();
-            for (int i = 0; i < numHeaders; ++i) {
-                String8 key = data.readString8();
-                String8 value = data.readString8();
-                headers.add(key, value);
-            }
             int audioSessionId = data.readInt32();
-
-            sp<IMediaPlayer> player = create(
-                    pid, client, url, numHeaders > 0 ? &headers : NULL, audioSessionId);
-
+            sp<IMediaPlayer> player = create(pid, client, audioSessionId);
             reply->writeStrongBinder(player->asBinder());
             return NO_ERROR;
         } break;
-        case CREATE_FD: {
-            CHECK_INTERFACE(IMediaPlayerService, data, reply);
-            pid_t pid = data.readInt32();
-            sp<IMediaPlayerClient> client = interface_cast<IMediaPlayerClient>(data.readStrongBinder());
-            int fd = dup(data.readFileDescriptor());
-            int64_t offset = data.readInt64();
-            int64_t length = data.readInt64();
-            int audioSessionId = data.readInt32();
-
-            sp<IMediaPlayer> player = create(pid, client, fd, offset, length, audioSessionId);
-            reply->writeStrongBinder(player->asBinder());
-            return NO_ERROR;
-        } break;
-        case CREATE_STREAM:
-        {
-            CHECK_INTERFACE(IMediaPlayerService, data, reply);
-
-            pid_t pid = static_cast<pid_t>(data.readInt32());
-
-            sp<IMediaPlayerClient> client =
-                interface_cast<IMediaPlayerClient>(data.readStrongBinder());
-
-            sp<IStreamSource> source =
-                interface_cast<IStreamSource>(data.readStrongBinder());
-
-            int audioSessionId = static_cast<int>(data.readInt32());
-
-            sp<IMediaPlayer> player =
-                create(pid, client, source, audioSessionId);
-
-            reply->writeStrongBinder(player->asBinder());
-            return OK;
-            break;
-        }
         case DECODE_URL: {
             CHECK_INTERFACE(IMediaPlayerService, data, reply);
             const char* url = data.readCString();
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index 67a66a2..0fc6a8a 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -108,7 +108,7 @@
 }
 
 
-status_t MediaPlayer::setDataSource(const sp<IMediaPlayer>& player)
+status_t MediaPlayer::attachNewPlayer(const sp<IMediaPlayer>& player)
 {
     status_t err = UNKNOWN_ERROR;
     sp<IMediaPlayer> p;
@@ -117,7 +117,7 @@
 
         if ( !( (mCurrentState & MEDIA_PLAYER_IDLE) ||
                 (mCurrentState == MEDIA_PLAYER_STATE_ERROR ) ) ) {
-            LOGE("setDataSource called in state %d", mCurrentState);
+            LOGE("attachNewPlayer called in state %d", mCurrentState);
             return INVALID_OPERATION;
         }
 
@@ -147,9 +147,11 @@
     if (url != NULL) {
         const sp<IMediaPlayerService>& service(getMediaPlayerService());
         if (service != 0) {
-            sp<IMediaPlayer> player(
-                    service->create(getpid(), this, url, headers, mAudioSessionId));
-            err = setDataSource(player);
+            sp<IMediaPlayer> player(service->create(getpid(), this, mAudioSessionId));
+            err = attachNewPlayer(player);
+            if (err == NO_ERROR) {
+                err = mPlayer->setDataSource(url, headers);
+            }
         }
     }
     return err;
@@ -161,8 +163,26 @@
     status_t err = UNKNOWN_ERROR;
     const sp<IMediaPlayerService>& service(getMediaPlayerService());
     if (service != 0) {
-        sp<IMediaPlayer> player(service->create(getpid(), this, fd, offset, length, mAudioSessionId));
-        err = setDataSource(player);
+        sp<IMediaPlayer> player(service->create(getpid(), this, mAudioSessionId));
+        err = attachNewPlayer(player);
+        if (err == NO_ERROR) {
+            err = mPlayer->setDataSource(fd, offset, length);
+        }
+    }
+    return err;
+}
+
+status_t MediaPlayer::setDataSource(const sp<IStreamSource> &source)
+{
+    LOGV("setDataSource");
+    status_t err = UNKNOWN_ERROR;
+    const sp<IMediaPlayerService>& service(getMediaPlayerService());
+    if (service != 0) {
+        sp<IMediaPlayer> player(service->create(getpid(), this, mAudioSessionId));
+        err = attachNewPlayer(player);
+        if (err == NO_ERROR) {
+            err = mPlayer->setDataSource(source);
+        }
     }
     return err;
 }
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 2051b3b..0386d4b 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -176,6 +176,16 @@
 
 namespace android {
 
+static bool checkPermission(const char* permissionString) {
+#ifndef HAVE_ANDROID_OS
+    return true;
+#endif
+    if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
+    bool ok = checkCallingPermission(String16(permissionString));
+    if (!ok) LOGE("Request requires %s", permissionString);
+    return ok;
+}
+
 // TODO: Temp hack until we can register players
 typedef struct {
     const char *extension;
@@ -245,31 +255,8 @@
     return retriever;
 }
 
-sp<IMediaPlayer> MediaPlayerService::create(
-        pid_t pid, const sp<IMediaPlayerClient>& client, const char* url,
-        const KeyedVector<String8, String8> *headers, int audioSessionId)
-{
-    int32_t connId = android_atomic_inc(&mNextConnId);
-
-    sp<Client> c = new Client(
-            this, pid, connId, client, audioSessionId,
-            IPCThreadState::self()->getCallingUid());
-
-    LOGV("Create new client(%d) from pid %d, uid %d, url=%s, connId=%d, audioSessionId=%d",
-            connId, pid, IPCThreadState::self()->getCallingUid(), url, connId, audioSessionId);
-    if (NO_ERROR != c->setDataSource(url, headers))
-    {
-        c.clear();
-        return c;
-    }
-    wp<Client> w = c;
-    Mutex::Autolock lock(mLock);
-    mClients.add(w);
-    return c;
-}
-
 sp<IMediaPlayer> MediaPlayerService::create(pid_t pid, const sp<IMediaPlayerClient>& client,
-        int fd, int64_t offset, int64_t length, int audioSessionId)
+        int audioSessionId)
 {
     int32_t connId = android_atomic_inc(&mNextConnId);
 
@@ -277,40 +264,14 @@
             this, pid, connId, client, audioSessionId,
             IPCThreadState::self()->getCallingUid());
 
-    LOGV("Create new client(%d) from pid %d, uid %d, fd=%d, offset=%lld, "
-         "length=%lld, audioSessionId=%d", connId, pid,
-         IPCThreadState::self()->getCallingUid(), fd, offset, length, audioSessionId);
-    if (NO_ERROR != c->setDataSource(fd, offset, length)) {
-        c.clear();
-    } else {
-        wp<Client> w = c;
+    LOGV("Create new client(%d) from pid %d, uid %d, ", connId, pid,
+         IPCThreadState::self()->getCallingUid());
+
+    wp<Client> w = c;
+    {
         Mutex::Autolock lock(mLock);
         mClients.add(w);
     }
-    ::close(fd);
-    return c;
-}
-
-sp<IMediaPlayer> MediaPlayerService::create(
-        pid_t pid, const sp<IMediaPlayerClient> &client,
-        const sp<IStreamSource> &source, int audioSessionId) {
-    int32_t connId = android_atomic_inc(&mNextConnId);
-
-    sp<Client> c = new Client(
-            this, pid, connId, client, audioSessionId,
-            IPCThreadState::self()->getCallingUid());
-
-    LOGV("Create new client(%d) from pid %d, audioSessionId=%d",
-         connId, pid, audioSessionId);
-
-    if (OK != c->setDataSource(source)) {
-        c.clear();
-    } else {
-        wp<Client> w = c;
-        Mutex::Autolock lock(mLock);
-        mClients.add(w);
-    }
-
     return c;
 }
 
@@ -701,6 +662,14 @@
     if (url == NULL)
         return UNKNOWN_ERROR;
 
+    if ((strncmp(url, "http://", 7) == 0) ||
+        (strncmp(url, "https://", 8) == 0) ||
+        (strncmp(url, "rtsp://", 7) == 0)) {
+        if (!checkPermission("android.permission.INTERNET")) {
+            return PERMISSION_DENIED;
+        }
+    }
+
     if (strncmp(url, "content://", 10) == 0) {
         // get a filedescriptor for the content Uri and
         // pass it to the setDataSource(fd) method
@@ -781,6 +750,7 @@
     // now set data source
     mStatus = p->setDataSource(fd, offset, length);
     if (mStatus == NO_ERROR) mPlayer = p;
+
     return mStatus;
 }
 
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index e32b92a..53e625a 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -188,16 +188,7 @@
     void    removeMediaRecorderClient(wp<MediaRecorderClient> client);
     virtual sp<IMediaMetadataRetriever> createMetadataRetriever(pid_t pid);
 
-    // House keeping for media player clients
-    virtual sp<IMediaPlayer>    create(
-            pid_t pid, const sp<IMediaPlayerClient>& client, const char* url,
-            const KeyedVector<String8, String8> *headers, int audioSessionId);
-
-    virtual sp<IMediaPlayer>    create(pid_t pid, const sp<IMediaPlayerClient>& client, int fd, int64_t offset, int64_t length, int audioSessionId);
-
-    virtual sp<IMediaPlayer>    create(
-            pid_t pid, const sp<IMediaPlayerClient> &client,
-            const sp<IStreamSource> &source, int audioSessionId);
+    virtual sp<IMediaPlayer>    create(pid_t pid, const sp<IMediaPlayerClient>& client, int audioSessionId);
 
     virtual sp<IMemory>         decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat);
     virtual sp<IMemory>         decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat);
@@ -284,13 +275,13 @@
 
         sp<MediaPlayerBase>     createPlayer(player_type playerType);
 
-                status_t        setDataSource(
+        virtual status_t        setDataSource(
                         const char *url,
                         const KeyedVector<String8, String8> *headers);
 
-                status_t        setDataSource(int fd, int64_t offset, int64_t length);
+        virtual status_t        setDataSource(int fd, int64_t offset, int64_t length);
 
-                status_t        setDataSource(const sp<IStreamSource> &source);
+        virtual status_t        setDataSource(const sp<IStreamSource> &source);
 
         static  void            notify(void* cookie, int msg,
                                        int ext1, int ext2, const Parcel *obj);
diff --git a/media/libstagefright/FileSource.cpp b/media/libstagefright/FileSource.cpp
index f2f3500..0794f57 100644
--- a/media/libstagefright/FileSource.cpp
+++ b/media/libstagefright/FileSource.cpp
@@ -110,6 +110,8 @@
 }
 
 status_t FileSource::getSize(off64_t *size) {
+    Mutex::Autolock autoLock(mLock);
+
     if (mFd < 0) {
         return NO_INIT;
     }
diff --git a/services/java/com/android/server/EventLogTags.logtags b/services/java/com/android/server/EventLogTags.logtags
index 5429c0c..f0b5958 100644
--- a/services/java/com/android/server/EventLogTags.logtags
+++ b/services/java/com/android/server/EventLogTags.logtags
@@ -137,3 +137,10 @@
 # [ 8- 3] Detailed state ordinal (as defined by NetworkInfo.DetailedState)
 # [ 2- 0] Network type (as defined by ConnectivityManager)
 50020 connectivity_state_changed (custom|1|5)
+
+
+# ---------------------------
+# NetworkStatsService.java
+# ---------------------------
+51100 netstats_mobile_sample (iface_rx|2|2),(iface_tx|2|2),(uid_rx|2|2),(uid_tx|2|2)
+51101 netstats_wifi_sample (iface_rx|2|2),(iface_tx|2|2),(uid_rx|2|2),(uid_tx|2|2)
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index bb831f5..0e1a1e3 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -655,7 +655,7 @@
         List<InputMethodSubtype> enabledSubtypes =
                 mSettings.getEnabledInputMethodSubtypeListLocked(imi);
         if (allowsImplicitlySelectedSubtypes && enabledSubtypes.isEmpty()) {
-            enabledSubtypes = getApplicableSubtypesLocked(mRes, getSubtypes(imi));
+            enabledSubtypes = getImplicitlyApplicableSubtypesLocked(mRes, imi);
         }
         return InputMethodSubtype.sort(mContext, 0, imi, enabledSubtypes);
     }
@@ -1668,13 +1668,13 @@
     }
 
     @Override
-    public boolean setAdditionalInputMethodSubtypes(String imiId, InputMethodSubtype[] subtypes) {
+    public void setAdditionalInputMethodSubtypes(String imiId, InputMethodSubtype[] subtypes) {
         // By this IPC call, only a process which shares the same uid with the IME can add
         // additional input method subtypes to the IME.
-        if (TextUtils.isEmpty(imiId) || subtypes == null || subtypes.length == 0) return false;
+        if (TextUtils.isEmpty(imiId) || subtypes == null || subtypes.length == 0) return;
         synchronized (mMethodMap) {
             final InputMethodInfo imi = mMethodMap.get(imiId);
-            if (imi == null) return false;
+            if (imi == null) return;
             final PackageManager pm = mContext.getPackageManager();
             final String[] packageInfos = pm.getPackagesForUid(Binder.getCallingUid());
             if (packageInfos != null) {
@@ -1688,12 +1688,12 @@
                         } finally {
                             Binder.restoreCallingIdentity(ident);
                         }
-                        return true;
+                        return;
                     }
                 }
             }
         }
-        return false;
+        return;
     }
 
     private void setInputMethodWithSubtypeId(IBinder token, String id, int subtypeId) {
@@ -1903,6 +1903,20 @@
         return subtypes;
     }
 
+
+    private static ArrayList<InputMethodSubtype> getOverridingImplicitlyEnabledSubtypes(
+            InputMethodInfo imi, String mode) {
+        ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
+        final int subtypeCount = imi.getSubtypeCount();
+        for (int i = 0; i < subtypeCount; ++i) {
+            final InputMethodSubtype subtype = imi.getSubtypeAt(i);
+            if (subtype.overridesImplicitlyEnabledSubtype() && subtype.getMode().equals(mode)) {
+                subtypes.add(subtype);
+            }
+        }
+        return subtypes;
+    }
+
     private boolean chooseNewDefaultIMELocked() {
         List<InputMethodInfo> enabled = mSettings.getEnabledInputMethodListLocked();
         if (enabled != null && enabled.size() > 0) {
@@ -2357,8 +2371,9 @@
         return NOT_A_SUBTYPE_ID;
     }
 
-    private static ArrayList<InputMethodSubtype> getApplicableSubtypesLocked(
-            Resources res, List<InputMethodSubtype> subtypes) {
+    private static ArrayList<InputMethodSubtype> getImplicitlyApplicableSubtypesLocked(
+            Resources res, InputMethodInfo imi) {
+        final List<InputMethodSubtype> subtypes = getSubtypes(imi);
         final String systemLocale = res.getConfiguration().locale.toString();
         if (TextUtils.isEmpty(systemLocale)) return new ArrayList<InputMethodSubtype>();
         HashMap<String, InputMethodSubtype> applicableModeAndSubtypesMap =
@@ -2366,6 +2381,19 @@
         final int N = subtypes.size();
         boolean containsKeyboardSubtype = false;
         for (int i = 0; i < N; ++i) {
+            // scan overriding implicitly enabled subtypes.
+            InputMethodSubtype subtype = subtypes.get(i);
+            if (subtype.overridesImplicitlyEnabledSubtype()) {
+                final String mode = subtype.getMode();
+                if (!applicableModeAndSubtypesMap.containsKey(mode)) {
+                    applicableModeAndSubtypesMap.put(mode, subtype);
+                }
+            }
+        }
+        if (applicableModeAndSubtypesMap.size() > 0) {
+            return new ArrayList<InputMethodSubtype>(applicableModeAndSubtypesMap.values());
+        }
+        for (int i = 0; i < N; ++i) {
             InputMethodSubtype subtype = subtypes.get(i);
             final String locale = subtype.getLocale();
             final String mode = subtype.getMode();
@@ -2489,16 +2517,21 @@
                 subtype = findLastResortApplicableSubtypeLocked(
                         mRes, enabledSubtypes, mode, null, true);
             }
+            final ArrayList<InputMethodSubtype> overridingImplicitlyEnabledSubtypes =
+                    getOverridingImplicitlyEnabledSubtypes(imi, mode);
+            final ArrayList<InputMethodSubtype> subtypesForSearch =
+                    overridingImplicitlyEnabledSubtypes.isEmpty()
+                            ? getSubtypes(imi) : overridingImplicitlyEnabledSubtypes;
             // 4. Search by the current subtype's locale from all subtypes.
             if (subtype == null && mCurrentSubtype != null) {
                 subtype = findLastResortApplicableSubtypeLocked(
-                        mRes, getSubtypes(imi), mode, mCurrentSubtype.getLocale(), false);
+                        mRes, subtypesForSearch, mode, mCurrentSubtype.getLocale(), false);
             }
             // 5. Search by the system locale from all subtypes.
             // 6. Search the first enabled subtype matched with mode from all subtypes.
             if (subtype == null) {
                 subtype = findLastResortApplicableSubtypeLocked(
-                        mRes, getSubtypes(imi), mode, null, true);
+                        mRes, subtypesForSearch, mode, null, true);
             }
             if (subtype != null) {
                 if (imiId.equals(mCurMethodId)) {
@@ -2945,12 +2978,12 @@
                     if (explicitlyEnabledSubtypes.size() == 0) {
                         // If there are no explicitly enabled subtypes, applicable subtypes are
                         // enabled implicitly.
-                        InputMethodInfo ime = mMethodMap.get(imeId);
+                        InputMethodInfo imi = mMethodMap.get(imeId);
                         // If IME is enabled and no subtypes are enabled, applicable subtypes
                         // are enabled implicitly, so needs to treat them to be enabled.
-                        if (ime != null && ime.getSubtypeCount() > 0) {
+                        if (imi != null && imi.getSubtypeCount() > 0) {
                             List<InputMethodSubtype> implicitlySelectedSubtypes =
-                                    getApplicableSubtypesLocked(mRes, getSubtypes(ime));
+                                    getImplicitlyApplicableSubtypesLocked(mRes, imi);
                             if (implicitlySelectedSubtypes != null) {
                                 final int N = implicitlySelectedSubtypes.size();
                                 for (int i = 0; i < N; ++i) {
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index 85d8cece..1497511 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -1033,6 +1033,38 @@
         final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 6);
         final NetworkStats.Entry entry = new NetworkStats.Entry();
 
+        final HashSet<String> knownIfaces = Sets.newHashSet();
+        final HashSet<String> activeIfaces = Sets.newHashSet();
+
+        // collect any historical stats and active state
+        // TODO: migrate to reading from single file
+        if (mBandwidthControlEnabled) {
+            for (String iface : fileListWithoutNull(mStatsXtIface)) {
+                final File ifacePath = new File(mStatsXtIface, iface);
+
+                final long active = readSingleLongFromFile(new File(ifacePath, "active"));
+                if (active == 1) {
+                    knownIfaces.add(iface);
+                    activeIfaces.add(iface);
+                } else if (active == 0) {
+                    knownIfaces.add(iface);
+                } else {
+                    continue;
+                }
+
+                entry.iface = iface;
+                entry.uid = UID_ALL;
+                entry.set = SET_DEFAULT;
+                entry.tag = TAG_NONE;
+                entry.rxBytes = readSingleLongFromFile(new File(ifacePath, "rx_bytes"));
+                entry.rxPackets = readSingleLongFromFile(new File(ifacePath, "rx_packets"));
+                entry.txBytes = readSingleLongFromFile(new File(ifacePath, "tx_bytes"));
+                entry.txPackets = readSingleLongFromFile(new File(ifacePath, "tx_packets"));
+
+                stats.addValues(entry);
+            }
+        }
+
         final ArrayList<String> values = Lists.newArrayList();
 
         BufferedReader reader = null;
@@ -1058,7 +1090,13 @@
                     entry.txBytes = Long.parseLong(values.get(9));
                     entry.txPackets = Long.parseLong(values.get(10));
 
-                    stats.addValues(entry);
+                    if (activeIfaces.contains(entry.iface)) {
+                        // combine stats when iface is active
+                        stats.combineValues(entry);
+                    } else if (!knownIfaces.contains(entry.iface)) {
+                        // add stats when iface is unknown
+                        stats.addValues(entry);
+                    }
                 } catch (NumberFormatException e) {
                     Slog.w(TAG, "problem parsing stats row '" + line + "': " + e);
                 }
@@ -1073,24 +1111,6 @@
             IoUtils.closeQuietly(reader);
         }
 
-        // splice in historical stats not reflected in mStatsIface
-        if (mBandwidthControlEnabled) {
-            for (String iface : fileListWithoutNull(mStatsXtIface)) {
-                final File ifacePath = new File(mStatsXtIface, iface);
-
-                entry.iface = iface;
-                entry.uid = UID_ALL;
-                entry.set = SET_DEFAULT;
-                entry.tag = TAG_NONE;
-                entry.rxBytes = readSingleLongFromFile(new File(ifacePath, "rx_bytes"));
-                entry.rxPackets = readSingleLongFromFile(new File(ifacePath, "rx_packets"));
-                entry.txBytes = readSingleLongFromFile(new File(ifacePath, "tx_bytes"));
-                entry.txPackets = readSingleLongFromFile(new File(ifacePath, "tx_packets"));
-
-                stats.combineValues(entry);
-            }
-        }
-
         return stats;
     }
 
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index cbd986f..bbc26d6 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -853,6 +853,14 @@
                 if ((wl.flags & PowerManager.ACQUIRE_CAUSES_WAKEUP) != 0) {
                     int oldWakeLockState = mWakeLockState;
                     mWakeLockState = mLocks.reactivateScreenLocksLocked();
+
+                    // Disable proximity sensor if if user presses power key while we are in the
+                    // "waiting for proximity sensor to go negative" state.
+                    if ((mWakeLockState & SCREEN_ON_BIT) != 0
+                            && mProximitySensorActive && mProximityWakeLockCount == 0) {
+                        mProximitySensorActive = false;
+                    }
+
                     if (mSpew) {
                         Slog.d(TAG, "wakeup here mUserState=0x" + Integer.toHexString(mUserState)
                                 + " mWakeLockState=0x"
diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java
index e0dc96f..4d54fd4 100644
--- a/services/java/com/android/server/net/NetworkStatsService.java
+++ b/services/java/com/android/server/net/NetworkStatsService.java
@@ -31,6 +31,8 @@
 import static android.net.NetworkStats.SET_FOREGROUND;
 import static android.net.NetworkStats.TAG_NONE;
 import static android.net.NetworkStats.UID_ALL;
+import static android.net.NetworkTemplate.buildTemplateMobileAll;
+import static android.net.NetworkTemplate.buildTemplateWifi;
 import static android.net.TrafficStats.UID_REMOVED;
 import static android.provider.Settings.Secure.NETSTATS_NETWORK_BUCKET_DURATION;
 import static android.provider.Settings.Secure.NETSTATS_NETWORK_MAX_HISTORY;
@@ -76,6 +78,7 @@
 import android.os.SystemClock;
 import android.provider.Settings;
 import android.telephony.TelephonyManager;
+import android.util.EventLog;
 import android.util.NtpTrustedTime;
 import android.util.Slog;
 import android.util.SparseIntArray;
@@ -83,6 +86,7 @@
 
 import com.android.internal.os.AtomicFile;
 import com.android.internal.util.Objects;
+import com.android.server.EventLogTags;
 import com.google.android.collect.Lists;
 import com.google.android.collect.Maps;
 import com.google.android.collect.Sets;
@@ -387,7 +391,9 @@
                     entry.uid = UID_ALL;
                     entry.tag = TAG_NONE;
                     entry.rxBytes = historyEntry.rxBytes;
+                    entry.rxPackets = historyEntry.rxPackets;
                     entry.txBytes = historyEntry.txBytes;
+                    entry.txPackets = historyEntry.txPackets;
 
                     stats.combineValues(entry);
                 }
@@ -716,6 +722,11 @@
             Slog.v(TAG, "performPollLocked() took " + duration + "ms");
         }
 
+        // sample stats after detailed poll
+        if (detailedPoll) {
+            performSample();
+        }
+
         // finally, dispatch updated event to any listeners
         final Intent updatedIntent = new Intent(ACTION_NETWORK_STATS_UPDATED);
         updatedIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
@@ -809,6 +820,33 @@
     }
 
     /**
+     * Sample recent statistics summary into {@link EventLog}.
+     */
+    private void performSample() {
+        // take sample as total over last 4 hours
+        final long end = mTime.hasCache() ? mTime.currentTimeMillis() : System.currentTimeMillis();
+        final long start = end - (4 * HOUR_IN_MILLIS);
+
+        NetworkTemplate template = null;
+        NetworkStats.Entry ifaceTotal = null;
+        NetworkStats.Entry uidTotal = null;
+
+        // collect mobile sample
+        template = buildTemplateMobileAll(getActiveSubscriberId(mContext));
+        ifaceTotal = getSummaryForNetwork(template, start, end).getTotal(ifaceTotal);
+        uidTotal = getSummaryForAllUid(template, start, end, false).getTotal(uidTotal);
+        EventLogTags.writeNetstatsMobileSample(
+                ifaceTotal.rxBytes, ifaceTotal.txBytes, uidTotal.rxBytes, uidTotal.txBytes);
+
+        // collect wifi sample
+        template = buildTemplateWifi();
+        ifaceTotal = getSummaryForNetwork(template, start, end).getTotal(ifaceTotal);
+        uidTotal = getSummaryForAllUid(template, start, end, false).getTotal(uidTotal);
+        EventLogTags.writeNetstatsWifiSample(
+                ifaceTotal.rxBytes, ifaceTotal.txBytes, uidTotal.rxBytes, uidTotal.txBytes);
+    }
+
+    /**
      * Clean up {@link #mUidStats} after UID is removed.
      */
     private void removeUidLocked(int uid) {
@@ -1249,6 +1287,12 @@
         }
     };
 
+    private static String getActiveSubscriberId(Context context) {
+        final TelephonyManager telephony = (TelephonyManager) context.getSystemService(
+                Context.TELEPHONY_SERVICE);
+        return telephony.getSubscriberId();
+    }
+
     /**
      * Key uniquely identifying a {@link NetworkStatsHistory} for a UID.
      */
diff --git a/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java
index ecf78d9..2a25866 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java
@@ -106,6 +106,7 @@
 
     public void testNetworkStatsSummaryDown() throws Exception {
         stageFile(R.raw.net_dev_typical, new File(mTestProc, "net/dev"));
+        stageLong(1L, new File(mTestProc, "net/xt_qtaguid/iface_stat/wlan0/active"));
         stageLong(1024L, new File(mTestProc, "net/xt_qtaguid/iface_stat/wlan0/rx_bytes"));
         stageLong(128L, new File(mTestProc, "net/xt_qtaguid/iface_stat/wlan0/rx_packets"));
         stageLong(2048L, new File(mTestProc, "net/xt_qtaguid/iface_stat/wlan0/tx_bytes"));
@@ -119,6 +120,7 @@
 
     public void testNetworkStatsCombined() throws Exception {
         stageFile(R.raw.net_dev_typical, new File(mTestProc, "net/dev"));
+        stageLong(1L, new File(mTestProc, "net/xt_qtaguid/iface_stat/rmnet0/active"));
         stageLong(10L, new File(mTestProc, "net/xt_qtaguid/iface_stat/rmnet0/rx_bytes"));
         stageLong(20L, new File(mTestProc, "net/xt_qtaguid/iface_stat/rmnet0/rx_packets"));
         stageLong(30L, new File(mTestProc, "net/xt_qtaguid/iface_stat/rmnet0/tx_bytes"));
@@ -129,6 +131,18 @@
                 2205L + 20L, 489339L + 30L, 2237L + 40L);
     }
 
+    public void testNetworkStatsCombinedInactive() throws Exception {
+        stageFile(R.raw.net_dev_typical, new File(mTestProc, "net/dev"));
+        stageLong(0L, new File(mTestProc, "net/xt_qtaguid/iface_stat/rmnet0/active"));
+        stageLong(10L, new File(mTestProc, "net/xt_qtaguid/iface_stat/rmnet0/rx_bytes"));
+        stageLong(20L, new File(mTestProc, "net/xt_qtaguid/iface_stat/rmnet0/rx_packets"));
+        stageLong(30L, new File(mTestProc, "net/xt_qtaguid/iface_stat/rmnet0/tx_bytes"));
+        stageLong(40L, new File(mTestProc, "net/xt_qtaguid/iface_stat/rmnet0/tx_packets"));
+
+        final NetworkStats stats = mService.getNetworkStatsSummary();
+        assertStatsEntry(stats, "rmnet0", UID_ALL, SET_DEFAULT, TAG_NONE, 10L, 20L, 30L, 40L);
+    }
+
     public void testKernelTags() throws Exception {
         assertEquals("0", tagToKernel(0x0));
         assertEquals("214748364800", tagToKernel(0x32));
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java
index 23e0ca1..2a52888 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java
@@ -107,10 +107,9 @@
 
     }
 
-    public boolean setAdditionalInputMethodSubtypes(String arg0, InputMethodSubtype[] arg1)
+    public void setAdditionalInputMethodSubtypes(String arg0, InputMethodSubtype[] arg1)
             throws RemoteException {
         // TODO Auto-generated method stub
-        return false;
     }
 
     public boolean setCurrentInputMethodSubtype(InputMethodSubtype arg0) throws RemoteException {
@@ -187,11 +186,4 @@
         // TODO Auto-generated method stub
         return null;
     }
-
-    public boolean setAdditionalInputMethodSubtypes(IBinder arg0, InputMethodSubtype[] arg1)
-            throws RemoteException {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
 }
diff --git a/wifi/java/android/net/wifi/WpsConfiguration.java b/wifi/java/android/net/wifi/WpsConfiguration.java
index 2e7689a..0c2adfd 100644
--- a/wifi/java/android/net/wifi/WpsConfiguration.java
+++ b/wifi/java/android/net/wifi/WpsConfiguration.java
@@ -46,16 +46,21 @@
 
     public Setup setup;
 
+    /** @hide */
     public String BSSID;
 
     public String pin;
 
+    /** @hide */
     public IpAssignment ipAssignment;
 
+    /** @hide */
     public ProxySettings proxySettings;
 
+    /** @hide */
     public LinkProperties linkProperties;
 
+    /** @hide */
     public WpsConfiguration() {
         setup = Setup.INVALID;
         BSSID = null;
@@ -65,6 +70,7 @@
         linkProperties = new LinkProperties();
     }
 
+    /** @hide */
     public String toString() {
         StringBuffer sbuf = new StringBuffer();
         sbuf.append(" setup: ").append(setup.toString());
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java b/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java
index 2d57363..686d698 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java
@@ -28,11 +28,6 @@
 public class WifiP2pConfig implements Parcelable {
 
     /**
-     * Device name
-     */
-    public String deviceName;
-
-    /**
      * Device address
      */
     public String deviceAddress;
@@ -53,6 +48,7 @@
 
     /**
      * Indicates whether the configuration is saved
+     * @hide
      */
     public enum Persist {
         SYSTEM_DEFAULT,
@@ -60,6 +56,7 @@
         NO
     }
 
+    /** @hide */
     public Persist persist = Persist.SYSTEM_DEFAULT;
 
     public WifiP2pConfig() {
@@ -110,7 +107,6 @@
 
     public String toString() {
         StringBuffer sbuf = new StringBuffer();
-        sbuf.append("Device: ").append(deviceName);
         sbuf.append("\n address: ").append(deviceAddress);
         sbuf.append("\n wps: ").append(wpsConfig);
         sbuf.append("\n groupOwnerIntent: ").append(groupOwnerIntent);
@@ -132,7 +128,6 @@
 
     /** Implement the Parcelable interface {@hide} */
     public void writeToParcel(Parcel dest, int flags) {
-        dest.writeString(deviceName);
         dest.writeString(deviceAddress);
         dest.writeParcelable(wpsConfig, flags);
         dest.writeInt(groupOwnerIntent);
@@ -144,7 +139,6 @@
         new Creator<WifiP2pConfig>() {
             public WifiP2pConfig createFromParcel(Parcel in) {
                 WifiP2pConfig config = new WifiP2pConfig();
-                config.deviceName = in.readString();
                 config.deviceAddress = in.readString();
                 config.wpsConfig = (WpsConfiguration) in.readParcelable(null);
                 config.groupOwnerIntent = in.readInt();
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pGroup.java b/wifi/java/android/net/wifi/p2p/WifiP2pGroup.java
index ca6e4d5..14246b4 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pGroup.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pGroup.java
@@ -69,7 +69,7 @@
     }
 
     /**
-     * @param string formats supported include
+     * @param supplicantEvent formats supported include
      *
      *  P2P-GROUP-STARTED p2p-wlan0-0 [client|GO] ssid="DIRECT-W8" freq=2437
      *  [psk=2182b2e50e53f260d04f3c7b25ef33c965a3291b9b36b455a82d77fd82ca15bc|
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pInfo.java b/wifi/java/android/net/wifi/p2p/WifiP2pInfo.java
index 9dc2fbf..a02175e 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pInfo.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pInfo.java
@@ -34,9 +34,11 @@
 
     public InetAddress groupOwnerAddress;
 
-    public WifiP2pInfo() {
+    /** @hide */
+    WifiP2pInfo() {
     }
 
+    /** @hide */
     public String toString() {
         StringBuffer sbuf = new StringBuffer();
         sbuf.append("groupFormed: ").append(groupFormed)
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
index 25daf1c..0bdd269 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
@@ -35,25 +35,64 @@
 import com.android.internal.util.Protocol;
 
 /**
- * This class provides the API for managing Wi-Fi p2p
- * connectivity. Get an instance of this class by calling
- * {@link android.content.Context#getSystemService(String)
+ * This class provides the API for managing Wi-Fi peer-to-peer connectivity. This lets an
+ * application discover available peers, setup connection to peers and query for the list of peers.
+ * When a p2p connection is formed over wifi, the device continues to maintain the uplink
+ * connection over mobile or any other available network for internet connectivity on the device.
+ *
+ * <p> The API is asynchronous and response to a request from an application is sent in the form
+ * of a {@link android.os.Message} on a {@link android.os.Handler} that needs to be initialized
+ * by the application right at the beginning before any p2p operations are performed via
+ * {@link #initialize}.
+ *
+ * <p> An application can request for the current list of peers using {@link #requestPeers}. The
+ * {@link #RESPONSE_PEERS} message on the handler indicates that the peer list is available.
+ * Use {@link #peersInResponse} to extract the peer device list upon the receiving the
+ * {@link #RESPONSE_PEERS} message.
+ *
+ * <p> If an application needs to initiate a discovery, use {@link #discoverPeers} and listen
+ * to {@link #WIFI_P2P_PEERS_CHANGED_ACTION} intent action to initiate a request to fetch
+ * list of peers with {@link #requestPeers}. An initiated discovery request from an application
+ * stays active until the device starts connecting to a peer or forms a p2p group.
+ *
+ * <p> An application can initiate a connection request to a peer through {@link #connect}. See
+ * {@link WifiP2pConfig} for details on setting up the configuration. For communication with legacy
+ * Wi-Fi devices that do not support p2p, an app can create a group using {@link #createGroup}
+ * which creates an access point whose details can be fetched with {@link #requestGroupInfo}.
+ *
+ * <p> After a successful group formation through {@link #createGroup} or through {@link #connect},
+ * use {@link #requestConnectionInfo} to fetch the connection details. Connection information
+ * can be obtained with {@link #connectionInfoInResponse} on a {@link #RESPONSE_CONNECTION_INFO}
+ * message. The connection info {@link WifiP2pInfo} contains the address of the group owner
+ * {@link WifiP2pInfo#groupOwnerAddress} and a flag {@link #WifiP2pInfo#isGroupOwner} to indicate
+ * if the current device is a p2p group owner. A p2p client can thus communicate with
+ * the p2p group owner through a socket connection.
+ *
+ * <p> Android has no platform support for service discovery yet, so applications could
+ * run a service discovery protocol to discover services on the peer-to-peer netework.
+ *
+ * <p class="note"><strong>Note:</strong>
+ * Registering an application handler with {@link #initialize} requires the permissions
+ * {@link android.Manifest.permission#ACCESS_WIFI_STATE} and
+ * {@link android.Manifest.permission#CHANGE_WIFI_STATE} to perform any further peer-to-peer
+ * operations.
+ *
+ * Get an instance of this class by calling {@link android.content.Context#getSystemService(String)
  * Context.getSystemService(Context.WIFI_P2P_SERVICE)}.
  *
- * It deals with the following:
- * <ul>
- * <li>Wi-Fi peer discovery and connection setup. Allows applications to initiate a discovery to
- * find available peers and then setup a connection </li>
- * <li>Configuration and status query. Allows applications to fetch the current list
- * of available and connected peers and query connection status </li>
- * <li>Intent actions that are broadcast to track operations
- * on a p2p connection</li>
- * </ul>
+ * {@see WifiP2pConfig}
+ * {@see WifiP2pInfo}
+ * {@see WifiP2pGroup}
+ * {@see WifiP2pDevice}
+ * {@see WifiP2pDeviceList}
  * @hide
  */
 public class WifiP2pManager {
     /**
-     * Broadcast intent action to indicate whether Wi-Fi p2p is enabled or disabled.
+     * Broadcast intent action to indicate whether Wi-Fi p2p is enabled or disabled. An
+     * extra {@link #EXTRA_WIFI_STATE} provides the state information as int.
+     *
+     * @see #EXTRA_WIFI_STATE
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String WIFI_P2P_STATE_CHANGED_ACTION =
@@ -72,7 +111,6 @@
      * Wi-Fi p2p is disabled.
      *
      * @see #WIFI_P2P_STATE_CHANGED_ACTION
-     * @see #getWifiP2pState()
      */
     public static final int WIFI_P2P_STATE_DISABLED = 1;
 
@@ -80,14 +118,16 @@
      * Wi-Fi p2p is enabled.
      *
      * @see #WIFI_P2P_STATE_CHANGED_ACTION
-     * @see #getWifiP2pState()
      */
     public static final int WIFI_P2P_STATE_ENABLED = 2;
 
     /**
      * Broadcast intent action indicating that the state of Wi-Fi p2p connectivity
-     * has changed. One extra provides the new state
-     * in the form of a {@link android.net.NetworkInfo} object.
+     * has changed. One extra {@link #EXTRA_WIFI_P2P_INFO} provides the p2p connection info in
+     * the form of a {@link WifiP2pInfo} object. Another extra {@link #EXTRA_NETWORK_INFO} provides
+     * the network info in the form of a {@link android.net.NetworkInfo}.
+     *
+     * @see #EXTRA_WIFI_P2P_INFO
      * @see #EXTRA_NETWORK_INFO
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
@@ -124,7 +164,8 @@
     public static final String EXTRA_LINK_CAPABILITIES = "linkCapabilities";
 
     /**
-     * Broadcast intent action indicating that the available peer list has changed
+     * Broadcast intent action indicating that the available peer list has changed. Fetch
+     * the changed list of peers with {@link #requestPeers}
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String WIFI_P2P_PEERS_CHANGED_ACTION =
@@ -134,6 +175,7 @@
      * Activity Action: Pick a Wi-Fi p2p network to connect to.
      * <p>Input: Nothing.
      * <p>Output: Nothing.
+     * @hide
      */
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_PICK_WIFI_P2P_NETWORK =
@@ -141,47 +183,169 @@
 
     IWifiP2pManager mService;
 
-    /* AsyncChannel notifications to apps */
-    public static final int HANDLER_CONNECTION = AsyncChannel.CMD_CHANNEL_HALF_CONNECTED;
+    /**
+     * Message {@link android.os.Message#what} sent on the application handler specified
+     * at {@link #initialize} indicating the asynchronous channel has disconnected. An
+     * application could choose to reconnect with {@link #initialize}
+     */
     public static final int HANDLER_DISCONNECTION = AsyncChannel.CMD_CHANNEL_DISCONNECTED;
 
     private static final int BASE = Protocol.BASE_WIFI_P2P_MANAGER;
 
+    /** @hide */
     public static final int ENABLE_P2P                              = BASE + 1;
+    /** @hide */
     public static final int ENABLE_P2P_FAILED                       = BASE + 2;
+    /** @hide */
     public static final int ENABLE_P2P_SUCCEEDED                    = BASE + 3;
 
+    /** @hide */
     public static final int DISABLE_P2P                             = BASE + 4;
+    /** @hide */
     public static final int DISABLE_P2P_FAILED                      = BASE + 5;
+    /** @hide */
     public static final int DISABLE_P2P_SUCCEEDED                   = BASE + 6;
 
+    /** @hide */
     public static final int DISCOVER_PEERS                          = BASE + 7;
+
+    /**
+     * Message {@link android.os.Message#what} value indicating that the {@link #discoverPeers}
+     * operation failed.
+     * <p> The reason for failure could be one of {@link #P2P_UNSUPPORTED}, {@link #P2P_DISABLED}
+     * or {@link #ALREADY_IN_EFFECT}
+     */
     public static final int DISCOVER_PEERS_FAILED                   = BASE + 8;
+    /**
+     * Message {@link android.os.Message#what} value indicating that the {@link #discoverPeers}
+     * operation succeeded.
+     * <p> The application can register for {@link #WIFI_P2P_PEERS_CHANGED_ACTION} intent
+     * to listen for changes in the peer list as a result of the discovery process.
+     */
     public static final int DISCOVER_PEERS_SUCCEEDED                = BASE + 9;
 
+    /** @hide */
     public static final int CONNECT                                 = BASE + 10;
+
+    /**
+     * Message {@link android.os.Message#what} value indicating that the {@link #connect}
+     * operation failed.
+     * <p> The reason for failure could be one of {@link #P2P_UNSUPPORTED}, {@link #P2P_DISABLED}
+     * or {@link #ALREADY_IN_EFFECT}
+     */
     public static final int CONNECT_FAILED                          = BASE + 11;
+    /**
+     * Message {@link android.os.Message#what} value indicating that the {@link #connect}
+     * operation succeeded.
+     * <p> The application can register for {@link #WIFI_P2P_CONNECTION_CHANGED_ACTION} intent
+     * to listen for connectivity change as a result of the connect operation
+     */
     public static final int CONNECT_SUCCEEDED                       = BASE + 12;
 
+    /** @hide */
     public static final int CREATE_GROUP                            = BASE + 13;
+
+    /**
+     * Message {@link android.os.Message#what} value indicating that the {@link #createGroup}
+     * operation failed.
+     * <p> The reason for failure could be one of {@link #P2P_UNSUPPORTED}, {@link #P2P_DISABLED}
+     * or {@link #ALREADY_IN_EFFECT}
+     */
     public static final int CREATE_GROUP_FAILED                     = BASE + 14;
+    /**
+     * Message {@link android.os.Message#what} value indicating that the {@link #createGroup}
+     * operation succeeded.
+     * <p> The application can request the group details with {@link #requestGroupInfo}
+     */
     public static final int CREATE_GROUP_SUCCEEDED                  = BASE + 15;
 
+    /** @hide */
     public static final int REMOVE_GROUP                            = BASE + 16;
+    /**
+     * Message {@link android.os.Message#what} value indicating that the {@link #removeGroup}
+     * operation failed.
+     * <p> The reason for failure could be one of {@link #P2P_UNSUPPORTED}, {@link #P2P_DISABLED}
+     * or {@link #ALREADY_IN_EFFECT}
+     */
     public static final int REMOVE_GROUP_FAILED                     = BASE + 17;
+    /**
+     * Message {@link android.os.Message#what} value indicating that the {@link #removeGroup}
+     * operation succeeded.
+     */
     public static final int REMOVE_GROUP_SUCCEEDED                  = BASE + 18;
 
-    public static final int REQUEST_PEERS                           = BASE + 19;
-    public static final int RESPONSE_PEERS                          = BASE + 20;
-
-    public static final int REQUEST_CONNECTION_INFO                 = BASE + 21;
-    public static final int RESPONSE_CONNECTION_INFO                = BASE + 22;
-
-    /* arg1 values on response messages from the framework */
+    /**
+     * Supported {@link android.os.Message#arg1} value on the following response messages:
+     * {@link #DISCOVER_PEERS_FAILED}, {@link #CONNECT_FAILED}, {@link #CREATE_GROUP_FAILED}
+     * and {@link #REMOVE_GROUP_FAILED}
+     *
+     * <p> This indicates that the reason for failure is because p2p is unsupported on the
+     * device
+     */
     public static final int P2P_UNSUPPORTED     = 1;
 
+    /**
+     * Supported {@link android.os.Message#arg1} value on the following response messages:
+     * {@link #DISCOVER_PEERS_FAILED}, {@link #CONNECT_FAILED}, {@link #CREATE_GROUP_FAILED}
+     * and {@link #REMOVE_GROUP_FAILED}
+     *
+     * <p> This indicates that the reason for failure is because p2p is currently disabled
+     * by the user
+     */
+    public static final int P2P_DISABLED        = 2;
+
+    /**
+     * Supported {@link android.os.Message#arg1} value on the following response messages:
+     * {@link #DISCOVER_PEERS_FAILED}, {@link #CONNECT_FAILED}, {@link #CREATE_GROUP_FAILED}
+     * and {@link #REMOVE_GROUP_FAILED}
+     *
+     * <p> This indicates that the reason for failure is because the operation is already in
+     * effect
+     */
+    public static final int ALREADY_IN_EFFECT   = 3;
+
+
+    /** @hide */
+    public static final int REQUEST_PEERS                           = BASE + 19;
+    /**
+     * Message {@link android.os.Message#what} delivered on the application hander
+     * in response to a {@link #requestPeers} call from the application.
+     *
+     * <p> Extract a {@link WifiP2pDeviceList} object by calling {@link #peersInResponse}
+     * on the message object
+     */
+    public static final int RESPONSE_PEERS                          = BASE + 20;
+
+    /** @hide */
+    public static final int REQUEST_CONNECTION_INFO                 = BASE + 21;
+
+    /**
+     * Message {@link android.os.Message#what} delivered on the application hander
+     * in response to a {@link #requestConnectionInfo} call from the application.
+     *
+     * <p> Extract a {@link WifiP2pInfo} object by calling {@link #connectionInfoInResponse}
+     * on the message object
+     */
+    public static final int RESPONSE_CONNECTION_INFO                = BASE + 22;
+
+    /** @hide */
+    public static final int REQUEST_GROUP_INFO                      = BASE + 23;
+
+    /**
+     * Message {@link android.os.Message#what} delivered on the application hander
+     * in response to a {@link #requestGroupInfo} call from the application.
+     *
+     * <p> Extract a {@link WifiP2pGroup} object by calling {@link #groupInfoInResponse}
+     * on the message object
+     */
+
+    public static final int RESPONSE_GROUP_INFO                     = BASE + 24;
+
+    /** @hide */
     public static final int WPS_PBC                                 = BASE + 23;
+    /** @hide */
     public static final int WPS_PIN                                 = BASE + 24;
+    /** @hide */
     public static final int WPS_PIN_AVAILABLE                       = BASE + 25;
 
     /**
@@ -199,7 +363,8 @@
 
     /**
      * A channel that connects the application handler to the Wifi framework.
-     * All p2p operations are performed on a channel.
+     * Most p2p operations require a Channel as an argument. An instance of Channel is obtained
+     * by doing a call on {@link #initialize}
      */
     public class Channel {
         Channel(AsyncChannel c) {
@@ -210,10 +375,17 @@
 
     /**
      * Registers the application handler with the Wi-Fi framework. This function
-     * must be the first to be called before any p2p control or query operations can be performed.
+     * must be the first to be called before any p2p operations are performed.
+     *
+     * <p class="note"><strong>Note:</strong>
+     * The handler registered with the framework should only handle messages
+     * with {@link android.os.Message#what} values defined in this file. Adding application
+     * specific private {@link android.os.Message#what} types should be done on a seperate handler
+     *
      * @param srcContext is the context of the source
-     * @param srcHandler is the handler on which the source receives messages
-     * @return Channel instance that is necessary for performing p2p operations
+     * @param srcHandler is the handler on which the source will receive message responses
+     * asynchronously
+     * @return Channel instance that is necessary for performing any further p2p operations
      */
     public Channel initialize(Context srcContext, Handler srcHandler) {
         Messenger messenger = getMessenger();
@@ -229,6 +401,7 @@
         }
     }
 
+    /** @hide */
     public boolean isP2pSupported() {
         try {
             return mService.isP2pSupported();
@@ -240,6 +413,7 @@
     /**
      * Sends in a request to the system to enable p2p. This will pop up a dialog
      * to the user and upon authorization will enable p2p.
+     * @hide
      */
     public void enableP2p(Channel c) {
         if (c == null) return;
@@ -249,6 +423,7 @@
     /**
      * Sends in a request to the system to disable p2p. This will pop up a dialog
      * to the user and upon authorization will enable p2p.
+     * @hide
      */
     public void disableP2p(Channel c) {
         if (c == null) return;
@@ -256,7 +431,22 @@
     }
 
     /**
-     * Initiates peer discovery
+     * Initiate peer discovery. A discovery process involves scanning for available Wi-Fi peers
+     * for the purpose of establishing a connection.
+     *
+     * <p> The function call immediately returns after sending a discovery request
+     * to the framework. The application handler is notified of a success or failure to initiate
+     * discovery with {@link #DISCOVER_PEERS_SUCCEEDED} or {@link #DISCOVER_PEERS_FAILED}.
+     *
+     * <p> The discovery remains active until a connection is initiated or
+     * a p2p group is formed. Register for {@link #WIFI_P2P_PEERS_CHANGED_ACTION} intent to
+     * determine when the framework notifies of a change as peers are discovered.
+     *
+     * <p> Upon receiving a {@link #WIFI_P2P_PEERS_CHANGED_ACTION} intent, an application
+     * can request for the list of peers using {@link #requestPeers} which will deliver a
+     * {@link #RESPONSE_PEERS} message on the application handler. The application can then
+     * extract a {@link WifiP2pDeviceList} object by calling {@link #peersInResponse}
+     * on the message.
      */
     public void discoverPeers(Channel c) {
         if (c == null) return;
@@ -264,9 +454,23 @@
     }
 
     /**
-     * Start a p2p connection
+     * Start a p2p connection to a device with the specified configuration.
      *
-     * @param peer Configuration described in a {@link WifiP2pConfig} object.
+     * <p> The function call immediately returns after sending a connection request
+     * to the framework. The application handler is notified of a success or failure to initiate
+     * connectivity with {@link #CONNECT_SUCCEEDED} or {@link #CONNECT_FAILED}.
+     *
+     * <p> Register for {@link #WIFI_P2P_CONNECTION_CHANGED_ACTION} intent to
+     * determine when the framework notifies of a change in connectivity.
+     *
+     * <p> If the current device is not part of a p2p group, a connect request initiates
+     * a group negotiation with the peer.
+     *
+     * <p> If the current device is part of an existing p2p group or has created
+     * a p2p group with {@link #createGroup}, an invitation to join the group is sent to
+     * the peer device.
+     *
+     * @param config options as described in {@link WifiP2pConfig} class.
      */
     public void connect(Channel c, WifiP2pConfig config) {
         if (c == null) return;
@@ -274,8 +478,20 @@
     }
 
     /**
-     * Create a p2p group. This is essentially an access point that can accept
-     * client connections.
+     * Create a p2p group with the current device as the group owner. This essentially creates
+     * an access point that can accept connections from legacy clients as well as other p2p
+     * devices.
+     * <p> For p2p operation, this would normally not be used unless the current device needs
+     * to form a p2p connection with a legacy client
+     *
+     * <p> The function call immediately returns after sending a group creation request
+     * to the framework. The application handler is notified of a success or failure to create
+     * group with {@link #CREATE_GROUP_SUCCEEDED} or {@link #CREATE_GROUP_FAILED}.
+     *
+     * <p> Application can request for the group details with {@link #requestGroupInfo} which will
+     * deliver a {@link #RESPONSE_GROUP_INFO} message on the application handler. The application
+     * can then extract a {@link WifiP2pGroup} object by calling {@link #groupInfoInResponse}
+     * on the message.
      */
     public void createGroup(Channel c) {
         if (c == null) return;
@@ -283,8 +499,11 @@
     }
 
     /**
-     * Remove the current group. This also removes the p2p interface created
-     * during group formation.
+     * Remove the current p2p group.
+     *
+     * <p> The function call immediately returns after sending a group removal request
+     * to the framework. The application handler is notified of a success or failure to remove
+     * a group with {@link #REMOVE_GROUP_SUCCEEDED} or {@link #REMOVE_GROUP_FAILED}.
      */
     public void removeGroup(Channel c) {
         if (c == null) return;
@@ -292,8 +511,9 @@
     }
 
     /**
-     * Request the list of peers. This returns a RESPONSE_PEERS on the source
-     * handler.
+     * Request the current list of peers. This returns a {@link #RESPONSE_PEERS} on the application
+     * handler. The {@link #RESPONSE_PEERS} message on the handler indicates that the peer list is
+     * available. Use {@link #peersInResponse} to extract {@link WifiP2pDeviceList} from the message
      */
     public void requestPeers(Channel c) {
         if (c == null) return;
@@ -301,15 +521,18 @@
     }
 
     /**
-     * Fetch device list from a RESPONSE_PEERS message
+     * Upon receiving a {@link #RESPONSE_PEERS} on the application handler, an application
+     * can extract the peer device list using this function.
      */
     public WifiP2pDeviceList peersInResponse(Message msg) {
         return (WifiP2pDeviceList) msg.obj;
     }
 
     /**
-     * Request device connection info. This returns a RESPONSE_CONNECTION_INFO on
-     * the source handler.
+     * Request device connection info. This returns a {@link #RESPONSE_CONNECTION_INFO} on
+     * the application handler. The {@link #RESPONSE_CONNECTION_INFO} message on the handler
+     * indicates that connection info is available. Use {@link #connectionInfoInResponse} to
+     * extract {@link WifiP2pInfo} from the message.
      */
     public void requestConnectionInfo(Channel c) {
         if (c == null) return;
@@ -317,12 +540,31 @@
     }
 
     /**
-     * Fetch p2p connection status from a RESPONSE_CONNECTION_INFO message
+     * Upon receiving a {@link #RESPONSE_CONNECTION_INFO} on the application handler, an application
+     * can extract the connection info using this function.
      */
     public WifiP2pInfo connectionInfoInResponse(Message msg) {
         return (WifiP2pInfo) msg.obj;
     }
 
+    /**
+     * Request p2p group info. This returns a {@link #RESPONSE_GROUP_INFO} on
+     * the application handler. The {@link #RESPONSE_GROUP_INFO} message on the handler
+     * indicates that group info is available. Use {@link #groupInfoInResponse} to
+     * extract {@link WifiP2pGroup} from the message.
+     */
+    public void requestGroupInfo(Channel c) {
+        if (c == null) return;
+        c.mAsyncChannel.sendMessage(REQUEST_GROUP_INFO);
+    }
+
+    /**
+     * Upon receiving a {@link #RESPONSE_GROUP_INFO} on the application handler, an application
+     * can extract the group info using this function.
+     */
+    public WifiP2pGroup groupInfoInResponse(Message msg) {
+        return (WifiP2pGroup) msg.obj;
+    }
 
     /**
      * Get a reference to WifiP2pService handler. This is used to establish
@@ -339,7 +581,6 @@
         }
     }
 
-
     /**
      * Setup DNS connectivity on the current process to the connected Wi-Fi p2p peers
      *