Merge "Allow system to disable lockscreen" into mnc-dev
diff --git a/api/current.txt b/api/current.txt
index 05e494b..e295a63 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -3412,6 +3412,7 @@
     method public boolean onSearchRequested(android.view.SearchEvent);
     method public boolean onSearchRequested();
     method protected void onStart();
+    method public void onStateNotSaved();
     method protected void onStop();
     method protected void onTitleChanged(java.lang.CharSequence, int);
     method public boolean onTouchEvent(android.view.MotionEvent);
@@ -35139,6 +35140,10 @@
     field public static final int KEYCODE_MEDIA_PREVIOUS = 88; // 0x58
     field public static final int KEYCODE_MEDIA_RECORD = 130; // 0x82
     field public static final int KEYCODE_MEDIA_REWIND = 89; // 0x59
+    field public static final int KEYCODE_MEDIA_SKIP_BACKWARD = 273; // 0x111
+    field public static final int KEYCODE_MEDIA_SKIP_FORWARD = 272; // 0x110
+    field public static final int KEYCODE_MEDIA_STEP_BACKWARD = 275; // 0x113
+    field public static final int KEYCODE_MEDIA_STEP_FORWARD = 274; // 0x112
     field public static final int KEYCODE_MEDIA_STOP = 86; // 0x56
     field public static final int KEYCODE_MEDIA_TOP_MENU = 226; // 0xe2
     field public static final int KEYCODE_MENU = 82; // 0x52
diff --git a/api/system-current.txt b/api/system-current.txt
index d9702ac..8b9af5e 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -115,7 +115,6 @@
     field public static final java.lang.String INTERNET = "android.permission.INTERNET";
     field public static final java.lang.String INVOKE_CARRIER_SETUP = "android.permission.INVOKE_CARRIER_SETUP";
     field public static final java.lang.String KILL_BACKGROUND_PROCESSES = "android.permission.KILL_BACKGROUND_PROCESSES";
-    field public static final java.lang.String KILL_UID = "android.permission.KILL_UID";
     field public static final java.lang.String LOCAL_MAC_ADDRESS = "android.permission.LOCAL_MAC_ADDRESS";
     field public static final java.lang.String LOCATION_HARDWARE = "android.permission.LOCATION_HARDWARE";
     field public static final java.lang.String LOOP_RADIO = "android.permission.LOOP_RADIO";
@@ -3516,6 +3515,7 @@
     method public boolean onSearchRequested(android.view.SearchEvent);
     method public boolean onSearchRequested();
     method protected void onStart();
+    method public void onStateNotSaved();
     method protected void onStop();
     method protected void onTitleChanged(java.lang.CharSequence, int);
     method public boolean onTouchEvent(android.view.MotionEvent);
@@ -3653,7 +3653,6 @@
     method public static boolean isRunningInTestHarness();
     method public static boolean isUserAMonkey();
     method public void killBackgroundProcesses(java.lang.String);
-    method public void killUid(int, java.lang.String);
     method public void moveTaskToFront(int, int);
     method public void moveTaskToFront(int, int, android.os.Bundle);
     method public deprecated void restartPackage(java.lang.String);
@@ -37433,6 +37432,10 @@
     field public static final int KEYCODE_MEDIA_PREVIOUS = 88; // 0x58
     field public static final int KEYCODE_MEDIA_RECORD = 130; // 0x82
     field public static final int KEYCODE_MEDIA_REWIND = 89; // 0x59
+    field public static final int KEYCODE_MEDIA_SKIP_BACKWARD = 273; // 0x111
+    field public static final int KEYCODE_MEDIA_SKIP_FORWARD = 272; // 0x110
+    field public static final int KEYCODE_MEDIA_STEP_BACKWARD = 275; // 0x113
+    field public static final int KEYCODE_MEDIA_STEP_FORWARD = 274; // 0x112
     field public static final int KEYCODE_MEDIA_STOP = 86; // 0x56
     field public static final int KEYCODE_MEDIA_TOP_MENU = 226; // 0xe2
     field public static final int KEYCODE_MENU = 82; // 0x52
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 3c8af0d..2cb3f39 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -1172,6 +1172,16 @@
     }
 
     /**
+     * Called when an {@link #onResume} is coming up, prior to other pre-resume callbacks
+     * such as {@link #onNewIntent} and {@link #onActivityResult}.  This is primarily intended
+     * to give the activity a hint that its state is no longer saved -- it will generally
+     * be called after {@link #onSaveInstanceState} and prior to the activity being
+     * resumed/started again.
+     */
+    public void onStateNotSaved() {
+    }
+
+    /**
      * Called after {@link #onRestoreInstanceState}, {@link #onRestart}, or
      * {@link #onPause}, for your activity to start interacting with the user.
      * This is a good place to begin animations, open exclusive-access devices
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 55b2fd9..87c9efc2 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -2430,11 +2430,11 @@
      *
      * @hide
      */
-    @SystemApi
     @RequiresPermission(Manifest.permission.KILL_UID)
     public void killUid(int uid, String reason) {
         try {
-            ActivityManagerNative.getDefault().killUid(uid, reason);
+            ActivityManagerNative.getDefault().killUid(UserHandle.getAppId(uid),
+                    UserHandle.getUserId(uid), reason);
         } catch (RemoteException e) {
             Log.e(TAG, "Couldn't kill uid:" + uid, e);
         }
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index e144c29..f6e0735 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -2245,9 +2245,10 @@
 
         case KILL_UID_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
-            int uid = data.readInt();
+            int appId = data.readInt();
+            int userId = data.readInt();
             String reason = data.readString();
-            killUid(uid, reason);
+            killUid(appId, userId, reason);
             reply.writeNoException();
             return true;
         }
@@ -5479,11 +5480,12 @@
         return res;
     }
 
-    public void killUid(int uid, String reason) throws RemoteException {
+    public void killUid(int appId, int userId, String reason) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(uid);
+        data.writeInt(appId);
+        data.writeInt(userId);
         data.writeString(reason);
         mRemote.transact(KILL_UID_TRANSACTION, data, reply, 0);
         reply.readException();
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 2b4d03b..fd88a05 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -3079,6 +3079,7 @@
                 r.activity.mStartedActivity = false;
             }
             try {
+                r.activity.onStateNotSaved();
                 r.activity.mFragments.noteStateNotSaved();
                 if (r.pendingIntents != null) {
                     deliverNewIntents(r, r.pendingIntents);
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 90216af..ef121ce 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -447,7 +447,7 @@
 
     public boolean showAssistFromActivity(IBinder token, Bundle args) throws RemoteException;
 
-    public void killUid(int uid, String reason) throws RemoteException;
+    public void killUid(int appId, int userId, String reason) throws RemoteException;
 
     public void hang(IBinder who, boolean allowRestart) throws RemoteException;
 
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 2d729c7..c505b0b 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -124,6 +124,12 @@
      *
      * <p> If provisioning fails, the managedProfile is removed so the device returns to its
      * previous state.
+     *
+     * <p>If launched with {@link android.app.Activity#startActivityForResult(Intent, int)} a
+     * result code of {@link android.app.Activity#RESULT_OK} implies that the synchronous part of
+     * the provisioning flow was successful, although this doesn't guarantee the full flow will
+     * succeed. Conversely a result code of {@link android.app.Activity#RESULT_CANCELED} implies
+     * that the user backed-out of provisioning, or some precondition for provisioning wasn't met.
      */
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_PROVISION_MANAGED_PROFILE
@@ -158,6 +164,10 @@
      *
      * <p> If provisioning fails, the device is factory reset.
      *
+     * <p>A result code of {@link android.app.Activity#RESULT_OK} implies that the synchronous part
+     * of the provisioning flow was successful, although this doesn't guarantee the full flow will
+     * succeed. Conversely a result code of {@link android.app.Activity#RESULT_CANCELED} implies
+     * that the user backed-out of provisioning, or some precondition for provisioning wasn't met.
      */
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_PROVISION_MANAGED_DEVICE
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index aa4b051..64877aa69 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -27,6 +27,12 @@
  *  {@hide}
  */
 interface IUserManager {
+
+    /*
+     * DO NOT MOVE - UserManager.h depends on the ordering of this function.
+     */
+    int getCredentialOwnerProfile(int userHandle);
+
     UserInfo createUser(in String name, int flags);
     UserInfo createProfileForUser(in String name, int flags, int userHandle);
     void setUserEnabled(int userHandle);
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 83a1993..045c1e8 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -1068,6 +1068,22 @@
     }
 
     /**
+     * Returns the device credential owner id of the profile from
+     * which this method is called, or userHandle if called from a user that
+     * is not a profile.
+     *
+     * @hide
+     */
+    public int getCredentialOwnerProfile(int userHandle) {
+        try {
+            return mService.getCredentialOwnerProfile(userHandle);
+        } catch (RemoteException re) {
+            Log.w(TAG, "Could not get credential owner", re);
+            return -1;
+        }
+    }
+
+    /**
      * Returns the parent of the profile which this method is called from
      * or null if called from a user that is not a profile.
      *
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index f6ce353..a9bf92b 100644
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -747,22 +747,32 @@
     public static final int KEYCODE_TV_TIMER_PROGRAMMING = 258;
     /** Key code constant: Help key. */
     public static final int KEYCODE_HELP = 259;
-    /** Key code constant: Navigate to previous key. 
+    /** Key code constant: Navigate to previous key.
      * Goes backward by one item in an ordered collection of items. */
     public static final int KEYCODE_NAVIGATE_PREVIOUS = 260;
-    /** Key code constant: Navigate to next key. 
+    /** Key code constant: Navigate to next key.
      * Advances to the next item in an ordered collection of items. */
     public static final int KEYCODE_NAVIGATE_NEXT   = 261;
     /** Key code constant: Navigate in key.
-     * Activates the item that currently has focus or expands to the next level of a navigation 
+     * Activates the item that currently has focus or expands to the next level of a navigation
      * hierarchy. */
     public static final int KEYCODE_NAVIGATE_IN     = 262;
     /** Key code constant: Navigate out key.
-     * Backs out one level of a navigation hierarchy or collapses the item that currently has 
+     * Backs out one level of a navigation hierarchy or collapses the item that currently has
      * focus. */
     public static final int KEYCODE_NAVIGATE_OUT    = 263;
+    /** Key code constant: Skip forward media key. */
+    public static final int KEYCODE_MEDIA_SKIP_FORWARD = 272;
+    /** Key code constant: Skip backward media key. */
+    public static final int KEYCODE_MEDIA_SKIP_BACKWARD = 273;
+    /** Key code constant: Step forward media key.
+     * Steps media forward, one frame at a time. */
+    public static final int KEYCODE_MEDIA_STEP_FORWARD = 274;
+    /** Key code constant: Step backward media key.
+     * Steps media backward, one frame at a time. */
+    public static final int KEYCODE_MEDIA_STEP_BACKWARD = 275;
 
-    private static final int LAST_KEYCODE = KEYCODE_NAVIGATE_OUT;
+    private static final int LAST_KEYCODE = KEYCODE_MEDIA_STEP_BACKWARD;
 
     // NOTE: If you add a new keycode here you must also add it to:
     //  isSystem()
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index fab81a4..52d6cbe 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -43,6 +43,7 @@
 import android.util.Log;
 import android.util.Pools.SynchronizedPool;
 import android.util.SparseArray;
+import android.util.SparseBooleanArray;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.animation.Animation;
@@ -2902,13 +2903,58 @@
                 final int childrenCount = getChildCount();
                 if (childrenCount > 0) {
                     structure.setChildCount(childrenCount);
-                    final ArrayList<View> preorderedList = buildOrderedChildList();
-                    final boolean customOrder = preorderedList == null
+                    ArrayList<View> preorderedList = buildOrderedChildList();
+                    boolean customOrder = preorderedList == null
                             && isChildrenDrawingOrderEnabled();
                     final View[] children = mChildren;
                     for (int i=0; i<childrenCount; i++) {
-                        final int childIndex = customOrder
-                                ? getChildDrawingOrder(childrenCount, i) : i;
+                        int childIndex;
+                        try {
+                            childIndex = customOrder ? getChildDrawingOrder(childrenCount, i) : i;
+                        } catch (IndexOutOfBoundsException e) {
+                            childIndex = i;
+                            if (mContext.getApplicationInfo().targetSdkVersion
+                                    < Build.VERSION_CODES.M) {
+                                Log.w(TAG, "Bad getChildDrawingOrder while collecting assist @ "
+                                        + i + " of " + childrenCount, e);
+                                // At least one app is failing when we call getChildDrawingOrder
+                                // at this point, so deal semi-gracefully with it by falling back
+                                // on the basic order.
+                                customOrder = false;
+                                if (i > 0) {
+                                    // If we failed at the first index, there really isn't
+                                    // anything to do -- we will just proceed with the simple
+                                    // sequence order.
+                                    // Otherwise, we failed in the middle, so need to come up
+                                    // with an order for the remaining indices and use that.
+                                    // Failed at the first one, easy peasy.
+                                    int[] permutation = new int[childrenCount];
+                                    SparseBooleanArray usedIndices = new SparseBooleanArray();
+                                    // Go back and collected the indices we have done so far.
+                                    for (int j=0; j<i; j++) {
+                                        permutation[j] = getChildDrawingOrder(childrenCount, j);
+                                        usedIndices.put(permutation[j], true);
+                                    }
+                                    // Fill in the remaining indices with indices that have not
+                                    // yet been used.
+                                    int nextIndex = 0;
+                                    for (int j=i; j<childrenCount; j++) {
+                                        while (usedIndices.get(nextIndex, false)) {
+                                            nextIndex++;
+                                        }
+                                        permutation[j] = nextIndex;
+                                        nextIndex++;
+                                    }
+                                    // Build the final view list.
+                                    preorderedList = new ArrayList<>(childrenCount);
+                                    for (int j=0; j<childrenCount; j++) {
+                                        preorderedList.add(children[permutation[j]]);
+                                    }
+                                }
+                            } else {
+                                throw e;
+                            }
+                        }
                         final View child = (preorderedList == null)
                                 ? children[childIndex] : preorderedList.get(childIndex);
                         ViewStructure cstructure = structure.newChild(i);
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index e13b96f..ddbaa9d 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -384,6 +384,10 @@
         assigned.
     */
     public Drawable getDrawable() {
+        if (mDrawable == mRecycleableBitmapDrawable) {
+            // Consider our cached version dirty since app code now has a reference to it
+            mRecycleableBitmapDrawable = null;
+        }
         return mDrawable;
     }
 
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index b4cbf35..f9fa027 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -105,7 +105,10 @@
     /** View that handles event dispatch and content transitions. */
     private PopupDecorView mDecorView;
 
-    /** The contents of the popup. */
+    /** View that holds the background and may animate during a transition. */
+    private View mBackgroundView;
+
+    /** The contents of the popup. May be identical to the background view. */
     private View mContentView;
 
     private boolean mFocusable;
@@ -1111,18 +1114,18 @@
         if (aboveAnchor != mAboveAnchor) {
             mAboveAnchor = aboveAnchor;
 
-            if (mBackground != null) {
-                // If the background drawable provided was a StateListDrawable with above-anchor
-                // and below-anchor states, use those. Otherwise rely on refreshDrawableState to
-                // do the job.
+            if (mBackground != null && mBackgroundView != null) {
+                // If the background drawable provided was a StateListDrawable
+                // with above-anchor and below-anchor states, use those.
+                // Otherwise, rely on refreshDrawableState to do the job.
                 if (mAboveAnchorBackgroundDrawable != null) {
                     if (mAboveAnchor) {
-                        mDecorView.setBackground(mAboveAnchorBackgroundDrawable);
+                        mBackgroundView.setBackground(mAboveAnchorBackgroundDrawable);
                     } else {
-                        mDecorView.setBackground(mBelowAnchorBackgroundDrawable);
+                        mBackgroundView.setBackground(mBelowAnchorBackgroundDrawable);
                     }
                 } else {
-                    mDecorView.refreshDrawableState();
+                    mBackgroundView.refreshDrawableState();
                 }
             }
         }
@@ -1164,22 +1167,21 @@
 
         // When a background is available, we embed the content view within
         // another view that owns the background drawable.
-        final View backgroundView;
         if (mBackground != null) {
-            backgroundView = createBackgroundView(mContentView);
-            backgroundView.setBackground(mBackground);
+            mBackgroundView = createBackgroundView(mContentView);
+            mBackgroundView.setBackground(mBackground);
         } else {
-            backgroundView = mContentView;
+            mBackgroundView = mContentView;
         }
 
-        mDecorView = createDecorView(backgroundView);
+        mDecorView = createDecorView(mBackgroundView);
 
         // The background owner should be elevated so that it casts a shadow.
-        backgroundView.setElevation(mElevation);
+        mBackgroundView.setElevation(mElevation);
 
         // We may wrap that in another view, so we'll need to manually specify
         // the surface insets.
-        final int surfaceInset = (int) Math.ceil(backgroundView.getZ() * 2);
+        final int surfaceInset = (int) Math.ceil(mBackgroundView.getZ() * 2);
         p.surfaceInsets.set(surfaceInset, surfaceInset, surfaceInset, surfaceInset);
         p.hasManualSurfaceInsets = true;
 
@@ -1650,6 +1652,7 @@
         // This needs to stay until after all transitions have ended since we
         // need the reference to cancel transitions in preparePopup().
         mDecorView = null;
+        mBackgroundView = null;
         mIsTransitioningToDismiss = false;
     }
 
diff --git a/core/java/com/android/internal/logging/MetricsLogger.java b/core/java/com/android/internal/logging/MetricsLogger.java
index d954b71..55493c3 100644
--- a/core/java/com/android/internal/logging/MetricsLogger.java
+++ b/core/java/com/android/internal/logging/MetricsLogger.java
@@ -28,6 +28,7 @@
 public class MetricsLogger implements MetricsConstants {
     // Temporary constants go here, to await migration to MetricsConstants.
     // next value is 239;
+    public static final int ACTION_ASSIST_LONG_PRESS = 239;
 
     public static void visible(Context context, int category) throws IllegalArgumentException {
         if (Build.IS_DEBUGGABLE && category == VIEW_UNKNOWN) {
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index db88962..7a725ae 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -298,11 +298,11 @@
 
     String8 storageSource;
     if (mount_mode == MOUNT_EXTERNAL_DEFAULT) {
-        storageSource = "/mnt/runtime_default";
+        storageSource = "/mnt/runtime/default";
     } else if (mount_mode == MOUNT_EXTERNAL_READ) {
-        storageSource = "/mnt/runtime_read";
+        storageSource = "/mnt/runtime/read";
     } else if (mount_mode == MOUNT_EXTERNAL_WRITE) {
-        storageSource = "/mnt/runtime_write";
+        storageSource = "/mnt/runtime/write";
     } else {
         // Sane default of no storage visible
         return true;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 1f47ce3..699e113 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2575,7 +2575,7 @@
     <permission android:name="android.permission.QUERY_DO_NOT_ASK_CREDENTIALS_ON_BOOT"
                 android:protectionLevel="signature" />
 
-    <!-- @SystemApi Allows applications to kill UIDs.
+    <!-- Allows applications to kill UIDs.
         <p>Not for use by third-party applications.
          @hide -->
     <permission android:name="android.permission.KILL_UID"
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index b1925ba..67abe8d 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -1806,6 +1806,10 @@
         <enum name="KEYCODE_NAVIGATE_NEXT" value="261" />
         <enum name="KEYCODE_NAVIGATE_IN" value="262" />
         <enum name="KEYCODE_NAVIGATE_OUT" value="263" />
+        <enum name="KEYCODE_MEDIA_SKIP_FORWARD" value="272" />
+        <enum name="KEYCODE_MEDIA_SKIP_BACKWARD" value="273" />
+        <enum name="KEYCODE_MEDIA_STEP_FORWARD" value="274" />
+        <enum name="KEYCODE_MEDIA_STEP_BACKWARD" value="275" />
     </attr>
 
     <!-- ***************************************************************** -->
diff --git a/media/java/android/media/AudioDeviceInfo.java b/media/java/android/media/AudioDeviceInfo.java
index 6104264..fef65ee 100644
--- a/media/java/android/media/AudioDeviceInfo.java
+++ b/media/java/android/media/AudioDeviceInfo.java
@@ -19,6 +19,8 @@
 import android.annotation.NonNull;
 import android.util.SparseIntArray;
 
+import java.util.TreeSet;
+
 /**
  * Class to provide information about the audio devices.
  */
@@ -109,6 +111,14 @@
      * A device type connected over IP.
      */
     public static final int TYPE_IP               = 20;
+    /**
+     * @hide
+     * A remote-submix device.
+     * We need this for CTS, but it is not part of the external API.
+     * FIXME It has been suggested that CTS should only be testing public APIs.
+     *   Consider this for a public API.
+     */
+    public static final int TYPE_REMOTE_SUBMIX    = 0x7FFF;
 
     private final AudioDevicePort mPort;
 
@@ -193,13 +203,24 @@
      * Note: an empty array indicates that the device supports arbitrary channel counts.
      */
     public @NonNull int[] getChannelCounts() {
-        int[] masks = getChannelMasks();
-        int[] counts = new int[masks.length];
-        // TODO: consider channel index masks
-        for (int mask_index = 0; mask_index < masks.length; mask_index++) {
-            counts[mask_index] = isSink()
-                    ? AudioFormat.channelCountFromOutChannelMask(masks[mask_index])
-                    : AudioFormat.channelCountFromInChannelMask(masks[mask_index]);
+        TreeSet<Integer> countSet = new TreeSet<Integer>();
+
+        // Channel Masks
+        for (int mask : getChannelMasks()) {
+            countSet.add(isSink() ?
+                    AudioFormat.channelCountFromOutChannelMask(mask)
+                    : AudioFormat.channelCountFromInChannelMask(mask));
+        }
+
+        // Index Masks
+        for (int index_mask : getChannelIndexMasks()) {
+            countSet.add(Integer.bitCount(index_mask));
+        }
+
+        int[] counts = new int[countSet.size()];
+        int index = 0;
+        for (int count : countSet) {
+            counts[index++] = count; 
         }
         return counts;
     }
@@ -265,6 +286,7 @@
         INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_FM, TYPE_FM);
         INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_AUX_LINE, TYPE_AUX_LINE);
         INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_IP, TYPE_IP);
+        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_REMOTE_SUBMIX, TYPE_REMOTE_SUBMIX);
 
         INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BUILTIN_MIC, TYPE_BUILTIN_MIC);
         INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BLUETOOTH_SCO_HEADSET, TYPE_BLUETOOTH_SCO);
@@ -282,10 +304,7 @@
         INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_SPDIF, TYPE_LINE_DIGITAL);
         INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, TYPE_BLUETOOTH_A2DP);
         INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_IP, TYPE_IP);
-
-        // not covered here, legacy
-        //AudioSystem.DEVICE_OUT_REMOTE_SUBMIX
-        //AudioSystem.DEVICE_IN_REMOTE_SUBMIX
+        INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_REMOTE_SUBMIX, TYPE_REMOTE_SUBMIX);
 
         // privileges mapping to output device
         EXT_TO_INT_DEVICE_MAPPING = new SparseIntArray();
diff --git a/media/java/android/media/MediaSync.java b/media/java/android/media/MediaSync.java
index b37e02c..5522d36 100644
--- a/media/java/android/media/MediaSync.java
+++ b/media/java/android/media/MediaSync.java
@@ -55,7 +55,7 @@
  *     }
  * }, null);
  * // This needs to be done since sync is paused on creation.
- * sync.setPlaybackRate(1.0f, MediaSync.PLAYBACK_RATE_AUDIO_MODE_RESAMPLE);
+ * sync.setPlaybackParams(new PlaybackParams().setSpeed(1.f));
  *
  * for (;;) {
  *   ...
@@ -69,7 +69,7 @@
  *   ...
  *     ...
  * }
- * sync.setPlaybackRate(0.0f, MediaSync.PLAYBACK_RATE_AUDIO_MODE_RESAMPLE);
+ * sync.setPlaybackParams(new PlaybackParams().setSpeed(0.f));
  * sync.release();
  * sync = null;
  *
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
index d99f741..e74334b 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
@@ -447,8 +447,10 @@
                     Settings.Global.putInt(cr,
                             Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, 0);
                 }
-                // !!! Give the wifi stack a moment to quiesce
-                try { Thread.sleep(1500); } catch (InterruptedException e) {}
+                // !!! Give the wifi stack a moment to quiesce.  We've observed the
+                // response to disabling WIFI_SCAN_ALWAYS_AVAILABLE taking more
+                // than 1500ms, so we wait a generous 2500 here before proceeding.
+                try { Thread.sleep(2500); } catch (InterruptedException e) {}
                 if (restoredSupplicantData != null) {
                     restoreWifiSupplicant(FILE_WIFI_SUPPLICANT,
                             restoredSupplicantData, restoredSupplicantData.length);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 789457d..b47fb304 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -419,8 +419,10 @@
         updateRecentsTasks();
 
         // If this is a new instance from a configuration change, then we have to manually trigger
-        // the enter animation state
-        if (mConfig.launchedHasConfigurationChanged) {
+        // the enter animation state, or if recents was relaunched by AM, without going through
+        // the normal mechanisms
+        boolean wasLaunchedByAm = !mConfig.launchedFromHome && !mConfig.launchedFromAppWithThumbnail;
+        if (mConfig.launchedHasConfigurationChanged || wasLaunchedByAm) {
             onEnterAnimationTriggered();
         }
 
@@ -454,6 +456,16 @@
 
         // Unregister any broadcast receivers for the task loader
         loader.unregisterReceivers();
+
+        // Workaround for b/22542869, if the RecentsActivity is started again, but without going
+        // through SystemUI, we need to reset the config launch flags to ensure that we do not
+        // wait on the system to send a signal that was never queued.
+        mConfig.launchedFromHome = false;
+        mConfig.launchedFromSearchHome = false;
+        mConfig.launchedFromAppWithThumbnail = false;
+        mConfig.launchedToTaskId = -1;
+        mConfig.launchedWithAltTab = false;
+        mConfig.launchedHasConfigurationChanged = false;
     }
 
     @Override
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 86755d1..efd72a7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -603,7 +603,7 @@
 
         // Lastly, call to the icon policy to install/update all the icons.
         mIconPolicy = new PhoneStatusBarPolicy(mContext, mCastController, mHotspotController,
-                mUserInfoController);
+                mUserInfoController, mBluetoothController);
         mIconPolicy.setCurrentUserSetup(mUserSetup);
         mSettingsObserver.onChange(false); // set up
 
@@ -1056,6 +1056,7 @@
             if (shouldDisableNavbarGestures()) {
                 return false;
             }
+            MetricsLogger.action(mContext, MetricsLogger.ACTION_ASSIST_LONG_PRESS);
             mAssistManager.startAssist(new Bundle() /* args */);
             awakenDreams();
             if (mNavigationBarView != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 53dae5c..540b9d0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -21,7 +21,6 @@
 import android.app.AlarmManager.AlarmClockInfo;
 import android.app.IUserSwitchObserver;
 import android.app.StatusBarManager;
-import android.bluetooth.BluetoothAdapter;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -41,6 +40,8 @@
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.systemui.R;
 import com.android.systemui.qs.tiles.DndTile;
+import com.android.systemui.statusbar.policy.BluetoothController;
+import com.android.systemui.statusbar.policy.BluetoothController.Callback;
 import com.android.systemui.statusbar.policy.CastController;
 import com.android.systemui.statusbar.policy.CastController.CastDevice;
 import com.android.systemui.statusbar.policy.HotspotController;
@@ -51,7 +52,7 @@
  * bar at boot time.  It goes through the normal API for icons, even though it probably
  * strictly doesn't need to.
  */
-public class PhoneStatusBarPolicy {
+public class PhoneStatusBarPolicy implements Callback {
     private static final String TAG = "PhoneStatusBarPolicy";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
@@ -82,12 +83,11 @@
 
     private int mZen;
 
-    private boolean mBluetoothEnabled = false;
-
     private boolean mManagedProfileFocused = false;
     private boolean mManagedProfileIconVisible = true;
 
     private boolean mKeyguardVisible = true;
+    private BluetoothController mBluetooth;
 
     private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
         @Override
@@ -96,10 +96,6 @@
             if (action.equals(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED)) {
                 updateAlarm();
             }
-            else if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED) ||
-                    action.equals(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED)) {
-                updateBluetooth();
-            }
             else if (action.equals(AudioManager.RINGER_MODE_CHANGED_ACTION) ||
                     action.equals(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION)) {
                 updateVolumeZen();
@@ -114,10 +110,12 @@
     };
 
     public PhoneStatusBarPolicy(Context context, CastController cast, HotspotController hotspot,
-            UserInfoController userInfoController) {
+            UserInfoController userInfoController, BluetoothController bluetooth) {
         mContext = context;
         mCast = cast;
         mHotspot = hotspot;
+        mBluetooth = bluetooth;
+        mBluetooth.addStateChangedCallback(this);
         mService = (StatusBarManager) context.getSystemService(Context.STATUS_BAR_SERVICE);
         mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
         mUserInfoController = userInfoController;
@@ -127,8 +125,6 @@
         filter.addAction(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED);
         filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
         filter.addAction(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION);
-        filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
-        filter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
         filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
         filter.addAction(TelecomManager.ACTION_CURRENT_TTY_MODE_CHANGED);
         mContext.registerReceiver(mIntentReceiver, filter, null, mHandler);
@@ -275,23 +271,31 @@
         updateAlarm();
     }
 
+    @Override
+    public void onBluetoothDevicesChanged() {
+        updateBluetooth();
+    }
+
+    @Override
+    public void onBluetoothStateChange(boolean enabled) {
+        updateBluetooth();
+    }
+
     private final void updateBluetooth() {
-        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
         int iconId = R.drawable.stat_sys_data_bluetooth;
         String contentDescription =
                 mContext.getString(R.string.accessibility_quick_settings_bluetooth_on);
-        if (adapter != null) {
-            mBluetoothEnabled = (adapter.getState() == BluetoothAdapter.STATE_ON);
-            if (adapter.getConnectionState() == BluetoothAdapter.STATE_CONNECTED) {
+        boolean bluetoothEnabled = false;
+        if (mBluetooth != null) {
+            bluetoothEnabled = mBluetooth.isBluetoothEnabled();
+            if (mBluetooth.isBluetoothConnected()) {
                 iconId = R.drawable.stat_sys_data_bluetooth_connected;
                 contentDescription = mContext.getString(R.string.accessibility_bluetooth_connected);
             }
-        } else {
-            mBluetoothEnabled = false;
         }
 
         mService.setIcon(SLOT_BLUETOOTH, iconId, 0, contentDescription);
-        mService.setIconVisibility(SLOT_BLUETOOTH, mBluetoothEnabled);
+        mService.setIconVisibility(SLOT_BLUETOOTH, bluetoothEnabled);
     }
 
     private final void updateTTY(Intent intent) {
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index 53e8d14..d10a457 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -766,6 +766,15 @@
         }
     }
 
+    private void addInternalVolume() {
+        // Create a stub volume that represents internal storage
+        final VolumeInfo internal = new VolumeInfo(VolumeInfo.ID_PRIVATE_INTERNAL,
+                VolumeInfo.TYPE_PRIVATE, null, null);
+        internal.state = VolumeInfo.STATE_MOUNTED;
+        internal.path = Environment.getDataDirectory().getAbsolutePath();
+        mVolumes.put(internal.id, internal);
+    }
+
     private void resetIfReadyAndConnectedLocked() {
         Slog.d(TAG, "Thinking about reset, mSystemReady=" + mSystemReady
                 + ", mDaemonConnected=" + mDaemonConnected);
@@ -775,12 +784,7 @@
             mDisks.clear();
             mVolumes.clear();
 
-            // Create a stub volume that represents internal storage
-            final VolumeInfo internal = new VolumeInfo(VolumeInfo.ID_PRIVATE_INTERNAL,
-                    VolumeInfo.TYPE_PRIVATE, null, null);
-            internal.state = VolumeInfo.STATE_MOUNTED;
-            internal.path = Environment.getDataDirectory().getAbsolutePath();
-            mVolumes.put(internal.id, internal);
+            addInternalVolume();
 
             try {
                 mConnector.execute("volume", "reset");
@@ -1412,6 +1416,8 @@
         userFilter.addAction(Intent.ACTION_USER_REMOVED);
         mContext.registerReceiver(mUserReceiver, userFilter, null, mHandler);
 
+        addInternalVolume();
+
         // Add ourself to the Watchdog monitors if enabled.
         if (WATCHDOG_ENABLE) {
             Watchdog.getInstance().addMonitor(this);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index b8d32c3..3d523d9 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -4118,7 +4118,7 @@
         final Intent intent;
         final int userId;
         synchronized (this) {
-            task = mRecentTasks.taskForIdLocked(taskId);
+            task = mStackSupervisor.anyTaskForIdLocked(taskId);
             if (task == null) {
                 throw new IllegalArgumentException("Task " + taskId + " not found.");
             }
@@ -5521,7 +5521,7 @@
                 // If no package is specified, we call all processes under the
                 // give user id.
                 if (packageName == null) {
-                    if (app.userId != userId) {
+                    if (userId != UserHandle.USER_ALL && app.userId != userId) {
                         continue;
                     }
                     if (appId >= 0 && UserHandle.getAppId(app.uid) != appId) {
@@ -8805,7 +8805,7 @@
             final long origId = Binder.clearCallingIdentity();
             try {
                 int taskId = ActivityRecord.getTaskForActivityLocked(token, !nonRoot);
-                final TaskRecord task = mRecentTasks.taskForIdLocked(taskId);
+                final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId);
                 if (task != null) {
                     if (mStackSupervisor.isLockedTask(task)) {
                         mStackSupervisor.showLockTaskToast();
@@ -11226,13 +11226,12 @@
     }
 
     @Override
-    public void killUid(int uid, String reason) {
+    public void killUid(int appId, int userId, String reason) {
         enforceCallingPermission(Manifest.permission.KILL_UID, "killUid");
         synchronized (this) {
             final long identity = Binder.clearCallingIdentity();
             try {
-                killPackageProcessesLocked(null, UserHandle.getAppId(uid),
-                        UserHandle.getUserId(uid),
+                killPackageProcessesLocked(null, appId, userId,
                         ProcessList.PERSISTENT_PROC_ADJ, false, true, true, true,
                         reason != null ? reason : "kill uid");
             } finally {
@@ -20573,7 +20572,7 @@
             synchronized (ActivityManagerService.this) {
                 long origId = Binder.clearCallingIdentity();
                 try {
-                    TaskRecord tr = mRecentTasks.taskForIdLocked(mTaskId);
+                    TaskRecord tr = mStackSupervisor.anyTaskForIdLocked(mTaskId);
                     if (tr == null) {
                         throw new IllegalArgumentException("Unable to find task ID " + mTaskId);
                     }
@@ -20600,7 +20599,7 @@
             TaskRecord tr;
             IApplicationThread appThread;
             synchronized (ActivityManagerService.this) {
-                tr = mRecentTasks.taskForIdLocked(mTaskId);
+                tr = mStackSupervisor.anyTaskForIdLocked(mTaskId);
                 if (tr == null) {
                     throw new IllegalArgumentException("Unable to find task ID " + mTaskId);
                 }
@@ -20621,7 +20620,7 @@
             synchronized (ActivityManagerService.this) {
                 long origId = Binder.clearCallingIdentity();
                 try {
-                    TaskRecord tr = mRecentTasks.taskForIdLocked(mTaskId);
+                    TaskRecord tr = mStackSupervisor.anyTaskForIdLocked(mTaskId);
                     if (tr == null) {
                         throw new IllegalArgumentException("Unable to find task ID " + mTaskId);
                     }
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 71fd49b..7c79661 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -1509,9 +1509,13 @@
                     intent.addCategory(Intent.CATEGORY_VOICE);
                     if (!AppGlobals.getPackageManager().activitySupportsIntent(
                             intent.getComponent(), intent, resolvedType)) {
+                        Slog.w(TAG,
+                                "Activity being started in current voice task does not support voice: "
+                                + intent);
                         err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
                     }
                 } catch (RemoteException e) {
+                    Slog.w(TAG, "Failure checking voice capabilities", e);
                     err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
                 }
             }
@@ -1523,9 +1527,13 @@
             try {
                 if (!AppGlobals.getPackageManager().activitySupportsIntent(intent.getComponent(),
                         intent, resolvedType)) {
+                    Slog.w(TAG,
+                            "Activity being started in new voice task does not support: "
+                            + intent);
                     err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
                 }
             } catch (RemoteException e) {
+                Slog.w(TAG, "Failure checking voice capabilities", e);
                 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
             }
         }
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 7e2ad29..9da30bf 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -786,7 +786,8 @@
     }
 
     boolean isLockTaskWhitelistedLocked() {
-        if (mCallingPackage == null) {
+        String pkg = (realActivity != null) ? realActivity.getPackageName() : null;
+        if (pkg == null) {
             return false;
         }
         String[] packages = mService.mLockTaskPackages.get(userId);
@@ -794,7 +795,7 @@
             return false;
         }
         for (int i = packages.length - 1; i >= 0; --i) {
-            if (mCallingPackage.equals(packages[i])) {
+            if (pkg.equals(packages[i])) {
                 return true;
             }
         }
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index a0ededf..7565e9d 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -5150,7 +5150,9 @@
                 continue;
             }
             try {
-                ActivityManagerNative.getDefault().killUid(pkg.applicationInfo.uid,
+                final int uid = pkg.applicationInfo.uid;
+                ActivityManagerNative.getDefault().killUid(UserHandle.getAppId(uid),
+                        UserHandle.getUserId(uid),
                         "killBackgroundUserProcessesWithAudioRecordPermission");
             } catch (RemoteException e) {
                 Log.w(TAG, "Error calling killUid", e);
diff --git a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
index 3227ef8..71a2d59 100644
--- a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
@@ -34,6 +34,7 @@
 import android.provider.ContactsContract;
 import android.provider.MediaStore;
 import android.provider.Telephony.Sms.Intents;
+import android.security.Credentials;
 import android.util.ArraySet;
 import android.util.Log;
 
@@ -298,6 +299,15 @@
                 grantRuntimePermissionsLPw(storagePackage, STORAGE_PERMISSIONS, userId);
             }
 
+            // CertInstaller
+            Intent certInstallerIntent = new Intent(Credentials.INSTALL_ACTION);
+            PackageParser.Package certInstallerPackage = getDefaultSystemHandlerActivityPackageLPr(
+                    certInstallerIntent, userId);
+            if (certInstallerPackage != null
+                    && doesPackageSupportRuntimePermissions(certInstallerPackage)) {
+                grantRuntimePermissionsLPw(certInstallerPackage, STORAGE_PERMISSIONS, true, userId);
+            }
+
             // Dialer
             if (dialerAppPackageNames == null) {
                 Intent dialerIntent = new Intent(Intent.ACTION_DIAL);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 11e30b5..ce40c28 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -3469,10 +3469,11 @@
                 }
 
                 case PermissionsState.PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED: {
+                    final int appId = UserHandle.getAppId(pkg.applicationInfo.uid);
                     mHandler.post(new Runnable() {
                         @Override
                         public void run() {
-                            killSettingPackagesForUser(sb, userId, KILL_APP_REASON_GIDS_CHANGED);
+                            killUid(appId, userId, KILL_APP_REASON_GIDS_CHANGED);
                         }
                     });
                 } break;
@@ -3516,7 +3517,7 @@
         enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false,
                 "revokeRuntimePermission");
 
-        final SettingBase sb;
+        final int appId;
 
         synchronized (mPackages) {
             final PackageParser.Package pkg = mPackages.get(packageName);
@@ -3531,7 +3532,7 @@
 
             enforceDeclaredAsUsedAndRuntimePermission(pkg, bp);
 
-            sb = (SettingBase) pkg.mExtras;
+            SettingBase sb = (SettingBase) pkg.mExtras;
             if (sb == null) {
                 throw new IllegalArgumentException("Unknown package: " + packageName);
             }
@@ -3553,9 +3554,11 @@
 
             // Critical, after this call app should never have the permission.
             mSettings.writeRuntimePermissionsForUserLPr(userId, true);
+
+            appId = UserHandle.getAppId(pkg.applicationInfo.uid);
         }
 
-        killSettingPackagesForUser(sb, userId, KILL_APP_REASON_PERMISSIONS_REVOKED);
+        killUid(appId, userId, KILL_APP_REASON_PERMISSIONS_REVOKED);
     }
 
     @Override
@@ -3859,28 +3862,15 @@
         }
     }
 
-    private void killSettingPackagesForUser(SettingBase sb, int userId, String reason) {
+    private void killUid(int appId, int userId, String reason) {
         final long identity = Binder.clearCallingIdentity();
         try {
-            if (sb instanceof SharedUserSetting) {
-                SharedUserSetting sus = (SharedUserSetting) sb;
-                final int packageCount = sus.packages.size();
-                for (int i = 0; i < packageCount; i++) {
-                    PackageSetting susPs = sus.packages.valueAt(i);
-                    if (userId == UserHandle.USER_ALL) {
-                        killApplication(susPs.pkg.packageName, susPs.appId, reason);
-                    } else {
-                        final int uid = UserHandle.getUid(userId, susPs.appId);
-                        killUid(uid, reason);
-                    }
-                }
-            } else if (sb instanceof PackageSetting) {
-                PackageSetting ps = (PackageSetting) sb;
-                if (userId == UserHandle.USER_ALL) {
-                    killApplication(ps.pkg.packageName, ps.appId, reason);
-                } else {
-                    final int uid = UserHandle.getUid(userId, ps.appId);
-                    killUid(uid, reason);
+            IActivityManager am = ActivityManagerNative.getDefault();
+            if (am != null) {
+                try {
+                    am.killUid(appId, userId, reason);
+                } catch (RemoteException e) {
+                    /* ignore - same process */
                 }
             }
         } finally {
@@ -3888,17 +3878,6 @@
         }
     }
 
-    private static void killUid(int uid, String reason) {
-        IActivityManager am = ActivityManagerNative.getDefault();
-        if (am != null) {
-            try {
-                am.killUid(uid, reason);
-            } catch (RemoteException e) {
-                /* ignore - same process */
-            }
-        }
-    }
-
     /**
      * Compares two sets of signatures. Returns:
      * <br />
@@ -12821,7 +12800,7 @@
                                     @Override
                                     public void run() {
                                         // This has to happen with no lock held.
-                                        killSettingPackagesForUser(deletedPs, userIdToKill,
+                                        killApplication(deletedPs.name, deletedPs.appId,
                                                 KILL_APP_REASON_GIDS_CHANGED);
                                     }
                                 });
@@ -12942,6 +12921,10 @@
         synchronized (mPackages) {
             PackageSetting ps = mSettings.mPackages.get(newPkg.packageName);
 
+            // Propagate the permissions state as we do not want to drop on the floor
+            // runtime permissions. The update permissions method below will take
+            // care of removing obsolete permissions and grant install permissions.
+            ps.getPermissionsState().copyFrom(newPs.getPermissionsState());
             updatePermissionsLPw(newPkg.packageName, newPkg,
                     UPDATE_PERMISSIONS_ALL | UPDATE_PERMISSIONS_REPLACE_PKG);
 
@@ -13403,13 +13386,11 @@
 
                     case PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED: {
                         writeRuntimePermissions = true;
-                        // If gids changed for this user, kill all affected packages.
+                        final int appId = ps.appId;
                         mHandler.post(new Runnable() {
                             @Override
                             public void run() {
-                                // This has to happen with no lock held.
-                                killSettingPackagesForUser(ps, userId,
-                                        KILL_APP_REASON_GIDS_CHANGED);
+                                killUid(appId, userId, KILL_APP_REASON_GIDS_CHANGED);
                             }
                         });
                     } break;
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 6707562..264170c 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -135,6 +135,11 @@
     // without first making sure that the rest of the framework is prepared for it.
     private static final int MAX_MANAGED_PROFILES = 1;
 
+    /**
+     * Flag indicating whether device credentials are shared among same-user profiles.
+     */
+    private static final boolean CONFIG_PROFILES_SHARE_CREDENTIAL = true;
+
     // Set of user restrictions, which can only be enforced by the system
     private static final Set<String> SYSTEM_CONTROLLED_RESTRICTIONS = Sets.newArraySet(
             UserManager.DISALLOW_RECORD_AUDIO);
@@ -241,7 +246,7 @@
                 }
                 for (int i = 0; i < partials.size(); i++) {
                     UserInfo ui = partials.get(i);
-                    Slog.w(LOG_TAG, "Removing partially created user #" + i
+                    Slog.w(LOG_TAG, "Removing partially created user " + ui.id
                             + " (name=" + ui.name + ")");
                     removeUserStateLocked(ui.id);
                 }
@@ -317,6 +322,21 @@
     }
 
     @Override
+    public int getCredentialOwnerProfile(int userHandle) {
+        checkManageUsersPermission("get the credential owner");
+        if (CONFIG_PROFILES_SHARE_CREDENTIAL) {
+            synchronized (mPackagesLock) {
+                UserInfo profileParent = getProfileParentLocked(userHandle);
+                if (profileParent != null) {
+                    return profileParent.id;
+                }
+            }
+        }
+
+        return userHandle;
+    }
+
+    @Override
     public UserInfo getProfileParent(int userHandle) {
         checkManageUsersPermission("get the profile parent");
         synchronized (mPackagesLock) {
@@ -943,7 +963,7 @@
         }
     }
 
-    private void writeRestrictionsLocked(XmlSerializer serializer, Bundle restrictions) 
+    private void writeRestrictionsLocked(XmlSerializer serializer, Bundle restrictions)
             throws IOException {
         serializer.startTag(null, TAG_RESTRICTIONS);
         writeBoolean(serializer, restrictions, UserManager.DISALLOW_CONFIG_WIFI);
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
index 04d6d98..1788e88 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
@@ -48,6 +48,7 @@
 import com.android.internal.app.IAssistScreenshotReceiver;
 import com.android.internal.app.IVoiceInteractionSessionShowCallback;
 import com.android.internal.app.IVoiceInteractor;
+import com.android.internal.logging.MetricsLogger;
 import com.android.internal.os.IResultReceiver;
 import com.android.server.LocalServices;
 import com.android.server.statusbar.StatusBarManagerInternal;
@@ -225,6 +226,7 @@
                         mSessionComponentName.getPackageName()) == AppOpsManager.MODE_ALLOWED
                         && structureEnabled) {
                     try {
+                        MetricsLogger.count(mContext, "assist_with_context", 1);
                         if (mAm.requestAssistContextExtras(ActivityManager.ASSIST_CONTEXT_FULL,
                                 mAssistReceiver, activityToken)) {
                             needDisclosure = true;
@@ -249,6 +251,7 @@
                         mSessionComponentName.getPackageName()) == AppOpsManager.MODE_ALLOWED
                         && screenshotEnabled) {
                     try {
+                        MetricsLogger.count(mContext, "assist_with_screen", 1);
                         needDisclosure = true;
                         mIWindowManager.requestAssistScreenshot(mScreenshotReceiver);
                     } catch (RemoteException e) {
diff --git a/tools/layoutlib/.idea/inspectionProfiles/Project_Default.xml b/tools/layoutlib/.idea/inspectionProfiles/Project_Default.xml
index 0ac7a44..5bb3e3e 100644
--- a/tools/layoutlib/.idea/inspectionProfiles/Project_Default.xml
+++ b/tools/layoutlib/.idea/inspectionProfiles/Project_Default.xml
@@ -1,3 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
 <component name="InspectionProjectProfileManager">
   <profile version="1.0" is_locked="false">
     <option name="myName" value="Project Default" />
@@ -7,5 +8,6 @@
       <option name="CHECK_TRY_CATCH_SECTION" value="true" />
       <option name="CHECK_METHOD_BODY" value="true" />
     </inspection_tool>
+    <inspection_tool class="ToArrayCallWithZeroLengthArrayArgument" enabled="false" level="WARNING" enabled_by_default="false" />
   </profile>
 </component>
\ No newline at end of file
diff --git a/tools/layoutlib/bridge/src/android/widget/SimpleMonthView_Delegate.java b/tools/layoutlib/bridge/src/android/widget/SimpleMonthView_Delegate.java
new file mode 100644
index 0000000..8e41e51
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/widget/SimpleMonthView_Delegate.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.widget;
+
+import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.icu.text.SimpleDateFormat;
+import android.text.format.DateFormat;
+
+import java.util.Calendar;
+import java.util.Locale;
+
+/**
+ * Delegate that provides implementation for some methods in {@link SimpleMonthView}.
+ * <p/>
+ * Through the layoutlib_create tool, selected methods of SimpleMonthView have been replaced by
+ * calls to methods of the same name in this delegate class.
+ * <p/>
+ * The main purpose of this class is to use {@link android.icu.text.SimpleDateFormat} instead of
+ * {@link java.text.SimpleDateFormat}.
+ */
+public class SimpleMonthView_Delegate {
+
+    private static final String DEFAULT_TITLE_FORMAT = "MMMMy";
+    private static final String DAY_OF_WEEK_FORMAT = "EEEEE";
+
+    // Maintain a cache of the last view used, so that the formatters can be reused.
+    @Nullable private static SimpleMonthView sLastView;
+    @Nullable private static SimpleMonthView_Delegate sLastDelegate;
+
+    private SimpleDateFormat mTitleFormatter;
+    private SimpleDateFormat mDayOfWeekFormatter;
+
+    private Locale locale;
+
+    @LayoutlibDelegate
+    /*package*/ static CharSequence getTitle(SimpleMonthView view) {
+        if (view.mTitle == null) {
+            SimpleMonthView_Delegate delegate = getDelegate(view);
+            if (delegate.mTitleFormatter == null) {
+                delegate.mTitleFormatter = new SimpleDateFormat(DateFormat.getBestDateTimePattern(
+                        getLocale(delegate, view), DEFAULT_TITLE_FORMAT));
+            }
+            view.mTitle = delegate.mTitleFormatter.format(view.mCalendar.getTime());
+        }
+        return view.mTitle;
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static String getDayOfWeekLabel(SimpleMonthView view, int dayOfWeek) {
+        view.mDayOfWeekLabelCalendar.set(Calendar.DAY_OF_WEEK, dayOfWeek);
+        SimpleMonthView_Delegate delegate = getDelegate(view);
+        if (delegate.mDayOfWeekFormatter == null) {
+            delegate.mDayOfWeekFormatter =
+                    new SimpleDateFormat(DAY_OF_WEEK_FORMAT, getLocale(delegate, view));
+        }
+        return delegate.mDayOfWeekFormatter.format(view.mDayOfWeekLabelCalendar.getTime());
+    }
+
+    private static Locale getLocale(SimpleMonthView_Delegate delegate, SimpleMonthView view) {
+        if (delegate.locale == null) {
+            delegate.locale = view.getContext().getResources().getConfiguration().locale;
+        }
+        return delegate.locale;
+    }
+
+    @NonNull
+    private static SimpleMonthView_Delegate getDelegate(SimpleMonthView view) {
+        if (view == sLastView) {
+            assert sLastDelegate != null;
+            return sLastDelegate;
+        } else {
+            sLastView = view;
+            sLastDelegate = new SimpleMonthView_Delegate();
+            return sLastDelegate;
+        }
+    }
+
+    public static void clearCache() {
+        sLastView = null;
+        sLastDelegate = null;
+    }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/AndroidLocale.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/AndroidLocale.java
index e589d9e..faaf105 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/AndroidLocale.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/AndroidLocale.java
@@ -16,6 +16,8 @@
 
 package com.android.layoutlib.bridge.android;
 
+import com.android.layoutlib.bridge.impl.RenderAction;
+
 import android.icu.util.ULocale;
 
 import java.util.Locale;
@@ -56,4 +58,15 @@
     public static String getScript(Locale locale) {
         return ULocale.forLocale(locale).getScript();
     }
+
+    public static Locale getDefault() {
+        BridgeContext context = RenderAction.getCurrentContext();
+        if (context != null) {
+            Locale locale = context.getConfiguration().locale;
+            if (locale != null) {
+                return locale;
+            }
+        }
+        return Locale.getDefault();
+    }
 }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java
index 9380ca7..92b39e3 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java
@@ -36,7 +36,9 @@
 import android.view.ViewConfiguration_Accessor;
 import android.view.inputmethod.InputMethodManager;
 import android.view.inputmethod.InputMethodManager_Accessor;
+import android.widget.SimpleMonthView_Delegate;
 
+import java.util.Locale;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.locks.ReentrantLock;
 
@@ -276,6 +278,7 @@
             mContext.getRenderResources().setLogger(null);
         }
         ParserFactory.setParserFactory(null);
+        SimpleMonthView_Delegate.clearCache();
     }
 
     public static BridgeContext getCurrentContext() {
@@ -397,6 +400,8 @@
             // preview releases of API 15.
             // TODO: Remove the try catch around Oct 2015.
         }
+        String locale = getParams().getLocale();
+        if (locale != null && !locale.isEmpty()) config.locale = new Locale(locale);
 
         // TODO: fill in more config info.
 
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmGenerator.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmGenerator.java
index f6c2626..8f0ad01 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmGenerator.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmGenerator.java
@@ -77,6 +77,8 @@
     /** Methods to inject. FQCN of class in which method should be injected => runnable that does
      * the injection. */
     private final Map<String, ICreateInfo.InjectMethodRunnable> mInjectedMethodsMap;
+    /** A map { FQCN => set { field names } } which should be promoted to public visibility */
+    private final Map<String, Set<String>> mPromotedFields;
 
     /**
      * Creates a new generator that can generate the output JAR with the stubbed classes.
@@ -109,20 +111,8 @@
 
         // Create the map/set of methods to change to delegates
         mDelegateMethods = new HashMap<String, Set<String>>();
-        for (String signature : createInfo.getDelegateMethods()) {
-            int pos = signature.indexOf('#');
-            if (pos <= 0 || pos >= signature.length() - 1) {
-                continue;
-            }
-            String className = binaryToInternalClassName(signature.substring(0, pos));
-            String methodName = signature.substring(pos + 1);
-            Set<String> methods = mDelegateMethods.get(className);
-            if (methods == null) {
-                methods = new HashSet<String>();
-                mDelegateMethods.put(className, methods);
-            }
-            methods.add(methodName);
-        }
+        addToMap(createInfo.getDelegateMethods(), mDelegateMethods);
+
         for (String className : createInfo.getDelegateClassNatives()) {
             className = binaryToInternalClassName(className);
             Set<String> methods = mDelegateMethods.get(className);
@@ -187,10 +177,34 @@
             returnTypes.add(binaryToInternalClassName(className));
         }
 
+        mPromotedFields = new HashMap<String, Set<String>>();
+        addToMap(createInfo.getPromotedFields(), mPromotedFields);
+
         mInjectedMethodsMap = createInfo.getInjectedMethodsMap();
     }
 
     /**
+     * For each value in the array, split the value on '#' and add the parts to the map as key
+     * and value.
+     */
+    private void addToMap(String[] entries, Map<String, Set<String>> map) {
+        for (String entry : entries) {
+            int pos = entry.indexOf('#');
+            if (pos <= 0 || pos >= entry.length() - 1) {
+                return;
+            }
+            String className = binaryToInternalClassName(entry.substring(0, pos));
+            String methodOrFieldName = entry.substring(pos + 1);
+            Set<String> set = map.get(className);
+            if (set == null) {
+                set = new HashSet<String>();
+                map.put(className, set);
+            }
+            set.add(methodOrFieldName);
+        }
+    }
+
+    /**
      * Returns the list of classes that have not been renamed yet.
      * <p/>
      * The names are "internal class names" rather than FQCN, i.e. they use "/" instead "."
@@ -380,6 +394,10 @@
             }
         }
 
+        Set<String> promoteFields = mPromotedFields.get(className);
+        if (promoteFields != null && !promoteFields.isEmpty()) {
+            cv = new PromoteFieldClassAdapter(cv, promoteFields);
+        }
         cr.accept(cv, 0);
         return cw.toByteArray();
     }
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
index 499bea4..484240f 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
@@ -120,6 +120,11 @@
     }
 
     @Override
+    public String[] getPromotedFields() {
+        return PROMOTED_FIELDS;
+    }
+
+    @Override
     public Map<String, InjectMethodRunnable> getInjectedMethodsMap() {
         return INJECTED_METHODS;
     }
@@ -185,6 +190,8 @@
         "android.view.RenderNode#nSetElevation",
         "android.view.RenderNode#nGetElevation",
         "android.view.ViewGroup#drawChild",
+        "android.widget.SimpleMonthView#getTitle",
+        "android.widget.SimpleMonthView#getDayOfWeekLabel",
         "android.widget.TimePickerClockDelegate#getAmOrPmKeyCode",
         "com.android.internal.view.menu.MenuBuilder#createNewMenuItem",
         "com.android.internal.util.XmlUtils#convertValueToInt",
@@ -289,6 +296,12 @@
             "org.kxml2.io.KXmlParser"
         };
 
+    private final static String[] PROMOTED_FIELDS = new String[] {
+        "android.widget.SimpleMonthView#mTitle",
+        "android.widget.SimpleMonthView#mCalendar",
+        "android.widget.SimpleMonthView#mDayOfWeekLabelCalendar"
+    };
+
     /**
      * List of classes for which the methods returning them should be deleted.
      * The array contains a list of null terminated section starting with the name of the class
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/ICreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/ICreateInfo.java
index 54b1fe6..6c62423 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/ICreateInfo.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/ICreateInfo.java
@@ -78,6 +78,13 @@
     Set<String> getExcludedClasses();
 
     /**
+     * Returns a list of fields which should be promoted to public visibility. The array values
+     * are in the form of the binary FQCN of the class containing the field and the field name
+     * separated by a '#'.
+     */
+    String[] getPromotedFields();
+
+    /**
      * Returns a map from binary FQCN className to {@link InjectMethodRunnable} which will be
      * called to inject methods into a class.
      * Can be empty but must not be null.
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/PromoteFieldClassAdapter.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/PromoteFieldClassAdapter.java
new file mode 100644
index 0000000..e4b70da
--- /dev/null
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/PromoteFieldClassAdapter.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.layoutlib.create;
+
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.FieldVisitor;
+
+import java.util.Set;
+
+import static org.objectweb.asm.Opcodes.ACC_PRIVATE;
+import static org.objectweb.asm.Opcodes.ACC_PROTECTED;
+import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
+import static org.objectweb.asm.Opcodes.ASM4;
+
+/**
+ * Promotes given fields to public visibility.
+ */
+public class PromoteFieldClassAdapter extends ClassVisitor {
+
+    private final Set<String> mFieldNames;
+    private static final int ACC_NOT_PUBLIC = ~(ACC_PRIVATE | ACC_PROTECTED);
+
+    public PromoteFieldClassAdapter(ClassVisitor cv, Set<String> fieldNames) {
+        super(ASM4, cv);
+        mFieldNames = fieldNames;
+    }
+
+    @Override
+    public FieldVisitor visitField(int access, String name, String desc, String signature,
+            Object value) {
+        if (mFieldNames.contains(name)) {
+            if ((access & ACC_PUBLIC) == 0) {
+                access = (access & ACC_NOT_PUBLIC) | ACC_PUBLIC;
+            }
+        }
+        return super.visitField(access, name, desc, signature, value);
+    }
+}
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/ReplaceMethodCallsAdapter.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/ReplaceMethodCallsAdapter.java
index 4369148..0b85c48 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/ReplaceMethodCallsAdapter.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/ReplaceMethodCallsAdapter.java
@@ -93,18 +93,22 @@
             }
         });
 
-        // Case 3: java.util.Locale.adjustLanguageCode() or java.util.Locale.forLanguageTag()
+        // Case 3: java.util.Locale.adjustLanguageCode() or java.util.Locale.forLanguageTag() or
+        // java.util.Locale.getDefault()
         METHOD_REPLACERS.add(new MethodReplacer() {
 
             private final String STRING_TO_STRING = Type.getMethodDescriptor(STRING, STRING);
             private final String STRING_TO_LOCALE = Type.getMethodDescriptor(
                     Type.getType(Locale.class), STRING);
+            private final String VOID_TO_LOCALE =
+                    Type.getMethodDescriptor(Type.getType(Locale.class));
 
             @Override
             public boolean isNeeded(String owner, String name, String desc, String sourceClass) {
                 return JAVA_LOCALE_CLASS.equals(owner) &&
                         ("adjustLanguageCode".equals(name) && desc.equals(STRING_TO_STRING) ||
-                        "forLanguageTag".equals(name) && desc.equals(STRING_TO_LOCALE));
+                        "forLanguageTag".equals(name) && desc.equals(STRING_TO_LOCALE) ||
+                        "getDefault".equals(name) && desc.equals(VOID_TO_LOCALE));
             }
 
             @Override
diff --git a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/AsmGeneratorTest.java b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/AsmGeneratorTest.java
index 2c21470..8a2235b 100644
--- a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/AsmGeneratorTest.java
+++ b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/AsmGeneratorTest.java
@@ -138,6 +138,11 @@
             }
 
             @Override
+            public String[] getPromotedFields() {
+                return new String[0];
+            }
+
+            @Override
             public Map<String, InjectMethodRunnable> getInjectedMethodsMap() {
                 return new HashMap<String, InjectMethodRunnable>(0);
             }
@@ -213,6 +218,11 @@
             }
 
             @Override
+            public String[] getPromotedFields() {
+                return new String[0];
+            }
+
+            @Override
             public Map<String, InjectMethodRunnable> getInjectedMethodsMap() {
                 return new HashMap<String, InjectMethodRunnable>(0);
             }
@@ -296,6 +306,11 @@
             }
 
             @Override
+            public String[] getPromotedFields() {
+                return new String[0];
+            }
+
+            @Override
             public Map<String, InjectMethodRunnable> getInjectedMethodsMap() {
                 return new HashMap<String, InjectMethodRunnable>(0);
             }
@@ -374,6 +389,11 @@
             }
 
             @Override
+            public String[] getPromotedFields() {
+                return new String[0];
+            }
+
+            @Override
             public Map<String, InjectMethodRunnable> getInjectedMethodsMap() {
                 HashMap<String, InjectMethodRunnable> map =
                         new HashMap<String, InjectMethodRunnable>(1);