Merge "Hide MIME_TYPE_PROVISIONING_NFC_V2" into mnc-dev
diff --git a/api/current.txt b/api/current.txt
index 02f4c01..8d6b3b3 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5615,8 +5615,8 @@
     method public void clearDeviceOwnerApp(java.lang.String);
     method public void clearPackagePersistentPreferredActivities(android.content.ComponentName, java.lang.String);
     method public void clearUserRestriction(android.content.ComponentName, java.lang.String);
-    method public android.os.UserHandle createAndInitializeUser(android.content.ComponentName, java.lang.String, java.lang.String, android.content.ComponentName, android.os.Bundle);
-    method public android.os.UserHandle createUser(android.content.ComponentName, java.lang.String);
+    method public deprecated android.os.UserHandle createAndInitializeUser(android.content.ComponentName, java.lang.String, java.lang.String, android.content.ComponentName, android.os.Bundle);
+    method public deprecated android.os.UserHandle createUser(android.content.ComponentName, java.lang.String);
     method public void enableSystemApp(android.content.ComponentName, java.lang.String);
     method public int enableSystemApp(android.content.ComponentName, android.content.Intent);
     method public java.lang.String[] getAccountTypesWithManagementDisabled();
@@ -5831,10 +5831,12 @@
   }
 
   public static class AssistStructure.ViewNode {
+    method public float getAlpha();
     method public android.app.assist.AssistStructure.ViewNode getChildAt(int);
     method public int getChildCount();
     method public java.lang.String getClassName();
     method public java.lang.CharSequence getContentDescription();
+    method public float getElevation();
     method public android.os.Bundle getExtras();
     method public int getHeight();
     method public java.lang.String getHint();
@@ -5853,6 +5855,7 @@
     method public float getTextSize();
     method public int getTextStyle();
     method public int getTop();
+    method public android.graphics.Matrix getTransformation();
     method public int getVisibility();
     method public int getWidth();
     method public boolean isAccessibilityFocused();
@@ -22696,7 +22699,7 @@
     field public static final int KITKAT_WATCH = 20; // 0x14
     field public static final int LOLLIPOP = 21; // 0x15
     field public static final int LOLLIPOP_MR1 = 22; // 0x16
-    field public static final int MNC = 10000; // 0x2710
+    field public static final int MNC = 23; // 0x17
   }
 
   public final class Bundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable {
@@ -31076,7 +31079,7 @@
     method public java.lang.String getLine1Number();
     method public java.lang.String getMmsUAProfUrl();
     method public java.lang.String getMmsUserAgent();
-    method public java.util.List<android.telephony.NeighboringCellInfo> getNeighboringCellInfo();
+    method public deprecated java.util.List<android.telephony.NeighboringCellInfo> getNeighboringCellInfo();
     method public java.lang.String getNetworkCountryIso();
     method public java.lang.String getNetworkOperator();
     method public java.lang.String getNetworkOperatorName();
@@ -36947,6 +36950,7 @@
     method public abstract android.view.ViewStructure newChild(int);
     method public abstract void setAccessibilityFocused(boolean);
     method public abstract void setActivated(boolean);
+    method public abstract void setAlpha(float);
     method public abstract void setCheckable(boolean);
     method public abstract void setChecked(boolean);
     method public abstract void setChildCount(int);
@@ -36955,6 +36959,7 @@
     method public abstract void setContentDescription(java.lang.CharSequence);
     method public abstract void setContextClickable(boolean);
     method public abstract void setDimens(int, int, int, int, int, int);
+    method public abstract void setElevation(float);
     method public abstract void setEnabled(boolean);
     method public abstract void setFocusable(boolean);
     method public abstract void setFocused(boolean);
@@ -36965,6 +36970,7 @@
     method public abstract void setText(java.lang.CharSequence);
     method public abstract void setText(java.lang.CharSequence, int, int);
     method public abstract void setTextStyle(float, int, int, int);
+    method public abstract void setTransformation(android.graphics.Matrix);
     method public abstract void setVisibility(int);
   }
 
diff --git a/api/system-current.txt b/api/system-current.txt
index 99bc95f..9784dcb 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -5736,8 +5736,8 @@
     method public void clearPackagePersistentPreferredActivities(android.content.ComponentName, java.lang.String);
     method public void clearProfileOwner(android.content.ComponentName);
     method public void clearUserRestriction(android.content.ComponentName, java.lang.String);
-    method public android.os.UserHandle createAndInitializeUser(android.content.ComponentName, java.lang.String, java.lang.String, android.content.ComponentName, android.os.Bundle);
-    method public android.os.UserHandle createUser(android.content.ComponentName, java.lang.String);
+    method public deprecated android.os.UserHandle createAndInitializeUser(android.content.ComponentName, java.lang.String, java.lang.String, android.content.ComponentName, android.os.Bundle);
+    method public deprecated android.os.UserHandle createUser(android.content.ComponentName, java.lang.String);
     method public void enableSystemApp(android.content.ComponentName, java.lang.String);
     method public int enableSystemApp(android.content.ComponentName, android.content.Intent);
     method public java.lang.String[] getAccountTypesWithManagementDisabled();
@@ -5963,10 +5963,12 @@
   }
 
   public static class AssistStructure.ViewNode {
+    method public float getAlpha();
     method public android.app.assist.AssistStructure.ViewNode getChildAt(int);
     method public int getChildCount();
     method public java.lang.String getClassName();
     method public java.lang.CharSequence getContentDescription();
+    method public float getElevation();
     method public android.os.Bundle getExtras();
     method public int getHeight();
     method public java.lang.String getHint();
@@ -5985,6 +5987,7 @@
     method public float getTextSize();
     method public int getTextStyle();
     method public int getTop();
+    method public android.graphics.Matrix getTransformation();
     method public int getVisibility();
     method public int getWidth();
     method public boolean isAccessibilityFocused();
@@ -24643,7 +24646,7 @@
     field public static final int KITKAT_WATCH = 20; // 0x14
     field public static final int LOLLIPOP = 21; // 0x15
     field public static final int LOLLIPOP_MR1 = 22; // 0x16
-    field public static final int MNC = 10000; // 0x2710
+    field public static final int MNC = 23; // 0x17
   }
 
   public final class Bundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable {
@@ -33332,7 +33335,7 @@
     method public java.lang.String getLine1Number();
     method public java.lang.String getMmsUAProfUrl();
     method public java.lang.String getMmsUserAgent();
-    method public java.util.List<android.telephony.NeighboringCellInfo> getNeighboringCellInfo();
+    method public deprecated java.util.List<android.telephony.NeighboringCellInfo> getNeighboringCellInfo();
     method public java.lang.String getNetworkCountryIso();
     method public java.lang.String getNetworkOperator();
     method public java.lang.String getNetworkOperatorName();
@@ -39242,6 +39245,7 @@
     method public abstract android.view.ViewStructure newChild(int);
     method public abstract void setAccessibilityFocused(boolean);
     method public abstract void setActivated(boolean);
+    method public abstract void setAlpha(float);
     method public abstract void setCheckable(boolean);
     method public abstract void setChecked(boolean);
     method public abstract void setChildCount(int);
@@ -39250,6 +39254,7 @@
     method public abstract void setContentDescription(java.lang.CharSequence);
     method public abstract void setContextClickable(boolean);
     method public abstract void setDimens(int, int, int, int, int, int);
+    method public abstract void setElevation(float);
     method public abstract void setEnabled(boolean);
     method public abstract void setFocusable(boolean);
     method public abstract void setFocused(boolean);
@@ -39260,6 +39265,7 @@
     method public abstract void setText(java.lang.CharSequence);
     method public abstract void setText(java.lang.CharSequence, int, int);
     method public abstract void setTextStyle(float, int, int, int);
+    method public abstract void setTransformation(android.graphics.Matrix);
     method public abstract void setVisibility(int);
   }
 
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index 2be44bc..ce83caa 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -204,6 +204,10 @@
             return runGrantRevokePermission(false);
         }
 
+        if ("reset-permissions".equals(op)) {
+            return runResetPermissions();
+        }
+
         if ("set-permission-enforced".equals(op)) {
             return runSetPermissionEnforced();
         }
@@ -1636,6 +1640,24 @@
         }
     }
 
+    private int runResetPermissions() {
+        try {
+            mPm.resetRuntimePermissions();
+            return 0;
+        } catch (RemoteException e) {
+            System.err.println(e.toString());
+            System.err.println(PM_NOT_RUNNING_ERR);
+            return 1;
+        } catch (IllegalArgumentException e) {
+            System.err.println("Bad argument: " + e.toString());
+            showUsage();
+            return 1;
+        } catch (SecurityException e) {
+            System.err.println("Operation not allowed: " + e.toString());
+            return 1;
+        }
+    }
+
     private int runSetPermissionEnforced() {
         final String permission = nextArg();
         if (permission == null) {
@@ -1911,6 +1933,7 @@
         System.err.println("       pm unhide [--user USER_ID] PACKAGE_OR_COMPONENT");
         System.err.println("       pm grant [--user USER_ID] PACKAGE PERMISSION");
         System.err.println("       pm revoke [--user USER_ID] PACKAGE PERMISSION");
+        System.err.println("       pm reset-permissions");
         System.err.println("       pm set-install-location [0/auto] [1/internal] [2/external]");
         System.err.println("       pm get-install-location");
         System.err.println("       pm set-permission-enforced PERMISSION [true|false]");
@@ -1988,6 +2011,8 @@
         System.err.println("    manifest, be runtime permissions (protection level dangerous),");
         System.err.println("    and the app targeting SDK greater than Lollipop MR1.");
         System.err.println("");
+        System.err.println("pm reset-permissions: revert all runtime permissions to their default state.");
+        System.err.println("");
         System.err.println("pm get-install-location: returns the current install location.");
         System.err.println("    0 [auto]: Let system decide the best location");
         System.err.println("    1 [internal]: Install on internal device storage");
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 3035e3d..2bb4e76 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -2217,6 +2217,14 @@
             return true;
         }
 
+        case IS_SCREEN_CAPTURE_ALLOWED_ON_CURRENT_ACTIVITY_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            boolean res = isScreenCaptureAllowedOnCurrentActivity();
+            reply.writeNoException();
+            reply.writeInt(res ? 1 : 0);
+            return true;
+        }
+
         case KILL_UID_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             int uid = data.readInt();
@@ -5409,6 +5417,18 @@
         return res;
     }
 
+    public boolean isScreenCaptureAllowedOnCurrentActivity() throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        mRemote.transact(IS_SCREEN_CAPTURE_ALLOWED_ON_CURRENT_ACTIVITY_TRANSACTION, data, reply, 0);
+        reply.readException();
+        boolean res = reply.readInt() != 0;
+        data.recycle();
+        reply.recycle();
+        return res;
+    }
+
     public void killUid(int uid, String reason) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 0328708..1423e4b 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -441,6 +441,8 @@
     public boolean launchAssistIntent(Intent intent, int requestType, String hint, int userHandle,
             Bundle args) throws RemoteException;
 
+    public boolean isScreenCaptureAllowedOnCurrentActivity() throws RemoteException;
+
     public void killUid(int uid, String reason) throws RemoteException;
 
     public void hang(IBinder who, boolean allowRestart) throws RemoteException;
@@ -852,4 +854,6 @@
     int KEYGUARD_GOING_AWAY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+296;
     int REGISTER_UID_OBSERVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+297;
     int UNREGISTER_UID_OBSERVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+298;
+    int IS_SCREEN_CAPTURE_ALLOWED_ON_CURRENT_ACTIVITY_TRANSACTION
+            = IBinder.FIRST_CALL_TRANSACTION+299;
 }
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index dcb4890..578419e 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -2405,6 +2405,9 @@
      * <p>The calling device admin must be a device or profile owner. If it is not, a
      * security exception will be thrown.
      *
+     * <p>From version {@link android.os.Build.VERSION_CODES#MNC} disabling screen capture also
+     * blocks assist requests for all activities of the relevant user.
+     *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param disabled Whether screen capture is disabled or not.
      */
@@ -3609,7 +3612,10 @@
      * @see UserHandle
      * @return the {@link android.os.UserHandle} object for the created user, or {@code null} if the
      *         user could not be created.
+     *
+     * @deprecated
      */
+    @Deprecated
     public UserHandle createUser(@NonNull ComponentName admin, String name) {
         try {
             return mService.createUser(admin, name);
@@ -3643,7 +3649,10 @@
      * @see UserHandle
      * @return the {@link android.os.UserHandle} object for the created user, or {@code null} if the
      *         user could not be created.
+     *
+     * @deprecated
      */
+    @Deprecated
     public UserHandle createAndInitializeUser(@NonNull ComponentName admin, String name,
             String ownerName, @NonNull ComponentName profileOwnerComponent, Bundle adminExtras) {
         try {
diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java
index 284dfd6..3429b6e 100644
--- a/core/java/android/app/assist/AssistStructure.java
+++ b/core/java/android/app/assist/AssistStructure.java
@@ -2,6 +2,7 @@
 
 import android.app.Activity;
 import android.content.ComponentName;
+import android.graphics.Matrix;
 import android.graphics.Rect;
 import android.os.Binder;
 import android.os.Bundle;
@@ -128,24 +129,24 @@
             view.dispatchProvideStructure(builder);
         }
 
-        WindowNode(Parcel in, PooledStringReader preader) {
+        WindowNode(Parcel in, PooledStringReader preader, float[] tmpMatrix) {
             mX = in.readInt();
             mY = in.readInt();
             mWidth = in.readInt();
             mHeight = in.readInt();
             mTitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
             mDisplayId = in.readInt();
-            mRoot = new ViewNode(in, preader);
+            mRoot = new ViewNode(in, preader, tmpMatrix);
         }
 
-        void writeToParcel(Parcel out, PooledStringWriter pwriter) {
+        int writeToParcel(Parcel out, PooledStringWriter pwriter, float[] tmpMatrix) {
             out.writeInt(mX);
             out.writeInt(mY);
             out.writeInt(mWidth);
             out.writeInt(mHeight);
             TextUtils.writeToParcel(mTitle, out, 0);
             out.writeInt(mDisplayId);
-            mRoot.writeToParcel(out, pwriter);
+            return mRoot.writeToParcel(out, pwriter, tmpMatrix);
         }
 
         /**
@@ -216,7 +217,7 @@
         public static final int TEXT_STYLE_UNDERLINE = 1<<2;
         public static final int TEXT_STYLE_STRIKE_THRU = 1<<3;
 
-        int mId;
+        int mId = View.NO_ID;
         String mIdPackage;
         String mIdType;
         String mIdEntry;
@@ -226,20 +227,35 @@
         int mScrollY;
         int mWidth;
         int mHeight;
+        Matrix mMatrix;
+        float mElevation;
+        float mAlpha = 1.0f;
 
         static final int FLAGS_DISABLED = 0x00000001;
         static final int FLAGS_VISIBILITY_MASK = View.VISIBLE|View.INVISIBLE|View.GONE;
         static final int FLAGS_FOCUSABLE = 0x00000010;
         static final int FLAGS_FOCUSED = 0x00000020;
-        static final int FLAGS_ACCESSIBILITY_FOCUSED = 0x04000000;
         static final int FLAGS_SELECTED = 0x00000040;
         static final int FLAGS_ASSIST_BLOCKED = 0x00000080;
-        static final int FLAGS_ACTIVATED = 0x40000000;
         static final int FLAGS_CHECKABLE = 0x00000100;
         static final int FLAGS_CHECKED = 0x00000200;
-        static final int FLAGS_CLICKABLE = 0x00004000;
-        static final int FLAGS_LONG_CLICKABLE = 0x00200000;
-        static final int FLAGS_CONTEXT_CLICKABLE = 0x00400000;
+        static final int FLAGS_CLICKABLE = 0x00000400;
+        static final int FLAGS_LONG_CLICKABLE = 0x00000800;
+        static final int FLAGS_ACCESSIBILITY_FOCUSED = 0x00001000;
+        static final int FLAGS_ACTIVATED = 0x00002000;
+        static final int FLAGS_CONTEXT_CLICKABLE = 0x00004000;
+
+        static final int FLAGS_HAS_MATRIX = 0x40000000;
+        static final int FLAGS_HAS_ALPHA = 0x20000000;
+        static final int FLAGS_HAS_ELEVATION = 0x10000000;
+        static final int FLAGS_HAS_SCROLL = 0x08000000;
+        static final int FLAGS_HAS_LARGE_COORDS = 0x04000000;
+        static final int FLAGS_HAS_CONTENT_DESCRIPTION = 0x02000000;
+        static final int FLAGS_HAS_TEXT = 0x01000000;
+        static final int FLAGS_HAS_EXTRAS = 0x00800000;
+        static final int FLAGS_HAS_ID = 0x00400000;
+        static final int FLAGS_HAS_CHILDREN = 0x00200000;
+        static final int FLAGS_ALL_CONTROL = 0xfff00000;
 
         int mFlags;
 
@@ -254,79 +270,153 @@
         ViewNode() {
         }
 
-        ViewNode(Parcel in, PooledStringReader preader) {
-            mId = in.readInt();
-            if (mId != 0) {
-                mIdEntry = preader.readString();
-                if (mIdEntry != null) {
-                    mIdType = preader.readString();
-                    mIdPackage = preader.readString();
-                } else {
-                    mIdPackage = mIdType = null;
-                }
-            } else {
-                mIdPackage = mIdType = mIdEntry = null;
-            }
-            mX = in.readInt();
-            mY = in.readInt();
-            mScrollX = in.readInt();
-            mScrollY = in.readInt();
-            mWidth = in.readInt();
-            mHeight = in.readInt();
-            mFlags = in.readInt();
+        ViewNode(Parcel in, PooledStringReader preader, float[] tmpMatrix) {
             mClassName = preader.readString();
-            mContentDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
-            if (in.readInt() != 0) {
-                mText = new ViewNodeText(in);
-            } else {
-                mText = null;
+            mFlags = in.readInt();
+            final int flags = mFlags;
+            if ((flags&FLAGS_HAS_ID) != 0) {
+                mId = in.readInt();
+                if (mId != 0) {
+                    mIdEntry = preader.readString();
+                    if (mIdEntry != null) {
+                        mIdType = preader.readString();
+                        mIdPackage = preader.readString();
+                    }
+                }
             }
-            mExtras = in.readBundle();
-            final int NCHILDREN = in.readInt();
-            if (NCHILDREN > 0) {
+            if ((flags&FLAGS_HAS_LARGE_COORDS) != 0) {
+                mX = in.readInt();
+                mY = in.readInt();
+                mWidth = in.readInt();
+                mHeight = in.readInt();
+            } else {
+                int val = in.readInt();
+                mX = val&0x7fff;
+                mY = (val>>16)&0x7fff;
+                val = in.readInt();
+                mWidth = val&0x7fff;
+                mHeight = (val>>16)&0x7fff;
+            }
+            if ((flags&FLAGS_HAS_SCROLL) != 0) {
+                mScrollX = in.readInt();
+                mScrollY = in.readInt();
+            }
+            if ((flags&FLAGS_HAS_MATRIX) != 0) {
+                mMatrix = new Matrix();
+                in.readFloatArray(tmpMatrix);
+                mMatrix.setValues(tmpMatrix);
+            }
+            if ((flags&FLAGS_HAS_ELEVATION) != 0) {
+                mElevation = in.readFloat();
+            }
+            if ((flags&FLAGS_HAS_ALPHA) != 0) {
+                mAlpha = in.readFloat();
+            }
+            if ((flags&FLAGS_HAS_CONTENT_DESCRIPTION) != 0) {
+                mContentDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+            }
+            if ((flags&FLAGS_HAS_TEXT) != 0) {
+                mText = new ViewNodeText(in);
+            }
+            if ((flags&FLAGS_HAS_EXTRAS) != 0) {
+                mExtras = in.readBundle();
+            }
+            if ((flags&FLAGS_HAS_CHILDREN) != 0) {
+                final int NCHILDREN = in.readInt();
                 mChildren = new ViewNode[NCHILDREN];
                 for (int i=0; i<NCHILDREN; i++) {
-                    mChildren[i] = new ViewNode(in, preader);
+                    mChildren[i] = new ViewNode(in, preader, tmpMatrix);
                 }
-            } else {
-                mChildren = null;
             }
         }
 
-        void writeToParcel(Parcel out, PooledStringWriter pwriter) {
-            out.writeInt(mId);
-            if (mId != 0) {
-                pwriter.writeString(mIdEntry);
-                if (mIdEntry != null) {
-                    pwriter.writeString(mIdType);
-                    pwriter.writeString(mIdPackage);
+        int writeToParcel(Parcel out, PooledStringWriter pwriter, float[] tmpMatrix) {
+            int flags = mFlags & ~FLAGS_ALL_CONTROL;
+            if (mId != View.NO_ID) {
+                flags |= FLAGS_HAS_ID;
+            }
+            if ((mX&~0x7fff) != 0 || (mY&~0x7fff) != 0
+                    || (mWidth&~0x7fff) != 0 | (mHeight&~0x7fff) != 0) {
+                flags |= FLAGS_HAS_LARGE_COORDS;
+            }
+            if (mScrollX != 0 || mScrollY != 0) {
+                flags |= FLAGS_HAS_SCROLL;
+            }
+            if (mMatrix != null) {
+                flags |= FLAGS_HAS_MATRIX;
+            }
+            if (mElevation != 0) {
+                flags |= FLAGS_HAS_ELEVATION;
+            }
+            if (mAlpha != 1.0f) {
+                flags |= FLAGS_HAS_ALPHA;
+            }
+            if (mContentDescription != null) {
+                flags |= FLAGS_HAS_CONTENT_DESCRIPTION;
+            }
+            if (mText != null) {
+                flags |= FLAGS_HAS_TEXT;
+            }
+            if (mExtras != null) {
+                flags |= FLAGS_HAS_EXTRAS;
+            }
+            if (mChildren != null) {
+                flags |= FLAGS_HAS_CHILDREN;
+            }
+
+            pwriter.writeString(mClassName);
+            out.writeInt(flags);
+            if ((flags&FLAGS_HAS_ID) != 0) {
+                out.writeInt(mId);
+                if (mId != 0) {
+                    pwriter.writeString(mIdEntry);
+                    if (mIdEntry != null) {
+                        pwriter.writeString(mIdType);
+                        pwriter.writeString(mIdPackage);
+                    }
                 }
             }
-            out.writeInt(mX);
-            out.writeInt(mY);
-            out.writeInt(mScrollX);
-            out.writeInt(mScrollY);
-            out.writeInt(mWidth);
-            out.writeInt(mHeight);
-            out.writeInt(mFlags);
-            pwriter.writeString(mClassName);
-            TextUtils.writeToParcel(mContentDescription, out, 0);
-            if (mText != null) {
-                out.writeInt(1);
-                mText.writeToParcel(out);
+            if ((flags&FLAGS_HAS_LARGE_COORDS) != 0) {
+                out.writeInt(mX);
+                out.writeInt(mY);
+                out.writeInt(mWidth);
+                out.writeInt(mHeight);
             } else {
-                out.writeInt(0);
+                out.writeInt((mY<<16) | mX);
+                out.writeInt((mHeight<<16) | mWidth);
             }
-            out.writeBundle(mExtras);
-            if (mChildren != null) {
+            if ((flags&FLAGS_HAS_SCROLL) != 0) {
+                out.writeInt(mScrollX);
+                out.writeInt(mScrollY);
+            }
+            if ((flags&FLAGS_HAS_MATRIX) != 0) {
+                mMatrix.getValues(tmpMatrix);
+                out.writeFloatArray(tmpMatrix);
+            }
+            if ((flags&FLAGS_HAS_ELEVATION) != 0) {
+                out.writeFloat(mElevation);
+            }
+            if ((flags&FLAGS_HAS_ALPHA) != 0) {
+                out.writeFloat(mAlpha);
+            }
+            if ((flags&FLAGS_HAS_CONTENT_DESCRIPTION) != 0) {
+                TextUtils.writeToParcel(mContentDescription, out, 0);
+            }
+            if ((flags&FLAGS_HAS_TEXT) != 0) {
+                mText.writeToParcel(out);
+            }
+            if ((flags&FLAGS_HAS_EXTRAS) != 0) {
+                out.writeBundle(mExtras);
+            }
+            int N = 1;
+            if ((flags&FLAGS_HAS_CHILDREN) != 0) {
                 final int NCHILDREN = mChildren.length;
                 out.writeInt(NCHILDREN);
                 for (int i=0; i<NCHILDREN; i++) {
-                    mChildren[i].writeToParcel(out, pwriter);
+                    N += mChildren[i].writeToParcel(out, pwriter, tmpMatrix);
                 }
-            } else {
-                out.writeInt(0);
             }
+            return N;
         }
 
         /**
@@ -408,6 +498,33 @@
         }
 
         /**
+         * Returns the transformation that has been applied to this view, such as a translation
+         * or scaling.  The returned Matrix object is owned by ViewNode; do not modify it.
+         * Returns null if there is no transformation applied to the view.
+         */
+        public Matrix getTransformation() {
+            return mMatrix;
+        }
+
+        /**
+         * Returns the visual elevation of the view, used for shadowing and other visual
+         * characterstics, as set by {@link ViewStructure#setElevation
+         * ViewStructure.setElevation(float)}.
+         */
+        public float getElevation() {
+            return mElevation;
+        }
+
+        /**
+         * Returns the alpha transformation of the view, used to reduce the overall opacity
+         * of the view's contents, as set by {@link ViewStructure#setAlpha
+         * ViewStructure.setAlpha(float)}.
+         */
+        public float getAlpha() {
+            return mAlpha;
+        }
+
+        /**
          * Returns the visibility mode of this view, as per
          * {@link android.view.View#getVisibility() View.getVisibility()}.
          */
@@ -646,6 +763,25 @@
         }
 
         @Override
+        public void setTransformation(Matrix matrix) {
+            if (matrix == null) {
+                mNode.mMatrix = null;
+            } else {
+                mNode.mMatrix = new Matrix(matrix);
+            }
+        }
+
+        @Override
+        public void setElevation(float elevation) {
+            mNode.mElevation = elevation;
+        }
+
+        @Override
+        public void setAlpha(float alpha) {
+            mNode.mAlpha = alpha;
+        }
+
+        @Override
         public void setVisibility(int visibility) {
             mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_VISIBILITY_MASK) | visibility;
         }
@@ -919,6 +1055,18 @@
         if (scrollX != 0 || scrollY != 0) {
             Log.i(TAG, prefix + "  Scroll: " + scrollX + "," + scrollY);
         }
+        Matrix matrix = node.getTransformation();
+        if (matrix != null) {
+            Log.i(TAG, prefix + "  Transformation: " + matrix);
+        }
+        float elevation = node.getElevation();
+        if (elevation != 0) {
+            Log.i(TAG, prefix + "  Elevation: " + elevation);
+        }
+        float alpha = node.getAlpha();
+        if (alpha != 0) {
+            Log.i(TAG, prefix + "  Alpha: " + elevation);
+        }
         CharSequence contentDescription = node.getContentDescription();
         if (contentDescription != null) {
             Log.i(TAG, prefix + "  Content description: " + contentDescription);
@@ -1010,27 +1158,33 @@
             }
             if (mPendingAsyncChildren.size() > 0) {
                 // We waited too long, assume none of the assist structure is valid.
+                Log.w(TAG, "Skipping assist structure, waiting too long for async children (have "
+                        + mPendingAsyncChildren.size() + " remaining");
                 skipStructure = true;
             }
         }
         int start = out.dataPosition();
         PooledStringWriter pwriter = new PooledStringWriter(out);
+        float[] tmpMatrix = new float[9];
         ComponentName.writeToParcel(mActivityComponent, out);
         final int N = skipStructure ? 0 : mWindowNodes.size();
         out.writeInt(N);
+        int NV = 0;
         for (int i=0; i<N; i++) {
-            mWindowNodes.get(i).writeToParcel(out, pwriter);
+            NV += mWindowNodes.get(i).writeToParcel(out, pwriter, tmpMatrix);
         }
         pwriter.finish();
-        Log.i(TAG, "Flattened assist data: " + (out.dataPosition() - start) + " bytes");
+        Log.i(TAG, "Flattened assist data: " + (out.dataPosition() - start) + " bytes, containing "
+                + N + " windows, " + NV + " views");
     }
 
     void readContentFromParcel(Parcel in) {
         PooledStringReader preader = new PooledStringReader(in);
+        float[] tmpMatrix = new float[9];
         mActivityComponent = ComponentName.readFromParcel(in);
         final int N = in.readInt();
         for (int i=0; i<N; i++) {
-            mWindowNodes.add(new WindowNode(in, preader));
+            mWindowNodes.add(new WindowNode(in, preader, tmpMatrix));
         }
         //dump();
     }
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 83d6cb0..b1d80f0 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -3784,6 +3784,9 @@
     /** {@hide} */
     public static final String EXTRA_REASON = "android.intent.extra.REASON";
 
+    /** {@hide} */
+    public static final String EXTRA_WIPE_EXTERNAL_STORAGE = "android.intent.extra.WIPE_EXTERNAL_STORAGE";
+
     /**
      * Optional {@link android.app.PendingIntent} extra used to deliver the result of the SIM
      * activation request.
diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java
index e267b52..19329ce 100644
--- a/core/java/android/content/IntentFilter.java
+++ b/core/java/android/content/IntentFilter.java
@@ -518,7 +518,8 @@
     }
 
     /**
-     * Return if this filter handle all HTTP or HTTPS data URI or not.
+     * Return if this filter handle all HTTP or HTTPS data URI or not.  This is the
+     * core check for whether a given activity qualifies as a "browser".
      *
      * @return True if the filter handle all HTTP or HTTPS data URI. False otherwise.
      *
@@ -533,23 +534,26 @@
      */
     public final boolean handleAllWebDataURI() {
         return hasCategory(Intent.CATEGORY_APP_BROWSER) ||
-                (hasOnlyWebDataURI() && countDataAuthorities() == 0);
+                (handlesWebUris(false) && countDataAuthorities() == 0);
     }
 
     /**
-     * Return if this filter handles only HTTP or HTTPS data URIs.
+     * Return if this filter handles HTTP or HTTPS data URIs.
      *
      * @return True if the filter handles ACTION_VIEW/CATEGORY_BROWSABLE,
-     * has at least one HTTP or HTTPS data URI pattern defined, and does not
-     * define any non-http/https data URI patterns.
+     * has at least one HTTP or HTTPS data URI pattern defined, and optionally
+     * does not define any non-http/https data URI patterns.
      *
      * This will check if if the Intent action is {@link android.content.Intent#ACTION_VIEW} and
      * the Intent category is {@link android.content.Intent#CATEGORY_BROWSABLE} and the Intent
      * data scheme is "http" or "https".
      *
+     * @param onlyWebSchemes When true, requires that the intent filter declare
+     *     that it handles *only* http: or https: schemes.  This is a requirement for
+     *     the intent filter's domain linkage being verifiable.
      * @hide
      */
-    public final boolean hasOnlyWebDataURI() {
+    public final boolean handlesWebUris(boolean onlyWebSchemes) {
         // Require ACTION_VIEW, CATEGORY_BROWSEABLE, and at least one scheme
         if (!hasAction(Intent.ACTION_VIEW)
             || !hasCategory(Intent.CATEGORY_BROWSABLE)
@@ -562,13 +566,28 @@
         final int N = mDataSchemes.size();
         for (int i = 0; i < N; i++) {
             final String scheme = mDataSchemes.get(i);
-            if (!SCHEME_HTTP.equals(scheme) && !SCHEME_HTTPS.equals(scheme)) {
-                return false;
+            final boolean isWebScheme =
+                    SCHEME_HTTP.equals(scheme) || SCHEME_HTTPS.equals(scheme);
+            if (onlyWebSchemes) {
+                // If we're specifically trying to ensure that there are no non-web schemes
+                // declared in this filter, then if we ever see a non-http/https scheme then
+                // we know it's a failure.
+                if (!isWebScheme) {
+                    return false;
+                }
+            } else {
+                // If we see any http/https scheme declaration in this case then the
+                // filter matches what we're looking for.
+                if (isWebScheme) {
+                    return true;
+                }
             }
         }
 
-        // Everything passed, so it's an only-web-URIs filter
-        return true;
+        // We get here if:
+        //   1) onlyWebSchemes and no non-web schemes were found, i.e success; or
+        //   2) !onlyWebSchemes and no http/https schemes were found, i.e. failure.
+        return onlyWebSchemes;
     }
 
     /**
@@ -585,7 +604,7 @@
      * @hide
      */
     public final boolean needsVerification() {
-        return getAutoVerify() && hasOnlyWebDataURI();
+        return getAutoVerify() && handlesWebUris(true);
     }
 
     /**
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index c9853df..cea6e99 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -102,6 +102,8 @@
 
     void revokeRuntimePermission(String packageName, String permissionName, int userId);
 
+    void resetRuntimePermissions();
+
     int getPermissionFlags(String permissionName, String packageName, int userId);
 
     void updatePermissionFlags(String permissionName, String packageName, int flagMask,
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index a88b71c..c47498d 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -2738,35 +2738,13 @@
     /**
      * <p>The maximum number of frames that can occur after a request
      * (different than the previous) has been submitted, and before the
-     * result's state becomes synchronized (by setting
-     * android.sync.frameNumber to a non-negative value).</p>
+     * result's state becomes synchronized.</p>
      * <p>This defines the maximum distance (in number of metadata results),
-     * between android.sync.frameNumber and the equivalent
-     * frame number for that result.</p>
+     * between the frame number of the request that has new controls to apply
+     * and the frame number of the result that has all the controls applied.</p>
      * <p>In other words this acts as an upper boundary for how many frames
      * must occur before the camera device knows for a fact that the new
      * submitted camera settings have been applied in outgoing frames.</p>
-     * <p>For example if the distance was 2,</p>
-     * <pre><code>initial request = X (repeating)
-     * request1 = X
-     * request2 = Y
-     * request3 = Y
-     * request4 = Y
-     *
-     * where requestN has frameNumber N, and the first of the repeating
-     * initial request's has frameNumber F (and F &lt; 1).
-     *
-     * initial result = X' + { android.sync.frameNumber == F }
-     * result1 = X' + { android.sync.frameNumber == F }
-     * result2 = X' + { android.sync.frameNumber == CONVERGING }
-     * result3 = X' + { android.sync.frameNumber == CONVERGING }
-     * result4 = X' + { android.sync.frameNumber == 2 }
-     *
-     * where resultN has frameNumber N.
-     * </code></pre>
-     * <p>Since <code>result4</code> has a <code>frameNumber == 4</code> and
-     * <code>android.sync.frameNumber == 2</code>, the distance is clearly
-     * <code>4 - 2 = 2</code>.</p>
      * <p><b>Units</b>: Frame counts</p>
      * <p><b>Possible values:</b>
      * <ul>
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index 006030c..639c8b1 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -236,13 +236,16 @@
      * {@link CameraCaptureSession.StateCallback}'s
      * {@link CameraCaptureSession.StateCallback#onConfigured} callback will be called.</p>
      *
-     * <p>If a prior CameraCaptureSession already exists when a new one is created, the previous
-     * session is closed. Any in-progress capture requests made on the prior session will be
-     * completed before the new session is configured and is able to start capturing its own
-     * requests. To minimize the transition time, the {@link CameraCaptureSession#abortCaptures}
-     * call can be used to discard the remaining requests for the prior capture session before a new
-     * one is created. Note that once the new session is created, the old one can no longer have its
-     * captures aborted.</p>
+     * <p>If a prior CameraCaptureSession already exists when this method is called, the previous
+     * session will no longer be able to accept new capture requests and will be closed. Any
+     * in-progress capture requests made on the prior session will be completed before it's closed.
+     * {@link CameraCaptureSession.StateListener#onConfigured} for the new session may be invoked
+     * before {@link CameraCaptureSession.StateListener#onClosed} is invoked for the prior
+     * session. Once the new session is {@link CameraCaptureSession.StateListener#onConfigured
+     * configured}, it is able to start capturing its own requests. To minimize the transition time,
+     * the {@link CameraCaptureSession#abortCaptures} call can be used to discard the remaining
+     * requests for the prior capture session before a new one is created. Note that once the new
+     * session is created, the old one can no longer have its captures aborted.</p>
      *
      * <p>Using larger resolution outputs, or more outputs, can result in slower
      * output rate from the device.</p>
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index 5a80585..e8dbc5b 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -955,8 +955,6 @@
 
     /**
      * <p>Every frame has the requests immediately applied.</p>
-     * <p>Furthermore for all results,
-     * <code>android.sync.frameNumber == {@link android.hardware.camera2.CaptureResult#getFrameNumber }</code></p>
      * <p>Changing controls over multiple requests one after another will
      * produce results that have those controls applied atomically
      * each frame.</p>
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index 75289f7..33cc962 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -1062,6 +1062,15 @@
      * capturing a high-resolution JPEG image will automatically trigger a
      * precapture sequence before the high-resolution capture, including
      * potentially firing a pre-capture flash.</p>
+     * <p>Using the precapture trigger and the auto-focus trigger {@link CaptureRequest#CONTROL_AF_TRIGGER android.control.afTrigger}
+     * simultaneously is allowed. However, since these triggers often require cooperation between
+     * the auto-focus and auto-exposure routines (for example, the may need to be enabled for a
+     * focus sweep), the camera device may delay acting on a later trigger until the previous
+     * trigger has been fully handled. This may lead to longer intervals between the trigger and
+     * changes to {@link CaptureResult#CONTROL_AE_STATE android.control.aeState} indicating the start of the precapture sequence, for
+     * example.</p>
+     * <p>If both the precapture and the auto-focus trigger are activated on the same request, then
+     * the camera device will complete them in the optimal order for that device.</p>
      * <p><b>Possible values:</b>
      * <ul>
      *   <li>{@link #CONTROL_AE_PRECAPTURE_TRIGGER_IDLE IDLE}</li>
@@ -1075,6 +1084,7 @@
      *
      * @see CaptureRequest#CONTROL_AE_LOCK
      * @see CaptureResult#CONTROL_AE_STATE
+     * @see CaptureRequest#CONTROL_AF_TRIGGER
      * @see CaptureRequest#CONTROL_CAPTURE_INTENT
      * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
      * @see #CONTROL_AE_PRECAPTURE_TRIGGER_IDLE
@@ -1179,6 +1189,12 @@
      * START for multiple captures in a row means restarting the AF operation over
      * and over again.</p>
      * <p>See {@link CaptureResult#CONTROL_AF_STATE android.control.afState} for what the trigger means for each AF mode.</p>
+     * <p>Using the autofocus trigger and the precapture trigger {@link CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER android.control.aePrecaptureTrigger}
+     * simultaneously is allowed. However, since these triggers often require cooperation between
+     * the auto-focus and auto-exposure routines (for example, the may need to be enabled for a
+     * focus sweep), the camera device may delay acting on a later trigger until the previous
+     * trigger has been fully handled. This may lead to longer intervals between the trigger and
+     * changes to {@link CaptureResult#CONTROL_AF_STATE android.control.afState}, for example.</p>
      * <p><b>Possible values:</b>
      * <ul>
      *   <li>{@link #CONTROL_AF_TRIGGER_IDLE IDLE}</li>
@@ -1187,6 +1203,7 @@
      * </ul></p>
      * <p>This key is available on all devices.</p>
      *
+     * @see CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER
      * @see CaptureResult#CONTROL_AF_STATE
      * @see #CONTROL_AF_TRIGGER_IDLE
      * @see #CONTROL_AF_TRIGGER_START
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index 1d31109..9dee045 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -779,6 +779,15 @@
      * capturing a high-resolution JPEG image will automatically trigger a
      * precapture sequence before the high-resolution capture, including
      * potentially firing a pre-capture flash.</p>
+     * <p>Using the precapture trigger and the auto-focus trigger {@link CaptureRequest#CONTROL_AF_TRIGGER android.control.afTrigger}
+     * simultaneously is allowed. However, since these triggers often require cooperation between
+     * the auto-focus and auto-exposure routines (for example, the may need to be enabled for a
+     * focus sweep), the camera device may delay acting on a later trigger until the previous
+     * trigger has been fully handled. This may lead to longer intervals between the trigger and
+     * changes to {@link CaptureResult#CONTROL_AE_STATE android.control.aeState} indicating the start of the precapture sequence, for
+     * example.</p>
+     * <p>If both the precapture and the auto-focus trigger are activated on the same request, then
+     * the camera device will complete them in the optimal order for that device.</p>
      * <p><b>Possible values:</b>
      * <ul>
      *   <li>{@link #CONTROL_AE_PRECAPTURE_TRIGGER_IDLE IDLE}</li>
@@ -792,6 +801,7 @@
      *
      * @see CaptureRequest#CONTROL_AE_LOCK
      * @see CaptureResult#CONTROL_AE_STATE
+     * @see CaptureRequest#CONTROL_AF_TRIGGER
      * @see CaptureRequest#CONTROL_CAPTURE_INTENT
      * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
      * @see #CONTROL_AE_PRECAPTURE_TRIGGER_IDLE
@@ -1139,6 +1149,12 @@
      * START for multiple captures in a row means restarting the AF operation over
      * and over again.</p>
      * <p>See {@link CaptureResult#CONTROL_AF_STATE android.control.afState} for what the trigger means for each AF mode.</p>
+     * <p>Using the autofocus trigger and the precapture trigger {@link CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER android.control.aePrecaptureTrigger}
+     * simultaneously is allowed. However, since these triggers often require cooperation between
+     * the auto-focus and auto-exposure routines (for example, the may need to be enabled for a
+     * focus sweep), the camera device may delay acting on a later trigger until the previous
+     * trigger has been fully handled. This may lead to longer intervals between the trigger and
+     * changes to {@link CaptureResult#CONTROL_AF_STATE android.control.afState}, for example.</p>
      * <p><b>Possible values:</b>
      * <ul>
      *   <li>{@link #CONTROL_AF_TRIGGER_IDLE IDLE}</li>
@@ -1147,6 +1163,7 @@
      * </ul></p>
      * <p>This key is available on all devices.</p>
      *
+     * @see CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER
      * @see CaptureResult#CONTROL_AF_STATE
      * @see #CONTROL_AF_TRIGGER_IDLE
      * @see #CONTROL_AF_TRIGGER_START
diff --git a/core/java/android/hardware/fingerprint/IFingerprintService.aidl b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
index 0484806..f596c93 100644
--- a/core/java/android/hardware/fingerprint/IFingerprintService.aidl
+++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
@@ -26,7 +26,7 @@
  */
 interface IFingerprintService {
     // Authenticate the given sessionId with a fingerprint
-    void authenticate(IBinder token, long sessionId, int groupId,
+    void authenticate(IBinder token, long sessionId, int userId,
             IFingerprintServiceReceiver receiver, int flags, String opPackageName);
 
     // Cancel authentication for the given sessionId
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 50eed3e..b2ced7f 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -622,7 +622,7 @@
         /**
          * M comes after L.
          */
-        public static final int MNC = CUR_DEVELOPMENT;
+        public static final int MNC = 23;
     }
 
     /** The type of build, like "user" or "eng". */
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index 0309d24..d424546 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -369,7 +369,9 @@
 
     /**
      * Inform the notification manager that these notifications have been viewed by the
-     * user.
+     * user. This should only be called when there is sufficient confidence that the user is
+     * looking at the notifications, such as when the notifications appear on the screen due to
+     * an explicit user interaction.
      * @param keys Notifications to mark as seen.
      */
     public final void setNotificationsShown(String[] keys) {
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index 3eeb04a..eae4329 100644
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -1486,19 +1486,28 @@
                     // Get the default voice for the locale.
                     String voiceName = service.getDefaultVoiceNameFor(language, country, variant);
                     if (TextUtils.isEmpty(voiceName)) {
-                        Log.w(TAG, "Couldn't find the default voice for " + language + "/" +
-                                country + "/" + variant);
+                        Log.w(TAG, "Couldn't find the default voice for " + language + "-" +
+                                country + "-" + variant);
                         return LANG_NOT_SUPPORTED;
                     }
 
                     // Load it.
                     if (service.loadVoice(getCallerIdentity(), voiceName) == TextToSpeech.ERROR) {
+                        Log.w(TAG, "The service claimed " + language + "-" + country + "-"
+                                + variant + " was available with voice name " + voiceName
+                                + " but loadVoice returned ERROR");
                         return LANG_NOT_SUPPORTED;
                     }
 
                     // Set the language/country/variant of the voice, so #getLanguage will return
                     // the currently set voice locale when called.
                     Voice voice = getVoice(service, voiceName);
+                    if (voice == null) {
+                        Log.w(TAG, "getDefaultVoiceNameFor returned " + voiceName + " for locale "
+                                + language + "-" + country + "-" + variant
+                                + " but getVoice returns null");
+                        return LANG_NOT_SUPPORTED;
+                    }
                     String voiceLanguage = "";
                     try {
                         voiceLanguage = voice.getLocale().getISO3Language();
@@ -1682,6 +1691,7 @@
     private Voice getVoice(ITextToSpeechService service, String voiceName) throws RemoteException {
         List<Voice> voices = service.getVoices();
         if (voices == null) {
+            Log.w(TAG, "getVoices returned null");
             return null;
         }
         for (Voice voice : voices) {
@@ -1689,6 +1699,7 @@
                 return voice;
             }
         }
+        Log.w(TAG, "Could not find voice " + voiceName + " in voice list");
         return null;
     }
 
diff --git a/core/java/android/speech/tts/TextToSpeechService.java b/core/java/android/speech/tts/TextToSpeechService.java
index ba98f27..fa015b2 100644
--- a/core/java/android/speech/tts/TextToSpeechService.java
+++ b/core/java/android/speech/tts/TextToSpeechService.java
@@ -293,7 +293,9 @@
             }
             Set<String> features = onGetFeaturesForLanguage(locale.getISO3Language(),
                     locale.getISO3Country(), locale.getVariant());
-            voices.add(new Voice(locale.toLanguageTag(), locale, Voice.QUALITY_NORMAL,
+            String voiceName = onGetDefaultVoiceNameFor(locale.getISO3Language(),
+                    locale.getISO3Country(), locale.getVariant());
+            voices.add(new Voice(voiceName, locale, Voice.QUALITY_NORMAL,
                     Voice.LATENCY_NORMAL, false, features));
         }
         return voices;
diff --git a/core/java/android/text/method/WordIterator.java b/core/java/android/text/method/WordIterator.java
index 5dda8a7..3688cfa 100644
--- a/core/java/android/text/method/WordIterator.java
+++ b/core/java/android/text/method/WordIterator.java
@@ -147,24 +147,13 @@
      * @throws IllegalArgumentException is offset is not valid.
      */
     public int getBeginning(int offset) {
-        final int shiftedOffset = offset - mOffsetShift;
-        checkOffsetIsValid(shiftedOffset);
-
-        if (isOnLetterOrDigit(shiftedOffset)) {
-            if (mIterator.isBoundary(shiftedOffset)) {
-                return shiftedOffset + mOffsetShift;
-            } else {
-                return mIterator.preceding(shiftedOffset) + mOffsetShift;
-            }
-        } else {
-            if (isAfterLetterOrDigit(shiftedOffset)) {
-                return mIterator.preceding(shiftedOffset) + mOffsetShift;
-            }
-        }
-        return BreakIterator.DONE;
+        // TODO: Check if usage of this can be updated to getBeginning(offset, true) if
+        // so this method can be removed.
+        return getBeginning(offset, false);
     }
 
-    /** If <code>offset</code> is within a word, returns the index of the last character of that
+    /**
+     * If <code>offset</code> is within a word, returns the index of the last character of that
      * word plus one, otherwise returns BreakIterator.DONE.
      *
      * The offsets that are considered to be part of a word are the indexes of its characters,
@@ -177,11 +166,106 @@
      * @throws IllegalArgumentException is offset is not valid.
      */
     public int getEnd(int offset) {
+        // TODO: Check if usage of this can be updated to getEnd(offset, true), if
+        // so this method can be removed.
+        return getEnd(offset, false);
+    }
+
+    /**
+     * If the <code>offset</code> is within a word or on a word boundary that can only be
+     * considered the start of a word (e.g. _word where "_" is any character that would not
+     * be considered part of the word) then this returns the index of the first character of
+     * that word.
+     *
+     * If the offset is on a word boundary that can be considered the start and end of a
+     * word, e.g. AABB (where AA and BB are both words) and the offset is the boundary
+     * between AA and BB, this would return the start of the previous word, AA.
+     *
+     * Returns BreakIterator.DONE if there is no previous boundary.
+     *
+     * @throws IllegalArgumentException is offset is not valid.
+     */
+    public int getPrevWordBeginningOnTwoWordsBoundary(int offset) {
+        return getBeginning(offset, true);
+    }
+
+    /**
+     * If the <code>offset</code> is within a word or on a word boundary that can only be
+     * considered the end of a word (e.g. word_ where "_" is any character that would not
+     * be considered part of the word) then this returns the index of the last character
+     * plus one of that word.
+     *
+     * If the offset is on a word boundary that can be considered the start and end of a
+     * word, e.g. AABB (where AA and BB are both words) and the offset is the boundary
+     * between AA and BB, this would return the end of the next word, BB.
+     *
+     * Returns BreakIterator.DONE if there is no next boundary.
+     *
+     * @throws IllegalArgumentException is offset is not valid.
+     */
+    public int getNextWordEndOnTwoWordBoundary(int offset) {
+        return getEnd(offset, true);
+    }
+
+    /**
+     * If the <code>offset</code> is within a word or on a word boundary that can only be
+     * considered the start of a word (e.g. _word where "_" is any character that would not
+     * be considered part of the word) then this returns the index of the first character of
+     * that word.
+     *
+     * If the offset is on a word boundary that can be considered the start and end of a
+     * word, e.g. AABB (where AA and BB are both words) and the offset is the boundary
+     * between AA and BB, and getPrevWordBeginningOnTwoWordsBoundary is true then this would
+     * return the start of the previous word, AA. Otherwise it would return the current offset,
+     * the start of BB.
+     *
+     * Returns BreakIterator.DONE if there is no previous boundary.
+     *
+     * @throws IllegalArgumentException is offset is not valid.
+     */
+    private int getBeginning(int offset, boolean getPrevWordBeginningOnTwoWordsBoundary) {
+        final int shiftedOffset = offset - mOffsetShift;
+        checkOffsetIsValid(shiftedOffset);
+
+        if (isOnLetterOrDigit(shiftedOffset)) {
+            if (mIterator.isBoundary(shiftedOffset)
+                    && (!isAfterLetterOrDigit(shiftedOffset)
+                            || !getPrevWordBeginningOnTwoWordsBoundary)) {
+                return shiftedOffset + mOffsetShift;
+            } else {
+                return mIterator.preceding(shiftedOffset) + mOffsetShift;
+            }
+        } else {
+            if (isAfterLetterOrDigit(shiftedOffset)) {
+                return mIterator.preceding(shiftedOffset) + mOffsetShift;
+            }
+        }
+        return BreakIterator.DONE;
+    }
+
+    /**
+     * If the <code>offset</code> is within a word or on a word boundary that can only be
+     * considered the end of a word (e.g. word_ where "_" is any character that would not be
+     * considered part of the word) then this returns the index of the last character plus one
+     * of that word.
+     *
+     * If the offset is on a word boundary that can be considered the start and end of a
+     * word, e.g. AABB (where AA and BB are both words) and the offset is the boundary
+     * between AA and BB, and getNextWordEndOnTwoWordBoundary is true then this would return
+     * the end of the next word, BB. Otherwise it would return the current offset, the end
+     * of AA.
+     *
+     * Returns BreakIterator.DONE if there is no next boundary.
+     *
+     * @throws IllegalArgumentException is offset is not valid.
+     */
+    private int getEnd(int offset, boolean getNextWordEndOnTwoWordBoundary) {
         final int shiftedOffset = offset - mOffsetShift;
         checkOffsetIsValid(shiftedOffset);
 
         if (isAfterLetterOrDigit(shiftedOffset)) {
-            if (mIterator.isBoundary(shiftedOffset)) {
+            if (mIterator.isBoundary(shiftedOffset)
+                    && (!isOnLetterOrDigit(shiftedOffset) || !getNextWordEndOnTwoWordBoundary)) {
                 return shiftedOffset + mOffsetShift;
             } else {
                 return mIterator.following(shiftedOffset) + mOffsetShift;
diff --git a/core/java/android/transition/Transition.java b/core/java/android/transition/Transition.java
index 868b262..e958058 100644
--- a/core/java/android/transition/Transition.java
+++ b/core/java/android/transition/Transition.java
@@ -528,11 +528,13 @@
             ArrayMap<View, TransitionValues> unmatchedEnd) {
         for (int i = unmatchedStart.size() - 1; i >= 0; i--) {
             View view = unmatchedStart.keyAt(i);
-            TransitionValues end = unmatchedEnd.remove(view);
-            if (end != null) {
-                TransitionValues start = unmatchedStart.removeAt(i);
-                mStartValuesList.add(start);
-                mEndValuesList.add(end);
+            if (view != null && isValidTarget(view)) {
+                TransitionValues end = unmatchedEnd.remove(view);
+                if (end != null && end.view != null && isValidTarget(end.view)) {
+                    TransitionValues start = unmatchedStart.removeAt(i);
+                    mStartValuesList.add(start);
+                    mEndValuesList.add(end);
+                }
             }
         }
     }
@@ -548,9 +550,9 @@
         int numStartIds = startItemIds.size();
         for (int i = 0; i < numStartIds; i++) {
             View startView = startItemIds.valueAt(i);
-            if (startView != null) {
+            if (startView != null && isValidTarget(startView)) {
                 View endView = endItemIds.get(startItemIds.keyAt(i));
-                if (endView != null) {
+                if (endView != null && isValidTarget(endView)) {
                     TransitionValues startValues = unmatchedStart.get(startView);
                     TransitionValues endValues = unmatchedEnd.get(endView);
                     if (startValues != null && endValues != null) {
@@ -626,14 +628,20 @@
             ArrayMap<View, TransitionValues> unmatchedEnd) {
         // Views that only exist in the start Scene
         for (int i = 0; i < unmatchedStart.size(); i++) {
-            mStartValuesList.add(unmatchedStart.valueAt(i));
-            mEndValuesList.add(null);
+            final TransitionValues start = unmatchedStart.valueAt(i);
+            if (isValidTarget(start.view)) {
+                mStartValuesList.add(start);
+                mEndValuesList.add(null);
+            }
         }
 
         // Views that only exist in the end Scene
         for (int i = 0; i < unmatchedEnd.size(); i++) {
-            mEndValuesList.add(unmatchedEnd.valueAt(i));
-            mStartValuesList.add(null);
+            final TransitionValues end = unmatchedEnd.valueAt(i);
+            if (isValidTarget(end.view)) {
+                mEndValuesList.add(end);
+                mStartValuesList.add(null);
+            }
         }
     }
 
diff --git a/core/java/android/transition/TransitionManager.java b/core/java/android/transition/TransitionManager.java
index 5209f90..71c8099 100644
--- a/core/java/android/transition/TransitionManager.java
+++ b/core/java/android/transition/TransitionManager.java
@@ -435,10 +435,11 @@
         sPendingTransitions.remove(sceneRoot);
 
         final ArrayList<Transition> runningTransitions = getRunningTransitions().get(sceneRoot);
-        if (runningTransitions != null) {
-            final int count = runningTransitions.size();
-            for (int i = 0; i < count; i++) {
-                final Transition transition = runningTransitions.get(i);
+        if (runningTransitions != null && !runningTransitions.isEmpty()) {
+            // Make a copy in case this is called by an onTransitionEnd listener
+            ArrayList<Transition> copy = new ArrayList(runningTransitions);
+            for (int i = copy.size() - 1; i >= 0; i--) {
+                final Transition transition = copy.get(i);
                 transition.end();
             }
         }
diff --git a/core/java/android/util/LocalLog.java b/core/java/android/util/LocalLog.java
index cab5d19..4862f01 100644
--- a/core/java/android/util/LocalLog.java
+++ b/core/java/android/util/LocalLog.java
@@ -54,4 +54,18 @@
             pw.println(itr.next());
         }
     }
+
+    public static class ReadOnlyLocalLog {
+        private final LocalLog mLog;
+        ReadOnlyLocalLog(LocalLog log) {
+            mLog = log;
+        }
+        public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+            mLog.dump(fd, pw, args);
+        }
+    }
+
+    public ReadOnlyLocalLog readOnlyLocalLog() {
+        return new ReadOnlyLocalLog(this);
+    }
 }
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 92dae2e..23da6d2 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -6179,6 +6179,10 @@
             structure.setId(id, null, null, null);
         }
         structure.setDimens(mLeft, mTop, mScrollX, mScrollY, mRight - mLeft, mBottom - mTop);
+        if (!hasIdentityMatrix()) {
+            structure.setTransformation(getMatrix());
+        }
+        structure.setElevation(getZ());
         structure.setVisibility(getVisibility());
         structure.setEnabled(isEnabled());
         if (isClickable()) {
@@ -6215,11 +6219,6 @@
         structure.setContentDescription(getContentDescription());
     }
 
-    /** @hide */
-    public void onProvideAssistStructure(ViewStructure structure) {
-        onProvideStructure(structure);
-    }
-
     /**
      * Called when assist structure is being retrieved from a view as part of
      * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
@@ -6232,7 +6231,6 @@
         AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
         if (provider != null) {
             AccessibilityNodeInfo info = createAccessibilityNodeInfo();
-            Log.i("View", "Provider of " + this + ": children=" + info.getChildCount());
             structure.setChildCount(1);
             ViewStructure root = structure.newChild(0);
             populateVirtualStructure(root, provider, info);
@@ -6240,11 +6238,6 @@
         }
     }
 
-    /** @hide */
-    public void onProvideVirtualAssistStructure(ViewStructure structure) {
-        onProvideVirtualStructure(structure);
-    }
-
     private void populateVirtualStructure(ViewStructure structure,
             AccessibilityNodeProvider provider, AccessibilityNodeInfo info) {
         structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
@@ -6284,8 +6277,6 @@
         CharSequence cname = info.getClassName();
         structure.setClassName(cname != null ? cname.toString() : null);
         structure.setContentDescription(info.getContentDescription());
-        Log.i("View", "vassist " + cname + " @ " + rect.toShortString()
-                + " text=" + info.getText() + " cd=" + info.getContentDescription());
         if (info.getText() != null || info.getError() != null) {
             structure.setText(info.getText(), info.getTextSelectionStart(),
                     info.getTextSelectionEnd());
@@ -6310,8 +6301,8 @@
      */
     public void dispatchProvideStructure(ViewStructure structure) {
         if (!isAssistBlocked()) {
-            onProvideAssistStructure(structure);
-            onProvideVirtualAssistStructure(structure);
+            onProvideStructure(structure);
+            onProvideVirtualStructure(structure);
         } else {
             structure.setClassName(getAccessibilityClassName().toString());
             structure.setAssistBlocked(true);
@@ -8710,14 +8701,14 @@
     }
 
     /**
-     * Adds the children of a given View for accessibility. Since some Views are
-     * not important for accessibility the children for accessibility are not
-     * necessarily direct children of the view, rather they are the first level of
-     * descendants important for accessibility.
+     * Adds the children of this View relevant for accessibility to the given list
+     * as output. Since some Views are not important for accessibility the added
+     * child views are not necessarily direct children of this view, rather they are
+     * the first level of descendants important for accessibility.
      *
-     * @param children The list of children for accessibility.
+     * @param outChildren The output list that will receive children for accessibility.
      */
-    public void addChildrenForAccessibility(ArrayList<View> children) {
+    public void addChildrenForAccessibility(ArrayList<View> outChildren) {
 
     }
 
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 2e2ba88..b53d93c 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -1919,7 +1919,7 @@
     }
 
     @Override
-    public void addChildrenForAccessibility(ArrayList<View> childrenForAccessibility) {
+    public void addChildrenForAccessibility(ArrayList<View> outChildren) {
         if (getAccessibilityNodeProvider() != null) {
             return;
         }
@@ -1930,9 +1930,9 @@
                 View child = children.getChildAt(i);
                 if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) {
                     if (child.includeForAccessibility()) {
-                        childrenForAccessibility.add(child);
+                        outChildren.add(child);
                     } else {
-                        child.addChildrenForAccessibility(childrenForAccessibility);
+                        child.addChildrenForAccessibility(outChildren);
                     }
                 }
             }
diff --git a/core/java/android/view/ViewStructure.java b/core/java/android/view/ViewStructure.java
index 9ab0ace..794622a 100644
--- a/core/java/android/view/ViewStructure.java
+++ b/core/java/android/view/ViewStructure.java
@@ -16,6 +16,7 @@
 
 package android.view;
 
+import android.graphics.Matrix;
 import android.graphics.Rect;
 import android.os.Bundle;
 
@@ -50,6 +51,28 @@
             int height);
 
     /**
+     * Set the transformation matrix associated with this view, as per
+     * {@link View#getMatrix View.getMatrix()}, or null if there is none.
+     */
+    public abstract void setTransformation(Matrix matrix);
+
+    /**
+     * Set the visual elevation (shadow) of the view, as per
+     * {@link View#getZ View.getZ()}.  Note this is <em>not</em> related
+     * to the physical Z-ordering of this view relative to its other siblings (that is how
+     * they overlap when drawing), it is only the visual representation for shadowing.
+     */
+    public abstract void setElevation(float elevation);
+
+    /**
+     * Set an alpha transformation that is applied to this view, as per
+     * {@link View#getAlpha View.getAlpha()}.  Value ranges from 0
+     * (completely transparent) to 1 (completely opaque); the default is 1, which means
+     * no transformation.
+     */
+    public abstract void setAlpha(float alpha);
+
+    /**
      * Set the visibility state of this view, as per
      * {@link View#getVisibility View.getVisibility()}.
      */
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 48e69a1..84e7db4 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -123,6 +123,7 @@
     private static final float[] TEMP_POSITION = new float[2];
     private static int DRAG_SHADOW_MAX_TEXT_LENGTH = 20;
     private static final float LINE_SLOP_MULTIPLIER_FOR_HANDLEVIEWS = 0.5f;
+    private static final int UNSET_X_VALUE = -1;
     // Tag used when the Editor maintains its own separate UndoManager.
     private static final String UNDO_OWNER_TAG = "Editor";
 
@@ -735,7 +736,7 @@
             retOffset = getWordIteratorWithText().getPunctuationBeginning(offset);
         } else {
             // Not on a punctuation boundary, find the word start.
-            retOffset = getWordIteratorWithText().getBeginning(offset);
+            retOffset = getWordIteratorWithText().getPrevWordBeginningOnTwoWordsBoundary(offset);
         }
         if (retOffset == BreakIterator.DONE) {
             return offset;
@@ -750,7 +751,7 @@
             retOffset = getWordIteratorWithText().getPunctuationEnd(offset);
         } else {
             // Not on a punctuation boundary, find the word end.
-            retOffset = getWordIteratorWithText().getEnd(offset);
+            retOffset = getWordIteratorWithText().getNextWordEndOnTwoWordBoundary(offset);
         }
         if (retOffset == BreakIterator.DONE) {
             return offset;
@@ -4067,6 +4068,10 @@
         private boolean mInWord = false;
         // Difference between touch position and word boundary position.
         private float mTouchWordDelta;
+        // X value of the previous updatePosition call.
+        private float mPrevX;
+        // Indicates if the handle has moved a boundary between LTR and RTL text.
+        private boolean mLanguageDirectionChanged = false;
 
         public SelectionStartHandleView(Drawable drawableLtr, Drawable drawableRtl) {
             super(drawableLtr, drawableRtl);
@@ -4127,13 +4132,56 @@
             int end = getWordEnd(offset);
             int start = getWordStart(offset);
 
-            if (offset < mPreviousOffset) {
+            if (mPrevX == UNSET_X_VALUE) {
+                mPrevX = x;
+            }
+
+            final int selectionStart = mTextView.getSelectionStart();
+            final boolean selectionStartRtl = layout.isRtlCharAt(selectionStart);
+            final boolean atRtl = layout.isRtlCharAt(offset);
+            final boolean isLvlBoundary = layout.isLevelBoundary(offset);
+            boolean isExpanding;
+
+            // We can't determine if the user is expanding or shrinking the selection if they're
+            // on a bi-di boundary, so until they've moved past the boundary we'll just place
+            // the cursor at the current position.
+            if (isLvlBoundary || (selectionStartRtl && !atRtl) || (!selectionStartRtl && atRtl)) {
+                // We're on a boundary or this is the first direction change -- just update
+                // to the current position.
+                mLanguageDirectionChanged = true;
+                mTouchWordDelta = 0.0f;
+                positionAtCursorOffset(offset, false);
+                return;
+            } else if (mLanguageDirectionChanged && !isLvlBoundary) {
+                // We've just moved past the boundary so update the position. After this we can
+                // figure out if the user is expanding or shrinking to go by word or character.
+                positionAtCursorOffset(offset, false);
+                mTouchWordDelta = 0.0f;
+                mLanguageDirectionChanged = false;
+                return;
+            } else {
+                final float xDiff = x - mPrevX;
+                if (atRtl) {
+                    isExpanding = xDiff > 0 || currLine > mPrevLine;
+                } else {
+                    isExpanding = xDiff < 0 || currLine < mPrevLine;
+                }
+            }
+
+            if (isExpanding) {
                 // User is increasing the selection.
                 if (!mInWord || currLine < mPrevLine) {
-                    // We're not in a word, or we're on a different line so we'll expand by
-                    // word. First ensure the user has at least entered the next word.
-                    int offsetToWord = Math.min((end - start) / 2, 2);
-                    if (offset <= end - offsetToWord || currLine < mPrevLine) {
+                    // Sometimes words can be broken across lines (Chinese, hyphenation).
+                    // We still snap to the start of the word but we only use the letters on the
+                    // current line to determine if the user is far enough into the word to snap.
+                    int wordStartOnCurrLine = start;
+                    if (layout != null && layout.getLineForOffset(start) != currLine) {
+                        wordStartOnCurrLine = layout.getLineStart(currLine);
+                    }
+                    int offsetThresholdToSnap = end - ((end - wordStartOnCurrLine) / 2);
+                    if (offset <= offsetThresholdToSnap || currLine < mPrevLine) {
+                        // User is far enough into the word or on a different
+                        // line so we expand by word.
                         offset = start;
                     } else {
                         offset = mPreviousOffset;
@@ -4182,6 +4230,7 @@
                 }
                 positionAtCursorOffset(offset, false);
             }
+            mPrevX = x;
         }
 
         @Override
@@ -4196,6 +4245,7 @@
             if (event.getActionMasked() == MotionEvent.ACTION_UP) {
                 // Reset the touch word offset when the user has lifted their finger.
                 mTouchWordDelta = 0.0f;
+                mPrevX = UNSET_X_VALUE;
             }
             return superResult;
         }
@@ -4206,6 +4256,10 @@
         private boolean mInWord = false;
         // Difference between touch position and word boundary position.
         private float mTouchWordDelta;
+        // X value of the previous updatePosition call.
+        private float mPrevX;
+        // Indicates if the handle has moved a boundary between LTR and RTL text.
+        private boolean mLanguageDirectionChanged = false;
 
         public SelectionEndHandleView(Drawable drawableLtr, Drawable drawableRtl) {
             super(drawableLtr, drawableRtl);
@@ -4266,13 +4320,56 @@
             int end = getWordEnd(offset);
             int start = getWordStart(offset);
 
-            if (offset > mPreviousOffset) {
+            if (mPrevX == UNSET_X_VALUE) {
+                mPrevX = x;
+            }
+
+            final int selectionEnd = mTextView.getSelectionEnd();
+            final boolean selectionEndRtl = layout.isRtlCharAt(selectionEnd);
+            final boolean atRtl = layout.isRtlCharAt(offset);
+            final boolean isLvlBoundary = layout.isLevelBoundary(offset);
+            boolean isExpanding;
+
+            // We can't determine if the user is expanding or shrinking the selection if they're
+            // on a bi-di boundary, so until they've moved past the boundary we'll just place
+            // the cursor at the current position.
+            if (isLvlBoundary || (selectionEndRtl && !atRtl) || (!selectionEndRtl && atRtl)) {
+                // We're on a boundary or this is the first direction change -- just update
+                // to the current position.
+                mLanguageDirectionChanged = true;
+                mTouchWordDelta = 0.0f;
+                positionAtCursorOffset(offset, false);
+                return;
+            } else if (mLanguageDirectionChanged && !isLvlBoundary) {
+                // We've just moved past the boundary so update the position. After this we can
+                // figure out if the user is expanding or shrinking to go by word or character.
+                positionAtCursorOffset(offset, false);
+                mTouchWordDelta = 0.0f;
+                mLanguageDirectionChanged = false;
+                return;
+            } else {
+                final float xDiff = x - mPrevX;
+                if (atRtl) {
+                    isExpanding = xDiff < 0 || currLine < mPrevLine;
+                } else {
+                    isExpanding = xDiff > 0 || currLine > mPrevLine;
+                }
+            }
+
+            if (isExpanding) {
                 // User is increasing the selection.
                 if (!mInWord || currLine > mPrevLine) {
-                    // We're not in a word, or we're on a different line so we'll expand by
-                    // word. First ensure the user has at least entered the next word.
-                    int midPoint = Math.min((end - start) / 2, 2);
-                    if (offset >= start + midPoint || currLine > mPrevLine) {
+                    // Sometimes words can be broken across lines (Chinese, hyphenation).
+                    // We still snap to the end of the word but we only use the letters on the
+                    // current line to determine if the user is far enough into the word to snap.
+                    int wordEndOnCurrLine = end;
+                    if (layout != null && layout.getLineForOffset(end) != currLine) {
+                        wordEndOnCurrLine = layout.getLineEnd(currLine);
+                    }
+                    final int offsetThresholdToSnap = start + ((wordEndOnCurrLine - start) / 2);
+                    if (offset >= offsetThresholdToSnap || currLine > mPrevLine) {
+                        // User is far enough into the word or on a different
+                        // line so we expand by word.
                         offset = end;
                     } else {
                         offset = mPreviousOffset;
@@ -4321,6 +4418,7 @@
                 }
                 positionAtCursorOffset(offset, false);
             }
+            mPrevX = x;
         }
 
         @Override
@@ -4335,6 +4433,7 @@
             if (event.getActionMasked() == MotionEvent.ACTION_UP) {
                 // Reset the touch word offset when the user has lifted their finger.
                 mTouchWordDelta = 0.0f;
+                mPrevX = UNSET_X_VALUE;
             }
             return superResult;
         }
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 310b474..7b58b5b 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -292,6 +292,9 @@
     // New state used to change background based on whether this TextView is multiline.
     private static final int[] MULTILINE_STATE_SET = { R.attr.state_multiline };
 
+    // Accessibility action to share selected text.
+    private static final int ACCESSIBILITY_ACTION_SHARE = 0x10000000;
+
     // System wide time for last cut, copy or text changed action.
     static long sLastCutCopyOrTextChangedTime;
 
@@ -7574,10 +7577,14 @@
     }
 
     String getSelectedText() {
-        if (hasSelection()) {
-            return String.valueOf(mText.subSequence(getSelectionStart(), getSelectionEnd()));
+        if (!hasSelection()) {
+            return null;
         }
-        return null;
+
+        final int start = getSelectionStart();
+        final int end = getSelectionEnd();
+        return String.valueOf(
+                start > end ? mText.subSequence(end, start) : mText.subSequence(start, end));
     }
 
     /**
@@ -8845,6 +8852,11 @@
             if (canCut()) {
                 info.addAction(AccessibilityNodeInfo.ACTION_CUT);
             }
+            if (canShare()) {
+                info.addAction(new AccessibilityNodeInfo.AccessibilityAction(
+                        ACCESSIBILITY_ACTION_SHARE,
+                        getResources().getString(com.android.internal.R.string.share)));
+            }
         }
 
         // Check for known input filter types.
@@ -8951,6 +8963,13 @@
                 ensureIterableTextForAccessibilitySelectable();
                 return super.performAccessibilityActionInternal(action, arguments);
             }
+            case ACCESSIBILITY_ACTION_SHARE: {
+                if (isFocused() && canShare()) {
+                    if (onTextContextMenuItem(ID_SHARE)) {
+                        return true;
+                    }
+                }
+            } return false;
             default: {
                 return super.performAccessibilityActionInternal(action, arguments);
             }
@@ -9658,6 +9677,7 @@
         // controllers interact with how selection behaves.
         if (mEditor != null) {
             mEditor.hideCursorAndSpanControllers();
+            mEditor.stopTextActionMode();
         }
         CharSequence text = getIterableTextForAccessibility();
         if (Math.min(start, end) >= 0 && Math.max(start, end) <= text.length()) {
diff --git a/core/java/com/android/internal/os/storage/ExternalStorageFormatter.java b/core/java/com/android/internal/os/storage/ExternalStorageFormatter.java
index 1d0511f..0a01ae9 100644
--- a/core/java/com/android/internal/os/storage/ExternalStorageFormatter.java
+++ b/core/java/com/android/internal/os/storage/ExternalStorageFormatter.java
@@ -17,6 +17,10 @@
 
 /**
  * Takes care of unmounting and formatting external storage.
+ *
+ * @deprecated Please use {@link Intent#ACTION_MASTER_CLEAR} broadcast with extra
+ * {@link Intent#EXTRA_WIPE_EXTERNAL_STORAGE} to wipe and factory reset, or call
+ * {@link StorageManager#wipeAdoptableDisks} directly to format external storages.
  */
 public class ExternalStorageFormatter extends Service {
     static final String TAG = "ExternalStorageFormatter";
diff --git a/core/java/com/android/internal/view/FloatingActionMode.java b/core/java/com/android/internal/view/FloatingActionMode.java
index 863506b..c869722 100644
--- a/core/java/com/android/internal/view/FloatingActionMode.java
+++ b/core/java/com/android/internal/view/FloatingActionMode.java
@@ -30,6 +30,8 @@
 import com.android.internal.view.menu.MenuBuilder;
 import com.android.internal.widget.FloatingToolbar;
 
+import java.util.Arrays;
+
 public class FloatingActionMode extends ActionMode {
 
     private static final int MAX_HIDE_DURATION = 3000;
@@ -42,7 +44,9 @@
     private final Rect mContentRectOnWindow;
     private final Rect mPreviousContentRectOnWindow;
     private final int[] mViewPosition;
+    private final int[] mPreviousViewPosition;
     private final Rect mViewRect;
+    private final Rect mPreviousViewRect;
     private final Rect mScreenRect;
     private final View mOriginatingView;
     private final int mBottomAllowance;
@@ -75,7 +79,9 @@
         mContentRectOnWindow = new Rect();
         mPreviousContentRectOnWindow = new Rect();
         mViewPosition = new int[2];
+        mPreviousViewPosition = new int[2];
         mViewRect = new Rect();
+        mPreviousViewRect = new Rect();
         mScreenRect = new Rect();
         mOriginatingView = Preconditions.checkNotNull(originatingView);
         mOriginatingView.getLocationInWindow(mViewPosition);
@@ -129,9 +135,17 @@
 
     public void updateViewLocationInWindow() {
         checkToolbarInitialized();
+
         mOriginatingView.getLocationInWindow(mViewPosition);
         mOriginatingView.getGlobalVisibleRect(mViewRect);
-        repositionToolbar();
+
+        if (!Arrays.equals(mViewPosition, mPreviousViewPosition)
+                || !mViewRect.equals(mPreviousViewRect)) {
+            repositionToolbar();
+            mPreviousViewPosition[0] = mViewPosition[0];
+            mPreviousViewPosition[1] = mViewPosition[1];
+            mPreviousViewRect.set(mViewRect);
+        }
     }
 
     private void repositionToolbar() {
diff --git a/core/java/com/android/internal/widget/FloatingToolbar.java b/core/java/com/android/internal/widget/FloatingToolbar.java
index 32a145c..163b8ce 100644
--- a/core/java/com/android/internal/widget/FloatingToolbar.java
+++ b/core/java/com/android/internal/widget/FloatingToolbar.java
@@ -85,6 +85,7 @@
     private final FloatingToolbarPopup mPopup;
 
     private final Rect mContentRect = new Rect();
+    private final Rect mPreviousContentRect = new Rect();
 
     private Menu mMenu;
     private List<Object> mShowingMenuItems = new ArrayList<Object>();
@@ -178,11 +179,13 @@
             mPopup.layoutMenuItems(menuItems, mMenuItemClickListener, mSuggestedWidth);
             mShowingMenuItems = getShowingMenuItemsReferences(menuItems);
         }
-        mPopup.updateCoordinates(mContentRect);
         if (!mPopup.isShowing()) {
             mPopup.show(mContentRect);
+        } else if (!mPreviousContentRect.equals(mContentRect)) {
+            mPopup.updateCoordinates(mContentRect);
         }
         mWidthChanged = false;
+        mPreviousContentRect.set(mContentRect);
         return this;
     }
 
@@ -318,24 +321,8 @@
                 };
         private final AnimatorSet mDismissAnimation;
         private final AnimatorSet mHideAnimation;
-        private final AnimationSet mOpenOverflowAnimation = new AnimationSet(true) {
-            @Override
-            public void cancel() {
-                if (hasStarted() && !hasEnded()) {
-                    super.cancel();
-                    setOverflowPanelAsContent();
-                }
-            }
-        };
-        private final AnimationSet mCloseOverflowAnimation = new AnimationSet(true) {
-            @Override
-            public void cancel() {
-                if (hasStarted() && !hasEnded()) {
-                    super.cancel();
-                    setMainPanelAsContent();
-                }
-            }
-        };
+        private final AnimationSet mOpenOverflowAnimation = new AnimationSet(true);
+        private final AnimationSet mCloseOverflowAnimation = new AnimationSet(true);
 
         private final Runnable mOpenOverflow = new Runnable() {
             @Override
@@ -657,8 +644,24 @@
         }
 
         private void cancelOverflowAnimations() {
-            mOpenOverflowAnimation.cancel();
-            mCloseOverflowAnimation.cancel();
+            if (mOpenOverflowAnimation.hasStarted()
+                    && !mOpenOverflowAnimation.hasEnded()) {
+                // Remove the animation listener, stop the animation,
+                // then trigger the lister explicitly so it is not posted
+                // to the message queue.
+                mOpenOverflowAnimation.setAnimationListener(null);
+                mContentContainer.clearAnimation();
+                mOnOverflowOpened.onAnimationEnd(null);
+            }
+            if (mCloseOverflowAnimation.hasStarted()
+                    && !mCloseOverflowAnimation.hasEnded()) {
+                // Remove the animation listener, stop the animation,
+                // then trigger the lister explicitly so it is not posted
+                // to the message queue.
+                mCloseOverflowAnimation.setAnimationListener(null);
+                mContentContainer.clearAnimation();
+                mOnOverflowClosed.onAnimationEnd(null);
+            }
         }
 
         /**
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 2cbfae2..bada791 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1034,11 +1034,11 @@
         android:priority="1000" />
 
     <!-- Allows access to the list of accounts in the Accounts Service.
-        <p>Protection level: dangerous
+        <p>Protection level: normal
     -->
     <permission android:name="android.permission.GET_ACCOUNTS"
         android:permissionGroup="android.permission-group.CONTACTS"
-        android:protectionLevel="dangerous"
+        android:protectionLevel="normal"
         android:description="@string/permdesc_getAccounts"
         android:label="@string/permlab_getAccounts" />
 
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index f6cefba..4bc2205 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1268,6 +1268,14 @@
          application is desired. -->
     <string name="default_sms_application" translatable="false">com.android.mms</string>
 
+    <!-- Default web browser.  This is the package name of the application that will
+         be the default browser when the device first boots.  Afterwards the user
+         can select whatever browser app they wish to use as the default.
+
+         If this string is empty or the specified package does not exist, then
+         the behavior will be as though no app was named as an explicit default. -->
+    <string name="default_browser" translatable="false"></string>
+
     <!-- Enable/disable default bluetooth profiles:
         HSP_AG, ObexObjectPush, Audio, NAP -->
     <bool name="config_bluetooth_default_profiles">true</bool>
@@ -2248,4 +2256,6 @@
          (range of 18 - 21 kHz). -->
     <bool name="config_supportSpeakerNearUltrasound">true</bool>
 
+    <!-- Flag indicating device support for EAP SIM, AKA, AKA' -->
+    <bool name="config_eap_sim_based_auth_supported">true</bool>
 </resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 5c974bd..5288fa3 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -584,7 +584,7 @@
     <string name="permgroupdesc_phone">make and manage phone calls</string>
 
     <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permgrouplab_sensors">Sensors</string>
+    <string name="permgrouplab_sensors">Body Sensors</string>
     <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permgroupdesc_sensors">access sensor data about your vital signs</string>
 
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 5c42d04..ebbbc4c 100755
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -903,6 +903,7 @@
   <java-symbol type="string" name="sipAddressTypeOther" />
   <java-symbol type="string" name="sipAddressTypeWork" />
   <java-symbol type="string" name="default_sms_application" />
+  <java-symbol type="string" name="default_browser" />
   <java-symbol type="string" name="sms_control_message" />
   <java-symbol type="string" name="sms_control_title" />
   <java-symbol type="string" name="sms_control_no" />
@@ -2319,5 +2320,5 @@
   <java-symbol type="drawable" name="ic_dialog_alert_material" />
 
   <java-symbol type="bool" name="allow_stacked_button_bar" />
-
+  <java-symbol type="bool" name="config_eap_sim_based_auth_supported" />
 </resources>
diff --git a/core/tests/coretests/apks/install_jni_lib_open_from_apk/Android.mk b/core/tests/coretests/apks/install_jni_lib_open_from_apk/Android.mk
index 6ee6ffa..6b3b55e 100644
--- a/core/tests/coretests/apks/install_jni_lib_open_from_apk/Android.mk
+++ b/core/tests/coretests/apks/install_jni_lib_open_from_apk/Android.mk
@@ -5,6 +5,4 @@
 
 LOCAL_PACKAGE_NAME := install_jni_lib_open_from_apk
 
-LOCAL_PAGE_ALIGN_JNI_SHARED_LIBRARIES := true
-
 include $(FrameworkCoreTests_BUILD_PACKAGE)
diff --git a/docs/html/images/tools/eclipse-notepad-pre-import--structure.png b/docs/html/images/tools/eclipse-notepad-pre-import--structure.png
new file mode 100644
index 0000000..b9c3814
--- /dev/null
+++ b/docs/html/images/tools/eclipse-notepad-pre-import--structure.png
Binary files differ
diff --git a/docs/html/images/tools/studio-import-destination-dir.png b/docs/html/images/tools/studio-import-destination-dir.png
new file mode 100644
index 0000000..d1c6c70
--- /dev/null
+++ b/docs/html/images/tools/studio-import-destination-dir.png
Binary files differ
diff --git a/docs/html/images/tools/studio-import-options.png b/docs/html/images/tools/studio-import-options.png
new file mode 100644
index 0000000..f14eca0
--- /dev/null
+++ b/docs/html/images/tools/studio-import-options.png
Binary files differ
diff --git a/docs/html/images/tools/studio-import-project-structure-android.png b/docs/html/images/tools/studio-import-project-structure-android.png
new file mode 100644
index 0000000..4cd7186
--- /dev/null
+++ b/docs/html/images/tools/studio-import-project-structure-android.png
Binary files differ
diff --git a/docs/html/images/tools/studio-import-project-structure-project.png b/docs/html/images/tools/studio-import-project-structure-project.png
new file mode 100644
index 0000000..c7ffda8
--- /dev/null
+++ b/docs/html/images/tools/studio-import-project-structure-project.png
Binary files differ
diff --git a/docs/html/images/tools/studio-import-summary.png b/docs/html/images/tools/studio-import-summary.png
new file mode 100644
index 0000000..a85e339
--- /dev/null
+++ b/docs/html/images/tools/studio-import-summary.png
Binary files differ
diff --git a/docs/html/images/tools/studio-select-project-forimport.png b/docs/html/images/tools/studio-select-project-forimport.png
new file mode 100644
index 0000000..c6a3599
--- /dev/null
+++ b/docs/html/images/tools/studio-select-project-forimport.png
Binary files differ
diff --git a/docs/html/sdk/installing/installing-adt.jd b/docs/html/sdk/installing/installing-adt.jd
index 5559d1a..b89c068 100644
--- a/docs/html/sdk/installing/installing-adt.jd
+++ b/docs/html/sdk/installing/installing-adt.jd
@@ -7,6 +7,14 @@
 @jd:body
 
 
+<p class="caution">
+  <strong>Important:</strong> Support for the Android Developer Tools (ADT) in Eclipse is ending,
+  per our <a href=
+  "http://android-developers.blogspot.com/2015/06/an-update-on-eclipse-android-developer.html"
+  class="external-link">announcement</a>. You should migrate your app development projects to
+  Android Studio as soon as possible. For more information on transitioning to Android Studio, see
+  <a href="{@docRoot}sdk/installing/migrate.html">Migrating to Android Studio</a>.
+</p>
 
 <p>Android offers a custom plugin for the Eclipse IDE, called Android
 Development Tools (ADT). This plugin provides a powerful, integrated
@@ -15,15 +23,6 @@
 UI, debug your app, and export signed (or unsigned) app packages (APKs) for distribution.
 </p>
 
-<p class="note"><strong>Note:</strong>
-If you have been using Eclipse with ADT, be aware that <a
-href="{@docRoot}tools/studio/index.html">Android Studio</a> is now the official IDE
-for Android, so you should migrate to Android Studio to receive all the
-latest IDE updates. For help moving projects,
-see <a href="/sdk/installing/migrate.html">Migrating to Android
-Studio</a>.</p>
-
-
 <p>You should install the ADT plugin
 only if you already have an Eclipse installation that you want to continue using.
 Your existing Eclipse installation must meet these requirements:</p>
diff --git a/docs/html/sdk/installing/migrate.jd b/docs/html/sdk/installing/migrate.jd
index 345e89a..d9829395 100644
--- a/docs/html/sdk/installing/migrate.jd
+++ b/docs/html/sdk/installing/migrate.jd
@@ -4,53 +4,264 @@
 
 <div id="qv-wrapper">
 <div id="qv">
+
+
+<h2>In this document</h2>
+<ol>
+  <li><a href="#overview">Migration Overview</a></li>
+  <li><a href="#prerequisites">Migration Prerequisites</a></li>
+  <li><a href="#migrate">Importing Projects to Android Studio</a></li>
+  <li><a href="#post-migration">Validating imported projects</a></li>
+</ol>
+
+
 <h2>See also</h2>
 <ul>
+  <li><a href="{@docRoot}tools/studio/eclipse-transition-guide.html">
+    Transition Guide for Eclipse ADT</a></li>
   <li><a href="http://confluence.jetbrains.com/display/IntelliJIDEA/FAQ+on+Migrating+to+IntelliJ+IDEA"
-  class="external-link">IntelliJ FAQ on migrating to IntelliJ IDEA</a></li>
- <li><a href="http://confluence.jetbrains.com/display/IntelliJIDEA/Working+in+Eclipse+Compatibility+Mode" class="external-link"
- >Eclipse Compatibility Mode</a></li>
- <li><a href="http://confluence.jetbrains.com/display/IntelliJIDEA/FAQ+on+Migrating+to+IntelliJ+IDEA" class="external-link"
- >FAQ on Migrating</a></li>
+    class="external-link">IntelliJ FAQ on migrating to IntelliJ IDEA</a></li>
+  <li><a href="http://confluence.jetbrains.com/display/IntelliJIDEA/IntelliJ+IDEA+for+Eclipse+Users"
+    class="external-link">IntelliJ IDEA for Eclipse users</a></li>
+  <li><a href="{@docRoot}tools/studio/index.html">Android Studio Overview</a></li>
 </ul>
 </div>
 </div>
 
 
-<p>If you have been using <a href="{@docRoot}tools/help/adt.html">Eclipse with ADT</a>, be aware
-that <a href="{@docRoot}tools/studio/index.html">Android Studio</a> is now the official IDE for
-Android, so you should migrate to Android Studio to receive all the latest IDE updates.</p>
+<p>Migrating from Eclipse ADT to Android Studio requires adapting to a new project structure,
+build system, and IDE functionality. To simplify the migration process, Android Studio provides an
+import tool so you can quickly transition your Eclipse ADT workspaces and Ant build scripts to
+Android Studio projects and <a href="http://www.gradle.org">Gradle</a>-based build files.</p>
 
-<p>To migrate existing Android projects, simply import them using Android Studio:</p>
+<p>This document provides an overview of the migration process and walks you
+through a sample import procedure. For more information about Android Studio features and the
+Gradle-based build system, see <a href="{@docRoot}tools/studio/index.html">Android Studio Overview</a>
+and <a href="{@docRoot}tools/building/configuring-gradle.html">Configuring Gradle Builds</a>.</p>
+
+
+
+<h2 id="overview">Migration Overview </h2>
+<p>Migrating from Eclipse to Android Studio requires that you change the structure of your
+development projects, move to a new build system, and use a new user interface. Here are some of
+the key changes you should be aware of as you prepare to migrate to Android Studio:</p>
+<ul>
+  <li><strong>Project files</strong>
+    <p>Android Studio uses a different project structure. Each Eclipse ADT
+    project is called a module in Android Studio. Each instance of Android
+    Studio contains a project with one or more app modules. For more information see,
+    <a href="{@docRoot}tools/studio/eclipse-migration-guide.html#project-structure">Project
+    Structure</a>.</p></li>
+
+  <li><strong>Manifest settings</strong>
+    <p>Several elements in the <code>AndroidManifest.xml</code> file are now properties in the
+    <code>defaultConfig</code> and <code>productFlavors</code> blocks in the
+    <code>build.gradle</code> file. These elements are still valid manifest entries and may
+    appear in manifests from older projects, imported projects, dependencies, and libraries. For
+    more information see,
+    <a href="{@docRoot}tools/studio/eclipse-migration-guide.html#manifest-settings">Manifest
+    Settings</a>.</p></li>
+
+  <li><strong>Dependencies</strong>
+    <p>Library dependencies are handled differently in Android Studio, using Gradle dependency
+    declarations and Maven dependencies for well-known local source and binary libraries with
+    Maven coordinates.  For more information see,
+    <a href="{@docRoot}tools/studio/eclipse-migration-guide.html#dependencies">Dependencies</a></p>
+    </li>
+
+  <li><strong>Test code</strong>
+    <p>With Eclipse ADT, test code is written in separate projects and integrated through the
+    <code>&lt;instrumentation&gt;</code> element in your manifest file. Android Studio provides a
+    <code>AndroidTest</code> folder within your project so you can easily add and maintain your test
+    code within the same project view. JUnit tests can also be configured to run locally to reduce
+    testing cycles.</p></li>
+
+  <li><strong>Gradle-based build system</strong>
+    <p>In place of XML-based Ant build files, Android Studio supports Gradle build files, which
+    use the Gradle Domain Specific Language (DSL) for ease of extensibility and customization.
+    The Android Studio build system also supports
+    <a href="{@docRoot}tools/building/configuring-gradle.html#workBuildVariants"> build variants</a>,
+    which are combinations of <code>productFlavor</code> and <code>buildTypes</code>, to customize
+    your build outputs.</p></li>
+
+  <li><strong>User interface</strong>
+    <p>Android Studio provides an intuitive interface and menu options based on the
+    <a class="external-link" href="https://www.jetbrains.com/idea/" target="_blank">IntelliJ IDEA</a>
+    IDE. To become familiar with the IDE basics, such as navigation, code completion, and keyboard
+    shortcuts, see
+    <a class="external-link" href="https://www.jetbrains.com/idea/help/intellij-idea-quick-start-guide.html"
+    target="_blank">IntelliJ IDEA Quick Start Guide</a>.</p></li>
+
+  <li><strong>Developer tools versioning</strong>
+    <p>Android Studio updates independently of the Gradle-based build system so different build
+    settings can be applied across different versions of command line, Android Studio, and
+    continuous integration builds. For more information, see
+    <a href="{@docRoot}tools/building/configuring-gradle.html">Configuring Gradle Builds</a>.</p>
+    </li>
+</ul>
+
+
+
+
+<h2 id="prerequisites">Migration Prerequisites</h2>
+<p>Before migrating your Eclipse ADT app to Android Studio, review the following steps to make
+sure your project is ready for conversion, and verify you have the tool configuration you need in
+Android Studio:</p>
+
+<ul>
+ <li>In Eclipse ADT:
+   <ul>
+     <li>Make sure the Eclipse ADT root directory contains the <code>AndroidManifest.xml</code>
+       file. Also, the root directory must contain either the <code>.project</code> and
+       <code>.classpath</code> files from Eclipse or the <code>res/</code> and <code>src/</code>
+       directories.</li>
+     <li>Build your project to ensure your latest workspace and project updates are saved and
+       included in the import.</li>
+     <li>Comment out any references to Eclipse ADT workspace library files in the
+       <code>project.properties</code> or <code>.classpath</code> files for import. You can
+       add these references in the <code>build.gradle</code> file after the import. For more
+       information, see
+       <a href="{@docRoot}tools/building/configuring-gradle.html">Configuring Gradle Builds</a>.</li>
+     <li>It may be useful to record your workspace directory, path variables, and any actual path
+       maps that could be used to specify any unresolved relative paths, path variables, and
+       linked resource references. Android Studio allows you to manually specify any unresolved
+       paths during the import process.</li>
+   </ul>
+ </li>
+ <li>In Android Studio:
+   <ul>
+    <li>Make a note of any third-party Eclipse ADT plugins in use and check for equivalent features
+      in Android Studio or search for a compatible plugin in the
+      <a href="https://plugins.jetbrains.com/?androidstudio" class="external-link">IntelliJ Android
+      Studio Plugins</a> repository. Use the <strong>File &gt; Settings &gt; Plugins</strong> menu
+      option to manage plugins in Android Studio. Android Studio does not migrate any third-party
+      Eclipse ADT plugins.</li>
+    <li>If you plan to run Android Studio behind a firewall, be sure to set the proxy settings for
+      Android Studio and the SDK Manager. Android Studio requires an internet connection for
+      Setup Wizard synchronization, 3rd-party library access, access to remote repositories,
+      <a href="http://www.gradle.org" class="external-link">Gradle</a>
+      initialization and synchronization, and Android Studio version updates. For more information,
+      see <a href="{@docRoot}tools/studio/index.html#proxy">Proxy Settings</a>.</li>
+    <li>Use the <strong>File &gt; Settings &gt; System Settings</strong> menu option to verify the
+      current version and, if necessary, update Android Studio to the latest version from the
+      stable channel. To install Android Studio, please visit the
+      <a href="{@docRoot}sdk/index.html">Android Studio download page</a>.</li>
+    </ul>
+  </li>
+ </ul>
+
+
+
+<h2 id="migrate">Importing Projects to Android Studio</h2>
+<p>Android Studio provides a function for importing Eclipse ADT projects, which creates a new
+Android Studio project and app modules based on your current
+Eclipse ADT workspace and projects. No changes are made to your Eclipse project files. The Eclipse
+ADT workspace becomes a new Android Studio project, and each Eclipse ADT project within the workspace
+becomes a new Android Studio module. Each instance of Android Studio contains a project with one or
+more app modules.</p>
+
+<p>After selecting an Eclipse ADT project to import, Android Studio creates the Android
+Studio project structure and app modules, generates the new Gradle-based build files and settings,
+and configures the required dependencies. The import options also allow you to enter your workspace
+directory and any actual path maps to handle any unresolved relative paths, path variables, and
+linked resource references.</p>
+
+<p>Depending on the structure of your Eclipse ADT development project, you should select specific
+files for importing:</p>
+<ul>
+<li>For workspaces with multiple projects, select the project folder for each Eclipse ADT
+  project individually to import the projects into the same Android Studio project. Android
+  Studio combines the Eclipse ADT projects into a single Android Studio project with different app
+  modules for each imported project.</li>
+
+<li>For Eclipse ADT projects with separate test projects, select the test project folder for
+  import. Android Studio imports the test project and then follows the dependency chain to import
+  the source project and any project dependencies.</li>
+
+ <li>If Eclipse ADT projects share dependencies within the same workspace, import each
+   project individually into Android Studio. Android Studio maintains the shared dependencies
+   across the newly created modules as part of the import process.</li>
+</ul>
+
+<p>To import a project to Android Studio:</p>
 
 <ol>
-  <li>In Android Studio, from the main menu or the <strong>Welcome to Android Studio</strong> page,
-  choose <strong>File &gt; Import Project</strong>.</li>
-  <li> Select the Eclipse root project directory</strong> and click <strong>OK</strong>.
-  <p class="note"><strong>Note:</strong> The Eclipse root directory must contain the
-  <code>AndroidManifest.xml</code> file. Also, the root directory must contain either the
-  <code>.project</code> and <strong>.classpath</strong> files from Eclipse or the
-  <code>res/</code> and <code>src/</code> directories.</p>
-  </li>
-  <li>Follow the steps in the import wizard. </li>
+ <li>Start Android Studio and close any open Android Studio projects.</li>
+ <li>From the Android Studio menu select <strong>File &gt; New &gt; Import Project</strong>.
+  <p>Alternatively, from the <em>Welcome</em> screen, select <strong>Import project
+  (Eclipse ADT, Gradle, etc.)</strong>.</p></li>
+ <li>Select the Eclipse ADT project folder with the <code>AndroidManifest.xml</code> file
+   and click <strong>Ok</strong>.
+   <p> <img src="{@docRoot}images/tools/studio-select-project-forimport.png" alt="" /></p>
+ </li>
+ <li>Select the destination folder and click <strong>Next</strong>.
+   <p> <img src="{@docRoot}images/tools/studio-import-destination-dir.png" alt="" /></p></li>
+ <li>Select the import options and click <strong>Finish</strong>.
+   <p>The import process prompts to migrate any library and project dependencies to Android Studio,
+   and add the dependency declarations to the <code>build.gradle</code> file. The import process
+   also replaces any well-known source libraries, binary libraries, and JAR files that have known
+   Maven coordinates with Maven dependencies, so you no longer need to maintain these dependencies
+   manually. The import options also allow you to enter your workspace directory and any actual
+   path maps to handle any unresolved relative paths, path variables, and linked resource
+   references.</p>
+   <p> <img src="{@docRoot}images/tools/studio-import-options.png" alt="" /></p></li>
+
+ <li>Android Studio imports the app and displays the project import summary. Review the summary
+   for details about the project restructuring and the import process.
+    <p> <img src="{@docRoot}images/tools/studio-import-summary.png"/></p>
+ </li>
 </ol>
 
-<p>Android Studio imports the current dependencies, downloads libraries, and
-creates an Android Studio project with the imported Eclipse project as the main module. Android
-Studio also creates the required Gradle build files. </p>
-
-<p>The import process replaces any JAR files and libraries with Gradle dependencies, and replaces
-source libraries and binary libraries with Maven dependencies, so you no longer need to maintain
-these files manually.</p>
-
- <p class="note"><strong>Note:</strong> If there are references to Eclipse workspace library files,
- comment them out in the <code>project.properties</code> or <code>.classpath</code> files
- that you imported from the Eclipse project. You can then add these files in the
- <code>build.gradle</code> file. See
- <a href="{@docRoot}tools/building/configuring-gradle.html">Configuring Gradle Builds</a>. </p>
+<p>After importing the project from Eclipse ADT to the new Android Studio project and module
+structure, each app module folder in Android Studio contains the complete source set for that
+module, including the {@code src/main} and {@code src/androidTest} directories, resources, build
+file, and Android manifest. Before starting app development, you should resolve any issues shown in
+the project import summary to make sure the project re-structuring and import process completed
+properly.</p>
 
 
-<p>For more help getting started with Android Studio and the IntelliJ user experience,
-<a href="{@docRoot}tools/studio/index.html">learn more about Android Studio</a> and
-read <a href="http://confluence.jetbrains.com/display/IntelliJIDEA/FAQ+on+Migrating+to+IntelliJ+IDEA"
-  class="external-link">FAQ on Migrating to IntelliJ IDEA</a>.</p>
+
+<h3 id="post-migration">Validating imported projects</h3>
+<p>After completing the import process, use the Android Studio <strong>Build</strong> and
+<strong>Run</strong> menu options to build your project and verify the output. If your project
+is not building properly, check the following settings:</p>
+
+<ul>
+<ul>
+  <li>Use the <strong>Android SDK</strong> button in Android Studio to launch the <a href=
+  "{@docRoot}tools/help/sdk-manager.html">SDK Manager</a> and verify the installed versions of SDK
+  tools, build tools, and platform match the settings for your Eclipse ADT project. Android Studio
+  inherits the SDK Manager and JDK settings from your imported Eclipse project.
+  </li>
+  <li>Use the <strong>File &gt; Project Structure</strong> menu option to verify additional
+    Android Studio settings:
+   <ul>
+     <li>Under <em>SDK Location</em> verify Android Studio has access to the correct SDK and
+       JDK locations and versions. </li>
+     <li>Under <em>Project</em> verify the Gradle version, Android Plugin version, and related
+       repositories.</li>
+     <li>Under <em>Modules</em> verify the app and module settings, such as signing configuration
+       and library dependencies. </li>
+   </ul>
+ </li>
+ <li>If your project depends on another project, make sure that dependency is defined properly in
+  the <code>build.gradle</code> file in the app module folder.</li>
+</ul>
+
+
+<p>If there still are unexpected issues when building and running your project in Android
+Studio after you have checked these settings, consider modifying the Eclipse ADT project and
+re-starting the import process. Importing an Eclipse ADT project to Android Studio creates a new
+Android Studio project and does not impact the existing Eclipse ADT project. </p>
+
+
+
+<p>To get started using Android Studio, review the
+<a href="{@docRoot}tools/studio/index.html">Android Studio</a> features and
+<a href="http://www.gradle.org">Gradle</a>-based build system to become familiar with the new
+project and module structure, flexible build settings, and other advanced Android development
+capabilities. For a comparison of Eclipse ADT and Android Studio features and usage, see
+<a href="{@docRoot}tools/studio/eclipse-migration-guide.html">Transitioning to Android Studio from
+Eclipse</a>. For specific Android Studio how-to documentation, see the pages in the
+<a href="{@docRoot}tools/workflow/index.html">Workflow</a> section.
+</p>
diff --git a/docs/html/tools/building/building-cmdline-ant.jd b/docs/html/tools/building/building-cmdline-ant.jd
index 51158de..add6ca2 100644
--- a/docs/html/tools/building/building-cmdline-ant.jd
+++ b/docs/html/tools/building/building-cmdline-ant.jd
@@ -31,6 +31,14 @@
     </div>
   </div>
 
+<p class="caution">
+  <strong>Important:</strong> Support for Ant as a build tool for Android is ending, per our
+  <a href="http://android-developers.blogspot.com/2015/06/an-update-on-eclipse-android-developer.html"
+  class="external-link">announcement</a>. You should migrate your app development projects to
+  Android Studio and Gradle as soon as possible. For more information on transitioning to these
+  tools, see <a href="{@docRoot}sdk/installing/migrate.html">Migrating to Android Studio</a>.
+</p>
+
   <p>There are two ways to build your application using the Ant build script: one for
   testing/debugging your application &mdash; <em>debug mode</em> &mdash; and one for building your
   final package for release &mdash; <em>release mode</em>. Regardless of which way you build your application,
diff --git a/docs/html/tools/building/manifest-merge.jd b/docs/html/tools/building/manifest-merge.jd
new file mode 100644
index 0000000..54166ec
--- /dev/null
+++ b/docs/html/tools/building/manifest-merge.jd
@@ -0,0 +1,510 @@
+page.title=Manifest Merging
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+
+  <h2>In this document</h2>
+  <ol>
+    <li><a href="#merge-rules">Merge Conflict Rules</a></li>
+    <li><a href="#markers-selectors">Merge Conflict Markers and Selectors</a></li>
+    <li><a href="#inject-values">Injecting Build Values into a Manifest</a></li>
+    <li><a href="#merge-prodflavorsGroups">Manifest Merging Across Product Flavor Groups</a></li>
+    <li><a href="#implicit-permissions">Implicit Permissions</a></li>
+    <li><a href="#merge-errors">Handling Manifest Merge Build Errors</a></li>
+  </ol>
+
+  <h2>See also</h2>
+  <ol>
+    <li><a href="{@docRoot}sdk/installing/studio-build.html">Build System Overview</a></li>
+    <li><a href="{@docRoot}tools/building/configuring-gradle.html">Configuring Gradle Builds</a> </li>
+  </ol>
+
+</div>
+</div>
+
+
+<p>With Android Studio and <a href="http://www.gradle.org">Gradle</a>-based builds, each app can
+contain manifest files in multiple locations, such as the <code>src/main/</code> folder for
+the <code>productFlavor</code>, libraries, Android ARchive (AAR) bundles of Android Library
+projects, and dependencies. During the build process, manifest merging combines the settings from
+the various <code>AndroidManifest.xml</code> files included in your app into a single, generated APK
+manifest file for app packaging and distribution. Manifest settings are merged based on the manifest
+priority, determined by the manifest's file location. Building your app merges the
+manifest elements, attributes, and sub-elements from these manifests for the specified
+<a href="{@docRoot}tools/building/configuring-gradle.html#workBuildVariants">build variant</a>.</p>
+
+
+<h2 id="merge-rules">Merge Conflict Rules</h2>
+<p>Merge conflicts occur when merged manifests contain the same manifest element but with a
+different attribute value that does not resolve based on the default merge conflict rules.
+<a href="#markers-selectors">Conflict markers and selectors</a> can also define custom merge rules,
+such as allowing an imported library to have a <code>minSdkVersion</code> higher than the
+version defined in the other higher priority manifests.  </p>
+
+<p>The manifest merge priority determines which manifest settings are retained in merge conflicts,
+with the settings in higher priority manifest overwriting those in lower priority manifests.
+The following list details which manifest settings are are the highest priority during the merge
+process:</p>
+
+<ul>
+ <li>Highest priority: <code>buildType</code> manifest settings </li>
+ <li>Higher priority: <code>productFlavor</code> manifest settings </li>
+ <li>Medium priority: Manifests in the <code>src/main/</code> directory of an app project</li>
+ <li>Low priority: Dependency and library manifest settings </li>
+</ul>
+
+<p>Manifest merge conflicts are resolved at the XML node and
+attribute levels based on the following merge rules. </p>
+
+<table>
+    <tr>
+        <th scope="col">High Priority Element</th>
+        <th scope="col">Low Priority Element</th>
+        <th scope="col">Manifest Merge Result</th>
+    </tr>
+    <tr>
+        <td rowspan="3">no attribute</td>
+        <td>no attribute</td>
+        <td>no attribute</td>
+    </tr>
+    <tr>
+
+        <td>attribute set to default</td>
+        <td>default attribute</td>
+    </tr>
+    <tr>
+
+        <td>attribute set to non-default </td>
+        <td>low priority attribute</td>
+    </tr>
+    <tr>
+        <td>attribute set to default</td>
+        <td rowspan="2">no attribute</td>
+        <td>default attribute</td>
+    </tr>
+    <tr>
+        <td>attribute set to non-default </td>
+
+        <td>high priority attribute</td>
+    </tr>
+    <tr>
+        <td>attribute set to default</td>
+        <td>attribute set to default</td>
+        <td>default attribute</td>
+    </tr>
+    <tr>
+        <td>attribute set to default</td>
+        <td>attribute set to non-default </td>
+        <td>low priority attribute</td>
+    </tr>
+    <tr>
+        <td>attribute set to non-default</td>
+        <td>attribute set to default</td>
+        <td>high priority attribute</td>
+    </tr>
+    <tr>
+        <td>attribute set to non-default</td>
+        <td>attribute set to non-default </td>
+        <td>Merge if settings match, otherwise causes conflict error.</td>
+    </tr>
+   </table>
+
+
+
+<p>Exceptions to the manifest merge rules: </p>
+
+<ul>
+ <li>The <code>uses-feature android:required;</code> and
+ <code>uses-library android:required</code> elements default to <code>true</code> and use
+ an <em>OR</em> merge so that any required feature or library is included in the generated APK. </li>
+
+ <li>If not declared, the
+ <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html"><code>&lt;uses-sdk&gt;</code></a>
+ elements, <code>minSdkVersion</code> and
+ <code>targetSdkVersion</code>, default to a value of 1. When
+ merge conflicts occur, the value in the higher priority manifest version is used.</li>
+
+ <li>Importing a library with a <code>minSdkVersion</code> value higher than the app's
+ <code>src/main/</code> manifest manifest generates an error unless
+ the <code>overrideLibrary</code> conflict marker is used.
+
+ <p class="note"><strong>Note:</strong> If not explicitly declared, the <code>targetSdkVersion</code>
+ defaults to the <code>minSdkVersion</code> value. When no <code><uses-sdk></code> element is
+ present in any manifest or the <code>build.gradle</code> file, the
+ <code>minSdkVersion</code> defaults to 1.</p> </li>
+
+ <li>When importing a library with a <code>targetSdkVersion</code> value lower than the app's
+ <code>src/main/</code> manifest, the manifest merge
+ process explicitly grants permissions and ensures that the imported library functions properly. </li>
+
+ <li>The <code>manifest</code> element only merges with child manifest elements. </li>
+
+ <li>The <code>intent-filter</code> element is never changed and is always added to the common
+ parent node in the merged manifest. </li>
+</ul>
+
+<p class="caution"><strong>Important:</strong> After the manifests are merged, the build process
+overrides the final manifest settings with any settings that are also in the
+<code>build.gradle</code> file. For more details, see
+<a href="{@docRoot}tools/building/configuring-gradle.html">Configuring Gradle Builds</a>. </p>
+
+
+
+<h2 id="markers-selectors">Merge Conflict Markers and Selectors</h2>
+<p>Manifest markers and selectors override the default merge rules through
+specific conflict resolutions. For example, use a conflict marker to
+merge a library manifest with a higher <code>minSdkVersion</code> value than the higher priority
+manifest, or to merge manifests with the same activity but different <code>android:theme</code>
+values. </p>
+
+<h3 id="conflict-markers">Merge Conflict Markers</h3>
+<p>A merge conflict marker is a special attribute in the Android tools namespace that defines a
+specific merge conflict resolution. Create a conflict marker to avoid a merge conflict error for
+conflicts not resolved by the default merge rules. Supported merge conflict markers include:</p>
+
+<dl>
+  <dt><code>merge</code></dt>
+    <dd>Merges attributes when there are no conflicts with the merge rules. The default merge
+    action.</dd>
+  <dt><code>replace</code></dt>
+    <dd>Replaces attributes in the lower priority manifest with those from the higher priority
+    manifest.</dd>
+  <dt><code>strict</code></dt>
+    <dd>Sets the merge policy level so that merged elements with same attributes, but different
+     values generate a build failure, unless resolved through the conflict rules.</dd>
+  <dt><code>merge-only</code></dt>
+    <dd>Allows merge actions for only lower priority attributes.</dd>
+  <dt><code>remove</code></dt>
+    <dd>Removes the specified lower priority element from the merged manifest.</dd>
+  <dt><code>remove-All</code></dt>
+    <dd>Removes all lower priority elements of the same node type from the merged manifest.</dd>
+</dl>
+
+
+<p>By default, the manifest merge process applies the <code>merge</code> conflict marker to
+the node level. All declared manifest attributes default to a <code>strict</code>
+merging policy. </p>
+
+<p>To set a merge conflict marker, first declare the namespace in the
+<code>AndroidManifest.xml</code> file. Then, enter the merge conflict marker in the manifest to
+specify a custom merge conflict action. This example inserts the <code>replace</code> marker to
+set a replace action to resolve conflicts between the <code>android:icon</code> and
+<code>android:label</code> manifest elements. </p>
+
+<pre>
+
+&lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"
+   package="com.android.tests.flavorlib.app"
+   xmlns:tools="http://schemas.android.com/tools"&gt;
+
+   &lt;application
+       android:icon="&#64;drawable/icon"
+       android:label="&#64;string/app_name"
+       tools:replace="icon, label"&gt;
+       ...
+
+</manifest>
+
+</pre>
+
+
+<h4>Marker attributes</h4>
+<p>Conflict markers use <code>tools:node</code> and <code>tools:attr</code> attributes to
+restrict merge actions at the XML node or attribute level. </p>
+
+<p>The <code>tools:attr</code> markers use only the <code>restrict</code>, <code>remove</code>, and
+<code>replace</code> merge actions. Multiple <code>tools:attr</code> marker values can be applied
+to a specific element. For example, use <code>tools:replace="icon, label, theme"</code> to replace
+lower priority <code>icon</code>, <code>label</code>, and <code>theme</code> attributes. </p>
+
+
+<h4>Merge conflict marker for imported libraries</h4>
+<p>The <code>overrideLibrary</code> conflict marker applies to the <code>&lt;uses-sdk&gt;</code>
+manifest declaration and is used to import a library even though the library's
+<code>&lt;uses-sdk&gt;</code> values, such as <code>minSdkVersion</code>
+are set to different values than those in the other higher priority manifests. </p>
+
+<p>Without this marker, library manifest merge conflicts from the
+<code>&lt;uses-sdk&gt;</code> values cause the merge process to fail.</p>
+
+<p>This example applies the <code>overrideLibrary</code> conflict marker to resolve the merge
+conflict between <code>minSdkVersion</code> values in the <code>src/main/</code> manifest and an
+imported library manifest.
+
+
+<p><code>src/main/</code> manifest: </p>
+<pre>
+&lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"
+   package="com.android.example.app"
+   xmlns:tools="http://schemas.android.com/tools"&gt;
+   ...
+   &lt;uses-sdk android:targetSdkVersion="22" android:minSdkVersion="2"
+             tools:overrideLibrary="com.example.lib1, com.example.lib2"/&gt;
+   ...
+</pre>
+
+<p>Library manifest: </p>
+
+<pre>
+&lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"
+   	 package="com.example.lib1"&gt;
+     ...
+   	 &lt;uses-sdk android:minSdkVersion="4" /&gt;
+     ...
+    &lt;/manifest&gt;
+</pre>
+
+<p class="note"><strong>Note:</strong> The default merge process does not allow importing a library
+with a higher <code>minSdkVersion</code> than the app's <code>src/main/</code> manifest unless
+the <code>overrideLibrary</code> conflict marker is used. </p>
+
+
+
+<h3 id="marker-selectors">Marker Selectors</h3>
+<p>Marker selectors limit a merge action to a specific lower priority manifest. For example, a
+marker selector can be used to remove a permission from only one library, while allowing the
+same permission from other libraries.</p>
+
+<p>This example uses the <code>tools:node</code> marker to remove the <code>permisionOne</code>
+attribute, while the <code>tools:selector</code> selector specifies the specific library as
+<em>com.example.lib1</em>. The <code>permisionOne</code> permission is filtered from only the
+<code>lib1</code> library manifests. </p>
+
+<pre>
+&lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"
+   package="com.android.example.app"
+   xmlns:tools="http://schemas.android.com/tools"&gt;
+   ...
+   &lt;permission
+         android:name="permissionOne"
+         tools:node="remove"
+         tools:selector="com.example.lib1"&gt;
+   ...
+</pre>
+
+
+
+<h2 id="inject-values">Injecting Build Values into a Manifest</h2>
+<p>Manifest merging can also be configured to use manifest placeholders to inject
+property values from the <code>build.gradle</code> file into the manifest attributes. </p>
+
+<p>Manifest placeholders use the syntax <code>&#36;{name}</code> for attribute values, where
+<code>name</code> is the injected <code>build.gradle</code> property. The <code>build.gradle</code>
+file uses the <code>manifestPlaceholders</code> property to define the placeholder values. </p>
+
+<p class="note"><strong>Note:</strong> Unresolved placeholder names in apps cause build failures.
+Unresolved placeholder names in libraries generate warnings and need to be resolved when importing
+the library into an app.</p>
+
+<p>This example shows the manifest placeholder <code>&#36;{applicationId}</code> used to inject the
+<code>build.gradle</code> <code>applicationId</code> property value in to <code>android:name</code>
+attribute value.  </p>
+
+<p class="note"><strong>Note:</strong> Android Studio provides a default
+<code>&#36;{applicationId}</code> placeholder for the <code>build.gradle</code>
+<code>applicationId</code> value that is not shown in the build file.</p>
+
+
+<p>Manifest entry:</p>
+
+<pre>
+
+&lt;activity
+android:name=".Main"&gt;
+     &lt;intent-filter&gt;
+     &lt;action android:name="&#36;{applicationId}.foo"&gt;
+         &lt;/action&gt;
+&lt;/intent-filter&gt;
+&lt;/activity&gt;
+
+</pre>
+
+
+<p>Gradle build file:</p>
+
+<pre>
+android {
+   compileSdkVersion 22
+   buildToolsVersion "22.0.1"
+
+   productFlavors {
+       flavor1 {
+           applicationId = "com.mycompany.myapplication.productFlavor1"
+       }
+}
+
+</pre>
+
+<p>Merged manifest value: </p>
+
+<pre>
+&lt;action android:name="com.mycompany.myapplication.productFlavor1.foo"&gt;
+</pre>
+
+
+<p>The manifest placeholder syntax and build file <code>manifestPlaceholders</code>
+property can be used to inject other manifest values. For properties other than the
+<code>applicationId</code>, the <code>manifestPlaceholders</code> property is explicitly declared
+in the <code>build.gradle</code> file. This example shows the manifest placeholder for injecting
+<code>activityLabel</code> values.</p>
+
+<p>Gradle build file: </p>
+
+<pre>
+android {
+    defaultConfig {
+        manifestPlaceholders = [ activityLabel:"defaultName"]
+    }
+    productFlavors {
+        free {
+        }
+        pro {
+            manifestPlaceholders = [ activityLabel:"proName" ]
+        }
+    }
+
+</pre>
+
+<p>Placeholder in the manifest file: </p>
+
+<pre>
+&lt;activity android:name=".MainActivity" android:label="&#36;{activityLabel}" &gt;
+</pre>
+
+<p class="note"><strong>Note:</strong> The placeholder value supports partial value injection,
+for example <code>android:authority="com.acme.&#36;{localApplicationId}.foo"</code>. </p>
+
+
+
+<h2 id="merge-prodflavorsGroups">Manifest Merging Across Product Flavor Groups</h2>
+
+<p>When using the <code>GroupableProductFlavor</code> property, the manifest merge
+priority of any manifests in the product flavor groups follows the order in which the
+product flavor groups are listed in the build file. The manifest merge process creates a single
+merged manifest for the product flavor groups based on the configured build variant. </p>
+
+<p>For example, if a build variant references the product flavors <code>x86</code>,
+<code>mdpi</code>, <code>21</code>, and <code>paid</code> from the respective product flavor
+groups <code>ABI</code>, <code>Density</code>, <code>API</code>, and <code>Prod</code>, listed
+in this order in the <code>build.gradle</code> file, then the manifest merge process merges the
+manifests in this priority order, which follows how the product flavors are listed in the build
+file.</p>
+
+<p>To illustrate this example, the following table shows how the product flavors are listed for
+each product flavor group. This combination of product flavors and groups defines the
+build variant. </p>
+<table>
+    <tr>
+        <th scope="col">Product Flavor Group</th>
+        <th scope="col">Product Flavor</th>
+    <tr>
+        <td>ABI</td>
+        <td>x86</td>
+    </tr>
+    <tr>
+       <td>density</td>
+        <td>mdpi</td>
+    </tr>
+    <tr>
+        <td>API</td>
+        <td>22</td>
+    </tr>
+    <tr>
+        <td>prod</td>
+        <td>paid</td>
+    </tr>
+</table>
+
+<p>Manifest merge order:</p>
+
+ <ul>
+  <li>prod-paid AndroidManifest.xml (lowest priority) merges into API-22 AndroidManifest.xml</li>
+  <li>API-22 AndroidManifest.xml merges into density-mpi AndroidManifest.xml</li>
+  <li>density-mpi AndroidManifest.xml merges into ABI-x86 AndroidManifest.xml (highest priority)</li>
+ </ul>
+
+
+<h2 id="implicit-permissions">Implicit Permissions</h2>
+<p>Importing a library that targets an Android runtime with implicitly
+granted permissions may automatically add the permissions to the resulting merged manifest.
+For example, if an application with a <code>targetSdkVersion</code> of 16 imports a library with a
+<code>targetSdkVersion</code> of 2, Android Studio adds the <code>WRITE_EXTERNAL_STORAGE</code>
+permission to ensure permission compatibility across the SDK versions.
+
+<p class="note"><strong>Note:</strong> More recent Android releases replace implicit
+permissions with permission declarations.</p>
+
+
+This table lists the importing library versions and the declared permissions.
+</p>
+
+  <table>
+    <tr>
+      <th>Importing this library version</th>
+      <th>Declares this permission in the manifest </th>
+    </tr>
+    <tr>
+      <td><code>targetSdkVersion</code> &lt; 2 </td>
+      <td><code>WRITE_EXTERNAL_STORAGE</code> </td>
+    </tr>
+    <tr>
+      <td><code>targetSdkVersion</code> &lt; 4 </td>
+      <td><code>WRITE_EXTERNAL_STORAGE</code>, <code>READ_PHONE_STATE</code> </td>
+    </tr>
+    <tr>
+      <td>Declared <code>WRITE_EXTERNAL_STORAGE</code></td>
+      <td><code>READ_EXTERNAL_STORAGE</code></td>
+    </tr>
+    <tr>
+      <td><code>targetSdkVersion</code> &lt; 16 and using the <code>READ_CONTACTS</code>
+      permission</td>
+      <td><code>READ_CALL_LOG</code></td>
+    </tr>
+    <tr>
+      <td><code>targetSdkVersion</code> &lt; 16 and using the <code>WRITE_CONTACTS</code>
+      permission</td>
+      <td><code>WRITE_CALL_LOG</code></td>
+    </tr>
+  </table>
+
+
+
+<h2 id="merge-errors">Handling Manifest Merge Build Errors</h2>
+<p>During the build process, the manifest merge process stores a record of each merge transaction
+in the <code>manifest-merger-&lt;productFlavor&gt;-report.txt</code> file in the module
+<code>build/outputs/logs</code> folder. A different log file is generated for each of the
+module's build variants. </p>
+
+<p>When a manifest merge build error occurs, the merge process records the error message
+describing the merge conflict in the log file. For example, the
+<code>android:screenOrientation</code> merge conflict between the following manifests causes
+a build error. </p>
+
+<p>Higher priority manifest declaration: </p>
+
+<pre>
+&lt;activity
+   android:name="com.foo.bar.ActivityOne"
+   android:screenOrientation="portrait"
+   android:theme="&#64;theme1"/&gt;
+</pre>
+
+<p>Lower priority manifest declaration: </p>
+
+<pre>
+&lt;activity
+   android:name="com.foo.bar.ActivityOne"
+   android:screenOrientation="landscape"/&gt;
+</pre>
+
+<p>Error log:</p>
+
+<pre>
+/project/app/src/main/AndroidManifest.xml:3:9 Error:
+ Attribute activity&#64;screenOrientation value=(portrait) from AndroidManifest.xml:3:9
+ is also present at flavorlib:lib1:unspecified:3:18 value=(landscape)
+ Suggestion: add 'tools:replace="icon"' to <activity> element at AndroidManifest.xml:1:5 to override
+</pre>
+
+
diff --git a/docs/html/tools/help/adt.jd b/docs/html/tools/help/adt.jd
index 8abe1b4..0fac62d 100644
--- a/docs/html/tools/help/adt.jd
+++ b/docs/html/tools/help/adt.jd
@@ -30,20 +30,21 @@
     </div>
   </div>
 
-  <p>ADT (Android Developer Tools) is a plugin for Eclipse that provides a suite of
+<p class="caution">
+  <strong>Important:</strong> Support for the Android Developer Tools (ADT) in Eclipse is ending,
+  per our <a href=
+  "http://android-developers.blogspot.com/2015/06/an-update-on-eclipse-android-developer.html"
+  class="external-link">announcement</a>. You should migrate your app development projects to
+  Android Studio as soon as possible. For more information on transitioning to Android Studio, see
+  <a href="{@docRoot}sdk/installing/migrate.html">Migrating to Android Studio</a>.
+</p>
+
+  <p>Android Developer Tools (ADT) is a plugin for Eclipse that provides a suite of
   tools that are integrated with the Eclipse IDE. It offers you access to many features that help
   you develop Android applications. ADT
   provides GUI access to many of the command line SDK tools as well as a UI design tool for rapid
   prototyping, designing, and building of your application's user interface.</p>
 
-<p class="note"><strong>Note:</strong>
-If you have been using Eclipse with ADT, be aware that <a
-href="{@docRoot}tools/studio/index.html">Android Studio</a> is now the official IDE
-for Android, so you should migrate to Android Studio to receive all the
-latest IDE updates. For help moving projects,
-see <a href="/sdk/installing/migrate.html">Migrating to Android
-Studio</a>.</p>
-
 <p>If you still wish to use the ADT plugin for Eclipse, see
 <a href="{@docRoot}sdk/installing/installing-adt.html">Installing Eclipse Plugin.</a>
 </p>
diff --git a/docs/html/tools/studio/eclipse-transition-guide.jd b/docs/html/tools/studio/eclipse-transition-guide.jd
new file mode 100644
index 0000000..aaacbe3b
--- /dev/null
+++ b/docs/html/tools/studio/eclipse-transition-guide.jd
@@ -0,0 +1,773 @@
+page.title=Transition Guide for Eclipse ADT
+@jd:body
+
+
+<div id="qv-wrapper">
+<div id="qv">
+
+<h2>In this document</h2>
+  <ol>
+    <li><a href="#project-structure">Project Structure</a></li>
+    <li><a href="#manifest-settings">Manifest Settings</a></li>
+    <li><a href="#dependencies">Dependencies</a></li>
+    <li><a href="#build-process">Gradle-based Build Process</a></li>
+    <li><a href="#debug-inspect">Debugging and Code Inspections</a></li>
+    <li><a href="#resource-optimization">Resource Optimization</a></li>
+    <li><a href="#signing">App Signing</a></li>
+    <li><a href="#support-lib">Android Support Repository and Google Play services Repository</a></li>
+    <li><a href="#app-package">App Packaging</a></li>
+    <li><a href="#software-updates">Software Updates </a></li>
+    <li><a href="#version-control">Version Control</a></li>
+    </ol>
+
+  <h2>See also</h2>
+  <ol>
+    <li><a class="external-link"
+      href="http://confluence.jetbrains.com/display/IntelliJIDEA/FAQ+on+Migrating+to+IntelliJ+IDEA">
+      IntelliJ FAQ on migrating to IntelliJ IDEA</a></li>
+    <li><a class="external-link"
+      href="https://confluence.jetbrains.com/display/IntelliJIDEA/IntelliJ+IDEA+for+Eclipse+Users">
+      IntelliJ IntelliJ for Eclipse Users</a></li>
+    <li><a href="{@docRoot}tools/studio/index.html">Android Studio Overview</a> </li>
+  </ol>
+
+</div>
+</div>
+
+
+<p>This document describes the differences between Eclipse ADT and Android Studio, including project
+  structure, build system, debugging, and application packaging. This guide is intended to help you
+  transition to using Android Studio as your development environment.</p>
+
+<h2 id="project-structure">Project Structure </h2>
+<p>Eclipse provides workspaces as a common area for grouping related projects, configurations, and
+settings. In Android Studio, each instance of Android Studio contains a top-level project with one
+or more app modules. Each app module folder contains the equivalent to an Eclipse
+project, the complete source sets for that module, including {@code src/main} and
+{@code src/androidTest} directories, resources, build file, and the Android manifest. In general,
+to update and build your app you modify the files under each module's
+{@code src/main} directory for source code updates, the <code>gradle.build</code> file for
+build specification, and the files under {@code src/androidTest} directory for test case creation. </p>
+
+<p>You can also customize the view of the project files in Android Studio to focus on specific
+aspects of your app development: </p>
+
+<ul>
+  <li><em>Packages</em> </li>
+  <li><em>Project Files</em> </li>
+  <li><em>Scratches</em> </li>
+  <li><em>Problems</em> </li>
+  <li><em>Production</em> </li>
+  <li><em>Tests</em> </li>
+</ul>
+
+
+<p>The following table shows the general mapping of the Eclipse ADT project structure and file
+locations to Android Studio.</p>
+
+<p class="table-caption" id="table-project-structure-mapping">
+  <strong>Table 1.</strong> Project structure mapping.</p>
+
+<table>
+    <tr>
+        <th scope="col">Eclipse ADT</th>
+        <th scope="col">Android Studio</th>
+    </tr>
+
+    <tr>
+        <td>Workspace </td>
+        <td>Project </td>
+    </tr>
+
+    <tr>
+        <td>Project </td>
+        <td>Module </td>
+    </tr>
+
+     <tr>
+        <td>Project-specific JRE </td>
+        <td>Module JDK </td>
+     </tr>
+
+     <tr>
+        <td>Classpath variable </td>
+        <td>Path variable</td>
+     </tr>
+
+     <tr>
+        <td>Project dependency</td>
+        <td>Module dependency</td>
+     </tr>
+
+     <tr>
+        <td>Library Module</td>
+        <td>Library </td>
+     </tr>
+
+     <tr>
+       <td><code>AndroidManifest.xml</code></td>
+       <td><code>app/src/main/AndroidManifest.xml</code> </td>
+     </tr>
+     <tr>
+       <td><code>assets/</code></td>
+       <td><code>app/src/main/assets</code> </td>
+     </tr>
+     <tr>
+       <td><code>res/</code></td>
+       <td><code>app/src/main/res/</code> </td>
+     </tr>
+     <tr>
+       <td><code>src/</code></td>
+       <td><code>app/src/main/java/ </code> </td>
+     </tr>
+     <tr>
+       <td><code>tests/src/</code></td>
+       <td><code>app/src/androidTest/java/</code> </td>
+     </tr>
+
+   </table>
+
+
+
+<p>Table 2 shows Eclipse ADT and Android Studio project views. </p>
+
+<p class="table-caption" id="table2">
+  <strong>Table 2.</strong> Comparing project views.</p>
+<table>
+  <tbody><tr>
+    <th>Eclipse ADT</th>
+    <th>Android Studio Project View</th>
+    <th>Android Studio Android View</th>
+  </tr>
+  <tr>
+    <td><img src="{@docRoot}images/tools/eclipse-notepad-pre-import--structure.png"/>  </td>
+    <td><img src="{@docRoot}images/tools/studio-import-project-structure-project.png"/>  </td>
+    <td><img src="{@docRoot}images/tools/studio-import-project-structure-android.png"/>  </td>
+  </tr>
+ </tbody>
+</table>
+
+
+<p class="note"><strong>Note:</strong> Multiple instances of Android Studio can be used to develop
+independent projects. </p>
+
+
+
+
+<h2 id="manifest-settings">Manifest Settings</h2>
+<p>Android Studio and <a href="http://www.gradle.org">Gradle</a>-based builds support
+<a href="{@docRoot}tools/building/configuring-gradle.html#workBuildVariants"> build variants</a>,
+which are combinations of <code>productFlavor</code> and <code>buildTypes</code>, to customize
+your build outputs. To support these custom builds, several elements in the
+<code>AndroidManifest.xml</code> file are now properties in the <code>defaultConfig</code> and
+<code>productFlavors</code> blocks in the <code>build.gradle</code> file. The import process
+copies these manifest settings to the properties in the <code>build.gradle</code> file.
+These properties overwrite the settings in any other manifest files as shown in table 3. </p>
+
+<p class="table-caption" id="table-manifest-gradle-settings">
+  <strong>Table 3.</strong> Manifest and Gradle property settings.</p>
+<table>
+    <tr>
+        <th scope="col">Manifest Setting</th>
+        <th scope="col">build.gradle Setting</th>
+    </tr>
+    <tr>
+        <td><code>&lt;uses-sdk</code> <br>
+            <p><code>android:minSdkVersion</code></p>
+            <p><code>android:targetSdkVersion /&gt;</code></p>
+    </td>
+        <td> <br>
+           <p><code>minSdkVersion</code></p>
+           <p><code>targetSdkVersion</code></p> </td>
+    </tr>
+    <tr>
+        <td><code>&lt;manifest</code>
+            <p>package (Required in the default manifest file.) </p>
+            <p><code>android:versionCode</code></p>
+            <p><code>android:versionName /&gt;</code></p>
+    </td>
+        <td> <br>
+            <p><code>applicationId</code> (See
+            <a href="{@docRoot}tools/studio/index.html#app-id"> Application ID
+            for Package Identification</a>)</p>
+            <p><code>versionCode</code></p>
+            <p><code>versionName</code></p> </td>
+    </tr>
+
+   </table>
+
+
+<p>Although these settings may no longer appear in the default app manifest file, they are still
+valid manifest entries and may still appear in manifests from older projects, imported projects,
+dependencies, and libraries.</p>
+
+<p>The <code>package</code> element must still be specified in the manifest file. It is used in
+your source code to refer to your <code>R</code> class and to resolve any relative activity/service
+registrations. </p>
+
+<p class="note"><strong>Note:</strong> When multiple manifests are present in your app, for
+example a library manifest and a <code>src/main/</code> manifest, the build process combines
+the manifest settings into a single merged manifest based on the manifest priority and
+manifest merge settings. For more information about the manifest merge process and merge settings,
+see
+<a href="{@docRoot}tools/building/manifest-merger.html"> Manifest Merger</a>. </p>
+
+
+<h2>Application ID for package identification </h2>
+<p>With the Android build system, the <code>applicationId</code> attribute is used to
+uniquely identify application packages for publishing. The application ID is set in the
+<code>android</code> section of the <code>build.gradle</code> file. This field is populated in the
+build file as part of the migration process. </p>
+
+<pre>
+apply plugin: &#39;com.android.application&#39;
+
+android {
+   compileSdkVersion 19
+   buildToolsVersion "19.1"
+
+   defaultConfig {
+       <strong>applicationId "com.example.my.app"</strong>
+       minSdkVersion 15
+       targetSdkVersion 19
+       versionCode 1
+       versionName "1.0"
+   }
+ ...
+</pre>
+
+<p class="note"><strong>Note:</strong> The <code>applicationId</code> is specified only in your
+<code>build.gradle</code> file, and not in the <code>AndroidManifest.xml</code> file.</p>
+
+<p><a href="{@docRoot}tools/building/configuring-gradle.html#workBuildVariants">Build variants</a>
+enable you to uniquely identify different
+packages for each product flavor and build type. The application ID in the build type setting can
+be added as a suffix to the ID specified for the product flavors. The following example adds the
+<code>.debug</code> suffix to the application ID of the <code>pro</code> and <code>free</code>
+product flavors: </p>
+
+<pre>
+productFlavors {
+     pro {
+          applicationId = &quot;com.example.my.pkg.pro&quot;
+     }
+     free {
+          applicationId = &quot;com.example.my.pkg.free&quot;
+     }
+}
+
+buildTypes {
+    debug {
+          applicationIdSuffix &quot;.debug&quot;
+    }
+}
+....
+</pre>
+
+
+
+<h2 id="dependencies">Dependencies</h2>
+<p>During the import process, Android Studio imports the current Eclipse ADT dependencies and
+downloads any project libraries as Android Studio modules. The dependency declarations are added to
+the <code>build.gradle</code> file. The declarations include a
+<a href="#scopes">dependency scope</a>, such as
+<code>compile</code>, to specify in which builds the dependency is included. </p>
+
+<p>The following example shows how to add an external library JAR dependency so it's included in
+each compile:</p>
+
+<pre>
+dependencies {
+    compile files(&#39;libs/*.jar&#39;)
+}
+
+android {
+    ...
+}
+</pre>
+
+<p class="note"><strong>Note:</strong> Android Studio supports the Android ARchive (AAR) format
+for the distribution of Android library projects as dependencies. For more information, see
+<a href="{@docRoot}tools/building/configuring-gradle.html">Configuring Gradle Builds</a>. </p>
+
+
+<p>The import process replaces any well-known source libraries, binary libraries, and JAR files
+that have known Maven coordinates with Maven dependencies, so you no longer need to
+maintain these dependencies manually. </p>
+
+<p>Android Studio enables access to Maven, JCenter, and Ivy repositories with the
+<code>repositories</code> block in the <code>build.gradle</code> as a shortcut to specifying
+the URL of the repository.
+
+<p>If there are required repositories not declared in the <code>build.gradle</code> file, first add
+the repository to the <code>repositories</code> block, and then declare the dependencies in a way
+that Maven, JCenter, or Ivy declare their artifacts. The following example shows how to add the
+Maven repository with the guava 11.0.2 dependency using the <code>mavenCentral()</code> property: </p>
+
+<pre>
+repositories {
+    mavenCentral()
+}
+
+android {
+    ...
+}
+
+dependencies {
+    compile &#39;com.google.guava:guava:11.0.2&#39;
+    instrumentationtestCompile &#39;com.squareup.fast-android:1:0.4&#39;
+}
+
+</pre>
+
+<p>The Android Studio project created during the import process can also re-use any
+dependencies on other components. These components can be external binary packages or other
+<a href="http://www.gradle.org">Gradle</a> projects. If a dependency has dependencies of its own,
+those dependencies are also included in the new Android Studio project. </p>
+
+
+<p class="note"><strong>Note:</strong> If there were references to Eclipse ADT workspace library
+files in the <code>project.properties</code> or <code>.classpath</code> files
+that were not imported from the Eclipse project, you can now add dependencies to these library files
+in the <code>build.gradle</code> file. For more information, see
+<a href="{@docRoot}tools/building/configuring-gradle.html">Configuring Gradle Builds</a>. </p>
+
+
+<h3 id="scopes">Dependency and compilation scopes </h3>
+<p>Android Studio supports compilation scopes to customize which dependencies get
+included in each build, for example assigning different dependencies to different
+<a href="{@docRoot}tools/building/configuring-gradle.html#workBuildVariants"> build variants</a>.</p>
+
+<p>This list shows the Android Studio scope names and definitions: </p>
+
+<ul>
+ <li>compile - <code>compile</code> </li>
+ <li>run time - <code>package</code></li>
+ <li>testCompile - <code>AndroidTestCompile</code></li>
+ <li>testRuntime - <code>AndroidTestRunPackage</code></li>
+ <li>buildTypeCompile - <code>buildTypeCompile</code> </li>
+ <li>productFlavorCompile - <code>productFlavorCompile</code> </li>
+</ul>
+
+<p class="note"><strong>Note:</strong> Dependencies for library projects must be added with the
+<code>compile</code> scope. </p>
+
+
+<p>With the <a href="http://www.gradle.org">Gradle</a>-based DSL, you can also add custom
+dependency scopes, such as <code>betaCompile file('libs/protobug.jar')</code> to define a beta
+build dependency. </p>
+
+<p>The scope and compilation configuration in the build file determine the
+components compiled into the app, added to the compilation classpath, and packaged in the final
+APK file. Based on the dependency and compilation scope, different compilation configurations
+can be specified to include the dependencies and classpaths, for example: </p>
+
+<ul>
+<li><code>compile</code> - for the main application. </li>
+<li><code>androidTestCompile</code> - for the test application. </li>
+<li><code>debugCompile</code> - for the debug buildType application.</li>
+<li><code>releaseCompile</code> - for the release buildType application. </li>
+</ul>
+
+<p class="note"><strong>Note:</strong> Because it’s not possible to build an APK that does not
+have an associated <code>buildType</code>, the APK built from your app is always configured with
+at least two dependency and compile configurations: <code>compile</code> and
+<code>debugCompile</code>. </p>
+
+<p>Unlike Eclipse ADT, by default Android Studio does not compile your code when there are changes.
+Use the <strong>File &gt; Settings &gt; Build, Execution, Deployment Compiler</strong> option
+to enable automatic compilation. </p>
+
+
+
+<h2 id="build-process">Gradle-based Build Process </h2>
+<p>Android Studio imports the Eclipse ADT Ant-based
+build tasks and converts the tasks to <a href="http://www.gradle.org">Gradle</a>-based build tasks.
+These new build tasks include the
+main <code>assemble</code> task and at least two outputs based on the default build types:
+a <code>debug</code> APK and a
+<code>release</code> APK. Each of these build tasks has its own Android build system anchor task
+to facilitate building them independently: </p>
+<ul>
+  <li><code>assemble</code></li>
+  <li><code>assembleDebug</code></li>
+  <li><code>assembleRelease</code></li>
+</ul>
+
+<p>In Android Studio, you can view all the supported build tasks in the
+<em>Gradle</em> project tab. </p>
+
+<p>With the <a href="http://www.gradle.org">Gradle</a>-based build system, Android Studio uses a
+<a href="http://www.gradle.org">Gradle</a> wrapper to fully integrate the
+Android Plugin for Gradle. The Android Plugin for Gradle also
+runs independent of Android Studio. This means that with Android Studio build system your build
+output is always the same, whether you build your Android apps from Android Studio, from the
+command line on your machine, or on machines where Android Studio is not installed (such as
+continuous integration servers). </p>
+
+<p>Unlike Eclipse ADT with dependent plugin and build updates, the <code>build.gradle</code>
+files allow you to customize the build settings for each Android Studio module and build variant,
+so the build versions can be set independently, and are not dependent on the Android Studio
+or build tools versions. This makes it easy to maintain and build legacy apps along with your
+current app, using build variants to generate different APKs from the same app modules, but
+built with different build versions and build chains. </p>
+
+<p>For more details about the Android Studio build system, see
+<a href="{@docRoot}sdk/installing/studio-build.html">Build System Overview</a>.</p>
+
+<h3>Using the Android Studio build system's declarative logic </h3>
+<p>In contrast with the XML statements in Ant build files, the Android build system and
+<a href="http://www.gradle.org">Gradle</a> DSL provide a declarative build language so you can
+easily extend the Gradle-based build process beyond the typical XML build tasks. For example,
+this build file shows how to define a custom function to inject a dynamic <code>versionCode</code>
+in build outputs: </p>
+
+<pre>
+def getVersionCode) {
+      def code = …
+      return code
+}
+
+android {
+    defaultConfig {
+        versionCode getVersionCode()
+              …
+    }
+}
+</pre>
+
+<p>This example shows how to append <em>debug</em> to your package and version names used in the
+<code>debug</code> build variant of your app: </p>
+
+<pre>
+android {
+    buildTypes {
+        debug {
+            packageNameSuffix ‘.debug’
+            versionNameSuffix ‘-DEBUG’
+              }
+            beta {
+                   …
+            }
+        }
+}
+</pre>
+
+
+<p>You can also use the declarative DSL in the Android build system to generate custom build
+versions, for example a debuggable version of your release APK. This examples adds the
+<code>debuggable true</code> property to the <code>release</code> build type in the
+<code>build.gradle</code> file to build an identical debuggable version of the release package.  </p>
+
+<pre>
+android {
+    buildTypes {
+        debugRelease.initWith(buildTypes.release)
+        debugRelease {
+            debuggable true
+            packageNameSuffix &#39;.debugrelease&#39;
+            signingConfig signingConfigs.debug
+        }
+
+    }
+    sourceSets.debugRelease.setRoot(&#39;src/release&#39;)
+}
+</pre>
+
+
+
+
+
+
+<h2 id="debug-inspect">Debugging and Code Inspections</h2>
+<p>Using code inspection tools such as <a href="{@docRoot}tools/help/lint.html">lint</a> is a
+standard part of Android development. Android Studio extends
+<a href="{@docRoot}tools/help/lint.html">lint</a> support with additional
+<a href="{@docRoot}tools/help/lint.html">lint</a> checks and supports Android
+<a href="{@docRoot}tools/debugging/annotations.html">annotations</a> that
+allow you to help detect more subtle code problems, such as null pointer exceptions and resource
+type conflicts. Annotations are added as metadata tags that you attach to variables, parameters,
+and return values to inspect method return values, passed parameters, and local variables and
+fields.  </p>
+
+<p>For more information on enabling <a href="{@docRoot}tools/help/lint.html">lint</a> inspections
+and running <a href="{@docRoot}tools/help/lint.html">lint</a>,
+see <a href="{@docRoot}tools/debugging/improving-w-lint.html">Improving Your Code with lint</a>.
+For more information about using annotations, see
+<a href="{@docRoot}tools/debugging/annotations.html#annotations">Improving your Code with
+Annotations</a>. </p>
+
+<p>In addition to code inspection, Android Studio provides an integrated
+<a href="{@docRoot}tools/studio/index.html#mem-cpu">memory and CPU monitor</a> view so you
+can more easily monitor your app's performance and memory usage to track CPU usage, find
+deallocated objects, locate memory leaks, and track the amount of memory the connected device is
+using. </p>
+
+
+
+<h2 id="resource-optimization">Resource Optimization </h2>
+<p>After importing and building your app, Android Studio supports several
+<a href="http://www.gradle.org">Gradle</a>-based properties to help you minimize your app's
+resource utilization. </p>
+
+
+<h3>Resource shrinking</h3>
+<p>In Android Studio, resource shrinking enables the automatic removal of unused resources from
+your packaged app and also removes resources from library dependencies if the resources are not
+actually used by your app.</p>
+
+<p>Use the <code>shrinkResources</code> attribute in the <code>buildType</code> block in your
+<code>build.gradle</code> file to enable resource shrinking. For example, if your application is
+using <a href="{@docRoot}google/play-services/index.html">Google Play services</a>
+to access Google Drive functionality, and you are not currently using
+<a href="{@docRoot}google/play-services/plus.html">Google+ Sign In</a>, then
+this setting removes the various drawable assets for the <code>SignInButton</code> buttons. </p>
+
+<p class="note"><strong>Note:</strong> Resource shrinking works in conjunction with code shrinking
+tools, such as <a href="{@docRoot}tools/help/proguard.html">ProGuard</a>. </p>
+
+<p>To enable resource shrinking, update the <code>buildTypes</code> block in the
+<code>build.gradle</code> file to include <code>minifyEnabled true</code>,
+<code>shrinkResources true</code>, and <code>proguardFiles</code> settings as shown in the
+following example <a href="http://www.gradle.org">Gradle</a> build file.</p>
+
+<pre>
+android {
+    ...
+
+    buildTypes {
+        release {
+            minifyEnabled true
+            shrinkResources true
+            proguardFiles getDefaultProguardFile('proguard-android.txt'),
+            'proguard-rules.pro'
+        }
+    }
+}
+</pre>
+
+
+
+<h3>Filtering language resources</h3>
+<p>Use the <code>resConfig</code> attribute in your <code>build.gradle</code> file
+to filter the locale resources included in your packaged app. This filtering can be especially
+useful when library dependencies such as <code>appcompat-v7</code> and other libraries such as
+<code>google-play-services_lib</code> are included in your app. </p>
+
+<p>The following example limits the locale resources to three language settings: <code>en</code>,
+<code>de</code>, and <code>es</code>:</p>
+
+<pre>
+apply plugin: 'android'
+
+android {
+    compileSdkVersion 22
+    buildToolsVersion "22.0.1"
+
+    defaultConfig {
+        minSdkVersion 8
+        targetSdkVersion 22
+        versionCode 1
+        versionName "1.0"
+        resConfigs "en", "de", "es" //Define the included language resources.
+    }
+...
+
+</pre>
+
+
+
+<h4>Filtering bundled resources</h4>
+<p>You can also use the <code>resConfig</code> build setting to limit the bundled resources
+in any resource folder. For example, you could also add <code>resConfigs</code>
+settings for density folders, such as <code>mdpi</code> or <code>hdpi</code> to limit the drawable
+resources that are packaged in your <code>APK</code> file. This example limits the app's
+bundled resources to medium-density (MDPI) and high-density (HDPI) resources. </p>
+
+<pre>
+android {
+    defaultConfig {
+        ...
+        resConfigs "mdpi", "hdpi"
+    }
+}
+</pre>
+
+For more information about screen and resource densities, see
+<a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a>
+and <a href="{@docRoot}training/multiscreen/screendensities.html">Supporting Different Densities</a>.
+
+
+<h3>Resource merging </h3>
+<p>With Android Studio, identical resources, such as copies of launcher and menu icons, may end up
+in different resource folders throughout your app. To reduce resource duplication and improve
+the performance of your app, Android Studio merges resources with an identical resource name, type,
+and qualifier into a single resource and passes the single, merged resource to the Android Asset
+Packaging Tool (AAPT) for distribution in the APK file. </p>
+
+<p>The resource merging process looks for identical resources in the following <code>/res/</code>
+folders: </p>
+<ul>
+  <li>AAR bundles of library project dependencies</li>
+  <li><code>src/main/</code> </li>
+  <li><code>src/<em>productFlavor</em>/</code> </li>
+  <li><code>src/<em>buildType</em>/</code> </li>
+</ul>
+
+<p>Identical resources are merged in the following low to high priority order: </p>
+<pre>
+dependencies --> src/main/ --> src/productFlavor/ --> src/buildType/
+</pre>
+
+<p>For example, if the <code>res/ic_menu.png</code> file is included in both the
+<code>src/main/res/</code> and <code>src/productFlavor/res/</code> folders, the resources are merged
+so only the file with the higher priority, in this case the <code>src/productFlavor/res/</code>
+file, is included in the APK file. </p>
+
+<p class="note"><strong>Note:</strong> Identical resources in the same source set are not merged
+and instead generate a resource merge error. This can happen if the <code>sourceSet</code> property
+in the <code>build.gradle</code> file is used to define multiple source sets, for example
+<code>src/main/res/</code> and <code>src/main/res2/</code>, and these folders contain identical
+resources. </p>
+
+
+
+
+<h2 id="signing">App Signing and ProGuard </h2>
+<p>Based on the imported Eclipse ADT app settings, Android Studio automatically sets up your app
+signing and maintains any ProGuard settings. </p>
+
+<h3>App Signing</h3>
+<p>If your app used a debug certificate in Eclipse ADT, Android Studio continues to reference that
+certificate. Otherwise, the <code>debug</code> configuration uses the Android Studio generated
+debug keystore, with a known password and a default key with a known password located in
+<code>$HOME/.android/debug.keystore</code>. The <code>debug</code> build type is set to use this
+debug <code>SigningConfig</code> automatically when you run or debug your project
+from Android Studio. </p>
+
+<p>In release mode, Android Studio applies the release certificate used in Eclipse ADT. If no
+release certificate was located during the import process, add the release signing configuration to
+the <code>build.gradle</code> file or use the <strong> Build > Generate Signed APK</strong> menu
+option to open the Generate Signed APK Wizard. For more information about signing your app, see
+<a href="{@docRoot}tools/publishing/app-signing.html">Signing Your Applications</a>. </p>
+
+
+<h3>ProGuard</h3>
+<p>If the <a href="{@docRoot}tools/help/proguard.html">ProGuard</a> option is specified in the
+<code>project.properties</code> file in the Eclipse ADT project, Android Studio imports the
+<a href="{@docRoot}tools/help/proguard.html">ProGuard</a> files and adds the
+<a href="{@docRoot}tools/help/proguard.html">ProGuard</a> settings to the
+<code>build.gradle</code> file. <a href="{@docRoot}tools/help/proguard.html">ProGuard</a> is
+supported through the <code>minifyEnabled</code> property as shown in this example. </p>
+
+<pre>
+android {
+    buildTypes {
+        release {
+            minifyEnabled true
+            proguardFile getDefaultProguardFile(&#39;proguard-android.txt&#39;)
+        }
+    }
+
+    productFlavors {
+        flavor1 {
+        }
+        flavor2 {
+            proguardFile &#39;some-other-rules.txt&#39;
+        }
+    }
+}
+
+</pre></p>
+
+
+
+
+<h2 id="support-lib">Android Support Repository and Google Play services Repository</h2>
+<p>While Eclipse ADT uses the Android <a href="{@docRoot}tools/support-library/index.html">Support
+Library</a> and Google Play services Library, Android Studio replaces these libraries during the
+import process with the Android Support Repository and Google Repository to maintain
+compatible functionality and support new Android features. Android Studio adds these dependencies
+as Maven dependencies using the known Maven coordinates, so these dependencies do not require
+manual updates.  </p>
+
+<p>In Eclipse, in order to use a
+<a href="{@docRoot}tools/support-library/index.html">Support Library</a>, you must modify your
+project's classpath dependencies within your development environment for each
+<a href="{@docRoot}tools/support-library/index.html">Support Library</a> you want to use. In
+Android Studio, you no longer need to copy library sources into your
+own projects, you can simply declare a dependency and the library is automatically downloaded and
+merged into your project. This includes automatically merging in resources, manifest entries,
+<a href="{@docRoot}tools/help/proguard.html">ProGuard</a> exclusion rules, and custom lint rules
+at build time. </p>
+
+<p>Android Studio also supports binary library Android ARchives (AARs). AARs are a library project's
+main output as a combination of compiled code (as a jar file and/or native .so files) and
+resources (manifest, res, assets). <p/>
+
+
+<h2 id="app-package">App Packaging</h2>
+<p>The Android build system introduces the use of the <code>applicationId</code> attribute to
+uniquely identify application packages for publishing. The application ID is set in the
+<code>android</code> section of the <code>build.gradle</code> file. </p>
+
+<p>The <code>applicationId</code> is specified only in your <code>build.gradle</code> file, and
+not in the
+<code>AndroidManifest.xml</code> file. The Gradle-based build system enables you
+to uniquely identify different packages for each build variant based on product flavors and build
+types. You can also add the <code>applicationIdSuffix</code> property to the build type in the
+<code>build.gradle</code> file to append an identifier, such as '.debug', to the  application ID
+generated for each product flavor. </p>
+
+
+
+<h2 id="software-updates">Software Updates</h2>
+<p>Android Studio provides several levels of update and maintenance to help you keep Android Studio
+up-to-date based on your code-level preference: </p>
+
+<ul>
+  <li><strong>Canary channel</strong>: Canary builds provide bleeding edge releases and are updated
+  about weekly. These builds do get tested, but are still subject to bugs, as these are
+  early releases. This is not recommended for production.</li>
+  <li><strong>Dev channel</strong>: Dev builds are canary builds that passed initial testing and
+  usage. They are updated roughly bi-weekly or monthly.</li>
+  <li><strong>Beta channel</strong>: Beta builds provide beta-quality releases for final testing
+  and feedback before a production release.</li>
+  <li><strong>Stable channel</strong>: Stable builds provide stable, production-ready release
+  versions.</li>
+</ul>
+
+
+
+<h2 id="version-control">Version Control </h2>
+<p>Eclipse ADT supports version control through the use of plugins, such as the EGit and Subversive
+plug-ins.  </p>
+
+<p>Android Studio supports a variety of version control systems (Git, GitHub, CVS, Mercurial,
+Subversion, and Google Cloud) so version control operations can continue from within Android
+Studio. </p>
+
+<p>After importing your Eclipse ADT app into Android Studio, use the
+Android Studio <em>VCS</em> menu options to enable VCS support for the desired version control
+system, create a repository, import the new files into version control, and perform other version
+control operations.  </p>
+
+<p class="note"><strong>Note:</strong> You can also use the
+<strong>File &gt; Setting &gt; Version Control</strong> menu option to setup and modify the version
+control settings. </p>
+
+<h3>Files to ignore </h3>
+<p>A number of Android Studio files are typically not added to version control as these are
+temporary files or files that get overwritten with each build. These files are listed in
+an exclusion file, such as <code>.gitignore</code>, for the project and each app module.
+Typically, the following files are excluded from version control:  </p>
+
+<ul>
+  <li>.gradle </li>
+  <li>/local.properties </li>
+  <li>/.idea/workspace.xml </li>
+  <li>/.idea/libraries </li>
+  <li>.DS_Store</li>
+  <li>/build </li>
+  <li>/captures </li>
+</ul>
diff --git a/docs/html/tools/studio/index.jd b/docs/html/tools/studio/index.jd
index 0113347..fa6d987 100644
--- a/docs/html/tools/studio/index.jd
+++ b/docs/html/tools/studio/index.jd
@@ -175,7 +175,7 @@
 <a href="{@docRoot}tools/building/configuring-gradle.html">Configuring Gradle Builds</a>.</p>
 
 
-<h3>Application ID for package identification </h3>
+<h3 id="app-id">Application ID for package identification </h3>
 <p>With the Android build system, the <em>applicationId</em> attribute is used to
 uniquely identify application packages for publishing. The application ID is set in the
 <em>android</em> section of the <code>build.gradle</code> file.
diff --git a/docs/html/tools/tools_toc.cs b/docs/html/tools/tools_toc.cs
index a5e617d..abfa030 100644
--- a/docs/html/tools/tools_toc.cs
+++ b/docs/html/tools/tools_toc.cs
@@ -151,12 +151,7 @@
     <div class="nav-section-header"><a href="<?cs var:toroot ?>tools/help/index.html"><span
 class="en">Tools Help</span></a></div>
     <ul>
-      <li class="nav-section">
-        <div class="nav-section-header"><a href="<?cs var:toroot ?>tools/help/adb.html">adb</a></div>
-        <ul>
-          <li><a href="<?cs var:toroot ?>tools/help/shell.html">Shell commands</a></li>
-        </ul>
-      </li>
+      <li><a href="<?cs var:toroot ?>tools/help/adb.html">adb</a></li>
       <li><a href="<?cs var:toroot ?>tools/help/android.html">android</a></li>
       <li><a href="<?cs var:toroot ?>tools/help/avd-manager.html">AVD Manager</a></li>
       <li><a href="<?cs var:toroot ?>tools/help/bmgr.html">bmgr</a>
@@ -173,7 +168,6 @@
       <li><a href="<?cs var:toroot ?>tools/help/mksdcard.html">mksdcard</a></li>
        <li><a href="<?cs var:toroot ?>tools/help/proguard.html" zh-cn-lang="ProGuard">ProGuard</a></li>
        <li><a href="<?cs var:toroot ?>tools/help/sdk-manager.html">SDK Manager</a></li>
-       <li><a href="<?cs var:toroot ?>tools/help/sqlite3.html">sqlite3</a></li>
        <li><a href="<?cs var:toroot ?>tools/help/systrace.html">Systrace</a></li>
        <li><a href="<?cs var:toroot ?>tools/help/gltracer.html">Tracer for OpenGL ES</a></li>
        <li><a href="<?cs var:toroot ?>tools/help/traceview.html">Traceview</a></li>
@@ -195,71 +189,13 @@
         <span class="en">Configuring Gradle Builds</span></a></li>
       <li><a href="<?cs var:toroot ?>tools/building/plugin-for-gradle.html">
         <span class="en">Android Plugin for Gradle</span></a></li>
+      <li><a href="<?cs var:toroot ?>tools/building/manifest-merge.html">
+        <span class="en">Manifest Merging</span></a></li>
       <li><a href="<?cs var:toroot ?>tools/building/multidex.html">
         <span class="en">Apps Over 65K Methods</span></a></li>
       </ul>
   </li><!-- end of build system -->
 
-<!-- Performance Tools menu-->
-  <li class="nav-section">
-    <div class="nav-section-header">
-      <a href="<?cs var:toroot ?>tools/performance/index.html">Peformance Tools</a>
-    </div>
-    <ul>
-      <li><a href="<?cs var:toroot ?>tools/performance/debug-gpu-overdraw/index.html">
-        Overdraw Debugger</a>
-      </li>
-      <li><a href="<?cs var:toroot ?>tools/performance/profile-gpu-rendering/index.html">
-        Rendering Profiler</a>
-      </li>
-      <li class="nav-section">
-        <div class="nav-section-header">
-          <a href="<?cs var:toroot ?>tools/performance/hierarchy-viewer/index.html">
-          Hierarchy Viewer</a></div>
-        <ul>
-          <li><a href="<?cs var:toroot ?>tools/performance/hierarchy-viewer/setup.html"><span
-            class="en">Setup</span></a>
-          </li>
-          <li><a href="<?cs var:toroot ?>tools/performance/hierarchy-viewer/profiling.html"><span
-            class="en">Profiling</span></a>
-          </li>
-        </ul>
-      </li>
-      <li class="nav-section">
-        <div class="nav-section-header">
-          <a href="<?cs var:toroot ?>tools/performance/comparison.html">
-          Memory Profilers</a></div>
-        <ul>
-          <li><a href="<?cs var:toroot ?>tools/performance/memory-monitor/index.html"><span
-            class="en">Memory Monitor</span></a>
-          </li>
-          <li><a href="<?cs var:toroot ?>tools/performance/heap-viewer/index.html"><span
-            class="en">Heap Viewer</span></a>
-          </li>
-          <li><a href="<?cs var:toroot ?>tools/performance/allocation-tracker/index.html"><span
-            class="en">Allocation Tracker</span></a>
-          </li>
-        </ul>
-      </li>
-      <li><a href="<?cs var:toroot ?>tools/performance/traceview/index.html">
-        Traceview</a>
-      </li>
-      <li><a href="<?cs var:toroot ?>tools/performance/systrace/index.html">
-        Systrace</a>
-      </li>
-      <li class="nav-section">
-        <div class="nav-section-header">
-          <a href="<?cs var:toroot ?>tools/performance/batterystats-battery-historian/index.html">
-          Battery Profilers</a></div>
-        <ul>
-          <li><a href="<?cs var:toroot ?>tools/performance/batterystats-battery-historian/charts.html"><span
-            class="en">Historian Charts</span></a>
-          </li>
-        </ul>
-      </li>
-    </ul>
-  </li><!-- End Performance Tools menu-->
-
   <!-- Testing Tools menu-->
 
   <li class="nav-section">
@@ -357,7 +293,15 @@
       <span class="en">Eclipse with ADT</span></a>
     </div>
     <ul>
-    <li><a href="<?cs var:toroot ?>sdk/installing/migrate.html">Migrating to Android Studio</a></li>
+        <li class="nav-section">
+        <div class="nav-section-header"><a href="<?cs var:toroot ?>sdk/installing/migrate.html">
+          <span class="en">Migrating to Android Studio</span></a></div>
+         <ul>
+            <li><a href="<?cs var:toroot ?>tools/studio/eclipse-transition-guide.html">
+            Transition Guide</span></a> </li>
+         </ul>
+        </li>
+
     <li><a href="<?cs var:toroot ?>sdk/installing/installing-adt.html">
         <span class="en">Installing the Eclipse Plugin</span></a></li>
     <li><a href="<?cs var:toroot ?>tools/projects/projects-eclipse.html">Managing Projects</a></li>
diff --git a/docs/html/training/volley/requestqueue.jd b/docs/html/training/volley/requestqueue.jd
index 5e892bf..6d19cee 100644
--- a/docs/html/training/volley/requestqueue.jd
+++ b/docs/html/training/volley/requestqueue.jd
@@ -139,7 +139,8 @@
 <p>Here is an example of a singleton class that provides {@code RequestQueue} and
 {@code ImageLoader} functionality:</p>
 
-<pre>private static MySingleton mInstance;
+<pre>public class MySingleton {
+    private static MySingleton mInstance;
     private RequestQueue mRequestQueue;
     private ImageLoader mImageLoader;
     private static Context mCtx;
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
index de483f4..dc8f1e3 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
@@ -140,21 +140,64 @@
             throw new NullPointerException("alias == null");
         }
 
-        byte[] certificate = mKeyStore.get(Credentials.USER_CERTIFICATE + alias);
-        if (certificate != null) {
-            return wrapIntoKeyStoreCertificate(
-                    Credentials.USER_PRIVATE_KEY + alias, toCertificate(certificate));
+        byte[] encodedCert = mKeyStore.get(Credentials.USER_CERTIFICATE + alias);
+        if (encodedCert != null) {
+            return getCertificateForPrivateKeyEntry(alias, encodedCert);
         }
 
-        certificate = mKeyStore.get(Credentials.CA_CERTIFICATE + alias);
-        if (certificate != null) {
-            return wrapIntoKeyStoreCertificate(
-                    Credentials.USER_PRIVATE_KEY + alias, toCertificate(certificate));
+        encodedCert = mKeyStore.get(Credentials.CA_CERTIFICATE + alias);
+        if (encodedCert != null) {
+            return getCertificateForTrustedCertificateEntry(encodedCert);
         }
 
+        // This entry/alias does not contain a certificate.
         return null;
     }
 
+    private Certificate getCertificateForTrustedCertificateEntry(byte[] encodedCert) {
+        // For this certificate there shouldn't be a private key in this KeyStore entry. Thus,
+        // there's no need to wrap this certificate as opposed to the certificate associated with
+        // a private key entry.
+        return toCertificate(encodedCert);
+    }
+
+    private Certificate getCertificateForPrivateKeyEntry(String alias, byte[] encodedCert) {
+        // All crypto algorithms offered by Android Keystore for its private keys must also
+        // be offered for the corresponding public keys stored in the Android Keystore. The
+        // complication is that the underlying keystore service operates only on full key pairs,
+        // rather than just public keys or private keys. As a result, Android Keystore-backed
+        // crypto can only be offered for public keys for which keystore contains the
+        // corresponding private key. This is not the case for certificate-only entries (e.g.,
+        // trusted certificates).
+        //
+        // getCertificate().getPublicKey() is the only way to obtain the public key
+        // corresponding to the private key stored in the KeyStore. Thus, we need to make sure
+        // that the returned public key points to the underlying key pair / private key
+        // when available.
+
+        X509Certificate cert = toCertificate(encodedCert);
+        if (cert == null) {
+            // Failed to parse the certificate.
+            return null;
+        }
+
+        String privateKeyAlias = Credentials.USER_PRIVATE_KEY + alias;
+        if (mKeyStore.contains(privateKeyAlias)) {
+            // As expected, keystore contains the private key corresponding to this public key. Wrap
+            // the certificate so that its getPublicKey method returns an Android Keystore
+            // PublicKey. This key will delegate crypto operations involving this public key to
+            // Android Keystore when higher-priority providers do not offer these crypto
+            // operations for this key.
+            return wrapIntoKeyStoreCertificate(privateKeyAlias, cert);
+        } else {
+            // This KeyStore entry/alias is supposed to contain the private key corresponding to
+            // the public key in this certificate, but it does not for some reason. It's probably a
+            // bug. Let other providers handle crypto operations involving the public key returned
+            // by this certificate's getPublicKey.
+            return cert;
+        }
+    }
+
     /**
      * Wraps the provided cerificate into {@link KeyStoreX509Certificate} so that the public key
      * returned by the certificate contains information about the alias of the private key in
diff --git a/libs/hwui/Outline.h b/libs/hwui/Outline.h
index 5e9b213..c98932c 100644
--- a/libs/hwui/Outline.h
+++ b/libs/hwui/Outline.h
@@ -19,6 +19,7 @@
 #include <SkPath.h>
 
 #include "Rect.h"
+#include "utils/MathUtils.h"
 
 namespace android {
 namespace uirenderer {
@@ -85,6 +86,11 @@
         return mShouldClip && (mType == kOutlineType_RoundRect);
     }
 
+    bool willRoundRectClip() const {
+        // only round rect outlines can be used for clipping
+        return willClip() && MathUtils::isPositive(mRadius);
+    }
+
     bool getAsRoundRect(Rect* outRect, float* outRadius) const {
         if (mType == kOutlineType_RoundRect) {
             outRect->set(mBounds);
diff --git a/libs/hwui/RenderProperties.h b/libs/hwui/RenderProperties.h
index 81cf2df..11abd70 100644
--- a/libs/hwui/RenderProperties.h
+++ b/libs/hwui/RenderProperties.h
@@ -169,7 +169,7 @@
         bool functorsNeedLayer = ancestorDictatesFunctorsNeedLayer
 
                 // Round rect clipping forces layer for functors
-                || CC_UNLIKELY(getOutline().willClip())
+                || CC_UNLIKELY(getOutline().willRoundRectClip())
                 || CC_UNLIKELY(getRevealClip().willClip())
 
                 // Complex matrices forces layer, due to stencil clipping
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index a806440..b3b2b97 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -619,10 +619,6 @@
                 com.android.internal.R.bool.config_useVolumeKeySounds);
         mUseFixedVolume = getContext().getResources().getBoolean(
                 com.android.internal.R.bool.config_useFixedVolume);
-        sAudioPortEventHandler.init();
-
-        mPortListener = new OnAmPortUpdateListener();
-        registerAudioPortUpdateListener(mPortListener);
     }
 
     private Context getContext() {
@@ -3554,6 +3550,7 @@
      * @hide
      */
     public void registerAudioPortUpdateListener(OnAudioPortUpdateListener l) {
+        sAudioPortEventHandler.init();
         sAudioPortEventHandler.registerListener(l);
     }
 
@@ -3586,6 +3583,7 @@
 
     static int updateAudioPortCache(ArrayList<AudioPort> ports, ArrayList<AudioPatch> patches,
                                     ArrayList<AudioPort> previousPorts) {
+        sAudioPortEventHandler.init();
         synchronized (sAudioPortGeneration) {
 
             if (sAudioPortGeneration == AUDIOPORT_GENERATION_INIT) {
@@ -3849,6 +3847,12 @@
             android.os.Handler handler) {
         if (callback != null && !mDeviceCallbacks.containsKey(callback)) {
             synchronized (mDeviceCallbacks) {
+                if (mDeviceCallbacks.size() == 0) {
+                    if (mPortListener == null) {
+                        mPortListener = new OnAmPortUpdateListener();
+                    }
+                    registerAudioPortUpdateListener(mPortListener);
+                }
                 NativeEventHandlerDelegate delegate =
                         new NativeEventHandlerDelegate(callback, handler);
                 mDeviceCallbacks.put(callback, delegate);
@@ -3867,6 +3871,9 @@
         synchronized (mDeviceCallbacks) {
             if (mDeviceCallbacks.containsKey(callback)) {
                 mDeviceCallbacks.remove(callback);
+                if (mDeviceCallbacks.size() == 0) {
+                    unregisterAudioPortUpdateListener(mPortListener);
+                }
             }
         }
     }
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index 0180a30..9325246 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -387,7 +387,7 @@
         } else if (isActive()) {
             // This is the active connection on non-passpoint network
             summary.append(getSummary(mContext, getDetailedState(),
-                    networkId == WifiConfiguration.INVALID_NETWORK_ID));
+                    mInfo != null && mInfo.isEphemeral()));
         } else if (mConfig != null && mConfig.isPasspoint()) {
             String format = mContext.getString(R.string.available_via_passpoint);
             summary.append(String.format(format, mConfig.providerFriendlyName));
@@ -620,7 +620,8 @@
     }
 
     public boolean isEphemeral() {
-        return !isSaved() && mNetworkInfo != null && mNetworkInfo.getState() != State.DISCONNECTED;
+        return mInfo != null && mInfo.isEphemeral() &&
+                mNetworkInfo != null && mNetworkInfo.getState() != State.DISCONNECTED;
     }
 
     /** Return whether the given {@link WifiInfo} is for this access point. */
@@ -757,7 +758,7 @@
             mAccessPointListener.onAccessPointChanged(this);
         }
     }
-    
+
     public static String getSummary(Context context, String ssid, DetailedState state,
             boolean isEphemeral, String passpointProvider) {
         if (state == DetailedState.CONNECTED && ssid == null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 860a6b7..3678cf1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -2931,6 +2931,9 @@
         if (mZenModeController != null) {
             mZenModeController.setUserId(mCurrentUserId);
         }
+        if (mSecurityController != null) {
+            mSecurityController.onUserSwitched(mCurrentUserId);
+        }
     }
 
     private void resetUserSetupObserver() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
index 962000a..b505d9d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
@@ -64,6 +64,7 @@
 
     private SparseArray<VpnConfig> mCurrentVpns = new SparseArray<>();
     private int mCurrentUserId;
+    private int mVpnUserId;
 
     public SecurityControllerImpl(Context context) {
         mContext = context;
@@ -78,7 +79,7 @@
 
         // TODO: re-register network callback on user change.
         mConnectivityManager.registerNetworkCallback(REQUEST, mNetworkCallback);
-        mCurrentUserId = ActivityManager.getCurrentUser();
+        onUserSwitched(ActivityManager.getCurrentUser());
     }
 
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
@@ -123,9 +124,9 @@
 
     @Override
     public String getPrimaryVpnName() {
-        VpnConfig cfg = mCurrentVpns.get(mCurrentUserId);
+        VpnConfig cfg = mCurrentVpns.get(mVpnUserId);
         if (cfg != null) {
-            return getNameForVpnConfig(cfg, new UserHandle(mCurrentUserId));
+            return getNameForVpnConfig(cfg, new UserHandle(mVpnUserId));
         } else {
             return null;
         }
@@ -133,8 +134,8 @@
 
     @Override
     public String getProfileVpnName() {
-        for (UserInfo profile : mUserManager.getProfiles(mCurrentUserId)) {
-            if (profile.id == mCurrentUserId) {
+        for (UserInfo profile : mUserManager.getProfiles(mVpnUserId)) {
+            if (profile.id == mVpnUserId) {
                 continue;
             }
             VpnConfig cfg = mCurrentVpns.get(profile.id);
@@ -147,7 +148,7 @@
 
     @Override
     public boolean isVpnEnabled() {
-        for (UserInfo profile : mUserManager.getProfiles(mCurrentUserId)) {
+        for (UserInfo profile : mUserManager.getProfiles(mVpnUserId)) {
             if (mCurrentVpns.get(profile.id) != null) {
                 return true;
             }
@@ -172,6 +173,12 @@
     @Override
     public void onUserSwitched(int newUserId) {
         mCurrentUserId = newUserId;
+        if (mUserManager.getUserInfo(newUserId).isRestricted()) {
+            // VPN for a restricted profile is routed through its owner user
+            mVpnUserId = UserHandle.USER_OWNER;
+        } else {
+            mVpnUserId = mCurrentUserId;
+        }
         fireCallbacks();
     }
 
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 839b87a..d58d3721 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -1611,8 +1611,7 @@
         if (mAlarmBatches.size() > 0) {
             final Batch firstWakeup = findFirstWakeupBatchLocked();
             final Batch firstBatch = mAlarmBatches.get(0);
-            // always update the kernel alarms, as a backstop against missed wakeups
-            if (firstWakeup != null) {
+            if (firstWakeup != null && mNextWakeup != firstWakeup.start) {
                 mNextWakeup = firstWakeup.start;
                 setLocked(ELAPSED_REALTIME_WAKEUP, firstWakeup.start);
             }
@@ -1625,8 +1624,7 @@
                 nextNonWakeup = mNextNonWakeupDeliveryTime;
             }
         }
-        // always update the kernel alarm, as a backstop against missed wakeups
-        if (nextNonWakeup != 0) {
+        if (nextNonWakeup != 0 && mNextNonWakeup != nextNonWakeup) {
             mNextNonWakeup = nextNonWakeup;
             setLocked(ELAPSED_REALTIME, nextNonWakeup);
         }
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 2d5141e..47971a1 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -93,6 +93,9 @@
 import android.security.KeyStore;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
+import android.util.LocalLog;
+import android.util.LocalLog.ReadOnlyLocalLog;
+import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.SparseBooleanArray;
@@ -140,6 +143,7 @@
 import java.net.Inet6Address;
 import java.net.InetAddress;
 import java.net.UnknownHostException;
+import java.util.ArrayDeque;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -415,6 +419,20 @@
     // sequence number of NetworkRequests
     private int mNextNetworkRequestId = 1;
 
+    // Array of <Network,ReadOnlyLocalLogs> tracking network validation and results
+    private static final int MAX_VALIDATION_LOGS = 10;
+    private final ArrayDeque<Pair<Network,ReadOnlyLocalLog>> mValidationLogs =
+            new ArrayDeque<Pair<Network,ReadOnlyLocalLog>>(MAX_VALIDATION_LOGS);
+
+    private void addValidationLogs(ReadOnlyLocalLog log, Network network) {
+        synchronized(mValidationLogs) {
+            while (mValidationLogs.size() >= MAX_VALIDATION_LOGS) {
+                mValidationLogs.removeLast();
+            }
+            mValidationLogs.addFirst(new Pair(network, log));
+        }
+    }
+
     /**
      * Implements support for the legacy "one network per network type" model.
      *
@@ -1716,11 +1734,9 @@
         return ret;
     }
 
-    private boolean shouldPerformDiagnostics(String[] args) {
+    private boolean argsContain(String[] args, String target) {
         for (String arg : args) {
-            if (arg.equals("--diag")) {
-                return true;
-            }
+            if (arg.equals(target)) return true;
         }
         return false;
     }
@@ -1738,7 +1754,7 @@
         }
 
         final List<NetworkDiagnostics> netDiags = new ArrayList<NetworkDiagnostics>();
-        if (shouldPerformDiagnostics(args)) {
+        if (argsContain(args, "--diag")) {
             final long DIAG_TIME_MS = 5000;
             for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
                 // Start gathering diagnostic information.
@@ -1825,6 +1841,19 @@
             }
             pw.decreaseIndent();
         }
+
+        if (argsContain(args, "--short") == false) {
+            pw.println();
+            synchronized (mValidationLogs) {
+                pw.println("mValidationLogs (most recent first):");
+                for (Pair<Network,ReadOnlyLocalLog> p : mValidationLogs) {
+                    pw.println(p.first);
+                    pw.increaseIndent();
+                    p.second.dump(fd, pw, args);
+                    pw.decreaseIndent();
+                }
+            }
+        }
     }
 
     private boolean isLiveNetworkAgent(NetworkAgentInfo nai, String msg) {
@@ -3841,6 +3870,7 @@
         synchronized (this) {
             nai.networkMonitor.systemReady = mSystemReady;
         }
+        addValidationLogs(nai.networkMonitor.getValidationLogs(), nai.network);
         if (DBG) log("registerNetworkAgent " + nai);
         mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_AGENT, nai));
         return nai.network.netId;
diff --git a/services/core/java/com/android/server/MasterClearReceiver.java b/services/core/java/com/android/server/MasterClearReceiver.java
index f1d5aa3..1653db9 100644
--- a/services/core/java/com/android/server/MasterClearReceiver.java
+++ b/services/core/java/com/android/server/MasterClearReceiver.java
@@ -16,12 +16,18 @@
 
 package com.android.server;
 
+import android.app.ProgressDialog;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
+import android.os.AsyncTask;
 import android.os.RecoverySystem;
+import android.os.storage.StorageManager;
 import android.util.Log;
 import android.util.Slog;
+import android.view.WindowManager;
+
+import com.android.internal.R;
 
 import java.io.IOException;
 
@@ -39,6 +45,8 @@
 
         final boolean shutdown = intent.getBooleanExtra("shutdown", false);
         final String reason = intent.getStringExtra(Intent.EXTRA_REASON);
+        final boolean wipeExternalStorage = intent.getBooleanExtra(
+                Intent.EXTRA_WIPE_EXTERNAL_STORAGE, false);
 
         Slog.w(TAG, "!!! FACTORY RESET !!!");
         // The reboot call is blocking, so we need to do it on another thread.
@@ -55,6 +63,48 @@
                 }
             }
         };
-        thr.start();
+
+        if (wipeExternalStorage) {
+            // thr will be started at the end of this task.
+            new WipeAdoptableDisksTask(context, thr).execute();
+        } else {
+            thr.start();
+        }
+    }
+
+    private class WipeAdoptableDisksTask extends AsyncTask<Void, Void, Void> {
+        private final Thread mChainedTask;
+        private final Context mContext;
+        private final ProgressDialog mProgressDialog;
+
+        public WipeAdoptableDisksTask(Context context, Thread chainedTask) {
+            mContext = context;
+            mChainedTask = chainedTask;
+            mProgressDialog = new ProgressDialog(context);
+        }
+
+        @Override
+        protected void onPreExecute() {
+            mProgressDialog.setIndeterminate(true);
+            mProgressDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
+            mProgressDialog.setMessage(mContext.getText(R.string.progress_erasing));
+            mProgressDialog.show();
+        }
+
+        @Override
+        protected Void doInBackground(Void... params) {
+            Slog.w(TAG, "Wiping adoptable disks");
+            StorageManager sm = (StorageManager) mContext.getSystemService(
+                    Context.STORAGE_SERVICE);
+            sm.wipeAdoptableDisks();
+            return null;
+        }
+
+        @Override
+        protected void onPostExecute(Void result) {
+            mProgressDialog.dismiss();
+            mChainedTask.start();
+        }
+
     }
 }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 7204a6e..959fd37 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -144,6 +144,7 @@
 import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.app.backup.IBackupManager;
+import android.app.admin.DevicePolicyManager;
 import android.content.ActivityNotFoundException;
 import android.content.BroadcastReceiver;
 import android.content.ClipData;
@@ -10691,6 +10692,21 @@
     }
 
     @Override
+    public boolean isScreenCaptureAllowedOnCurrentActivity() {
+        int userId = mCurrentUserId;
+        synchronized (this) {
+            ActivityRecord activity = getFocusedStack().topActivity();
+            if (activity == null) {
+                return false;
+            }
+            userId = activity.userId;
+        }
+        DevicePolicyManager dpm = (DevicePolicyManager) mContext.getSystemService(
+                Context.DEVICE_POLICY_SERVICE);
+        return (dpm == null) || (!dpm.getScreenCaptureDisabled(null, userId));
+    }
+
+    @Override
     public void requestAssistContextExtras(int requestType, IResultReceiver receiver) {
         enqueueAssistContext(requestType, null, null, receiver, UserHandle.getCallingUserId(),
                 null, PENDING_ASSIST_EXTRAS_LONG_TIMEOUT);
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 78557634..6cc1b11 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -864,8 +864,7 @@
     }
 
     final class WakeupReasonThread extends Thread {
-        final int[] mIrqs = new int[32];
-        final String[] mReasons = new String[32];
+        final String[] mReason = new String[1];
 
         WakeupReasonThread() {
             super("BatteryStats_wakeupReason");
@@ -876,12 +875,11 @@
 
             try {
                 int num;
-                while ((num=nativeWaitWakeup(mIrqs, mReasons)) >= 0) {
+                while ((num = nativeWaitWakeup(mReason)) >= 0) {
                     synchronized (mStats) {
+                        // num will be either 0 or 1.
                         if (num > 0) {
-                            for (int i=0; i<num; i++) {
-                                mStats.noteWakeupReasonLocked(mReasons[i]);
-                            }
+                            mStats.noteWakeupReasonLocked(mReason[0]);
                         } else {
                             mStats.noteWakeupReasonLocked("unknown");
                         }
@@ -893,7 +891,7 @@
         }
     }
 
-    private static native int nativeWaitWakeup(int[] outIrqs, String[] outReasons);
+    private static native int nativeWaitWakeup(String[] outReason);
 
     private void dumpHelp(PrintWriter pw) {
         pw.println("Battery stats (batterystats) dump options:");
diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
index 99a0567..310e361 100644
--- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
@@ -47,6 +47,8 @@
 import android.telephony.CellInfoLte;
 import android.telephony.CellInfoWcdma;
 import android.telephony.TelephonyManager;
+import android.util.LocalLog;
+import android.util.LocalLog.ReadOnlyLocalLog;
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -232,6 +234,8 @@
     private CustomIntentReceiver mLaunchCaptivePortalAppBroadcastReceiver = null;
     private String mCaptivePortalLoggedInResponseToken = null;
 
+    private final LocalLog validationLogs = new LocalLog(20); // 20 lines
+
     public NetworkMonitor(Context context, Handler handler, NetworkAgentInfo networkAgentInfo,
             NetworkRequest defaultRequest) {
         // Add suffix indicating which NetworkMonitor we're talking about.
@@ -272,6 +276,15 @@
         Log.d(TAG + "/" + mNetworkAgentInfo.name(), s);
     }
 
+    private void validationLog(String s) {
+        if (DBG) log(s);
+        validationLogs.log(s);
+    }
+
+    public ReadOnlyLocalLog getValidationLogs() {
+        return validationLogs.readOnlyLocalLog();
+    }
+
     // DefaultState is the parent of all States.  It exists only to handle CMD_* messages but
     // does not entail any real state (hence no enter() or exit() routines).
     private class DefaultState extends State {
@@ -649,10 +662,8 @@
                     fetchPac = true;
                 }
             }
-            if (DBG) {
-                log("Checking " + url.toString() + " on " +
-                        mNetworkAgentInfo.networkInfo.getExtraInfo());
-            }
+            validationLog("Checking " + url.toString() + " on " +
+                    mNetworkAgentInfo.networkInfo.getExtraInfo());
             urlConnection = (HttpURLConnection) mNetworkAgentInfo.network.openConnection(url);
             urlConnection.setInstanceFollowRedirects(fetchPac);
             urlConnection.setConnectTimeout(SOCKET_TIMEOUT_MS);
@@ -668,10 +679,8 @@
             long responseTimestamp = SystemClock.elapsedRealtime();
 
             httpResponseCode = urlConnection.getResponseCode();
-            if (DBG) {
-                log("isCaptivePortal: ret=" + httpResponseCode +
-                        " headers=" + urlConnection.getHeaderFields());
-            }
+            validationLog("isCaptivePortal: ret=" + httpResponseCode +
+                    " headers=" + urlConnection.getHeaderFields());
             // NOTE: We may want to consider an "HTTP/1.0 204" response to be a captive
             // portal.  The only example of this seen so far was a captive portal.  For
             // the time being go with prior behavior of assuming it's not a captive
@@ -684,12 +693,12 @@
             // sign-in to an empty page.  Probably the result of a broken transparent proxy.
             // See http://b/9972012.
             if (httpResponseCode == 200 && urlConnection.getContentLength() == 0) {
-                if (DBG) log("Empty 200 response interpreted as 204 response.");
+                validationLog("Empty 200 response interpreted as 204 response.");
                 httpResponseCode = 204;
             }
 
             if (httpResponseCode == 200 && fetchPac) {
-                if (DBG) log("PAC fetch 200 response interpreted as 204 response.");
+                validationLog("PAC fetch 200 response interpreted as 204 response.");
                 httpResponseCode = 204;
             }
 
@@ -697,7 +706,7 @@
                     httpResponseCode != 204 /* isCaptivePortal */,
                     requestTimestamp, responseTimestamp);
         } catch (IOException e) {
-            if (DBG) log("Probably not a portal: exception " + e);
+            validationLog("Probably not a portal: exception " + e);
             if (httpResponseCode == 599) {
                 // TODO: Ping gateway and DNS server and log results.
             }
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index c52a1c1..9ee3bc2 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -30,9 +30,11 @@
 import android.os.IRemoteCallback;
 import android.os.Looper;
 import android.os.MessageQueue;
+import android.os.PowerManager;
 import android.os.RemoteException;
 import android.os.SELinux;
 import android.os.ServiceManager;
+import android.os.SystemClock;
 import android.os.UserHandle;
 import android.util.Slog;
 
@@ -70,6 +72,7 @@
     private static final int MSG_USER_SWITCHING = 10;
     private static final int ENROLLMENT_TIMEOUT_MS = 60 * 1000; // 1 minute
 
+    private boolean mIsKeyguard; // true if the authentication client is keyguard
     private ClientMonitor mAuthClient = null;
     private ClientMonitor mEnrollClient = null;
     private ClientMonitor mRemoveClient = null;
@@ -78,6 +81,7 @@
     private static final long MS_PER_SEC = 1000;
     private static final long FAIL_LOCKOUT_TIMEOUT_MS = 30*1000;
     private static final int MAX_FAILED_ATTEMPTS = 5;
+    private static final int FINGERPRINT_ACQUIRED_GOOD = 0;
 
     Handler mHandler = new Handler() {
         public void handleMessage(android.os.Message msg) {
@@ -97,6 +101,7 @@
     private long mHalDeviceId;
     private int mFailedAttempts;
     private IFingerprintDaemon mDaemon;
+    private PowerManager mPowerManager;
 
     private final Runnable mLockoutReset = new Runnable() {
         @Override
@@ -109,6 +114,7 @@
         super(context);
         mContext = context;
         mAppOps = context.getSystemService(AppOpsManager.class);
+        mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
     }
 
     @Override
@@ -191,7 +197,11 @@
                 removeClient(mAuthClient);
             }
         }
+    }
 
+    private void userActivity() {
+        long now = SystemClock.uptimeMillis();
+        mPowerManager.userActivity(now, PowerManager.USER_ACTIVITY_EVENT_TOUCH, 0);
     }
 
     void handleUserSwitching(int userId) {
@@ -498,9 +508,10 @@
          */
         private boolean sendAuthenticated(int fpId, int groupId) {
             boolean result = false;
+            boolean authenticated = fpId != 0;
             if (receiver != null) {
                 try {
-                    if (fpId == 0) {
+                    if (!authenticated) {
                         receiver.onAuthenticationFailed(mHalDeviceId);
                     } else {
                         Fingerprint fp = !restricted ?
@@ -522,6 +533,11 @@
                 result |= true; // we have a valid fingerprint
                 mLockoutReset.run();
             }
+            // For fingerprint devices that support touch-to-wake, this will ensure the device
+            // wakes up and turns the screen on when fingerprint is authenticated.
+            if (mIsKeyguard && authenticated) {
+                mPowerManager.wakeUp(SystemClock.uptimeMillis());
+            }
             return result;
         }
 
@@ -537,6 +553,12 @@
                 Slog.w(TAG, "Failed to invoke sendAcquired:", e);
                 return true; // client failed
             }
+            finally {
+                // Good scans will keep the device awake
+                if (acquiredInfo == FINGERPRINT_ACQUIRED_GOOD) {
+                    userActivity();
+                }
+            }
         }
 
         /*
@@ -589,6 +611,8 @@
     };
 
     private final class FingerprintServiceWrapper extends IFingerprintService.Stub {
+        private static final String KEYGUARD_PACKAGE = "com.android.systemui";
+
         @Override // Binder call
         public long preEnroll(IBinder token) {
             checkPermission(MANAGE_FINGERPRINT);
@@ -638,7 +662,8 @@
 
         @Override // Binder call
         public void authenticate(final IBinder token, final long opId, final int groupId,
-                final IFingerprintServiceReceiver receiver, final int flags, String opPackageName) {
+                final IFingerprintServiceReceiver receiver, final int flags,
+                final String opPackageName) {
 
             if (!canUseFingerprint(opPackageName)) {
                 return;
@@ -647,6 +672,7 @@
             mHandler.post(new Runnable() {
                 @Override
                 public void run() {
+                    mIsKeyguard = KEYGUARD_PACKAGE.equals(opPackageName);
                     startAuthentication(token, opId, groupId, receiver, flags, restricted);
                 }
             });
diff --git a/services/core/java/com/android/server/location/GpsLocationProvider.java b/services/core/java/com/android/server/location/GpsLocationProvider.java
index 3850306..45a4829 100644
--- a/services/core/java/com/android/server/location/GpsLocationProvider.java
+++ b/services/core/java/com/android/server/location/GpsLocationProvider.java
@@ -281,8 +281,16 @@
     // current setting 24 hours
     private static final long NTP_INTERVAL = 24*60*60*1000;
     // how long to wait if we have a network error in NTP or XTRA downloading
+    // the initial value of the exponential backoff
     // current setting - 5 minutes
     private static final long RETRY_INTERVAL = 5*60*1000;
+    // how long to wait if we have a network error in NTP or XTRA downloading
+    // the max value of the exponential backoff
+    // current setting - 4 hours
+    private static final long MAX_RETRY_INTERVAL = 4*60*60*1000;
+
+    private BackOff mNtpBackOff = new BackOff(RETRY_INTERVAL, MAX_RETRY_INTERVAL);
+    private BackOff mXtraBackOff = new BackOff(RETRY_INTERVAL, MAX_RETRY_INTERVAL);
 
     // true if we are enabled, protected by this
     private boolean mEnabled;
@@ -832,9 +840,10 @@
 
                     native_inject_time(time, timeReference, (int) certainty);
                     delay = NTP_INTERVAL;
+                    mNtpBackOff.reset();
                 } else {
                     if (DEBUG) Log.d(TAG, "requestTime failed");
-                    delay = RETRY_INTERVAL;
+                    delay = mNtpBackOff.nextBackoffMillis();
                 }
 
                 sendMessage(INJECT_NTP_TIME_FINISHED, 0, null);
@@ -875,6 +884,7 @@
                         Log.d(TAG, "calling native_inject_xtra_data");
                     }
                     native_inject_xtra_data(data, data.length);
+                    mXtraBackOff.reset();
                 }
 
                 sendMessage(DOWNLOAD_XTRA_DATA_FINISHED, 0, null);
@@ -882,7 +892,8 @@
                 if (data == null) {
                     // try again later
                     // since this is delayed and not urgent we do not hold a wake lock here
-                    mHandler.sendEmptyMessageDelayed(DOWNLOAD_XTRA_DATA, RETRY_INTERVAL);
+                    mHandler.sendEmptyMessageDelayed(DOWNLOAD_XTRA_DATA,
+                            mXtraBackOff.nextBackoffMillis());
                 }
 
                 // release wake lock held by task
@@ -2190,6 +2201,36 @@
         pw.append(s);
     }
 
+    /**
+     * A simple implementation of exponential backoff.
+     */
+    private static final class BackOff {
+        private static final int MULTIPLIER = 2;
+        private final long mInitIntervalMillis;
+        private final long mMaxIntervalMillis;
+        private long mCurrentIntervalMillis;
+
+        public BackOff(long initIntervalMillis, long maxIntervalMillis) {
+            mInitIntervalMillis = initIntervalMillis;
+            mMaxIntervalMillis = maxIntervalMillis;
+
+            mCurrentIntervalMillis = mInitIntervalMillis / MULTIPLIER;
+        }
+
+        public long nextBackoffMillis() {
+            if (mCurrentIntervalMillis > mMaxIntervalMillis) {
+                return mMaxIntervalMillis;
+            }
+
+            mCurrentIntervalMillis *= MULTIPLIER;
+            return mCurrentIntervalMillis;
+        }
+
+        public void reset() {
+            mCurrentIntervalMillis = mInitIntervalMillis / MULTIPLIER;
+        }
+    }
+
     // for GPS SV statistics
     private static final int MAX_SVS = 32;
     private static final int EPHEMERIS_MASK = 0;
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 847bcb5..d4b7256 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -2093,8 +2093,10 @@
         for (UserInfo user : users) {
             for (int i = mPowerSaveTempWhitelistAppIds.size() - 1; i >= 0; i--) {
                 int appId = mPowerSaveTempWhitelistAppIds.keyAt(i);
+                boolean isAllow = mPowerSaveTempWhitelistAppIds.valueAt(i);
                 int uid = UserHandle.getUid(user.id, appId);
                 updateRulesForUidLocked(uid);
+                setUidFirewallRule(FIREWALL_CHAIN_DOZABLE, uid, !isAllow);
             }
         }
     }
@@ -2190,11 +2192,6 @@
         final boolean firewallReject = (uidRules & RULE_REJECT_ALL) != 0;
         if (oldFirewallReject != firewallReject) {
             setUidFirewallRule(FIREWALL_CHAIN_STANDBY, uid, firewallReject);
-            if (mFirewallChainStates.get(FIREWALL_CHAIN_DOZABLE) && !firewallReject) {
-                // if the dozable chain is on, and we decide to allow this uid.  we need to punch
-                // a hole in the dozable chain.
-                setUidFirewallRule(FIREWALL_CHAIN_DOZABLE, uid, false);
-            }
         }
 
         // dispatch changed rule to existing listeners
diff --git a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
index 3ea384c..c9555c4a 100644
--- a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
@@ -17,11 +17,13 @@
 package com.android.server.pm;
 
 import android.Manifest;
+import android.app.DownloadManager;
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal.PackagesProvider;
 import android.content.pm.PackageParser;
+import android.content.pm.ProviderInfo;
 import android.content.pm.ResolveInfo;
 import android.net.Uri;
 import android.os.Build;
@@ -228,6 +230,7 @@
             for (int i = 0; i < installerCount; i++) {
                 PackageParser.Package installPackage = installerPackages.get(i);
                 grantInstallPermissionsLPw(installPackage, INSTALLER_PERMISSIONS, userId);
+                grantRuntimePermissionsLPw(installPackage, STORAGE_PERMISSIONS, userId);
             }
 
             // Verifiers
@@ -239,6 +242,7 @@
             for (int i = 0; i < verifierCount; i++) {
                 PackageParser.Package verifierPackage = verifierPackages.get(i);
                 grantInstallPermissionsLPw(verifierPackage, VERIFIER_PERMISSIONS, userId);
+                grantRuntimePermissionsLPw(verifierPackage, STORAGE_PERMISSIONS, userId);
             }
 
             // SetupWizard
@@ -273,6 +277,30 @@
                     && doesPackageSupportRuntimePermissions(cameraPackage)) {
                 grantRuntimePermissionsLPw(cameraPackage, CAMERA_PERMISSIONS, userId);
                 grantRuntimePermissionsLPw(cameraPackage, MICROPHONE_PERMISSIONS, userId);
+                grantRuntimePermissionsLPw(cameraPackage, STORAGE_PERMISSIONS, userId);
+            }
+
+            // Media provider
+            PackageParser.Package mediaStorePackage = getDefaultProviderAuthorityPackageLPr(
+                    MediaStore.AUTHORITY, userId);
+            if (mediaStorePackage != null) {
+                grantRuntimePermissionsLPw(mediaStorePackage, STORAGE_PERMISSIONS, userId);
+            }
+
+            // Downloads provider
+            PackageParser.Package downloadsPackage = getDefaultProviderAuthorityPackageLPr(
+                    "downloads", userId);
+            if (downloadsPackage != null) {
+                grantRuntimePermissionsLPw(downloadsPackage, STORAGE_PERMISSIONS, userId);
+            }
+
+            // Downloads UI
+            Intent downloadsUiIntent = new Intent(DownloadManager.ACTION_VIEW_DOWNLOADS);
+            PackageParser.Package downloadsUiPackage = getDefaultSystemHandlerActvityPackageLPr(
+                    downloadsUiIntent, userId);
+            if (downloadsUiPackage != null
+                    && doesPackageSupportRuntimePermissions(downloadsUiPackage)) {
+                grantRuntimePermissionsLPw(downloadsUiPackage, STORAGE_PERMISSIONS, userId);
             }
 
             // Messaging
@@ -403,6 +431,8 @@
                     }
                 }
             }
+
+            mService.mSettings.onDefaultRuntimePermissionsGrantedLPr(userId);
         }
     }
 
@@ -452,6 +482,15 @@
         return null;
     }
 
+    private PackageParser.Package getDefaultProviderAuthorityPackageLPr(
+            String authority, int userId) {
+        ProviderInfo provider = mService.resolveContentProvider(authority, 0, userId);
+        if (provider != null) {
+            return getSystemPackageLPr(provider.packageName);
+        }
+        return null;
+    }
+
     private PackageParser.Package getSystemPackageLPr(String packageName) {
         PackageParser.Package pkg = mService.mPackages.get(packageName);
         if (pkg != null && pkg.isSystemApp()) {
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index d787919..4582828 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -271,7 +271,8 @@
             Intent launchIntent = new Intent(Intent.ACTION_MAIN);
             launchIntent.addCategory(Intent.CATEGORY_LAUNCHER);
             launchIntent.setSourceBounds(sourceBounds);
-            launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                    | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
             launchIntent.setPackage(component.getPackageName());
 
             long ident = Binder.clearCallingIdentity();
@@ -470,4 +471,4 @@
             }
         }
     }
-}
\ No newline at end of file
+}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 40ff3f4..43f80d4 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -2191,7 +2191,8 @@
             // If this is the first boot, and it is a normal boot, then
             // we need to initialize the default preferred apps.
             if (!mRestoredSettings && !onlyCore) {
-                mSettings.readDefaultPreferredAppsLPw(this, 0);
+                mSettings.applyDefaultPreferredAppsLPw(this, UserHandle.USER_OWNER);
+                applyFactoryDefaultBrowserLPw(UserHandle.USER_OWNER);
             }
 
             // If this is first boot after an OTA, and a normal boot, then
@@ -2375,13 +2376,72 @@
         if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG, "End priming domain verifications");
     }
 
+    private void applyFactoryDefaultBrowserLPw(int userId) {
+        // The default browser app's package name is stored in a string resource,
+        // with a product-specific overlay used for vendor customization.
+        String browserPkg = mContext.getResources().getString(
+                com.android.internal.R.string.default_browser);
+        if (browserPkg != null) {
+            // non-empty string => required to be a known package
+            PackageSetting ps = mSettings.mPackages.get(browserPkg);
+            if (ps == null) {
+                Slog.e(TAG, "Product default browser app does not exist: " + browserPkg);
+                browserPkg = null;
+            } else {
+                mSettings.setDefaultBrowserPackageNameLPw(browserPkg, userId);
+            }
+        }
+
+        // Nothing valid explicitly set? Make the factory-installed browser the explicit
+        // default.  If there's more than one, just leave everything alone.
+        if (browserPkg == null) {
+            calculateDefaultBrowserLPw(userId);
+        }
+    }
+
+    private void calculateDefaultBrowserLPw(int userId) {
+        List<String> allBrowsers = resolveAllBrowserApps(userId);
+        final String browserPkg = (allBrowsers.size() == 1) ? allBrowsers.get(0) : null;
+        mSettings.setDefaultBrowserPackageNameLPw(browserPkg, userId);
+    }
+
+    private List<String> resolveAllBrowserApps(int userId) {
+        // Match all generic http: browser apps
+        Intent intent = new Intent();
+        intent.setAction(Intent.ACTION_VIEW);
+        intent.addCategory(Intent.CATEGORY_BROWSABLE);
+        intent.setData(Uri.parse("http:"));
+
+        // Resolve that intent and check that the handleAllWebDataURI boolean is set
+        List<ResolveInfo> list = queryIntentActivities(intent, null, 0, userId);
+
+        final int count = list.size();
+        List<String> result = new ArrayList<String>(count);
+        for (int i=0; i<count; i++) {
+            ResolveInfo info = list.get(i);
+            if (info.activityInfo == null
+                    || !info.handleAllWebDataURI
+                    || (info.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0
+                    || result.contains(info.activityInfo.packageName)) {
+                continue;
+            }
+            result.add(info.activityInfo.packageName);
+        }
+
+        return result;
+    }
+
     private void checkDefaultBrowser() {
         final int myUserId = UserHandle.myUserId();
         final String packageName = getDefaultBrowserPackageName(myUserId);
-        PackageInfo info = getPackageInfo(packageName, 0, myUserId);
-        if (info == null) {
-            Slog.w(TAG, "Default browser no longer installed: " + packageName);
-            setDefaultBrowserPackageName(null, myUserId);
+        if (packageName != null) {
+            PackageInfo info = getPackageInfo(packageName, 0, myUserId);
+            if (info == null) {
+                Slog.w(TAG, "Default browser no longer installed: " + packageName);
+                synchronized (mPackages) {
+                    applyFactoryDefaultBrowserLPw(myUserId);    // leaves ambiguous when > 1
+                }
+            }
         }
     }
 
@@ -3340,6 +3400,27 @@
     }
 
     @Override
+    public void resetRuntimePermissions() {
+        mContext.enforceCallingOrSelfPermission(
+                android.Manifest.permission.GRANT_REVOKE_PERMISSIONS,
+                "revokeRuntimePermission");
+
+        int callingUid = Binder.getCallingUid();
+        if (callingUid != Process.SYSTEM_UID && callingUid != 0) {
+            mContext.enforceCallingOrSelfPermission(
+                    android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+                    "resetRuntimePermissions");
+        }
+
+        synchronized (mPackages) {
+            updatePermissionsLPw(null, null, UPDATE_PERMISSIONS_ALL);
+            for (int userId : UserManagerService.getInstance().getUserIds()) {
+                mDefaultPermissionPolicy.grantDefaultPermissions(userId);
+            }
+        }
+    }
+
+    @Override
     public int getPermissionFlags(String name, String packageName, int userId) {
         if (!sUserManager.exists(userId)) {
             return 0;
@@ -4443,7 +4524,7 @@
 
         synchronized (mPackages) {
             final int count = candidates.size();
-            // First, try to use the domain prefered App. Partition the candidates into four lists:
+            // First, try to use the domain preferred app. Partition the candidates into four lists:
             // one for the final results, one for the "do not use ever", one for "undefined status"
             // and finally one for "Browser App type".
             for (int n=0; n<count; n++) {
@@ -9577,6 +9658,9 @@
 
     @Override
     public boolean updateIntentVerificationStatus(String packageName, int status, int userId) {
+        mContext.enforceCallingOrSelfPermission(
+                android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
+
         boolean result = false;
         synchronized (mPackages) {
             result = mSettings.updateIntentFilterVerificationStatusLPw(packageName, status, userId);
@@ -9618,8 +9702,11 @@
 
     @Override
     public boolean setDefaultBrowserPackageName(String packageName, int userId) {
+        mContext.enforceCallingOrSelfPermission(
+                android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
+
         synchronized (mPackages) {
-            boolean result = mSettings.setDefaultBrowserPackageNameLPr(packageName, userId);
+            boolean result = mSettings.setDefaultBrowserPackageNameLPw(packageName, userId);
             if (packageName != null) {
                 result |= updateIntentVerificationStatus(packageName,
                         PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS,
@@ -12051,7 +12138,7 @@
                 final int verificationId = mIntentFilterVerificationToken++;
                 for (PackageParser.Activity a : pkg.activities) {
                     for (ActivityIntentInfo filter : a.intents) {
-                        if (filter.hasOnlyWebDataURI() && needsNetworkVerificationLPr(filter)) {
+                        if (filter.handlesWebUris(true) && needsNetworkVerificationLPr(filter)) {
                             if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG,
                                     "Verification needed for IntentFilter:" + filter.toString());
                             mIntentFilterVerifier.addOneIntentFilterVerification(
@@ -13379,15 +13466,15 @@
 
     @Override
     public void resetPreferredActivities(int userId) {
-        /* TODO: Actually use userId. Why is it being passed in? */
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
         // writer
         synchronized (mPackages) {
-            int user = UserHandle.getCallingUserId();
-            clearPackagePreferredActivitiesLPw(null, user);
-            mSettings.readDefaultPreferredAppsLPw(this, user);
-            scheduleWritePackageRestrictionsLocked(user);
+            clearPackagePreferredActivitiesLPw(null, userId);
+            mSettings.applyDefaultPreferredAppsLPw(this, userId);
+            applyFactoryDefaultBrowserLPw(userId);
+
+            scheduleWritePackageRestrictionsLocked(userId);
         }
     }
 
@@ -14023,6 +14110,8 @@
             Log.d(TAG, "compatibility mode:" + compatibilityModeEnabled);
         }
 
+        int[] grantPermissionsUserIds = EMPTY_INT_ARRAY;
+
         synchronized (mPackages) {
             // Verify that all of the preferred activity components actually
             // exist.  It is possible for applications to be updated and at
@@ -14052,15 +14141,19 @@
                             mSettings.mPreferredActivities.keyAt(i));
                 }
             }
+
+            for (int userId : UserManagerService.getInstance().getUserIds()) {
+                if (!mSettings.areDefaultRuntimePermissionsGrantedLPr(userId)) {
+                    grantPermissionsUserIds = ArrayUtils.appendInt(
+                            grantPermissionsUserIds, userId);
+                }
+            }
         }
         sUserManager.systemReady();
 
         // If we upgraded grant all default permissions before kicking off.
-        if (isFirstBoot() || (CLEAR_RUNTIME_PERMISSIONS_ON_UPGRADE && mIsUpgrade)) {
-            updatePermissionsLPw(null, null, UPDATE_PERMISSIONS_ALL);
-            for (int userId : UserManagerService.getInstance().getUserIds()) {
-                mDefaultPermissionPolicy.grantDefaultPermissions(userId);
-            }
+        for (int userId : grantPermissionsUserIds) {
+            mDefaultPermissionPolicy.grantDefaultPermissions(userId);
         }
 
         // Kick off any messages waiting for system ready
@@ -14190,6 +14283,7 @@
         boolean checkin = false;
 
         String packageName = null;
+        ArraySet<String> permissionNames = null;
 
         int opti = 0;
         while (opti < args.length) {
@@ -14213,6 +14307,7 @@
                 pw.println("    k[eysets]: print known keysets");
                 pw.println("    r[esolvers]: dump intent resolvers");
                 pw.println("    perm[issions]: dump permissions");
+                pw.println("    permission [name ...]: dump declaration and use of given permission");
                 pw.println("    pref[erred]: print preferred package settings");
                 pw.println("    preferred-xml [--full]: print preferred package settings as xml");
                 pw.println("    prov[iders]: dump content providers");
@@ -14254,6 +14349,18 @@
                 dumpState.setDump(DumpState.DUMP_RESOLVERS);
             } else if ("perm".equals(cmd) || "permissions".equals(cmd)) {
                 dumpState.setDump(DumpState.DUMP_PERMISSIONS);
+            } else if ("permission".equals(cmd)) {
+                if (opti >= args.length) {
+                    pw.println("Error: permission requires permission name");
+                    return;
+                }
+                permissionNames = new ArraySet<>();
+                while (opti < args.length) {
+                    permissionNames.add(args[opti]);
+                    opti++;
+                }
+                dumpState.setDump(DumpState.DUMP_PERMISSIONS
+                        | DumpState.DUMP_PACKAGES | DumpState.DUMP_SHARED_USERS);
             } else if ("pref".equals(cmd) || "preferred".equals(cmd)) {
                 dumpState.setDump(DumpState.DUMP_PREFERRED);
             } else if ("preferred-xml".equals(cmd)) {
@@ -14536,8 +14643,8 @@
             }
 
             if (!checkin && dumpState.isDumping(DumpState.DUMP_PERMISSIONS)) {
-                mSettings.dumpPermissionsLPr(pw, packageName, dumpState);
-                if (packageName == null) {
+                mSettings.dumpPermissionsLPr(pw, packageName, permissionNames, dumpState);
+                if (packageName == null && permissionNames == null) {
                     for (int iperm=0; iperm<mAppOpPermissionPackages.size(); iperm++) {
                         if (iperm == 0) {
                             if (dumpState.onTitlePrinted())
@@ -14597,11 +14704,11 @@
             }
 
             if (dumpState.isDumping(DumpState.DUMP_PACKAGES)) {
-                mSettings.dumpPackagesLPr(pw, packageName, dumpState, checkin);
+                mSettings.dumpPackagesLPr(pw, packageName, permissionNames, dumpState, checkin);
             }
 
             if (dumpState.isDumping(DumpState.DUMP_SHARED_USERS)) {
-                mSettings.dumpSharedUsersLPr(pw, packageName, dumpState, checkin);
+                mSettings.dumpSharedUsersLPr(pw, packageName, permissionNames, dumpState, checkin);
             }
 
             if (!checkin && dumpState.isDumping(DumpState.DUMP_INSTALLS) && packageName == null) {
@@ -15449,6 +15556,7 @@
         if (mInstaller != null) {
             mInstaller.createUserConfig(userHandle);
             mSettings.createNewUserLILPw(this, mInstaller, userHandle, path);
+            applyFactoryDefaultBrowserLPw(userHandle);
         }
     }
 
diff --git a/services/core/java/com/android/server/pm/PermissionsState.java b/services/core/java/com/android/server/pm/PermissionsState.java
index 04beafd..57ef284 100644
--- a/services/core/java/com/android/server/pm/PermissionsState.java
+++ b/services/core/java/com/android/server/pm/PermissionsState.java
@@ -219,6 +219,22 @@
     }
 
     /**
+     * Returns whether the state has any known request for the given permission name,
+     * whether or not it has been granted.
+     */
+    public boolean hasRequestedPermission(ArraySet<String> names) {
+        if (mPermissions == null) {
+            return false;
+        }
+        for (int i=names.size()-1; i>=0; i--) {
+            if (mPermissions.get(names.valueAt(i)) != null) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
      * Gets all permissions for a given device user id regardless if they
      * are install time or runtime permissions.
      *
@@ -446,7 +462,7 @@
             }
         }
 
-        return  permissionStates;
+        return permissionStates;
     }
 
     private int grantPermission(BasePermission permission, int userId) {
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index dcd7799..51ac81d 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -195,6 +195,7 @@
     private static final String ATTR_BLOCK_UNINSTALL = "blockUninstall";
     private static final String ATTR_DOMAIN_VERIFICATON_STATE = "domainVerificationStatus";
     private static final String ATTR_PACKAGE_NAME= "packageName";
+    private static final String ATTR_FINGERPRINT = "fingerprint";
 
     private final Object mLock;
 
@@ -1130,7 +1131,7 @@
         return result;
     }
 
-    boolean setDefaultBrowserPackageNameLPr(String packageName, int userId) {
+    boolean setDefaultBrowserPackageNameLPw(String packageName, int userId) {
         if (userId == UserHandle.USER_ALL) {
             return false;
         }
@@ -1177,6 +1178,16 @@
         }
     }
 
+    boolean areDefaultRuntimePermissionsGrantedLPr(int userId) {
+        return mRuntimePermissionsPersistence
+                .areDefaultRuntimPermissionsGrantedLPr(userId);
+    }
+
+    void onDefaultRuntimePermissionsGrantedLPr(int userId) {
+        mRuntimePermissionsPersistence
+                .onDefaultRuntimePermissionsGrantedLPr(userId);
+    }
+
     /**
      * Returns whether the current database has is older than {@code version}
      * for apps on internal storage.
@@ -2710,7 +2721,7 @@
         return true;
     }
 
-    void readDefaultPreferredAppsLPw(PackageManagerService service, int userId) {
+    void applyDefaultPreferredAppsLPw(PackageManagerService service, int userId) {
         // First pull data from any pre-installed apps.
         for (PackageSetting ps : mPackages.values()) {
             if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0 && ps.pkg != null
@@ -3618,7 +3629,7 @@
                     UserHandle.getUid(userHandle, ps.appId), userHandle,
                     ps.pkg.applicationInfo.seinfo);
         }
-        readDefaultPreferredAppsLPw(service, userHandle);
+        applyDefaultPreferredAppsLPw(service, userHandle);
         writePackageRestrictionsLPr(userHandle);
         writePackageListLPr(userHandle);
     }
@@ -3881,8 +3892,9 @@
         ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE, "CANT_SAVE_STATE",
     };
 
-    void dumpPackageLPr(PrintWriter pw, String prefix, String checkinTag, PackageSetting ps,
-            SimpleDateFormat sdf, Date date, List<UserInfo> users) {
+    void dumpPackageLPr(PrintWriter pw, String prefix, String checkinTag,
+            ArraySet<String> permissionNames, PackageSetting ps, SimpleDateFormat sdf,
+            Date date, List<UserInfo> users) {
         if (checkinTag != null) {
             pw.print(checkinTag);
             pw.print(",");
@@ -3953,10 +3965,13 @@
         }
         pw.print(prefix); pw.print("  pkg="); pw.println(ps.pkg);
         pw.print(prefix); pw.print("  codePath="); pw.println(ps.codePathString);
-        pw.print(prefix); pw.print("  resourcePath="); pw.println(ps.resourcePathString);
-        pw.print(prefix); pw.print("  legacyNativeLibraryDir="); pw.println(ps.legacyNativeLibraryPathString);
-        pw.print(prefix); pw.print("  primaryCpuAbi="); pw.println(ps.primaryCpuAbiString);
-        pw.print(prefix); pw.print("  secondaryCpuAbi="); pw.println(ps.secondaryCpuAbiString);
+        if (permissionNames == null) {
+            pw.print(prefix); pw.print("  resourcePath="); pw.println(ps.resourcePathString);
+            pw.print(prefix); pw.print("  legacyNativeLibraryDir=");
+            pw.println(ps.legacyNativeLibraryPathString);
+            pw.print(prefix); pw.print("  primaryCpuAbi="); pw.println(ps.primaryCpuAbiString);
+            pw.print(prefix); pw.print("  secondaryCpuAbi="); pw.println(ps.secondaryCpuAbiString);
+        }
         pw.print(prefix); pw.print("  versionCode="); pw.print(ps.versionCode);
         if (ps.pkg != null) {
             pw.print(" targetSdk="); pw.print(ps.pkg.applicationInfo.targetSdkVersion);
@@ -3969,8 +3984,10 @@
                 pw.println(ps.pkg.applicationInfo.toString());
             pw.print(prefix); pw.print("  flags="); printFlags(pw, ps.pkg.applicationInfo.flags,
                     FLAG_DUMP_SPEC); pw.println();
-            pw.print(prefix); pw.print("  priavateFlags="); printFlags(pw,
-                    ps.pkg.applicationInfo.privateFlags, PRIVATE_FLAG_DUMP_SPEC); pw.println();
+            if (ps.pkg.applicationInfo.privateFlags != 0) {
+                pw.print(prefix); pw.print("  privateFlags="); printFlags(pw,
+                        ps.pkg.applicationInfo.privateFlags, PRIVATE_FLAG_DUMP_SPEC); pw.println();
+            }
             pw.print(prefix); pw.print("  dataDir="); pw.println(ps.pkg.applicationInfo.dataDir);
             pw.print(prefix); pw.print("  supportsScreens=[");
             boolean first = true;
@@ -4063,9 +4080,9 @@
         pw.print(prefix); pw.print("  pkgFlags="); printFlags(pw, ps.pkgFlags, FLAG_DUMP_SPEC);
                 pw.println();
 
-        if (ps.sharedUser == null) {
+        if (ps.sharedUser == null || permissionNames != null) {
             PermissionsState permissionsState = ps.getPermissionsState();
-            dumpInstallPermissionsLPr(pw, prefix + "  ", permissionsState);
+            dumpInstallPermissionsLPr(pw, prefix + "  ", permissionNames, permissionsState);
         }
 
         for (UserInfo user : users) {
@@ -4089,28 +4106,31 @@
             if (ps.sharedUser == null) {
                 PermissionsState permissionsState = ps.getPermissionsState();
                 dumpGidsLPr(pw, prefix + "    ", permissionsState.computeGids(user.id));
-                dumpRuntimePermissionsLPr(pw, prefix + "    ", permissionsState
+                dumpRuntimePermissionsLPr(pw, prefix + "    ", permissionNames, permissionsState
                         .getRuntimePermissionStates(user.id));
             }
 
-            ArraySet<String> cmp = ps.getDisabledComponents(user.id);
-            if (cmp != null && cmp.size() > 0) {
-                pw.print(prefix); pw.println("    disabledComponents:");
-                for (String s : cmp) {
-                    pw.print(prefix); pw.print("    "); pw.println(s);
+            if (permissionNames == null) {
+                ArraySet<String> cmp = ps.getDisabledComponents(user.id);
+                if (cmp != null && cmp.size() > 0) {
+                    pw.print(prefix); pw.println("    disabledComponents:");
+                    for (String s : cmp) {
+                        pw.print(prefix); pw.print("    "); pw.println(s);
+                    }
                 }
-            }
-            cmp = ps.getEnabledComponents(user.id);
-            if (cmp != null && cmp.size() > 0) {
-                pw.print(prefix); pw.println("    enabledComponents:");
-                for (String s : cmp) {
-                    pw.print(prefix); pw.print("    "); pw.println(s);
+                cmp = ps.getEnabledComponents(user.id);
+                if (cmp != null && cmp.size() > 0) {
+                    pw.print(prefix); pw.println("    enabledComponents:");
+                    for (String s : cmp) {
+                        pw.print(prefix); pw.print("    "); pw.println(s);
+                    }
                 }
             }
         }
     }
 
-    void dumpPackagesLPr(PrintWriter pw, String packageName, DumpState dumpState, boolean checkin) {
+    void dumpPackagesLPr(PrintWriter pw, String packageName, ArraySet<String> permissionNames,
+            DumpState dumpState, boolean checkin) {
         final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
         final Date date = new Date();
         boolean printedSomething = false;
@@ -4120,6 +4140,10 @@
                     && !packageName.equals(ps.name)) {
                 continue;
             }
+            if (permissionNames != null
+                    && !ps.getPermissionsState().hasRequestedPermission(permissionNames)) {
+                continue;
+            }
 
             if (!checkin && packageName != null) {
                 dumpState.setSharedUser(ps.sharedUser);
@@ -4131,11 +4155,11 @@
                 pw.println("Packages:");
                 printedSomething = true;
             }
-            dumpPackageLPr(pw, "  ", checkin ? "pkg" : null, ps, sdf, date, users);
+            dumpPackageLPr(pw, "  ", checkin ? "pkg" : null, permissionNames, ps, sdf, date, users);
         }
 
         printedSomething = false;
-        if (!checkin && mRenamedPackages.size() > 0) {
+        if (!checkin && mRenamedPackages.size() > 0 && permissionNames == null) {
             for (final Map.Entry<String, String> e : mRenamedPackages.entrySet()) {
                 if (packageName != null && !packageName.equals(e.getKey())
                         && !packageName.equals(e.getValue())) {
@@ -4159,7 +4183,7 @@
         }
 
         printedSomething = false;
-        if (mDisabledSysPackages.size() > 0) {
+        if (mDisabledSysPackages.size() > 0 && permissionNames == null) {
             for (final PackageSetting ps : mDisabledSysPackages.values()) {
                 if (packageName != null && !packageName.equals(ps.realName)
                         && !packageName.equals(ps.name)) {
@@ -4171,17 +4195,22 @@
                     pw.println("Hidden system packages:");
                     printedSomething = true;
                 }
-                dumpPackageLPr(pw, "  ", checkin ? "dis" : null, ps, sdf, date, users);
+                dumpPackageLPr(pw, "  ", checkin ? "dis" : null, permissionNames, ps, sdf, date,
+                        users);
             }
         }
     }
 
-    void dumpPermissionsLPr(PrintWriter pw, String packageName, DumpState dumpState) {
+    void dumpPermissionsLPr(PrintWriter pw, String packageName, ArraySet<String> permissionNames,
+            DumpState dumpState) {
         boolean printedSomething = false;
         for (BasePermission p : mPermissions.values()) {
             if (packageName != null && !packageName.equals(p.sourcePackage)) {
                 continue;
             }
+            if (permissionNames != null && !permissionNames.contains(p.name)) {
+                continue;
+            }
             if (!printedSomething) {
                 if (dumpState.onTitlePrinted())
                     pw.println();
@@ -4211,13 +4240,17 @@
         }
     }
 
-    void dumpSharedUsersLPr(PrintWriter pw, String packageName, DumpState dumpState,
-            boolean checkin) {
+    void dumpSharedUsersLPr(PrintWriter pw, String packageName, ArraySet<String> permissionNames,
+            DumpState dumpState, boolean checkin) {
         boolean printedSomething = false;
         for (SharedUserSetting su : mSharedUsers.values()) {
             if (packageName != null && su != dumpState.getSharedUser()) {
                 continue;
             }
+            if (permissionNames != null
+                    && !su.getPermissionsState().hasRequestedPermission(permissionNames)) {
+                continue;
+            }
             if (!checkin) {
                 if (!printedSomething) {
                     if (dumpState.onTitlePrinted())
@@ -4235,7 +4268,7 @@
                 pw.print(prefix); pw.print("userId="); pw.println(su.userId);
 
                 PermissionsState permissionsState = su.getPermissionsState();
-                dumpInstallPermissionsLPr(pw, prefix, permissionsState);
+                dumpInstallPermissionsLPr(pw, prefix, permissionNames, permissionsState);
 
                 for (int userId : UserManagerService.getInstance().getUserIds()) {
                     final int[] gids = permissionsState.computeGids(userId);
@@ -4244,7 +4277,7 @@
                     if (!ArrayUtils.isEmpty(gids) || !permissions.isEmpty()) {
                         pw.print(prefix); pw.print("User "); pw.print(userId); pw.println(": ");
                         dumpGidsLPr(pw, prefix + "  ", gids);
-                        dumpRuntimePermissionsLPr(pw, prefix + "  ", permissions);
+                        dumpRuntimePermissionsLPr(pw, prefix + "  ", permissionNames, permissions);
                     }
                 }
             } else {
@@ -4289,11 +4322,15 @@
         }
     }
 
-    void dumpRuntimePermissionsLPr(PrintWriter pw, String prefix,
+    void dumpRuntimePermissionsLPr(PrintWriter pw, String prefix, ArraySet<String> permissionNames,
             List<PermissionState> permissionStates) {
         if (!permissionStates.isEmpty()) {
             pw.print(prefix); pw.println("runtime permissions:");
             for (PermissionState permissionState : permissionStates) {
+                if (permissionNames != null
+                        && !permissionNames.contains(permissionState.getName())) {
+                    continue;
+                }
                 pw.print(prefix); pw.print("  "); pw.print(permissionState.getName());
                 pw.print(", granted="); pw.print(permissionState.isGranted());
                     pw.print(", flags=0x"); pw.println(Integer.toHexString(
@@ -4302,12 +4339,16 @@
         }
     }
 
-    void dumpInstallPermissionsLPr(PrintWriter pw, String prefix,
+    void dumpInstallPermissionsLPr(PrintWriter pw, String prefix, ArraySet<String> permissionNames,
             PermissionsState permissionsState) {
         List<PermissionState> permissionStates = permissionsState.getInstallPermissionStates();
         if (!permissionStates.isEmpty()) {
             pw.print(prefix); pw.println("install permissions:");
             for (PermissionState permissionState : permissionStates) {
+                if (permissionNames != null
+                        && !permissionNames.contains(permissionState.getName())) {
+                    continue;
+                }
                 pw.print(prefix); pw.print("  "); pw.print(permissionState.getName());
                     pw.print(", granted="); pw.print(permissionState.isGranted());
                     pw.print(", flags=0x"); pw.println(Integer.toHexString(
@@ -4334,15 +4375,33 @@
         private final Object mLock;
 
         @GuardedBy("mLock")
-        private SparseBooleanArray mWriteScheduled = new SparseBooleanArray();
+        private final SparseBooleanArray mWriteScheduled = new SparseBooleanArray();
 
         @GuardedBy("mLock")
-        private SparseLongArray mLastNotWrittenMutationTimesMillis = new SparseLongArray();
+        // The mapping keys are user ids.
+        private final SparseLongArray mLastNotWrittenMutationTimesMillis = new SparseLongArray();
+
+        @GuardedBy("mLock")
+        // The mapping keys are user ids.
+        private final SparseArray<String> mFingerprints = new SparseArray<>();
+
+        @GuardedBy("mLock")
+        // The mapping keys are user ids.
+        private final SparseBooleanArray mDefaultPermissionsGranted = new SparseBooleanArray();
 
         public RuntimePermissionPersistence(Object lock) {
             mLock = lock;
         }
 
+        public boolean areDefaultRuntimPermissionsGrantedLPr(int userId) {
+            return mDefaultPermissionsGranted.get(userId);
+        }
+
+        public void onDefaultRuntimePermissionsGrantedLPr(int userId) {
+            mFingerprints.put(userId, Build.FINGERPRINT);
+            writePermissionsForUserAsyncLPr(userId);
+        }
+
         public void writePermissionsForUserSyncLPr(int userId) {
             mHandler.removeMessages(userId);
             writePermissionsSync(userId);
@@ -4427,6 +4486,9 @@
                 serializer.startDocument(null, true);
                 serializer.startTag(null, TAG_RUNTIME_PERMISSIONS);
 
+                String fingerprint = mFingerprints.get(userId);
+                serializer.attribute(null, ATTR_FINGERPRINT, fingerprint);
+
                 final int packageCount = permissionsForPackage.size();
                 for (int i = 0; i < packageCount; i++) {
                     String packageName = permissionsForPackage.keyAt(i);
@@ -4451,7 +4513,10 @@
                 serializer.endDocument();
                 destination.finishWrite(out);
 
-                // Any error while writing is fatal.
+                if (Build.FINGERPRINT.equals(fingerprint)) {
+                    mDefaultPermissionsGranted.put(userId, true);
+                }
+            // Any error while writing is fatal.
             } catch (Throwable t) {
                 Slog.wtf(PackageManagerService.TAG,
                         "Failed to write settings, restoring backup", t);
@@ -4529,6 +4594,13 @@
                 }
 
                 switch (parser.getName()) {
+                    case TAG_RUNTIME_PERMISSIONS: {
+                        String fingerprint = parser.getAttributeValue(null, ATTR_FINGERPRINT);
+                        mFingerprints.put(userId, fingerprint);
+                        final boolean defaultsGranted = Build.FINGERPRINT.equals(fingerprint);
+                        mDefaultPermissionsGranted.put(userId, defaultsGranted);
+                    } break;
+
                     case TAG_PACKAGE: {
                         String name = parser.getAttributeValue(null, ATTR_NAME);
                         PackageSetting ps = mPackages.get(name);
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 51bb36f..5a0bee9 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -3117,7 +3117,7 @@
                 return;
             }
 
-            if (eventTime > SystemClock.uptimeMillis()) {
+            if (eventTime > now) {
                 throw new IllegalArgumentException("event time must not be in the future");
             }
 
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index d7b202d..76baaa7 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -343,7 +343,9 @@
                         boolean applyExistingExitAnimation = mPostKeyguardExitAnimation != null
                                 && !winAnimator.mKeyguardGoingAwayAnimation
                                 && win.hasDrawnLw()
-                                && win.mAttachedWindow == null;
+                                && win.mAttachedWindow == null
+                                && !win.mIsImWindow
+                                && displayId == Display.DEFAULT_DISPLAY;
 
                         // If the window is already showing and we don't need to apply an existing
                         // Keyguard exit animation, skip.
diff --git a/services/core/jni/com_android_server_am_BatteryStatsService.cpp b/services/core/jni/com_android_server_am_BatteryStatsService.cpp
index 3b9cc9d..e257e89 100644
--- a/services/core/jni/com_android_server_am_BatteryStatsService.cpp
+++ b/services/core/jni/com_android_server_am_BatteryStatsService.cpp
@@ -48,9 +48,9 @@
 static bool wakeup_init = false;
 static sem_t wakeup_sem;
 
-static void wakeup_callback(void)
+static void wakeup_callback(bool success)
 {
-    ALOGV("In wakeup_callback");
+    ALOGV("In wakeup_callback: %s", success ? "resumed from suspend" : "suspend aborted");
     int ret = sem_post(&wakeup_sem);
     if (ret < 0) {
         char buf[80];
@@ -59,10 +59,9 @@
     }
 }
 
-static jint nativeWaitWakeup(JNIEnv *env, jobject clazz, jintArray outIrqs,
-        jobjectArray outReasons)
+static jint nativeWaitWakeup(JNIEnv *env, jobject clazz, jobjectArray outReasons)
 {
-    if (outIrqs == NULL || outReasons == NULL) {
+    if (outReasons == NULL) {
         jniThrowException(env, "java/lang/NullPointerException", "null argument");
         return -1;
     }
@@ -100,32 +99,47 @@
         return -1;
     }
 
-    int numOut = env->GetArrayLength(outIrqs);
-    ScopedIntArrayRW irqs(env, outIrqs);
-
-    ALOGV("Reading up to %d wakeup reasons", numOut);
+    ALOGV("Reading wakeup reasons");
 
     char mergedreason[MAX_REASON_SIZE];
     char* mergedreasonpos = mergedreason;
     int remainreasonlen = MAX_REASON_SIZE;
-    int firstirq = 0;
     char reasonline[128];
     int i = 0;
-    while (fgets(reasonline, sizeof(reasonline), fp) != NULL && i < numOut) {
+    while (fgets(reasonline, sizeof(reasonline), fp) != NULL) {
         char* pos = reasonline;
         char* endPos;
-        // First field is the index.
+        int len;
+        // First field is the index or 'Abort'.
         int irq = (int)strtol(pos, &endPos, 10);
-        if (pos == endPos) {
-            // Ooops.
-            ALOGE("Bad reason line: %s", reasonline);
-            continue;
+        if (pos != endPos) {
+            // Write the irq number to the merged reason string.
+            len = snprintf(mergedreasonpos, remainreasonlen, i == 0 ? "%d" : ":%d", irq);
+        } else {
+            // The first field is not an irq, it may be the word Abort.
+            const size_t abortPrefixLen = strlen("Abort:");
+            if (strncmp(pos, "Abort:", abortPrefixLen) != 0) {
+                // Ooops.
+                ALOGE("Bad reason line: %s", reasonline);
+                continue;
+            }
+
+            // Write 'Abort' to the merged reason string.
+            len = snprintf(mergedreasonpos, remainreasonlen, i == 0 ? "Abort" : ":Abort");
+            endPos = pos + abortPrefixLen;
         }
         pos = endPos;
+
+        if (len >= 0 && len < remainreasonlen) {
+            mergedreasonpos += len;
+            remainreasonlen -= len;
+        }
+
         // Skip whitespace; rest of the buffer is the reason string.
         while (*pos == ' ') {
             pos++;
         }
+
         // Chop newline at end.
         char* endpos = pos;
         while (*endpos != 0) {
@@ -135,38 +149,17 @@
             }
             endpos++;
         }
-        // For now we are not separating out the first irq.
-        // This is because in practice there are always multiple
-        // lines of wakeup reasons, so it is better to just treat
-        // them all together as a single string.
-        if (false && i == 0) {
-            firstirq = irq;
-        } else {
-            int len = snprintf(mergedreasonpos, remainreasonlen,
-                    i == 0 ? "%d" : ":%d", irq);
-            if (len >= 0 && len < remainreasonlen) {
-                mergedreasonpos += len;
-                remainreasonlen -= len;
-            }
-        }
-        int len = snprintf(mergedreasonpos, remainreasonlen, ":%s", pos);
+
+        len = snprintf(mergedreasonpos, remainreasonlen, ":%s", pos);
         if (len >= 0 && len < remainreasonlen) {
             mergedreasonpos += len;
             remainreasonlen -= len;
         }
-        // For now it is better to combine all of these in to one entry in the
-        // battery history.  In the future, it might be nice to figure out a way
-        // to efficiently store multiple lines as a single entry in the history.
-        //irqs[i] = irq;
-        //ScopedLocalRef<jstring> reasonString(env, env->NewStringUTF(pos));
-        //env->SetObjectArrayElement(outReasons, i, reasonString.get());
-        //ALOGV("Wakeup reason #%d: irw %d reason %s", i, irq, pos);
         i++;
     }
 
     ALOGV("Got %d reasons", i);
     if (i > 0) {
-        irqs[0] = firstirq;
         *mergedreasonpos = 0;
         ScopedLocalRef<jstring> reasonString(env, env->NewStringUTF(mergedreason));
         env->SetObjectArrayElement(outReasons, 0, reasonString.get());
@@ -182,7 +175,7 @@
 }
 
 static JNINativeMethod method_table[] = {
-    { "nativeWaitWakeup", "([I[Ljava/lang/String;)I", (void*)nativeWaitWakeup },
+    { "nativeWaitWakeup", "([Ljava/lang/String;)I", (void*)nativeWaitWakeup },
 };
 
 int register_android_server_BatteryStatsService(JNIEnv *env)
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 491b412..5cfbb40 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -85,6 +85,7 @@
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.os.storage.StorageManager;
 import android.provider.ContactsContract.QuickContact;
 import android.provider.ContactsInternal;
 import android.provider.Settings;
@@ -108,7 +109,6 @@
 import android.view.inputmethod.InputMethodManager;
 
 import com.android.internal.R;
-import com.android.internal.os.storage.ExternalStorageFormatter;
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.JournaledFile;
@@ -3307,25 +3307,15 @@
     }
 
     private void wipeDataLocked(boolean wipeExtRequested, String reason) {
-        // TODO: wipe all public volumes on device
-
-        // If the SD card is encrypted and non-removable, we have to force a wipe.
-        boolean forceExtWipe = !Environment.isExternalStorageRemovable() && isExtStorageEncrypted();
-
-        // Note: we can only do the wipe via ExternalStorageFormatter if the volume is not emulated.
-        if ((forceExtWipe || wipeExtRequested) && !Environment.isExternalStorageEmulated()) {
-            Intent intent = new Intent(ExternalStorageFormatter.FORMAT_AND_FACTORY_RESET);
-            intent.putExtra(ExternalStorageFormatter.EXTRA_ALWAYS_RESET, true);
-            intent.putExtra(Intent.EXTRA_REASON, reason);
-            intent.setComponent(ExternalStorageFormatter.COMPONENT_NAME);
-            mWakeLock.acquire(10000);
-            mContext.startService(intent);
-        } else {
-            try {
-                RecoverySystem.rebootWipeUserData(mContext, reason);
-            } catch (IOException | SecurityException e) {
-                Slog.w(LOG_TAG, "Failed requesting data wipe", e);
-            }
+        if (wipeExtRequested) {
+            StorageManager sm = (StorageManager) mContext.getSystemService(
+                    Context.STORAGE_SERVICE);
+            sm.wipeAdoptableDisks();
+        }
+        try {
+            RecoverySystem.rebootWipeUserData(mContext, reason);
+        } catch (IOException | SecurityException e) {
+            Slog.w(LOG_TAG, "Failed requesting data wipe", e);
         }
     }
 
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index b68abab..cde87bd 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -433,6 +433,11 @@
                     + " user=" + userHandle);
         }
 
+        void resetCurAssistant(int userHandle) {
+            Settings.Secure.putStringForUser(mContext.getContentResolver(),
+                    Settings.Secure.ASSISTANT, null, userHandle);
+        }
+
         @Override
         public void showSession(IVoiceInteractionService service, Bundle args, int flags) {
             synchronized (this) {
@@ -897,6 +902,7 @@
                         }
                         setCurInteractor(null, userHandle);
                         setCurRecognizer(null, userHandle);
+                        resetCurAssistant(userHandle);
                         initForUser(userHandle);
                         switchImplementationIfNeededLocked(true);
                     }
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
index cc6a9c5..549a511 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
@@ -193,8 +193,14 @@
                         new UserHandle(mUser));
             }
             mShown = true;
-            boolean allDataEnabled = Settings.Secure.getIntForUser(mContext.getContentResolver(),
-                    Settings.Secure.ASSIST_STRUCTURE_ENABLED, 1, mUser) != 0;
+            boolean isScreenCaptureAllowed = true;
+            try {
+                isScreenCaptureAllowed = mAm.isScreenCaptureAllowedOnCurrentActivity();
+            } catch (RemoteException e) {
+            }
+            boolean allDataEnabled = (Settings.Secure.getIntForUser(mContext.getContentResolver(),
+                    Settings.Secure.ASSIST_STRUCTURE_ENABLED, 1, mUser) != 0)
+                    && isScreenCaptureAllowed;
             mShowArgs = args;
             mShowFlags = flags;
             mHaveAssistData = false;
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index a2bd74b..ab2a98d 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -891,16 +891,17 @@
     }
 
     /**
-     * Returns the neighboring cell information of the device. The getAllCellInfo is preferred
-     * and use this only if getAllCellInfo return nulls or an empty list.
-     *<p>
-     * In the future this call will be deprecated.
-     *<p>
+     * Returns the neighboring cell information of the device.
+     *
      * @return List of NeighboringCellInfo or null if info unavailable.
      *
      * <p>Requires Permission:
      * (@link android.Manifest.permission#ACCESS_COARSE_UPDATES}
+     *
+     * @deprecated Use (@link getAllCellInfo} which returns a superset of the information
+     *             from NeighboringCellInfo.
      */
+    @Deprecated
     public List<NeighboringCellInfo> getNeighboringCellInfo() {
         try {
             ITelephony telephony = getITelephony();
diff --git a/telephony/java/com/android/internal/telephony/CellNetworkScanResult.java b/telephony/java/com/android/internal/telephony/CellNetworkScanResult.java
index c708c14..5a6bd1d 100644
--- a/telephony/java/com/android/internal/telephony/CellNetworkScanResult.java
+++ b/telephony/java/com/android/internal/telephony/CellNetworkScanResult.java
@@ -88,6 +88,7 @@
     public void writeToParcel(Parcel out, int flags) {
         out.writeInt(mStatus);
         if (mOperators != null && mOperators.size() > 0) {
+            out.writeInt(mOperators.size());
             for (OperatorInfo network : mOperators) {
                 network.writeToParcel(out, flags);
             }
diff --git a/tests/VoiceInteraction/res/layout/voice_interaction_session.xml b/tests/VoiceInteraction/res/layout/voice_interaction_session.xml
index d44afb0..610f30b 100644
--- a/tests/VoiceInteraction/res/layout/voice_interaction_session.xml
+++ b/tests/VoiceInteraction/res/layout/voice_interaction_session.xml
@@ -18,6 +18,11 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent">
 
+    <ImageView android:id="@+id/full_screenshot"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:visibility="invisible"/>
+
     <com.android.test.voiceinteraction.AssistVisualizer android:id="@+id/assist_visualizer"
             android:layout_width="match_parent"
             android:layout_height="match_parent" />
@@ -30,19 +35,29 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:layout_gravity="top"
-            android:orientation="vertical"
+            android:orientation="horizontal"
             android:background="#ffffffff"
             android:elevation="8dp"
             >
+            <ImageView android:id="@+id/screenshot"
+                android:layout_width="wrap_content"
+                android:layout_height="46dp"
+                android:adjustViewBounds="true" />
+            <View android:layout_width="0dp"
+                android:layout_height="0dp"
+                android:layout_weight="1" />
+            <Button android:id="@+id/do_tree"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/tree" />
+            <Button android:id="@+id/do_text"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/text" />
             <Button android:id="@+id/start"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_gravity="top|right"
-                android:text="@string/start"
-                />
-            <ImageView android:id="@+id/screenshot"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"/>
+                android:text="@string/start" />
         </LinearLayout>
 
         <LinearLayout android:id="@+id/bottom_content"
@@ -58,26 +73,22 @@
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:layout_marginBottom="16dp"
-                android:textAppearance="?android:attr/textAppearanceMedium"
-                />
+                android:textAppearance="?android:attr/textAppearanceMedium" />
 
             <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content"
                     android:orientation="horizontal">
                 <Button android:id="@+id/confirm"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
-                    android:text="@string/confirm"
-                    />
+                    android:text="@string/confirm" />
                 <Button android:id="@+id/complete"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
-                    android:text="@string/complete"
-                    />
+                    android:text="@string/complete" />
                 <Button android:id="@+id/abort"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
-                    android:text="@string/abort"
-                    />
+                    android:text="@string/abort" />
             </LinearLayout>
 
         </LinearLayout>
diff --git a/tests/VoiceInteraction/res/values/strings.xml b/tests/VoiceInteraction/res/values/strings.xml
index 6289929..4cf4104 100644
--- a/tests/VoiceInteraction/res/values/strings.xml
+++ b/tests/VoiceInteraction/res/values/strings.xml
@@ -17,6 +17,8 @@
 <resources>
 
     <string name="start">Start</string>
+    <string name="tree">Tree</string>
+    <string name="text">Text</string>
     <string name="asyncStructure">(Async structure goes here)</string>
     <string name="confirm">Confirm</string>
     <string name="abort">Abort</string>
diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/AssistVisualizer.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/AssistVisualizer.java
index 439ace8..339755f 100644
--- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/AssistVisualizer.java
+++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/AssistVisualizer.java
@@ -20,6 +20,7 @@
 import android.app.assist.AssistStructure;
 import android.content.Context;
 import android.graphics.Canvas;
+import android.graphics.Matrix;
 import android.graphics.Paint;
 import android.graphics.Rect;
 import android.util.AttributeSet;
@@ -31,10 +32,32 @@
 public class AssistVisualizer extends View {
     static final String TAG = "AssistVisualizer";
 
+    static class TextEntry {
+        final Rect bounds;
+        final int parentLeft, parentTop;
+        final Matrix matrix;
+        final String className;
+        final CharSequence text;
+
+        TextEntry(AssistStructure.ViewNode node, int parentLeft, int parentTop, Matrix matrix) {
+            int left = parentLeft+node.getLeft();
+            int top = parentTop+node.getTop();
+            bounds = new Rect(left, top, left+node.getWidth(), top+node.getHeight());
+            this.parentLeft = parentLeft;
+            this.parentTop = parentTop;
+            this.matrix = new Matrix(matrix);
+            this.className = node.getClassName();
+            this.text = node.getText() != null ? node.getText() : node.getContentDescription();
+        }
+    }
+
     AssistStructure mAssistStructure;
     final Paint mFramePaint = new Paint();
-    final ArrayList<Rect> mTextRects = new ArrayList<>();
+    final Paint mFrameNoTransformPaint = new Paint();
+    final ArrayList<Matrix> mMatrixStack = new ArrayList<>();
+    final ArrayList<TextEntry> mTextRects = new ArrayList<>();
     final int[] mTmpLocation = new int[2];
+    final float[] mTmpMatrixPoint = new float[2];
 
     public AssistVisualizer(Context context, @Nullable AttributeSet attrs) {
         super(context, attrs);
@@ -42,17 +65,26 @@
         mFramePaint.setColor(0xffff0000);
         mFramePaint.setStyle(Paint.Style.STROKE);
         mFramePaint.setStrokeWidth(0);
+        float density = getResources().getDisplayMetrics().density;
+        mFramePaint.setShadowLayer(density, density, density, 0xff000000);
+        mFrameNoTransformPaint.setColor(0xff0000ff);
+        mFrameNoTransformPaint.setStyle(Paint.Style.STROKE);
+        mFrameNoTransformPaint.setStrokeWidth(0);
+        mFrameNoTransformPaint.setShadowLayer(density, density, density, 0xff000000);
     }
 
     public void setAssistStructure(AssistStructure as) {
         mAssistStructure = as;
-        mAssistStructure.dump();
         mTextRects.clear();
         final int N = as.getWindowNodeCount();
         if (N > 0) {
             for (int i=0; i<N; i++) {
                 AssistStructure.WindowNode windowNode = as.getWindowNodeAt(i);
-                buildTextRects(windowNode.getRootViewNode(), windowNode.getLeft(),
+                mMatrixStack.clear();
+                Matrix matrix = new Matrix();
+                matrix.setTranslate(windowNode.getLeft(), windowNode.getTop());
+                mMatrixStack.add(matrix);
+                buildTextRects(windowNode.getRootViewNode(), 0, windowNode.getLeft(),
                         windowNode.getTop());
             }
         }
@@ -60,31 +92,62 @@
         invalidate();
     }
 
+    public void logTree() {
+        if (mAssistStructure != null) {
+            mAssistStructure.dump();
+        }
+    }
+
+    public void logText() {
+        final int N = mTextRects.size();
+        for (int i=0; i<N; i++) {
+            TextEntry te = mTextRects.get(i);
+            Log.d(TAG, "View " + te.className + " " + te.bounds.toShortString()
+                    + " in " + te.parentLeft + "," + te.parentTop
+                    + " matrix=" + te.matrix.toShortString() + ": "
+                    + te.text);
+        }
+    }
+
     public void clearAssistData() {
         mAssistStructure = null;
         mTextRects.clear();
     }
 
-    void buildTextRects(AssistStructure.ViewNode root, int parentLeft, int parentTop) {
+    void buildTextRects(AssistStructure.ViewNode root, int matrixStackIndex,
+            int parentLeft, int parentTop) {
         if (root.getVisibility() != View.VISIBLE) {
             return;
         }
-        int left = parentLeft+root.getLeft();
-        int top = parentTop+root.getTop();
+        Matrix parentMatrix = mMatrixStack.get(matrixStackIndex);
+        matrixStackIndex++;
+        Matrix matrix;
+        if (mMatrixStack.size() > matrixStackIndex) {
+            matrix = mMatrixStack.get(matrixStackIndex);
+            matrix.set(parentMatrix);
+        } else {
+            matrix = new Matrix(parentMatrix);
+            mMatrixStack.add(matrix);
+        }
+        matrix.preTranslate(root.getLeft(), root.getTop());
+        int left = parentLeft + root.getLeft();
+        int top = parentTop + root.getTop();
+        Matrix transform = root.getTransformation();
+        if (transform != null) {
+            matrix.preConcat(transform);
+        }
         if (root.getText() != null || root.getContentDescription() != null) {
-            Rect r = new Rect(left, top, left+root.getWidth(), top+root.getHeight());
-            Log.d(TAG, "View " + root.getClassName() + " " + left + "," + top + " tr "
-                    + r.toShortString() + ": "
-                    + (root.getText() != null ? root.getText() : root.getContentDescription()));
-            mTextRects.add(r);
+            TextEntry te = new TextEntry(root, parentLeft, parentTop, matrix);
+            mTextRects.add(te);
         }
         final int N = root.getChildCount();
         if (N > 0) {
             left -= root.getScrollX();
             top -= root.getScrollY();
+            matrix.preTranslate(-root.getScrollX(), -root.getScrollY());
             for (int i=0; i<N; i++) {
                 AssistStructure.ViewNode child = root.getChildAt(i);
-                buildTextRects(child, left, top);
+                buildTextRects(child, matrixStackIndex, left, top);
             }
         }
     }
@@ -96,9 +159,19 @@
         final int N = mTextRects.size();
         Log.d(TAG, "Drawing text rects in " + this + ": found " + mTextRects.size());
         for (int i=0; i<N; i++) {
-            Rect r = mTextRects.get(i);
-            canvas.drawRect(r.left-mTmpLocation[0], r.top-mTmpLocation[1],
-                    r.right-mTmpLocation[0], r.bottom-mTmpLocation[1], mFramePaint);
+            TextEntry te = mTextRects.get(i);
+            canvas.drawRect(te.bounds.left - mTmpLocation[0], te.bounds.top - mTmpLocation[1],
+                    te.bounds.right - mTmpLocation[0], te.bounds.bottom - mTmpLocation[1],
+                    mFrameNoTransformPaint);
+        }
+        for (int i=0; i<N; i++) {
+            TextEntry te = mTextRects.get(i);
+            canvas.save();
+            canvas.translate(-mTmpLocation[0], -mTmpLocation[1]);
+            canvas.concat(te.matrix);
+            canvas.drawRect(0, 0, te.bounds.right - te.bounds.left, te.bounds.bottom - te.bounds.top,
+                    mFramePaint);
+            canvas.restore();
         }
     }
 }
diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java
index 90a781c..97c1e85 100644
--- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java
+++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java
@@ -42,8 +42,11 @@
     View mTopContent;
     View mBottomContent;
     TextView mText;
+    Button mTreeButton;
+    Button mTextButton;
     Button mStartButton;
     ImageView mScreenshot;
+    ImageView mFullScreenshot;
     Button mConfirmButton;
     Button mCompleteButton;
     Button mAbortButton;
@@ -110,9 +113,15 @@
         mTopContent = mContentView.findViewById(R.id.top_content);
         mBottomContent = mContentView.findViewById(R.id.bottom_content);
         mText = (TextView)mContentView.findViewById(R.id.text);
+        mTreeButton = (Button)mContentView.findViewById(R.id.do_tree);
+        mTreeButton.setOnClickListener(this);
+        mTextButton = (Button)mContentView.findViewById(R.id.do_text);
+        mTextButton.setOnClickListener(this);
         mStartButton = (Button)mContentView.findViewById(R.id.start);
         mStartButton.setOnClickListener(this);
         mScreenshot = (ImageView)mContentView.findViewById(R.id.screenshot);
+        mScreenshot.setOnClickListener(this);
+        mFullScreenshot = (ImageView)mContentView.findViewById(R.id.full_screenshot);
         mConfirmButton = (Button)mContentView.findViewById(R.id.confirm);
         mConfirmButton.setOnClickListener(this);
         mCompleteButton = (Button)mContentView.findViewById(R.id.complete);
@@ -156,8 +165,10 @@
             mScreenshot.setAdjustViewBounds(true);
             mScreenshot.setMaxWidth(screenshot.getWidth()/3);
             mScreenshot.setMaxHeight(screenshot.getHeight()/3);
+            mFullScreenshot.setImageBitmap(screenshot);
         } else {
             mScreenshot.setImageDrawable(null);
+            mFullScreenshot.setImageDrawable(null);
         }
     }
 
@@ -183,7 +194,15 @@
     }
 
     public void onClick(View v) {
-        if (v == mStartButton) {
+        if (v == mTreeButton) {
+            if (mAssistVisualizer != null) {
+                mAssistVisualizer.logTree();
+            }
+        } else if (v == mTextButton) {
+            if (mAssistVisualizer != null) {
+                mAssistVisualizer.logText();
+            }
+        } else if (v == mStartButton) {
             mState = STATE_LAUNCHING;
             updateState();
             startVoiceActivity(mStartIntent);
@@ -219,9 +238,15 @@
         } else if (v == mAbortButton) {
             mPendingRequest.sendAbortVoiceResult(null);
             mPendingRequest = null;
-        } else if (v== mCompleteButton) {
+        } else if (v == mCompleteButton) {
             mPendingRequest.sendCompleteVoiceResult(null);
             mPendingRequest = null;
+        } else if (v == mScreenshot) {
+            if (mFullScreenshot.getVisibility() != View.VISIBLE) {
+                mFullScreenshot.setVisibility(View.VISIBLE);
+            } else {
+                mFullScreenshot.setVisibility(View.INVISIBLE);
+            }
         }
         updateState();
     }
diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java
index 2ba38e1..e25b38c 100644
--- a/wifi/java/android/net/wifi/WifiInfo.java
+++ b/wifi/java/android/net/wifi/WifiInfo.java
@@ -101,6 +101,8 @@
     private InetAddress mIpAddress;
     private String mMacAddress = DEFAULT_MAC_ADDRESS;
 
+    private boolean mEphemeral;
+
     /**
      * @hide
      */
@@ -253,6 +255,7 @@
         setLinkSpeed(-1);
         setFrequency(-1);
         setMeteredHint(false);
+        setEphemeral(false);
         txBad = 0;
         txSuccess = 0;
         rxSuccess = 0;
@@ -283,6 +286,7 @@
             mIpAddress = source.mIpAddress;
             mMacAddress = source.mMacAddress;
             mMeteredHint = source.mMeteredHint;
+            mEphemeral = source.mEphemeral;
             txBad = source.txBad;
             txRetries = source.txRetries;
             txSuccess = source.txSuccess;
@@ -430,6 +434,16 @@
         return mMeteredHint;
     }
 
+    /** {@hide} */
+    public void setEphemeral(boolean ephemeral) {
+        mEphemeral = ephemeral;
+    }
+
+    /** {@hide} */
+    public boolean isEphemeral() {
+        return mEphemeral;
+    }
+
     /** @hide */
     public void setNetworkId(int id) {
         mNetworkId = id;
@@ -567,6 +581,7 @@
         dest.writeString(mBSSID);
         dest.writeString(mMacAddress);
         dest.writeInt(mMeteredHint ? 1 : 0);
+        dest.writeInt(mEphemeral ? 1 : 0);
         dest.writeInt(score);
         dest.writeDouble(txSuccessRate);
         dest.writeDouble(txRetriesRate);
@@ -597,6 +612,7 @@
                 info.mBSSID = in.readString();
                 info.mMacAddress = in.readString();
                 info.mMeteredHint = in.readInt() != 0;
+                info.mEphemeral = in.readInt() != 0;
                 info.score = in.readInt();
                 info.txSuccessRate = in.readDouble();
                 info.txRetriesRate = in.readDouble();