Merge "Deprecate Resources constructor and updateConfiguration() method" into nyc-mr1-dev
diff --git a/core/java/android/app/ITransientNotification.aidl b/core/java/android/app/ITransientNotification.aidl
index 35b53a4..d5b3ed0 100644
--- a/core/java/android/app/ITransientNotification.aidl
+++ b/core/java/android/app/ITransientNotification.aidl
@@ -19,7 +19,7 @@
 
 /** @hide */
 oneway interface ITransientNotification {
-    void show();
+    void show(IBinder windowToken);
     void hide();
 }
 
diff --git a/core/java/android/app/IWallpaperManager.aidl b/core/java/android/app/IWallpaperManager.aidl
index 9cd70e6..db7d54b 100644
--- a/core/java/android/app/IWallpaperManager.aidl
+++ b/core/java/android/app/IWallpaperManager.aidl
@@ -49,7 +49,7 @@
     /**
      * Set the live wallpaper. This only affects the system wallpaper.
      */
-    void setWallpaperComponentChecked(in ComponentName name, in String callingPackage);
+    void setWallpaperComponentChecked(in ComponentName name, in String callingPackage, int userId);
 
     /**
      * Set the live wallpaper. This only affects the system wallpaper.
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 2e37db2..b12ab75 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -3474,6 +3474,8 @@
                 mN.mSmallIcon = Icon.createWithResource(mContext, mN.icon);
             }
             contentView.setImageViewIcon(R.id.icon, mN.mSmallIcon);
+            contentView.setDrawableParameters(R.id.icon, false /* targetBackground */,
+                    -1 /* alpha */, -1 /* colorFilter */, null /* mode */, mN.iconLevel);
             processSmallIconColor(mN.mSmallIcon, contentView);
         }
 
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 53da4e3..4858557 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -1404,12 +1404,26 @@
      */
     @SystemApi
     public boolean setWallpaperComponent(ComponentName name) {
+        return setWallpaperComponent(name, UserHandle.myUserId());
+    }
+
+    /**
+     * Set the live wallpaper.
+     *
+     * This can only be called by packages with android.permission.SET_WALLPAPER_COMPONENT
+     * permission. The caller must hold the INTERACT_ACROSS_USERS_FULL permission to change
+     * another user's wallpaper.
+     *
+     * @hide
+     */
+    public boolean setWallpaperComponent(ComponentName name, int userId) {
         if (sGlobals.mService == null) {
             Log.w(TAG, "WallpaperService not running");
             throw new RuntimeException(new DeadSystemException());
         }
         try {
-            sGlobals.mService.setWallpaperComponentChecked(name, mContext.getOpPackageName());
+            sGlobals.mService.setWallpaperComponentChecked(name, mContext.getOpPackageName(),
+                    userId);
             return true;
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
diff --git a/core/java/android/app/job/JobInfo.java b/core/java/android/app/job/JobInfo.java
index 5823abf..734bf69 100644
--- a/core/java/android/app/job/JobInfo.java
+++ b/core/java/android/app/job/JobInfo.java
@@ -165,6 +165,9 @@
      * network restrictions for the requesting app. Note that this flag alone
      * doesn't actually place your {@link JobService} in the foreground; you
      * still need to post the notification yourself.
+     * <p>
+     * To use this flag, the caller must hold the
+     * {@link android.Manifest.permission#CONNECTIVITY_INTERNAL} permission.
      *
      * @hide
      */
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index c140f1bd5..4d9db98 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -2219,6 +2219,22 @@
         "android.intent.action.EXTERNAL_APPLICATIONS_UNAVAILABLE";
 
     /**
+     * Broadcast Action: preferred activities have changed *explicitly*.
+     *
+     * <p>Note there are cases where a preferred activity is invalidated *implicitly*, e.g.
+     * when an app is installed or uninstalled, but in such cases this broadcast will *not*
+     * be sent.
+     *
+     * {@link #EXTRA_USER_HANDLE} contains the user ID in question.
+     *
+     * @hide
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_PREFERRED_ACTIVITY_CHANGED =
+            "android.intent.action.ACTION_PREFERRED_ACTIVITY_CHANGED";
+
+
+    /**
      * Broadcast Action:  The current system wallpaper has changed.  See
      * {@link android.app.WallpaperManager} for retrieving the new wallpaper.
      * This should <em>only</em> be used to determine when the wallpaper
diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java
index 8ea77d6..f66e1f4 100644
--- a/core/java/android/content/pm/ShortcutInfo.java
+++ b/core/java/android/content/pm/ShortcutInfo.java
@@ -652,7 +652,7 @@
     /** @hide */
     public static IllegalArgumentException getInvalidIconException() {
         return new IllegalArgumentException("Unsupported icon type:"
-                +" only bitmap, resource and content URI are supported");
+                +" only the bitmap and resource types are supported");
     }
 
     /**
diff --git a/core/java/android/content/pm/ShortcutServiceInternal.java b/core/java/android/content/pm/ShortcutServiceInternal.java
index 3f8bad1..f994d7e 100644
--- a/core/java/android/content/pm/ShortcutServiceInternal.java
+++ b/core/java/android/content/pm/ShortcutServiceInternal.java
@@ -67,10 +67,4 @@
 
     public abstract boolean hasShortcutHostPermission(int launcherUserId,
             @NonNull String callingPackage);
-
-    /**
-     * Called by AM when the system locale changes *within the AM lock*.  ABSOLUTELY do not take
-     * any locks in this method.
-     */
-    public abstract void onSystemLocaleChangedNoLock();
 }
diff --git a/core/java/android/hardware/location/ContextHubService.java b/core/java/android/hardware/location/ContextHubService.java
index fcbc962..062c958 100644
--- a/core/java/android/hardware/location/ContextHubService.java
+++ b/core/java/android/hardware/location/ContextHubService.java
@@ -166,9 +166,12 @@
         msgHeader[HEADER_FIELD_LOAD_APP_ID_LO] = (int)(appId & 0xFFFFFFFF);
         msgHeader[HEADER_FIELD_LOAD_APP_ID_HI] = (int)((appId >> 32) & 0xFFFFFFFF);
 
-        if (nativeSendMessage(msgHeader, app.getAppBinary()) != 0) {
+        int errVal = nativeSendMessage(msgHeader, app.getAppBinary());
+        if (errVal != 0) {
+            Log.e(TAG, "Send Message returns error" + contextHubHandle);
             return -1;
         }
+
         // Do not add an entry to mNanoAppInstance Hash yet. The HAL may reject the app
         return 0;
     }
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 5c2778d..3eb2ac3 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -5295,15 +5295,6 @@
                 "accessibility_display_daltonizer";
 
         /**
-         * Float list that specifies the color matrix to apply to
-         * the display. Valid values are defined in AccessibilityManager.
-         *
-         * @hide
-         */
-        public static final String ACCESSIBILITY_DISPLAY_COLOR_MATRIX =
-                "accessibility_display_color_matrix";
-
-        /**
          * Setting that specifies whether automatic click when the mouse pointer stops moving is
          * enabled.
          *
@@ -6334,7 +6325,6 @@
             USB_MASS_STORAGE_ENABLED,                           // moved to global
             ACCESSIBILITY_DISPLAY_INVERSION_ENABLED,
             ACCESSIBILITY_DISPLAY_DALTONIZER,
-            ACCESSIBILITY_DISPLAY_COLOR_MATRIX,
             ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED,
             ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED,
             ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE,
@@ -6390,7 +6380,11 @@
             PREFERRED_TTY_MODE,
             ENHANCED_VOICE_PRIVACY_ENABLED,
             TTY_MODE_ENABLED,
-            INCALL_POWER_BUTTON_BEHAVIOR
+            INCALL_POWER_BUTTON_BEHAVIOR,
+            NIGHT_DISPLAY_CUSTOM_START_TIME,
+            NIGHT_DISPLAY_CUSTOM_END_TIME,
+            NIGHT_DISPLAY_AUTO_MODE,
+            NIGHT_DISPLAY_ACTIVATED
         };
 
         /**
diff --git a/core/java/android/service/quicksettings/IQSService.aidl b/core/java/android/service/quicksettings/IQSService.aidl
index bf96357..d03ff93 100644
--- a/core/java/android/service/quicksettings/IQSService.aidl
+++ b/core/java/android/service/quicksettings/IQSService.aidl
@@ -23,16 +23,16 @@
  * @hide
  */
 interface IQSService {
-    Tile getTile(in ComponentName component);
-    void updateQsTile(in Tile tile);
-    void updateStatusIcon(in Tile tile, in Icon icon,
+    Tile getTile(in IBinder tile);
+    void updateQsTile(in Tile tile, in IBinder service);
+    void updateStatusIcon(in IBinder tile, in Icon icon,
             String contentDescription);
-    void onShowDialog(in Tile tile);
-    void onStartActivity(in Tile tile);
+    void onShowDialog(in IBinder tile);
+    void onStartActivity(in IBinder tile);
     boolean isLocked();
     boolean isSecure();
-    void startUnlockAndRun(in Tile tile);
+    void startUnlockAndRun(in IBinder tile);
 
-    void onDialogHidden(in Tile tile);
-    void onStartSuccessful(in Tile tile);
+    void onDialogHidden(in IBinder tile);
+    void onStartSuccessful(in IBinder tile);
 }
diff --git a/core/java/android/service/quicksettings/Tile.java b/core/java/android/service/quicksettings/Tile.java
index 3d7d53e..4b81a72 100644
--- a/core/java/android/service/quicksettings/Tile.java
+++ b/core/java/android/service/quicksettings/Tile.java
@@ -15,8 +15,8 @@
  */
 package android.service.quicksettings;
 
-import android.content.ComponentName;
 import android.graphics.drawable.Icon;
+import android.os.IBinder;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.RemoteException;
@@ -59,7 +59,7 @@
      */
     public static final int STATE_ACTIVE = 2;
 
-    private ComponentName mComponentName;
+    private IBinder mToken;
     private Icon mIcon;
     private CharSequence mLabel;
     private CharSequence mContentDescription;
@@ -78,29 +78,15 @@
     /**
      * @hide
      */
-    public Tile(ComponentName componentName) {
-        mComponentName = componentName;
+    public Tile() {
     }
 
     /**
      * @hide
      */
-    public void setService(IQSService service) {
+    public void setService(IQSService service, IBinder stub) {
         mService = service;
-    }
-
-    /**
-     * @hide
-     */
-    public ComponentName getComponentName() {
-        return mComponentName;
-    }
-
-    /**
-     * @hide
-     */
-    public IQSService getQsService() {
-        return mService;
+        mToken = stub;
     }
 
     /**
@@ -193,7 +179,7 @@
      */
     public void updateTile() {
         try {
-            mService.updateQsTile(this);
+            mService.updateQsTile(this, mToken);
         } catch (RemoteException e) {
             Log.e(TAG, "Couldn't update tile");
         }
@@ -201,12 +187,6 @@
 
     @Override
     public void writeToParcel(Parcel dest, int flags) {
-        if (mComponentName != null) {
-            dest.writeByte((byte) 1);
-            mComponentName.writeToParcel(dest, flags);
-        } else {
-            dest.writeByte((byte) 0);
-        }
         if (mIcon != null) {
             dest.writeByte((byte) 1);
             mIcon.writeToParcel(dest, flags);
@@ -220,11 +200,6 @@
 
     private void readFromParcel(Parcel source) {
         if (source.readByte() != 0) {
-            mComponentName = ComponentName.CREATOR.createFromParcel(source);
-        } else {
-            mComponentName = null;
-        }
-        if (source.readByte() != 0) {
             mIcon = Icon.CREATOR.createFromParcel(source);
         } else {
             mIcon = null;
diff --git a/core/java/android/service/quicksettings/TileService.java b/core/java/android/service/quicksettings/TileService.java
index 50411ab..887f4b6 100644
--- a/core/java/android/service/quicksettings/TileService.java
+++ b/core/java/android/service/quicksettings/TileService.java
@@ -123,6 +123,11 @@
     /**
      * @hide
      */
+    public static final String EXTRA_TOKEN = "token";
+
+    /**
+     * @hide
+     */
     public static final String EXTRA_COMPONENT = "android.service.quicksettings.extra.COMPONENT";
 
     private final H mHandler = new H(Looper.getMainLooper());
@@ -132,6 +137,7 @@
     private IBinder mToken;
     private IQSService mService;
     private Runnable mUnlockRunnable;
+    private IBinder mTileToken;
 
     @Override
     public void onDestroy() {
@@ -197,7 +203,7 @@
     public final void setStatusIcon(Icon icon, String contentDescription) {
         if (mService != null) {
             try {
-                mService.updateStatusIcon(mTile, icon, contentDescription);
+                mService.updateStatusIcon(mTileToken, icon, contentDescription);
             } catch (RemoteException e) {
             }
         }
@@ -224,14 +230,14 @@
             @Override
             public void onViewDetachedFromWindow(View v) {
                 try {
-                    mService.onDialogHidden(getQsTile());
+                    mService.onDialogHidden(mTileToken);
                 } catch (RemoteException e) {
                 }
             }
         });
         dialog.show();
         try {
-            mService.onShowDialog(mTile);
+            mService.onShowDialog(mTileToken);
         } catch (RemoteException e) {
         }
     }
@@ -246,7 +252,7 @@
     public final void unlockAndRun(Runnable runnable) {
         mUnlockRunnable = runnable;
         try {
-            mService.startUnlockAndRun(mTile);
+            mService.startUnlockAndRun(mTileToken);
         } catch (RemoteException e) {
         }
     }
@@ -292,7 +298,7 @@
     public final void startActivityAndCollapse(Intent intent) {
         startActivity(intent);
         try {
-            mService.onStartActivity(mTile);
+            mService.onStartActivity(mTileToken);
         } catch (RemoteException e) {
         }
     }
@@ -311,14 +317,14 @@
     @Override
     public IBinder onBind(Intent intent) {
         mService = IQSService.Stub.asInterface(intent.getIBinderExtra(EXTRA_SERVICE));
+        mTileToken = intent.getIBinderExtra(EXTRA_TOKEN);
         try {
-            ComponentName component = intent.getParcelableExtra(EXTRA_COMPONENT);
-            mTile = mService.getTile(component);
+            mTile = mService.getTile(mTileToken);
         } catch (RemoteException e) {
             throw new RuntimeException("Unable to reach IQSService", e);
         }
         if (mTile != null) {
-            mTile.setService(mService);
+            mTile.setService(mService, mTileToken);
             mHandler.sendEmptyMessage(H.MSG_START_SUCCESS);
         }
         return new IQSTileService.Stub() {
@@ -403,7 +409,7 @@
                     break;
                 case MSG_START_SUCCESS:
                     try {
-                        mService.onStartSuccessful(mTile);
+                        mService.onStartSuccessful(mTileToken);
                     } catch (RemoteException e) {
                     }
                     break;
diff --git a/core/java/android/text/Emoji.java b/core/java/android/text/Emoji.java
index b62cc66..b6d720d 100644
--- a/core/java/android/text/Emoji.java
+++ b/core/java/android/text/Emoji.java
@@ -32,111 +32,112 @@
         0x23EC, 0x23ED, 0x23EE, 0x23EF, 0x23F0, 0x23F1, 0x23F2, 0x23F3, 0x23F8, 0x23F9, 0x23FA,
         0x24C2, 0x25AA, 0x25AB, 0x25B6, 0x25C0, 0x25FB, 0x25FC, 0x25FD, 0x25FE, 0x2600, 0x2601,
         0x2602, 0x2603, 0x2604, 0x260E, 0x2611, 0x2614, 0x2615, 0x2618, 0x261D, 0x2620, 0x2622,
-        0x2623, 0x2626, 0x262A, 0x262E, 0x262F, 0x2638, 0x2639, 0x263A, 0x2648, 0x2649, 0x264A,
-        0x264B, 0x264C, 0x264D, 0x264E, 0x264F, 0x2650, 0x2651, 0x2652, 0x2653, 0x2660, 0x2663,
-        0x2665, 0x2666, 0x2668, 0x267B, 0x267F, 0x2692, 0x2693, 0x2694, 0x2696, 0x2697, 0x2699,
-        0x269B, 0x269C, 0x26A0, 0x26A1, 0x26AA, 0x26AB, 0x26B0, 0x26B1, 0x26BD, 0x26BE, 0x26C4,
-        0x26C5, 0x26C8, 0x26CE, 0x26CF, 0x26D1, 0x26D3, 0x26D4, 0x26E9, 0x26EA, 0x26F0, 0x26F1,
-        0x26F2, 0x26F3, 0x26F4, 0x26F5, 0x26F7, 0x26F8, 0x26F9, 0x26FA, 0x26FD, 0x2702, 0x2705,
-        0x2708, 0x2709, 0x270A, 0x270B, 0x270C, 0x270D, 0x270F, 0x2712, 0x2714, 0x2716, 0x271D,
-        0x2721, 0x2728, 0x2733, 0x2734, 0x2744, 0x2747, 0x274C, 0x274E, 0x2753, 0x2754, 0x2755,
-        0x2757, 0x2763, 0x2764, 0x2795, 0x2796, 0x2797, 0x27A1, 0x27B0, 0x27BF, 0x2934, 0x2935,
-        0x2B05, 0x2B06, 0x2B07, 0x2B1B, 0x2B1C, 0x2B50, 0x2B55, 0x3030, 0x303D, 0x3297, 0x3299,
-        0x1F004, 0x1F0CF, 0x1F170, 0x1F171, 0x1F17E, 0x1F17F, 0x1F18E, 0x1F191, 0x1F192, 0x1F193,
-        0x1F194, 0x1F195, 0x1F196, 0x1F197, 0x1F198, 0x1F199, 0x1F19A, 0x1F1E6, 0x1F1E7, 0x1F1E8,
-        0x1F1E9, 0x1F1EA, 0x1F1EB, 0x1F1EC, 0x1F1ED, 0x1F1EE, 0x1F1EF, 0x1F1F0, 0x1F1F1, 0x1F1F2,
-        0x1F1F3, 0x1F1F4, 0x1F1F5, 0x1F1F6, 0x1F1F7, 0x1F1F8, 0x1F1F9, 0x1F1FA, 0x1F1FB, 0x1F1FC,
-        0x1F1FD, 0x1F1FE, 0x1F1FF, 0x1F201, 0x1F202, 0x1F21A, 0x1F22F, 0x1F232, 0x1F233, 0x1F234,
-        0x1F235, 0x1F236, 0x1F237, 0x1F238, 0x1F239, 0x1F23A, 0x1F250, 0x1F251, 0x1F300, 0x1F301,
-        0x1F302, 0x1F303, 0x1F304, 0x1F305, 0x1F306, 0x1F307, 0x1F308, 0x1F309, 0x1F30A, 0x1F30B,
-        0x1F30C, 0x1F30D, 0x1F30E, 0x1F30F, 0x1F310, 0x1F311, 0x1F312, 0x1F313, 0x1F314, 0x1F315,
-        0x1F316, 0x1F317, 0x1F318, 0x1F319, 0x1F31A, 0x1F31B, 0x1F31C, 0x1F31D, 0x1F31E, 0x1F31F,
-        0x1F320, 0x1F321, 0x1F324, 0x1F325, 0x1F326, 0x1F327, 0x1F328, 0x1F329, 0x1F32A, 0x1F32B,
-        0x1F32C, 0x1F32D, 0x1F32E, 0x1F32F, 0x1F330, 0x1F331, 0x1F332, 0x1F333, 0x1F334, 0x1F335,
-        0x1F336, 0x1F337, 0x1F338, 0x1F339, 0x1F33A, 0x1F33B, 0x1F33C, 0x1F33D, 0x1F33E, 0x1F33F,
-        0x1F340, 0x1F341, 0x1F342, 0x1F343, 0x1F344, 0x1F345, 0x1F346, 0x1F347, 0x1F348, 0x1F349,
-        0x1F34A, 0x1F34B, 0x1F34C, 0x1F34D, 0x1F34E, 0x1F34F, 0x1F350, 0x1F351, 0x1F352, 0x1F353,
-        0x1F354, 0x1F355, 0x1F356, 0x1F357, 0x1F358, 0x1F359, 0x1F35A, 0x1F35B, 0x1F35C, 0x1F35D,
-        0x1F35E, 0x1F35F, 0x1F360, 0x1F361, 0x1F362, 0x1F363, 0x1F364, 0x1F365, 0x1F366, 0x1F367,
-        0x1F368, 0x1F369, 0x1F36A, 0x1F36B, 0x1F36C, 0x1F36D, 0x1F36E, 0x1F36F, 0x1F370, 0x1F371,
-        0x1F372, 0x1F373, 0x1F374, 0x1F375, 0x1F376, 0x1F377, 0x1F378, 0x1F379, 0x1F37A, 0x1F37B,
-        0x1F37C, 0x1F37D, 0x1F37E, 0x1F37F, 0x1F380, 0x1F381, 0x1F382, 0x1F383, 0x1F384, 0x1F385,
-        0x1F386, 0x1F387, 0x1F388, 0x1F389, 0x1F38A, 0x1F38B, 0x1F38C, 0x1F38D, 0x1F38E, 0x1F38F,
-        0x1F390, 0x1F391, 0x1F392, 0x1F393, 0x1F396, 0x1F397, 0x1F399, 0x1F39A, 0x1F39B, 0x1F39E,
-        0x1F39F, 0x1F3A0, 0x1F3A1, 0x1F3A2, 0x1F3A3, 0x1F3A4, 0x1F3A5, 0x1F3A6, 0x1F3A7, 0x1F3A8,
-        0x1F3A9, 0x1F3AA, 0x1F3AB, 0x1F3AC, 0x1F3AD, 0x1F3AE, 0x1F3AF, 0x1F3B0, 0x1F3B1, 0x1F3B2,
-        0x1F3B3, 0x1F3B4, 0x1F3B5, 0x1F3B6, 0x1F3B7, 0x1F3B8, 0x1F3B9, 0x1F3BA, 0x1F3BB, 0x1F3BC,
-        0x1F3BD, 0x1F3BE, 0x1F3BF, 0x1F3C0, 0x1F3C1, 0x1F3C2, 0x1F3C3, 0x1F3C4, 0x1F3C5, 0x1F3C6,
-        0x1F3C7, 0x1F3C8, 0x1F3C9, 0x1F3CA, 0x1F3CB, 0x1F3CC, 0x1F3CD, 0x1F3CE, 0x1F3CF, 0x1F3D0,
-        0x1F3D1, 0x1F3D2, 0x1F3D3, 0x1F3D4, 0x1F3D5, 0x1F3D6, 0x1F3D7, 0x1F3D8, 0x1F3D9, 0x1F3DA,
-        0x1F3DB, 0x1F3DC, 0x1F3DD, 0x1F3DE, 0x1F3DF, 0x1F3E0, 0x1F3E1, 0x1F3E2, 0x1F3E3, 0x1F3E4,
-        0x1F3E5, 0x1F3E6, 0x1F3E7, 0x1F3E8, 0x1F3E9, 0x1F3EA, 0x1F3EB, 0x1F3EC, 0x1F3ED, 0x1F3EE,
-        0x1F3EF, 0x1F3F0, 0x1F3F3, 0x1F3F4, 0x1F3F5, 0x1F3F7, 0x1F3F8, 0x1F3F9, 0x1F3FA, 0x1F3FB,
-        0x1F3FC, 0x1F3FD, 0x1F3FE, 0x1F3FF, 0x1F400, 0x1F401, 0x1F402, 0x1F403, 0x1F404, 0x1F405,
-        0x1F406, 0x1F407, 0x1F408, 0x1F409, 0x1F40A, 0x1F40B, 0x1F40C, 0x1F40D, 0x1F40E, 0x1F40F,
-        0x1F410, 0x1F411, 0x1F412, 0x1F413, 0x1F414, 0x1F415, 0x1F416, 0x1F417, 0x1F418, 0x1F419,
-        0x1F41A, 0x1F41B, 0x1F41C, 0x1F41D, 0x1F41E, 0x1F41F, 0x1F420, 0x1F421, 0x1F422, 0x1F423,
-        0x1F424, 0x1F425, 0x1F426, 0x1F427, 0x1F428, 0x1F429, 0x1F42A, 0x1F42B, 0x1F42C, 0x1F42D,
-        0x1F42E, 0x1F42F, 0x1F430, 0x1F431, 0x1F432, 0x1F433, 0x1F434, 0x1F435, 0x1F436, 0x1F437,
-        0x1F438, 0x1F439, 0x1F43A, 0x1F43B, 0x1F43C, 0x1F43D, 0x1F43E, 0x1F43F, 0x1F440, 0x1F441,
-        0x1F442, 0x1F443, 0x1F444, 0x1F445, 0x1F446, 0x1F447, 0x1F448, 0x1F449, 0x1F44A, 0x1F44B,
-        0x1F44C, 0x1F44D, 0x1F44E, 0x1F44F, 0x1F450, 0x1F451, 0x1F452, 0x1F453, 0x1F454, 0x1F455,
-        0x1F456, 0x1F457, 0x1F458, 0x1F459, 0x1F45A, 0x1F45B, 0x1F45C, 0x1F45D, 0x1F45E, 0x1F45F,
-        0x1F460, 0x1F461, 0x1F462, 0x1F463, 0x1F464, 0x1F465, 0x1F466, 0x1F467, 0x1F468, 0x1F469,
-        0x1F46A, 0x1F46B, 0x1F46C, 0x1F46D, 0x1F46E, 0x1F46F, 0x1F470, 0x1F471, 0x1F472, 0x1F473,
-        0x1F474, 0x1F475, 0x1F476, 0x1F477, 0x1F478, 0x1F479, 0x1F47A, 0x1F47B, 0x1F47C, 0x1F47D,
-        0x1F47E, 0x1F47F, 0x1F480, 0x1F481, 0x1F482, 0x1F483, 0x1F484, 0x1F485, 0x1F486, 0x1F487,
-        0x1F488, 0x1F489, 0x1F48A, 0x1F48B, 0x1F48C, 0x1F48D, 0x1F48E, 0x1F48F, 0x1F490, 0x1F491,
-        0x1F492, 0x1F493, 0x1F494, 0x1F495, 0x1F496, 0x1F497, 0x1F498, 0x1F499, 0x1F49A, 0x1F49B,
-        0x1F49C, 0x1F49D, 0x1F49E, 0x1F49F, 0x1F4A0, 0x1F4A1, 0x1F4A2, 0x1F4A3, 0x1F4A4, 0x1F4A5,
-        0x1F4A6, 0x1F4A7, 0x1F4A8, 0x1F4A9, 0x1F4AA, 0x1F4AB, 0x1F4AC, 0x1F4AD, 0x1F4AE, 0x1F4AF,
-        0x1F4B0, 0x1F4B1, 0x1F4B2, 0x1F4B3, 0x1F4B4, 0x1F4B5, 0x1F4B6, 0x1F4B7, 0x1F4B8, 0x1F4B9,
-        0x1F4BA, 0x1F4BB, 0x1F4BC, 0x1F4BD, 0x1F4BE, 0x1F4BF, 0x1F4C0, 0x1F4C1, 0x1F4C2, 0x1F4C3,
-        0x1F4C4, 0x1F4C5, 0x1F4C6, 0x1F4C7, 0x1F4C8, 0x1F4C9, 0x1F4CA, 0x1F4CB, 0x1F4CC, 0x1F4CD,
-        0x1F4CE, 0x1F4CF, 0x1F4D0, 0x1F4D1, 0x1F4D2, 0x1F4D3, 0x1F4D4, 0x1F4D5, 0x1F4D6, 0x1F4D7,
-        0x1F4D8, 0x1F4D9, 0x1F4DA, 0x1F4DB, 0x1F4DC, 0x1F4DD, 0x1F4DE, 0x1F4DF, 0x1F4E0, 0x1F4E1,
-        0x1F4E2, 0x1F4E3, 0x1F4E4, 0x1F4E5, 0x1F4E6, 0x1F4E7, 0x1F4E8, 0x1F4E9, 0x1F4EA, 0x1F4EB,
-        0x1F4EC, 0x1F4ED, 0x1F4EE, 0x1F4EF, 0x1F4F0, 0x1F4F1, 0x1F4F2, 0x1F4F3, 0x1F4F4, 0x1F4F5,
-        0x1F4F6, 0x1F4F7, 0x1F4F8, 0x1F4F9, 0x1F4FA, 0x1F4FB, 0x1F4FC, 0x1F4FD, 0x1F4FF, 0x1F500,
-        0x1F501, 0x1F502, 0x1F503, 0x1F504, 0x1F505, 0x1F506, 0x1F507, 0x1F508, 0x1F509, 0x1F50A,
-        0x1F50B, 0x1F50C, 0x1F50D, 0x1F50E, 0x1F50F, 0x1F510, 0x1F511, 0x1F512, 0x1F513, 0x1F514,
-        0x1F515, 0x1F516, 0x1F517, 0x1F518, 0x1F519, 0x1F51A, 0x1F51B, 0x1F51C, 0x1F51D, 0x1F51E,
-        0x1F51F, 0x1F520, 0x1F521, 0x1F522, 0x1F523, 0x1F524, 0x1F525, 0x1F526, 0x1F527, 0x1F528,
-        0x1F529, 0x1F52A, 0x1F52B, 0x1F52C, 0x1F52D, 0x1F52E, 0x1F52F, 0x1F530, 0x1F531, 0x1F532,
-        0x1F533, 0x1F534, 0x1F535, 0x1F536, 0x1F537, 0x1F538, 0x1F539, 0x1F53A, 0x1F53B, 0x1F53C,
-        0x1F53D, 0x1F549, 0x1F54A, 0x1F54B, 0x1F54C, 0x1F54D, 0x1F54E, 0x1F550, 0x1F551, 0x1F552,
-        0x1F553, 0x1F554, 0x1F555, 0x1F556, 0x1F557, 0x1F558, 0x1F559, 0x1F55A, 0x1F55B, 0x1F55C,
-        0x1F55D, 0x1F55E, 0x1F55F, 0x1F560, 0x1F561, 0x1F562, 0x1F563, 0x1F564, 0x1F565, 0x1F566,
-        0x1F567, 0x1F56F, 0x1F570, 0x1F573, 0x1F574, 0x1F575, 0x1F576, 0x1F577, 0x1F578, 0x1F579,
-        0x1F57A, 0x1F587, 0x1F58A, 0x1F58B, 0x1F58C, 0x1F58D, 0x1F590, 0x1F595, 0x1F596, 0x1F5A4,
-        0x1F5A5, 0x1F5A8, 0x1F5B1, 0x1F5B2, 0x1F5BC, 0x1F5C2, 0x1F5C3, 0x1F5C4, 0x1F5D1, 0x1F5D2,
-        0x1F5D3, 0x1F5DC, 0x1F5DD, 0x1F5DE, 0x1F5E1, 0x1F5E3, 0x1F5E8, 0x1F5EF, 0x1F5F3, 0x1F5FA,
-        0x1F5FB, 0x1F5FC, 0x1F5FD, 0x1F5FE, 0x1F5FF, 0x1F600, 0x1F601, 0x1F602, 0x1F603, 0x1F604,
-        0x1F605, 0x1F606, 0x1F607, 0x1F608, 0x1F609, 0x1F60A, 0x1F60B, 0x1F60C, 0x1F60D, 0x1F60E,
-        0x1F60F, 0x1F610, 0x1F611, 0x1F612, 0x1F613, 0x1F614, 0x1F615, 0x1F616, 0x1F617, 0x1F618,
-        0x1F619, 0x1F61A, 0x1F61B, 0x1F61C, 0x1F61D, 0x1F61E, 0x1F61F, 0x1F620, 0x1F621, 0x1F622,
-        0x1F623, 0x1F624, 0x1F625, 0x1F626, 0x1F627, 0x1F628, 0x1F629, 0x1F62A, 0x1F62B, 0x1F62C,
-        0x1F62D, 0x1F62E, 0x1F62F, 0x1F630, 0x1F631, 0x1F632, 0x1F633, 0x1F634, 0x1F635, 0x1F636,
-        0x1F637, 0x1F638, 0x1F639, 0x1F63A, 0x1F63B, 0x1F63C, 0x1F63D, 0x1F63E, 0x1F63F, 0x1F640,
-        0x1F641, 0x1F642, 0x1F643, 0x1F644, 0x1F645, 0x1F646, 0x1F647, 0x1F648, 0x1F649, 0x1F64A,
-        0x1F64B, 0x1F64C, 0x1F64D, 0x1F64E, 0x1F64F, 0x1F680, 0x1F681, 0x1F682, 0x1F683, 0x1F684,
-        0x1F685, 0x1F686, 0x1F687, 0x1F688, 0x1F689, 0x1F68A, 0x1F68B, 0x1F68C, 0x1F68D, 0x1F68E,
-        0x1F68F, 0x1F690, 0x1F691, 0x1F692, 0x1F693, 0x1F694, 0x1F695, 0x1F696, 0x1F697, 0x1F698,
-        0x1F699, 0x1F69A, 0x1F69B, 0x1F69C, 0x1F69D, 0x1F69E, 0x1F69F, 0x1F6A0, 0x1F6A1, 0x1F6A2,
-        0x1F6A3, 0x1F6A4, 0x1F6A5, 0x1F6A6, 0x1F6A7, 0x1F6A8, 0x1F6A9, 0x1F6AA, 0x1F6AB, 0x1F6AC,
-        0x1F6AD, 0x1F6AE, 0x1F6AF, 0x1F6B0, 0x1F6B1, 0x1F6B2, 0x1F6B3, 0x1F6B4, 0x1F6B5, 0x1F6B6,
-        0x1F6B7, 0x1F6B8, 0x1F6B9, 0x1F6BA, 0x1F6BB, 0x1F6BC, 0x1F6BD, 0x1F6BE, 0x1F6BF, 0x1F6C0,
-        0x1F6C1, 0x1F6C2, 0x1F6C3, 0x1F6C4, 0x1F6C5, 0x1F6CB, 0x1F6CC, 0x1F6CD, 0x1F6CE, 0x1F6CF,
-        0x1F6D0, 0x1F6D1, 0x1F6D2, 0x1F6E0, 0x1F6E1, 0x1F6E2, 0x1F6E3, 0x1F6E4, 0x1F6E5, 0x1F6E9,
-        0x1F6EB, 0x1F6EC, 0x1F6F0, 0x1F6F3, 0x1F6F4, 0x1F6F5, 0x1F6F6, 0x1F910, 0x1F911, 0x1F912,
-        0x1F913, 0x1F914, 0x1F915, 0x1F916, 0x1F917, 0x1F918, 0x1F919, 0x1F91A, 0x1F91B, 0x1F91C,
-        0x1F91D, 0x1F91E, 0x1F920, 0x1F921, 0x1F922, 0x1F923, 0x1F924, 0x1F925, 0x1F926, 0x1F927,
-        0x1F930, 0x1F933, 0x1F934, 0x1F935, 0x1F936, 0x1F937, 0x1F938, 0x1F939, 0x1F93A, 0x1F93B,
-        0x1F93C, 0x1F93D, 0x1F93E, 0x1F940, 0x1F941, 0x1F942, 0x1F943, 0x1F944, 0x1F945, 0x1F946,
-        0x1F947, 0x1F948, 0x1F949, 0x1F94A, 0x1F94B, 0x1F950, 0x1F951, 0x1F952, 0x1F953, 0x1F954,
-        0x1F955, 0x1F956, 0x1F957, 0x1F958, 0x1F959, 0x1F95A, 0x1F95B, 0x1F95C, 0x1F95D, 0x1F95E,
-        0x1F980, 0x1F981, 0x1F982, 0x1F983, 0x1F984, 0x1F985, 0x1F986, 0x1F987, 0x1F988, 0x1F989,
-        0x1F98A, 0x1F98B, 0x1F98C, 0x1F98D, 0x1F98E, 0x1F98F, 0x1F990, 0x1F991, 0x1F9C0
+        0x2623, 0x2626, 0x262A, 0x262E, 0x262F, 0x2638, 0x2639, 0x263A, 0x2640, 0x2642, 0x2648,
+        0x2649, 0x264A, 0x264B, 0x264C, 0x264D, 0x264E, 0x264F, 0x2650, 0x2651, 0x2652, 0x2653,
+        0x2660, 0x2663, 0x2665, 0x2666, 0x2668, 0x267B, 0x267F, 0x2692, 0x2693, 0x2694, 0x2695,
+        0x2696, 0x2697, 0x2699, 0x269B, 0x269C, 0x26A0, 0x26A1, 0x26AA, 0x26AB, 0x26B0, 0x26B1,
+        0x26BD, 0x26BE, 0x26C4, 0x26C5, 0x26C8, 0x26CE, 0x26CF, 0x26D1, 0x26D3, 0x26D4, 0x26E9,
+        0x26EA, 0x26F0, 0x26F1, 0x26F2, 0x26F3, 0x26F4, 0x26F5, 0x26F7, 0x26F8, 0x26F9, 0x26FA,
+        0x26FD, 0x2702, 0x2705, 0x2708, 0x2709, 0x270A, 0x270B, 0x270C, 0x270D, 0x270F, 0x2712,
+        0x2714, 0x2716, 0x271D, 0x2721, 0x2728, 0x2733, 0x2734, 0x2744, 0x2747, 0x274C, 0x274E,
+        0x2753, 0x2754, 0x2755, 0x2757, 0x2763, 0x2764, 0x2795, 0x2796, 0x2797, 0x27A1, 0x27B0,
+        0x27BF, 0x2934, 0x2935, 0x2B05, 0x2B06, 0x2B07, 0x2B1B, 0x2B1C, 0x2B50, 0x2B55, 0x3030,
+        0x303D, 0x3297, 0x3299, 0x1F004, 0x1F0CF, 0x1F170, 0x1F171, 0x1F17E, 0x1F17F, 0x1F18E,
+        0x1F191, 0x1F192, 0x1F193, 0x1F194, 0x1F195, 0x1F196, 0x1F197, 0x1F198, 0x1F199, 0x1F19A,
+        0x1F1E6, 0x1F1E7, 0x1F1E8, 0x1F1E9, 0x1F1EA, 0x1F1EB, 0x1F1EC, 0x1F1ED, 0x1F1EE, 0x1F1EF,
+        0x1F1F0, 0x1F1F1, 0x1F1F2, 0x1F1F3, 0x1F1F4, 0x1F1F5, 0x1F1F6, 0x1F1F7, 0x1F1F8, 0x1F1F9,
+        0x1F1FA, 0x1F1FB, 0x1F1FC, 0x1F1FD, 0x1F1FE, 0x1F1FF, 0x1F201, 0x1F202, 0x1F21A, 0x1F22F,
+        0x1F232, 0x1F233, 0x1F234, 0x1F235, 0x1F236, 0x1F237, 0x1F238, 0x1F239, 0x1F23A, 0x1F250,
+        0x1F251, 0x1F300, 0x1F301, 0x1F302, 0x1F303, 0x1F304, 0x1F305, 0x1F306, 0x1F307, 0x1F308,
+        0x1F309, 0x1F30A, 0x1F30B, 0x1F30C, 0x1F30D, 0x1F30E, 0x1F30F, 0x1F310, 0x1F311, 0x1F312,
+        0x1F313, 0x1F314, 0x1F315, 0x1F316, 0x1F317, 0x1F318, 0x1F319, 0x1F31A, 0x1F31B, 0x1F31C,
+        0x1F31D, 0x1F31E, 0x1F31F, 0x1F320, 0x1F321, 0x1F324, 0x1F325, 0x1F326, 0x1F327, 0x1F328,
+        0x1F329, 0x1F32A, 0x1F32B, 0x1F32C, 0x1F32D, 0x1F32E, 0x1F32F, 0x1F330, 0x1F331, 0x1F332,
+        0x1F333, 0x1F334, 0x1F335, 0x1F336, 0x1F337, 0x1F338, 0x1F339, 0x1F33A, 0x1F33B, 0x1F33C,
+        0x1F33D, 0x1F33E, 0x1F33F, 0x1F340, 0x1F341, 0x1F342, 0x1F343, 0x1F344, 0x1F345, 0x1F346,
+        0x1F347, 0x1F348, 0x1F349, 0x1F34A, 0x1F34B, 0x1F34C, 0x1F34D, 0x1F34E, 0x1F34F, 0x1F350,
+        0x1F351, 0x1F352, 0x1F353, 0x1F354, 0x1F355, 0x1F356, 0x1F357, 0x1F358, 0x1F359, 0x1F35A,
+        0x1F35B, 0x1F35C, 0x1F35D, 0x1F35E, 0x1F35F, 0x1F360, 0x1F361, 0x1F362, 0x1F363, 0x1F364,
+        0x1F365, 0x1F366, 0x1F367, 0x1F368, 0x1F369, 0x1F36A, 0x1F36B, 0x1F36C, 0x1F36D, 0x1F36E,
+        0x1F36F, 0x1F370, 0x1F371, 0x1F372, 0x1F373, 0x1F374, 0x1F375, 0x1F376, 0x1F377, 0x1F378,
+        0x1F379, 0x1F37A, 0x1F37B, 0x1F37C, 0x1F37D, 0x1F37E, 0x1F37F, 0x1F380, 0x1F381, 0x1F382,
+        0x1F383, 0x1F384, 0x1F385, 0x1F386, 0x1F387, 0x1F388, 0x1F389, 0x1F38A, 0x1F38B, 0x1F38C,
+        0x1F38D, 0x1F38E, 0x1F38F, 0x1F390, 0x1F391, 0x1F392, 0x1F393, 0x1F396, 0x1F397, 0x1F399,
+        0x1F39A, 0x1F39B, 0x1F39E, 0x1F39F, 0x1F3A0, 0x1F3A1, 0x1F3A2, 0x1F3A3, 0x1F3A4, 0x1F3A5,
+        0x1F3A6, 0x1F3A7, 0x1F3A8, 0x1F3A9, 0x1F3AA, 0x1F3AB, 0x1F3AC, 0x1F3AD, 0x1F3AE, 0x1F3AF,
+        0x1F3B0, 0x1F3B1, 0x1F3B2, 0x1F3B3, 0x1F3B4, 0x1F3B5, 0x1F3B6, 0x1F3B7, 0x1F3B8, 0x1F3B9,
+        0x1F3BA, 0x1F3BB, 0x1F3BC, 0x1F3BD, 0x1F3BE, 0x1F3BF, 0x1F3C0, 0x1F3C1, 0x1F3C2, 0x1F3C3,
+        0x1F3C4, 0x1F3C5, 0x1F3C6, 0x1F3C7, 0x1F3C8, 0x1F3C9, 0x1F3CA, 0x1F3CB, 0x1F3CC, 0x1F3CD,
+        0x1F3CE, 0x1F3CF, 0x1F3D0, 0x1F3D1, 0x1F3D2, 0x1F3D3, 0x1F3D4, 0x1F3D5, 0x1F3D6, 0x1F3D7,
+        0x1F3D8, 0x1F3D9, 0x1F3DA, 0x1F3DB, 0x1F3DC, 0x1F3DD, 0x1F3DE, 0x1F3DF, 0x1F3E0, 0x1F3E1,
+        0x1F3E2, 0x1F3E3, 0x1F3E4, 0x1F3E5, 0x1F3E6, 0x1F3E7, 0x1F3E8, 0x1F3E9, 0x1F3EA, 0x1F3EB,
+        0x1F3EC, 0x1F3ED, 0x1F3EE, 0x1F3EF, 0x1F3F0, 0x1F3F3, 0x1F3F4, 0x1F3F5, 0x1F3F7, 0x1F3F8,
+        0x1F3F9, 0x1F3FA, 0x1F3FB, 0x1F3FC, 0x1F3FD, 0x1F3FE, 0x1F3FF, 0x1F400, 0x1F401, 0x1F402,
+        0x1F403, 0x1F404, 0x1F405, 0x1F406, 0x1F407, 0x1F408, 0x1F409, 0x1F40A, 0x1F40B, 0x1F40C,
+        0x1F40D, 0x1F40E, 0x1F40F, 0x1F410, 0x1F411, 0x1F412, 0x1F413, 0x1F414, 0x1F415, 0x1F416,
+        0x1F417, 0x1F418, 0x1F419, 0x1F41A, 0x1F41B, 0x1F41C, 0x1F41D, 0x1F41E, 0x1F41F, 0x1F420,
+        0x1F421, 0x1F422, 0x1F423, 0x1F424, 0x1F425, 0x1F426, 0x1F427, 0x1F428, 0x1F429, 0x1F42A,
+        0x1F42B, 0x1F42C, 0x1F42D, 0x1F42E, 0x1F42F, 0x1F430, 0x1F431, 0x1F432, 0x1F433, 0x1F434,
+        0x1F435, 0x1F436, 0x1F437, 0x1F438, 0x1F439, 0x1F43A, 0x1F43B, 0x1F43C, 0x1F43D, 0x1F43E,
+        0x1F43F, 0x1F440, 0x1F441, 0x1F442, 0x1F443, 0x1F444, 0x1F445, 0x1F446, 0x1F447, 0x1F448,
+        0x1F449, 0x1F44A, 0x1F44B, 0x1F44C, 0x1F44D, 0x1F44E, 0x1F44F, 0x1F450, 0x1F451, 0x1F452,
+        0x1F453, 0x1F454, 0x1F455, 0x1F456, 0x1F457, 0x1F458, 0x1F459, 0x1F45A, 0x1F45B, 0x1F45C,
+        0x1F45D, 0x1F45E, 0x1F45F, 0x1F460, 0x1F461, 0x1F462, 0x1F463, 0x1F464, 0x1F465, 0x1F466,
+        0x1F467, 0x1F468, 0x1F469, 0x1F46A, 0x1F46B, 0x1F46C, 0x1F46D, 0x1F46E, 0x1F46F, 0x1F470,
+        0x1F471, 0x1F472, 0x1F473, 0x1F474, 0x1F475, 0x1F476, 0x1F477, 0x1F478, 0x1F479, 0x1F47A,
+        0x1F47B, 0x1F47C, 0x1F47D, 0x1F47E, 0x1F47F, 0x1F480, 0x1F481, 0x1F482, 0x1F483, 0x1F484,
+        0x1F485, 0x1F486, 0x1F487, 0x1F488, 0x1F489, 0x1F48A, 0x1F48B, 0x1F48C, 0x1F48D, 0x1F48E,
+        0x1F48F, 0x1F490, 0x1F491, 0x1F492, 0x1F493, 0x1F494, 0x1F495, 0x1F496, 0x1F497, 0x1F498,
+        0x1F499, 0x1F49A, 0x1F49B, 0x1F49C, 0x1F49D, 0x1F49E, 0x1F49F, 0x1F4A0, 0x1F4A1, 0x1F4A2,
+        0x1F4A3, 0x1F4A4, 0x1F4A5, 0x1F4A6, 0x1F4A7, 0x1F4A8, 0x1F4A9, 0x1F4AA, 0x1F4AB, 0x1F4AC,
+        0x1F4AD, 0x1F4AE, 0x1F4AF, 0x1F4B0, 0x1F4B1, 0x1F4B2, 0x1F4B3, 0x1F4B4, 0x1F4B5, 0x1F4B6,
+        0x1F4B7, 0x1F4B8, 0x1F4B9, 0x1F4BA, 0x1F4BB, 0x1F4BC, 0x1F4BD, 0x1F4BE, 0x1F4BF, 0x1F4C0,
+        0x1F4C1, 0x1F4C2, 0x1F4C3, 0x1F4C4, 0x1F4C5, 0x1F4C6, 0x1F4C7, 0x1F4C8, 0x1F4C9, 0x1F4CA,
+        0x1F4CB, 0x1F4CC, 0x1F4CD, 0x1F4CE, 0x1F4CF, 0x1F4D0, 0x1F4D1, 0x1F4D2, 0x1F4D3, 0x1F4D4,
+        0x1F4D5, 0x1F4D6, 0x1F4D7, 0x1F4D8, 0x1F4D9, 0x1F4DA, 0x1F4DB, 0x1F4DC, 0x1F4DD, 0x1F4DE,
+        0x1F4DF, 0x1F4E0, 0x1F4E1, 0x1F4E2, 0x1F4E3, 0x1F4E4, 0x1F4E5, 0x1F4E6, 0x1F4E7, 0x1F4E8,
+        0x1F4E9, 0x1F4EA, 0x1F4EB, 0x1F4EC, 0x1F4ED, 0x1F4EE, 0x1F4EF, 0x1F4F0, 0x1F4F1, 0x1F4F2,
+        0x1F4F3, 0x1F4F4, 0x1F4F5, 0x1F4F6, 0x1F4F7, 0x1F4F8, 0x1F4F9, 0x1F4FA, 0x1F4FB, 0x1F4FC,
+        0x1F4FD, 0x1F4FF, 0x1F500, 0x1F501, 0x1F502, 0x1F503, 0x1F504, 0x1F505, 0x1F506, 0x1F507,
+        0x1F508, 0x1F509, 0x1F50A, 0x1F50B, 0x1F50C, 0x1F50D, 0x1F50E, 0x1F50F, 0x1F510, 0x1F511,
+        0x1F512, 0x1F513, 0x1F514, 0x1F515, 0x1F516, 0x1F517, 0x1F518, 0x1F519, 0x1F51A, 0x1F51B,
+        0x1F51C, 0x1F51D, 0x1F51E, 0x1F51F, 0x1F520, 0x1F521, 0x1F522, 0x1F523, 0x1F524, 0x1F525,
+        0x1F526, 0x1F527, 0x1F528, 0x1F529, 0x1F52A, 0x1F52B, 0x1F52C, 0x1F52D, 0x1F52E, 0x1F52F,
+        0x1F530, 0x1F531, 0x1F532, 0x1F533, 0x1F534, 0x1F535, 0x1F536, 0x1F537, 0x1F538, 0x1F539,
+        0x1F53A, 0x1F53B, 0x1F53C, 0x1F53D, 0x1F549, 0x1F54A, 0x1F54B, 0x1F54C, 0x1F54D, 0x1F54E,
+        0x1F550, 0x1F551, 0x1F552, 0x1F553, 0x1F554, 0x1F555, 0x1F556, 0x1F557, 0x1F558, 0x1F559,
+        0x1F55A, 0x1F55B, 0x1F55C, 0x1F55D, 0x1F55E, 0x1F55F, 0x1F560, 0x1F561, 0x1F562, 0x1F563,
+        0x1F564, 0x1F565, 0x1F566, 0x1F567, 0x1F56F, 0x1F570, 0x1F573, 0x1F574, 0x1F575, 0x1F576,
+        0x1F577, 0x1F578, 0x1F579, 0x1F57A, 0x1F587, 0x1F58A, 0x1F58B, 0x1F58C, 0x1F58D, 0x1F590,
+        0x1F595, 0x1F596, 0x1F5A4, 0x1F5A5, 0x1F5A8, 0x1F5B1, 0x1F5B2, 0x1F5BC, 0x1F5C2, 0x1F5C3,
+        0x1F5C4, 0x1F5D1, 0x1F5D2, 0x1F5D3, 0x1F5DC, 0x1F5DD, 0x1F5DE, 0x1F5E1, 0x1F5E3, 0x1F5E8,
+        0x1F5EF, 0x1F5F3, 0x1F5FA, 0x1F5FB, 0x1F5FC, 0x1F5FD, 0x1F5FE, 0x1F5FF, 0x1F600, 0x1F601,
+        0x1F602, 0x1F603, 0x1F604, 0x1F605, 0x1F606, 0x1F607, 0x1F608, 0x1F609, 0x1F60A, 0x1F60B,
+        0x1F60C, 0x1F60D, 0x1F60E, 0x1F60F, 0x1F610, 0x1F611, 0x1F612, 0x1F613, 0x1F614, 0x1F615,
+        0x1F616, 0x1F617, 0x1F618, 0x1F619, 0x1F61A, 0x1F61B, 0x1F61C, 0x1F61D, 0x1F61E, 0x1F61F,
+        0x1F620, 0x1F621, 0x1F622, 0x1F623, 0x1F624, 0x1F625, 0x1F626, 0x1F627, 0x1F628, 0x1F629,
+        0x1F62A, 0x1F62B, 0x1F62C, 0x1F62D, 0x1F62E, 0x1F62F, 0x1F630, 0x1F631, 0x1F632, 0x1F633,
+        0x1F634, 0x1F635, 0x1F636, 0x1F637, 0x1F638, 0x1F639, 0x1F63A, 0x1F63B, 0x1F63C, 0x1F63D,
+        0x1F63E, 0x1F63F, 0x1F640, 0x1F641, 0x1F642, 0x1F643, 0x1F644, 0x1F645, 0x1F646, 0x1F647,
+        0x1F648, 0x1F649, 0x1F64A, 0x1F64B, 0x1F64C, 0x1F64D, 0x1F64E, 0x1F64F, 0x1F680, 0x1F681,
+        0x1F682, 0x1F683, 0x1F684, 0x1F685, 0x1F686, 0x1F687, 0x1F688, 0x1F689, 0x1F68A, 0x1F68B,
+        0x1F68C, 0x1F68D, 0x1F68E, 0x1F68F, 0x1F690, 0x1F691, 0x1F692, 0x1F693, 0x1F694, 0x1F695,
+        0x1F696, 0x1F697, 0x1F698, 0x1F699, 0x1F69A, 0x1F69B, 0x1F69C, 0x1F69D, 0x1F69E, 0x1F69F,
+        0x1F6A0, 0x1F6A1, 0x1F6A2, 0x1F6A3, 0x1F6A4, 0x1F6A5, 0x1F6A6, 0x1F6A7, 0x1F6A8, 0x1F6A9,
+        0x1F6AA, 0x1F6AB, 0x1F6AC, 0x1F6AD, 0x1F6AE, 0x1F6AF, 0x1F6B0, 0x1F6B1, 0x1F6B2, 0x1F6B3,
+        0x1F6B4, 0x1F6B5, 0x1F6B6, 0x1F6B7, 0x1F6B8, 0x1F6B9, 0x1F6BA, 0x1F6BB, 0x1F6BC, 0x1F6BD,
+        0x1F6BE, 0x1F6BF, 0x1F6C0, 0x1F6C1, 0x1F6C2, 0x1F6C3, 0x1F6C4, 0x1F6C5, 0x1F6CB, 0x1F6CC,
+        0x1F6CD, 0x1F6CE, 0x1F6CF, 0x1F6D0, 0x1F6D1, 0x1F6D2, 0x1F6E0, 0x1F6E1, 0x1F6E2, 0x1F6E3,
+        0x1F6E4, 0x1F6E5, 0x1F6E9, 0x1F6EB, 0x1F6EC, 0x1F6F0, 0x1F6F3, 0x1F6F4, 0x1F6F5, 0x1F6F6,
+        0x1F910, 0x1F911, 0x1F912, 0x1F913, 0x1F914, 0x1F915, 0x1F916, 0x1F917, 0x1F918, 0x1F919,
+        0x1F91A, 0x1F91B, 0x1F91C, 0x1F91D, 0x1F91E, 0x1F920, 0x1F921, 0x1F922, 0x1F923, 0x1F924,
+        0x1F925, 0x1F926, 0x1F927, 0x1F930, 0x1F933, 0x1F934, 0x1F935, 0x1F936, 0x1F937, 0x1F938,
+        0x1F939, 0x1F93A, 0x1F93B, 0x1F93C, 0x1F93D, 0x1F93E, 0x1F940, 0x1F941, 0x1F942, 0x1F943,
+        0x1F944, 0x1F945, 0x1F946, 0x1F947, 0x1F948, 0x1F949, 0x1F94A, 0x1F94B, 0x1F950, 0x1F951,
+        0x1F952, 0x1F953, 0x1F954, 0x1F955, 0x1F956, 0x1F957, 0x1F958, 0x1F959, 0x1F95A, 0x1F95B,
+        0x1F95C, 0x1F95D, 0x1F95E, 0x1F980, 0x1F981, 0x1F982, 0x1F983, 0x1F984, 0x1F985, 0x1F986,
+        0x1F987, 0x1F988, 0x1F989, 0x1F98A, 0x1F98B, 0x1F98C, 0x1F98D, 0x1F98E, 0x1F98F, 0x1F990,
+        0x1F991, 0x1F9C0
     };
 
     // See http://www.unicode.org/Public/emoji/3.0/emoji-data.txt
diff --git a/core/java/android/text/method/BaseKeyListener.java b/core/java/android/text/method/BaseKeyListener.java
index 3770a45..2f327f3 100644
--- a/core/java/android/text/method/BaseKeyListener.java
+++ b/core/java/android/text/method/BaseKeyListener.java
@@ -129,8 +129,8 @@
         // The offset is immediately before a variation selector.
         final int STATE_BEFORE_VS = 6;
 
-        // The offset is immediately before a ZWJ emoji.
-        final int STATE_BEFORE_ZWJ_EMOJI = 7;
+        // The offset is immediately before an emoji.
+        final int STATE_BEFORE_EMOJI = 7;
         // The offset is immediately before a ZWJ that were seen before a ZWJ emoji.
         final int STATE_BEFORE_ZWJ = 8;
         // The offset is immediately before a variation selector and a ZWJ that were seen before a
@@ -169,7 +169,7 @@
                     } else if (codePoint == Emoji.COMBINING_ENCLOSING_KEYCAP) {
                         state = STATE_BEFORE_KEYCAP;
                     } else if (Emoji.isEmoji(codePoint)) {
-                        state = STATE_BEFORE_ZWJ_EMOJI;
+                        state = STATE_BEFORE_EMOJI;
                     } else {
                         state = STATE_FINISHED;
                     }
@@ -232,7 +232,7 @@
                 case STATE_BEFORE_VS:
                     if (Emoji.isEmoji(codePoint)) {
                         deleteCharCount += Character.charCount(codePoint);
-                        state = STATE_BEFORE_ZWJ_EMOJI;
+                        state = STATE_BEFORE_EMOJI;
                         break;
                     }
 
@@ -242,7 +242,7 @@
                     }
                     state = STATE_FINISHED;
                     break;
-                case STATE_BEFORE_ZWJ_EMOJI:
+                case STATE_BEFORE_EMOJI:
                     if (codePoint == Emoji.ZERO_WIDTH_JOINER) {
                         state = STATE_BEFORE_ZWJ;
                     } else {
@@ -252,7 +252,8 @@
                 case STATE_BEFORE_ZWJ:
                     if (Emoji.isEmoji(codePoint)) {
                         deleteCharCount += Character.charCount(codePoint) + 1;  // +1 for ZWJ.
-                        state = STATE_BEFORE_ZWJ_EMOJI;
+                        state = Emoji.isEmojiModifier(codePoint) ?
+                                STATE_BEFORE_EMOJI_MODIFIER : STATE_BEFORE_EMOJI;
                     } else if (isVariationSelector(codePoint)) {
                         lastSeenVSCharCount = Character.charCount(codePoint);
                         state = STATE_BEFORE_VS_AND_ZWJ;
@@ -265,7 +266,7 @@
                         // +1 for ZWJ.
                         deleteCharCount += lastSeenVSCharCount + 1 + Character.charCount(codePoint);
                         lastSeenVSCharCount = 0;
-                        state = STATE_BEFORE_ZWJ_EMOJI;
+                        state = STATE_BEFORE_EMOJI;
                     } else {
                         state = STATE_FINISHED;
                     }
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 209886b..4dc1009 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -5502,6 +5502,15 @@
         if (mView != null && mAdded) {
             final int what = event.mAction;
 
+            // Cache the drag description when the operation starts, then fill it in
+            // on subsequent calls as a convenience
+            if (what == DragEvent.ACTION_DRAG_STARTED) {
+                mCurrentDragView = null;    // Start the current-recipient tracking
+                mDragDescription = event.mClipDescription;
+            } else {
+                event.mClipDescription = mDragDescription;
+            }
+
             if (what == DragEvent.ACTION_DRAG_EXITED) {
                 // A direct EXITED event means that the window manager knows we've just crossed
                 // a window boundary, so the current drag target within this one must have
@@ -5509,15 +5518,6 @@
                 // for now.
                 mView.dispatchDragEvent(event);
             } else {
-                // Cache the drag description when the operation starts, then fill it in
-                // on subsequent calls as a convenience
-                if (what == DragEvent.ACTION_DRAG_STARTED) {
-                    mCurrentDragView = null;    // Start the current-recipient tracking
-                    mDragDescription = event.mClipDescription;
-                } else {
-                    event.mClipDescription = mDragDescription;
-                }
-
                 // For events with a [screen] location, translate into window coordinates
                 if ((what == DragEvent.ACTION_DRAG_LOCATION) || (what == DragEvent.ACTION_DROP)) {
                     mDragPoint.set(event.mX, event.mY);
diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java
index 7762675..4074166 100644
--- a/core/java/android/widget/Toast.java
+++ b/core/java/android/widget/Toast.java
@@ -24,7 +24,10 @@
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.graphics.PixelFormat;
+import android.os.Binder;
 import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.util.Log;
@@ -326,13 +329,6 @@
     }
 
     private static class TN extends ITransientNotification.Stub {
-        final Runnable mShow = new Runnable() {
-            @Override
-            public void run() {
-                handleShow();
-            }
-        };
-
         final Runnable mHide = new Runnable() {
             @Override
             public void run() {
@@ -343,7 +339,13 @@
         };
 
         private final WindowManager.LayoutParams mParams = new WindowManager.LayoutParams();
-        final Handler mHandler = new Handler();
+        final Handler mHandler = new Handler() {
+            @Override
+            public void handleMessage(Message msg) {
+                IBinder token = (IBinder) msg.obj;
+                handleShow(token);
+            }
+        };
 
         int mGravity;
         int mX, mY;
@@ -379,9 +381,9 @@
          * schedule handleShow into the right thread
          */
         @Override
-        public void show() {
+        public void show(IBinder windowToken) {
             if (localLOGV) Log.v(TAG, "SHOW: " + this);
-            mHandler.post(mShow);
+            mHandler.obtainMessage(0, windowToken).sendToTarget();
         }
 
         /**
@@ -393,7 +395,7 @@
             mHandler.post(mHide);
         }
 
-        public void handleShow() {
+        public void handleShow(IBinder windowToken) {
             if (localLOGV) Log.v(TAG, "HANDLE SHOW: " + this + " mView=" + mView
                     + " mNextView=" + mNextView);
             if (mView != mNextView) {
@@ -424,6 +426,7 @@
                 mParams.packageName = packageName;
                 mParams.removeTimeoutMilliseconds = mDuration ==
                     Toast.LENGTH_LONG ? LONG_DURATION_TIMEOUT : SHORT_DURATION_TIMEOUT;
+                mParams.token = windowToken;
                 if (mView.getParent() != null) {
                     if (localLOGV) Log.v(TAG, "REMOVE! " + mView + " in " + this);
                     mWM.removeView(mView);
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index 898cf77..85092ad 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -768,6 +768,21 @@
         return false;
     }
 
+    // Don't count glyphs that are the recommended "space" glyph and are zero width.
+    // This logic makes assumptions about HarfBuzz layout, but does correctly handle
+    // cases where ligatures form and zero width space glyphs are left in as
+    // placeholders.
+    static size_t countNonSpaceGlyphs(const Layout& layout) {
+        size_t count = 0;
+        static unsigned int kSpaceGlyphId = 3;
+        for (size_t i = 0; i < layout.nGlyphs(); i++) {
+            if (layout.getGlyphId(i) != kSpaceGlyphId || layout.getCharAdvance(i) != 0.0) {
+                count++;
+            }
+        }
+        return count;
+    }
+
     // Returns true if the given string is exact one pair of regional indicators.
     static bool isFlag(const jchar* str, size_t length) {
         const jchar RI_LEAD_SURROGATE = 0xD83C;
@@ -831,7 +846,7 @@
         Layout layout;
         MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, str.get(), 0, str.size(),
                 str.size());
-        size_t nGlyphs = layout.nGlyphs();
+        size_t nGlyphs = countNonSpaceGlyphs(layout);
         if (nGlyphs != 1 && nChars > 1) {
             // multiple-character input, and was not a ligature
             // TODO: handle ZWJ/ZWNJ characters specially so we can detect certain ligatures
diff --git a/core/jni/android_hardware_location_ContextHubService.cpp b/core/jni/android_hardware_location_ContextHubService.cpp
index 46f76de..9515a0e 100644
--- a/core/jni/android_hardware_location_ContextHubService.cpp
+++ b/core/jni/android_hardware_location_ContextHubService.cpp
@@ -423,7 +423,7 @@
     txnInfo->appInfo.num_mem_ranges = 0;
     txnInfo->appInfo.version = -1; // Awaited
 
-    if (!addTxn(CONTEXT_HUB_LOAD_APP, txnInfo)) {
+    if (addTxn(CONTEXT_HUB_LOAD_APP, txnInfo) != 0) {
         return_id(instanceId);
         free(txnInfo);
         return -1;
@@ -726,6 +726,7 @@
           if (isValidOsStatus(msg, msgLen, &rsp)) {
               rsp.result = 0;
               ALOGW("Context Hub handle %d restarted", hubHandle);
+              closeTxn();
               passOnOsResponse(hubHandle, msgType, &rsp, nullptr, 0);
               invalidateNanoApps(hubHandle);
               query_hub_for_apps(ALL_APPS, hubHandle);
@@ -1012,10 +1013,12 @@
 
         if (msgType == CONTEXT_HUB_LOAD_APP) {
             if (startLoadAppTxn(appId, hubHandle) != 0) {
+                ALOGW("Cannot Start Load Transaction");
                 return -1;
             }
         } else if (msgType == CONTEXT_HUB_UNLOAD_APP) {
             if (startUnloadAppTxn(appInstanceHandle) != 0) {
+                ALOGW("Cannot Start UnLoad Transaction");
                 return -1;
             }
         }
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 8388f05..4b66f70 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -49,6 +49,7 @@
     <protected-broadcast android:name="android.intent.action.PACKAGE_VERIFIED" />
     <protected-broadcast android:name="android.intent.action.PACKAGES_SUSPENDED" />
     <protected-broadcast android:name="android.intent.action.PACKAGES_UNSUSPENDED" />
+    <protected-broadcast android:name="android.intent.action.ACTION_PREFERRED_ACTIVITY_CHANGED" />
     <protected-broadcast android:name="android.intent.action.UID_REMOVED" />
     <protected-broadcast android:name="android.intent.action.QUERY_PACKAGE_RESTART" />
     <protected-broadcast android:name="android.intent.action.CONFIGURATION_CHANGED" />
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 6eabd52..d5c1dd8 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Optimeer tans berging."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android gradeer tans op"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"Sommige programme sal dalk nie behoorlik werk voordat die opgradering voltooi is nie"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Optimeer program <xliff:g id="NUMBER_0">%1$d</xliff:g> van <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"Berei tans <xliff:g id="APPNAME">%1$s</xliff:g> voor."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Begin programme."</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index e3cae6a..a90d056 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"ማከማቻን በማመቻቸት ላይ።"</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android በማላቅ ላይ ነው"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"አንዳንድ መተግበሪያዎች ማላቁ እስኪጠናቀቅ ድረስ በአግባቡ ላይሰሩ ይችላሉ"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"መተግበሪያዎች በአግባቡ በመጠቀም ላይ <xliff:g id="NUMBER_0">%1$d</xliff:g> ከ <xliff:g id="NUMBER_1">%2$d</xliff:g> ፡፡"</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g>ን ማዘጋጀት።"</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"መተግበሪያዎችን በማስጀመር ላይ፡፡"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 1778e0c..10cb7c5 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -1116,6 +1116,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"جارٍ تحسين السعة التخزينية."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"‏جارٍ ترقية Android"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"قد لا تعمل بعض التطبيقات بشكل مناسب إلا بعد انتهاء الترقية"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"جارٍ تحسين التطبيق <xliff:g id="NUMBER_0">%1$d</xliff:g> من <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"جارٍ تحضير <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"بدء التطبيقات."</string>
diff --git a/core/res/res/values-az-rAZ/strings.xml b/core/res/res/values-az-rAZ/strings.xml
index a1e851b..53a238b 100644
--- a/core/res/res/values-az-rAZ/strings.xml
+++ b/core/res/res/values-az-rAZ/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Yaddaş optimallaşdırılır."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android təkmilləşdirilir"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"Güncəllənmə tamamlanana kimi bəzi tətbiqlər düzgün işləməyə bilər"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_1">%2$d</xliff:g> əddədən <xliff:g id="NUMBER_0">%1$d</xliff:g> tətbiq optimallaşır."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> proqramının hazırlanması."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Tətbiqlər başladılır."</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 17dfef1..54c4710 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Хранилището се оптимизира."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android се надстройва"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"Някои приложения може да не работят правилно, докато надстройването не завърши"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Оптимизира се приложение <xliff:g id="NUMBER_0">%1$d</xliff:g> от <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> се подготвя."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Приложенията се стартират."</string>
diff --git a/core/res/res/values-bn-rBD/strings.xml b/core/res/res/values-bn-rBD/strings.xml
index 8435f96..292fefd 100644
--- a/core/res/res/values-bn-rBD/strings.xml
+++ b/core/res/res/values-bn-rBD/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"সঞ্চয়স্থান অপ্টিমাইজ করা হচ্ছে৷"</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android আপগ্রেড করা হচ্ছে"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"আপগ্রেড সম্পন্ন না হওয়া পর্যন্ত কিছু অ্যাপ্লিকেশান সঠিকভাবে কাজ নাও করতে পারে"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_1">%2$d</xliff:g>টির মধ্যে <xliff:g id="NUMBER_0">%1$d</xliff:g>টি অ্যাপ্লিকেশান অপ্টিমাইজ করা হচ্ছে৷"</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> প্রস্তুত করা হচ্ছে৷"</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"অ্যাপ্লিকেশানগুলি শুরু করা হচ্ছে৷"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 59f7d95..7890068 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"S\'està optimitzant l\'emmagatzematge."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android s\'està actualitzant"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"Pot ser que algunes aplicacions no funcionin correctament fins que no es completi l\'actualització"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"S\'està optimitzant l\'aplicació <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"S\'està preparant <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"S\'estan iniciant les aplicacions."</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 1eb497f..f5e74ce 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1070,6 +1070,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Probíhá optimalizace úložiště."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android se upgraduje"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"Před dokončením upgradu nemusí některé aplikace fungovat správně"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Optimalizování aplikace <xliff:g id="NUMBER_0">%1$d</xliff:g> z <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"Příprava aplikace <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Spouštění aplikací."</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index f5b7788..446c950 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Lageret optimeres."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android opgraderes"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"Nogle apps fungerer muligvis ikke korrekt, før opgraderingen er gennemført"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Optimerer app <xliff:g id="NUMBER_0">%1$d</xliff:g> ud af <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"Forbereder <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Åbner dine apps."</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 1345f76..25f3912 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Speicher wird optimiert"</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android wird aktualisiert"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"Einige Apps funktionieren unter Umständen nicht richtig, bis das Upgrade abgeschlossen ist"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"App <xliff:g id="NUMBER_0">%1$d</xliff:g> von <xliff:g id="NUMBER_1">%2$d</xliff:g> wird optimiert..."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> wird vorbereitet"</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Apps werden gestartet..."</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 8434fff..3e220da 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Βελτιστοποίηση αποθηκευτικού χώρου."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Το Android αναβαθμίζεται"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"Ορισμένες εφαρμογές ενδέχεται να μην λειτουργούν σωστά μέχρι την ολοκλήρωση της αναβάθμισης"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Βελτιστοποίηση της εφαρμογής <xliff:g id="NUMBER_0">%1$d</xliff:g> από <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"Προετοιμασία <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Έναρξη εφαρμογών."</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 6c693bc..60e9e86 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Optimising storage."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android is upgrading"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"Some apps may not work properly until the upgrade finishes"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Optimising app <xliff:g id="NUMBER_0">%1$d</xliff:g> of <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"Preparing <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Starting apps."</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 6c693bc..60e9e86 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Optimising storage."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android is upgrading"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"Some apps may not work properly until the upgrade finishes"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Optimising app <xliff:g id="NUMBER_0">%1$d</xliff:g> of <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"Preparing <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Starting apps."</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 6c693bc..60e9e86 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Optimising storage."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android is upgrading"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"Some apps may not work properly until the upgrade finishes"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Optimising app <xliff:g id="NUMBER_0">%1$d</xliff:g> of <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"Preparing <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Starting apps."</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index fcfc752..c5dc210 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Optimizando almacenamiento"</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android se está actualizando"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"Es posible que algunas apps no funcionen correctamente hasta que termine la actualización"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Optimizando la aplicación <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>"</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"Preparando <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Iniciando aplicaciones"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 21b4af3..9e1859b 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Optimizando almacenamiento."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Actualizando Android"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"Es posible que algunas aplicaciones no funcionen correctamente hasta que finalice la actualización"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Optimizando aplicación <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>..."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"Preparando <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Iniciando aplicaciones"</string>
diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml
index e96c93f..aa1a252 100644
--- a/core/res/res/values-et-rEE/strings.xml
+++ b/core/res/res/values-et-rEE/strings.xml
@@ -1024,6 +1024,7 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Salvestusruumi optimeerimine."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android viiakse üle uuemale versioonile"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"Mõned rakendused ei pruugi enne uuemale versioonile ülemineku lõpetamist korralikult töötada"</string>
+    <string name="app_upgrading_toast" msgid="3008139776215597053">"Rakenduse <xliff:g id="APPLICATION">%1$s</xliff:g> versiooni uuendatakse …"</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_0">%1$d</xliff:g>. rakenduse <xliff:g id="NUMBER_1">%2$d</xliff:g>-st optimeerimine."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"Rakenduse <xliff:g id="APPNAME">%1$s</xliff:g> ettevalmistamine."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Rakenduste käivitamine."</string>
diff --git a/core/res/res/values-eu-rES/strings.xml b/core/res/res/values-eu-rES/strings.xml
index 49ee82f..70ee283 100644
--- a/core/res/res/values-eu-rES/strings.xml
+++ b/core/res/res/values-eu-rES/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Memoria optimizatzen."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android bertsioa berritzen ari gara"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"Aplikazio batzuek agian ez dute behar bezala funtzionatuko bertsioa berritzen amaitu arte"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_0">%1$d</xliff:g>/<xliff:g id="NUMBER_1">%2$d</xliff:g> aplikazio optimizatzen."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> prestatzen."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Aplikazioak abiarazten."</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 71bdc2e..aa9c148 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -937,7 +937,7 @@
     <string name="selectAll" msgid="6876518925844129331">"انتخاب همه"</string>
     <string name="cut" msgid="3092569408438626261">"برش"</string>
     <string name="copy" msgid="2681946229533511987">"کپی"</string>
-    <string name="paste" msgid="5629880836805036433">"جای گذاری"</string>
+    <string name="paste" msgid="5629880836805036433">"جای‌گذاری"</string>
     <string name="paste_as_plain_text" msgid="5427792741908010675">"جای‌گذاری به عنوان متن ساده"</string>
     <string name="replace" msgid="5781686059063148930">"جایگزین شود..."</string>
     <string name="delete" msgid="6098684844021697789">"حذف"</string>
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"بهینه‌سازی فضای ذخیره‌سازی."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"‏Android درحال ارتقا است"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"تا پایان ارتقا، ممکن است برخی از برنامه‌ها به‌درستی کار نکنند."</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"در حال بهینه‌سازی برنامهٔ <xliff:g id="NUMBER_0">%1$d</xliff:g> از <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"آماده‌سازی <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"در حال آغاز برنامه‌ها."</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 62c148e..1aca741 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Optimoidaan tallennustilaa."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Androidia päivitetään"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"Kaikki sovellukset eivät ehkä toimi oikein, ennen kuin päivitys on valmis."</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Optimoidaan sovellusta <xliff:g id="NUMBER_0">%1$d</xliff:g>/<xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"Valmistellaan: <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Käynnistetään sovelluksia."</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 2df3680..7b194a09e 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Optimisation du stockage."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Installation de la m. à niveau d\'Android"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"Il se peut que certaines applications ne fonctionnent pas correctement jusqu\'à ce que la mise à niveau soit terminée"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Optimisation de l\'application <xliff:g id="NUMBER_0">%1$d</xliff:g> sur <xliff:g id="NUMBER_1">%2$d</xliff:g>…"</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"Préparation de <xliff:g id="APPNAME">%1$s</xliff:g> en cours…"</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Lancement des applications…"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 90def0d..ff0876e 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Optimisation du stockage en cours…"</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Mise à jour d\'Android…"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"Certaines applications peuvent ne pas fonctionner correctement jusqu\'à ce que la mise à jour soit terminée."</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Optimisation de l\'application <xliff:g id="NUMBER_0">%1$d</xliff:g> sur <xliff:g id="NUMBER_1">%2$d</xliff:g>…"</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"Préparation de <xliff:g id="APPNAME">%1$s</xliff:g> en cours…"</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Lancement des applications…"</string>
diff --git a/core/res/res/values-gl-rES/strings.xml b/core/res/res/values-gl-rES/strings.xml
index 85be7f3..abe09de 100644
--- a/core/res/res/values-gl-rES/strings.xml
+++ b/core/res/res/values-gl-rES/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Optimizando almacenamento."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Estase actualizando Android"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"É posible que algunhas aplicacións non funcionen correctamente ata que finalice o proceso de actualización"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Optimizando aplicación <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"Preparando <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Iniciando aplicacións."</string>
diff --git a/core/res/res/values-gu-rIN/strings.xml b/core/res/res/values-gu-rIN/strings.xml
index e611f30..1589426 100644
--- a/core/res/res/values-gu-rIN/strings.xml
+++ b/core/res/res/values-gu-rIN/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"સંગ્રહ ઓપ્ટિમાઇઝ કરી રહ્યું છે."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android અપગ્રેડ થઈ રહ્યું છે"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"અપગ્રેડ સમાપ્ત ન થાય ત્યાં સુધી કેટલીક ઍપ્લિકેશનો કદાચ યોગ્ય રીતે કામ ન કરે"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_1">%2$d</xliff:g> માંથી <xliff:g id="NUMBER_0">%1$d</xliff:g> ઍપ્લિકેશન ઓપ્ટિમાઇઝ કરી રહ્યું છે."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> તૈયાર કરી રહ્યું છે."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"ઍપ્લિકેશનો શરૂ કરી રહ્યાં છે."</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 76bc028..7a81b47 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"मेमोरी ऑप्‍टिमाइज़ हो रही है."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android अपग्रेड हो रहा है"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"जब तक अपग्रेड पूरा नहीं हो जाता, तब तक संभव है कि कुछ ऐप्लिकेशन ठीक से कार्य ना करें"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_1">%2$d</xliff:g> में से <xliff:g id="NUMBER_0">%1$d</xliff:g> ऐप्स  अनुकूलित हो रहा है."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> तैयार हो रहा है."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"ऐप्स  प्रारंभ होने वाले हैं"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 461888a..9ff8363 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -1047,6 +1047,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Optimiziranje pohrane."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android se nadograđuje"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"Neke aplikacije možda neće funkcionirati pravilno dok nadogradnja ne završi"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Optimiziranje aplikacije <xliff:g id="NUMBER_0">%1$d</xliff:g> od <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"Pripremanje aplikacije <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Pokretanje aplikacija."</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 920fc39..ce4bef5 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -1024,6 +1024,7 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Tárhely-optimalizálás."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android frissítése folyamatban"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"A frissítés befejezéséig előfordulhat, hogy egyes alkalmazások nem megfelelően működnek."</string>
+    <string name="app_upgrading_toast" msgid="3008139776215597053">"A(z) <xliff:g id="APPLICATION">%1$s</xliff:g> frissítése folyamatban van"</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Alkalmazás optimalizálása: <xliff:g id="NUMBER_0">%1$d</xliff:g>/<xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"A(z) <xliff:g id="APPNAME">%1$s</xliff:g> előkészítése."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Kezdő alkalmazások."</string>
diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml
index 2f6efcb..76bc42e 100644
--- a/core/res/res/values-hy-rAM/strings.xml
+++ b/core/res/res/values-hy-rAM/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Պահեստի օպտիմալացում:"</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android-ը նորացվում է"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"Հնարավոր է՝ որոշ հավելվածներ մինչև նորացման ավարտը ճիշտ չաշխատեն"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Օպտիմալացվում է հավելված <xliff:g id="NUMBER_0">%1$d</xliff:g>-ը <xliff:g id="NUMBER_1">%2$d</xliff:g>-ից:"</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> հավելվածը պատրաստվում է:"</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Հավելվածները մեկնարկում են:"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 9a6f48e..d780b8c 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Mengoptimalkan penyimpanan."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android sedang meningkatkan versi"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"Beberapa aplikasi mungkin tidak berfungsi dengan baik jika peningkatan versi belum selesai"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Mengoptimalkan aplikasi <xliff:g id="NUMBER_0">%1$d</xliff:g> dari <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"Menyiapkan <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Memulai aplikasi."</string>
diff --git a/core/res/res/values-is-rIS/strings.xml b/core/res/res/values-is-rIS/strings.xml
index a40db198..33b4783 100644
--- a/core/res/res/values-is-rIS/strings.xml
+++ b/core/res/res/values-is-rIS/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Fínstillir geymslu."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android er að uppfæra"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"Hugsanlega virka sum forrit ekki fyrr en uppfærslunni lýkur"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Fínstillir forrit <xliff:g id="NUMBER_0">%1$d</xliff:g> af <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"Undirbýr <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Ræsir forrit."</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 12e18db..d03b91d 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Ottimizzazione archiviazione."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Aggiornamento di Android in corso"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"Alcune app potrebbero non funzionare correttamente fino al completamento dell\'upgrade"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Ottimizzazione applicazione <xliff:g id="NUMBER_0">%1$d</xliff:g> di <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> in preparazione."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Avvio applicazioni."</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 6efa246..6df7a0f 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -1070,6 +1070,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"מתבצעת אופטימיזציה של האחסון."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"‏Android מבצע שדרוג"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"ייתכן שאפליקציות מסוימות לא יפעלו כראוי עד סיום השדרוג"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"מבצע אופטימיזציה של אפליקציה <xliff:g id="NUMBER_0">%1$d</xliff:g> מתוך <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"מכין את <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"מפעיל אפליקציות."</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index ef63264..e08520e 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"ストレージを最適化しています。"</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android のアップグレード中"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"アップグレードが完了するまで一部のアプリが正常に動作しない可能性があります"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_1">%2$d</xliff:g>個中<xliff:g id="NUMBER_0">%1$d</xliff:g>個のアプリを最適化しています。"</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g>をペア設定しています。"</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"アプリを起動しています。"</string>
diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml
index 2091e4a..9ab0f2b20 100644
--- a/core/res/res/values-ka-rGE/strings.xml
+++ b/core/res/res/values-ka-rGE/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"მეხსიერების ოპტიმიზირება."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android ახალ ვერსიაზე გადადის"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"ახალ ვერსიაზე გადასვლის დასრულებამდე, ზოგიერთმა აპმა შეიძლება არასწორად იმუშაოს"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"მიმდინარეობს აპლიკაციების ოპტიმიზაცია. დასრულებულია <xliff:g id="NUMBER_0">%1$d</xliff:g>, სულ <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"ემზადება <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"აპების ჩართვა"</string>
diff --git a/core/res/res/values-kk-rKZ/strings.xml b/core/res/res/values-kk-rKZ/strings.xml
index 174f430..49d7139 100644
--- a/core/res/res/values-kk-rKZ/strings.xml
+++ b/core/res/res/values-kk-rKZ/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Қойманы оңтайландыру."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android жаңартылуда"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"Жаңарту аяқталғанға дейін кейбір қолданбалар дұрыс жұмыс істемеуі мүмкін"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_1">%2$d</xliff:g> ішінен <xliff:g id="NUMBER_0">%1$d</xliff:g> қолданба оңтайландырылуда."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> дайындалуда."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Қолданбалар іске қосылуда."</string>
diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml
index 4584d21..3ffa561 100644
--- a/core/res/res/values-km-rKH/strings.xml
+++ b/core/res/res/values-km-rKH/strings.xml
@@ -975,7 +975,7 @@
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"កែសម្រួល​ជាមួយ​ %1$s"</string>
     <string name="whichEditApplicationLabel" msgid="7183524181625290300">"កែសម្រួល"</string>
     <string name="whichSendApplication" msgid="6902512414057341668">"ចែករំលែក​ជាមួយ"</string>
-    <string name="whichSendApplicationNamed" msgid="2799370240005424391">"ចែករំលែក​ជាមួយ"</string>
+    <string name="whichSendApplicationNamed" msgid="2799370240005424391">"ចែករំលែក​ជាមួយ %1$s"</string>
     <string name="whichSendApplicationLabel" msgid="4579076294675975354">"ចែករំលែក"</string>
     <string name="whichSendToApplication" msgid="8272422260066642057">"ផ្ញើដោយប្រើ"</string>
     <string name="whichSendToApplicationNamed" msgid="7768387871529295325">"ផ្ញើដោយប្រើ %1$s"</string>
@@ -1026,6 +1026,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"កំពុងធ្វើឲ្យឧបករណ៍ផ្ទុកមានប្រសិទ្ធភាព។"</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android កំពុងអាប់គ្រេត..."</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"កម្មវិធីមួយចំនួនអាចនឹងមិនដំណើរការប្រក្រតីនោះទេ រហូតដល់ការអាប់គ្រេតបញ្ចប់"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"ធ្វើ​ឲ្យ​កម្មវិធី​ប្រសើរ​ឡើង <xliff:g id="NUMBER_0">%1$d</xliff:g> នៃ <xliff:g id="NUMBER_1">%2$d</xliff:g> ។"</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"កំពុងរៀបចំ <xliff:g id="APPNAME">%1$s</xliff:g>។"</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"ចាប់ផ្ដើម​កម្មវិធី។"</string>
diff --git a/core/res/res/values-kn-rIN/strings.xml b/core/res/res/values-kn-rIN/strings.xml
index a6d754d..7960cba 100644
--- a/core/res/res/values-kn-rIN/strings.xml
+++ b/core/res/res/values-kn-rIN/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"ಸಂಗ್ರಹಣೆಯನ್ನು ಆಪ್ಟಿಮೈಸ್ ಮಾಡಲಾಗುತ್ತಿದೆ."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android ಅಪ್‌ಗ್ರೇಡ್‌ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"ಅಪ್‌ಗ್ರೇಡ್ ಮುಗಿಯುವ ತನಕ ಕೆಲವು ಅಪ್ಲಿಕೇಶನ್‌ಗಳು ಸರಿಯಾಗಿ ಕೆಲಸ ಮಾಡದಿರಬಹುದು"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_1">%2$d</xliff:g> ರಲ್ಲಿ <xliff:g id="NUMBER_0">%1$d</xliff:g> ಅಪ್ಲಿಕೇಶನ್‌ ಆಪ್ಟಿಮೈಸ್ ಮಾಡಲಾಗುತ್ತಿದೆ."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> ಸಿದ್ಧಪಡಿಸಲಾಗುತ್ತಿದೆ."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ಪ್ರಾರಂಭಿಸಲಾಗುತ್ತಿದೆ."</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 6d07713..2e58e82 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"저장소 최적화 중"</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android 업그레이드 중"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"특정 앱은 업그레이드가 완료될 때까지 제대로 작동하지 않을 수 있습니다."</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"앱 <xliff:g id="NUMBER_1">%2$d</xliff:g>개 중 <xliff:g id="NUMBER_0">%1$d</xliff:g>개 최적화 중"</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> 준비 중..."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"앱을 시작하는 중입니다."</string>
diff --git a/core/res/res/values-ky-rKG/strings.xml b/core/res/res/values-ky-rKG/strings.xml
index a024db69..5ba9427 100644
--- a/core/res/res/values-ky-rKG/strings.xml
+++ b/core/res/res/values-ky-rKG/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Сактагыч ыңгайлаштырылууда."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android жаңыртылууда"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"Жаңыртуу аягына чыкмайынча айрым колдонмолор талаптагыдай иштебей калышы мүмкүн"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_1">%2$d</xliff:g> ичинен <xliff:g id="NUMBER_0">%1$d</xliff:g> колдонмо ыңгайлаштырылууда."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> даярдалууда."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Колдонмолорду иштетип баштоо"</string>
diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml
index 0be6875..aa4d468 100644
--- a/core/res/res/values-lo-rLA/strings.xml
+++ b/core/res/res/values-lo-rLA/strings.xml
@@ -1024,6 +1024,7 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"ການ​ປັບ​ບ່ອນ​ເກັບ​ຂໍ້​ມູນ​ໃຫ້​ເໝາະ​ສົມ."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"ກຳລັງອັບເກຣດ Android"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"ບາງແອັບອາດບໍ່ສາມາດເຮັດວຽກໄດ້ປົກກະຕິຈົນກວ່າຈະອັບເກຣດສຳເລັດ"</string>
+    <string name="app_upgrading_toast" msgid="3008139776215597053">"ກຳລັງອັບເກຣດ<xliff:g id="APPLICATION">%1$s</xliff:g>…"</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"ກຳລັງ​ປັບປຸງ​ປະສິດທິພາບ​ແອັບຯ​ທີ <xliff:g id="NUMBER_0">%1$d</xliff:g> ຈາກ​ທັງ​ໝົດ <xliff:g id="NUMBER_1">%2$d</xliff:g> ແອັບຯ."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"ກຳ​ລັງ​ກຽມ <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"ກຳລັງເປີດແອັບຯ."</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index f4da72e..c8e3532 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -1070,6 +1070,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Optimizuojama saugykla."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"„Android“ naujovinama"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"Kai kurios programos gali tinkamai neveikti, kol naujovinimo procesas nebus baigtas"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Optimizuojama <xliff:g id="NUMBER_0">%1$d</xliff:g> progr. iš <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"Ruošiama „<xliff:g id="APPNAME">%1$s</xliff:g>“."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Paleidžiamos programos."</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index dba8beb..e482618 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -1047,6 +1047,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Notiek krātuves optimizēšana."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Notiek Android jaunināšana..."</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"Kamēr jaunināšana nebūs pabeigta, dažas lietotnes, iespējams, nedarbosies pareizi."</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Tiek optimizēta <xliff:g id="NUMBER_0">%1$d</xliff:g>. lietotne no <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"Notiek lietotnes <xliff:g id="APPNAME">%1$s</xliff:g> sagatavošana."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Notiek lietotņu palaišana."</string>
diff --git a/core/res/res/values-mk-rMK/strings.xml b/core/res/res/values-mk-rMK/strings.xml
index a6a7793..4ebd66b 100644
--- a/core/res/res/values-mk-rMK/strings.xml
+++ b/core/res/res/values-mk-rMK/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Оптимизирање на складирањето."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android се ажурира"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"Некои апликации може да не работат правилно додека не се заврши надградбата"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Се оптимизира апликација <xliff:g id="NUMBER_0">%1$d</xliff:g> од <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"Се подготвува <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Се стартуваат апликациите."</string>
diff --git a/core/res/res/values-ml-rIN/strings.xml b/core/res/res/values-ml-rIN/strings.xml
index 284db98..ac9018cf 100644
--- a/core/res/res/values-ml-rIN/strings.xml
+++ b/core/res/res/values-ml-rIN/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"സ്റ്റോറേജ്  ഒപ്‌റ്റിമൈസ് ചെയ്യുന്നു."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android അപ്ഗ്രേഡുചെയ്യുന്നു"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"അപ്‌ഗ്രേഡ് പൂർത്തിയാകുന്നത് വരെ ചില ആപ്‌സ് ശരിയായി പ്രവർത്തിച്ചേക്കില്ല"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_0">%1$d</xliff:g> / <xliff:g id="NUMBER_1">%2$d</xliff:g> അപ്ലിക്കേഷൻ ഓപ്റ്റിമൈസ് ചെയ്യുന്നു."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> തയ്യാറാക്കുന്നു."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"അപ്ലിക്കേഷനുകൾ ആരംഭിക്കുന്നു."</string>
diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml
index 8160813..0b55a7a 100644
--- a/core/res/res/values-mn-rMN/strings.xml
+++ b/core/res/res/values-mn-rMN/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Хадгалалтыг сайжруулж байна."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Андройдыг дэвшүүлж байна"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"Шинэчилж дуустал зарим апп хэвийн бус ажиллаж болзошгүй"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_1">%2$d</xliff:g>-н <xliff:g id="NUMBER_0">%1$d</xliff:g> апп-г тохируулж байна."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"Бэлдэж байна <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Апп-г эхлүүлж байна."</string>
diff --git a/core/res/res/values-mr-rIN/strings.xml b/core/res/res/values-mr-rIN/strings.xml
index 7d0fa6d..a1269e1 100644
--- a/core/res/res/values-mr-rIN/strings.xml
+++ b/core/res/res/values-mr-rIN/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"संचयन ऑप्टिमाइझ करत आहे."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android श्रेणीसुधारित होत आहे"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"श्रेणीसुधारणा पूर्ण होईपर्यंत काही अॅप्स योग्यरित्या कार्य करणार नाहीत"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_1">%2$d</xliff:g> पैकी <xliff:g id="NUMBER_0">%1$d</xliff:g> अॅप ऑप्टिमाइझ करत आहे."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> तयार करीत आहे."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"अॅप्स प्रारंभ करत आहे."</string>
diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml
index b66ea933..3f9e156 100644
--- a/core/res/res/values-ms-rMY/strings.xml
+++ b/core/res/res/values-ms-rMY/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Mengoptimumkan storan."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android sedang ditingkatkan"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"Sesetengah apl mungkin tidak berfungsi dengan betul sehingga peningkatan selesai"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Mengoptimumkan apl <xliff:g id="NUMBER_0">%1$d</xliff:g> daripada <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"Menyediakan <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Memulakan apl."</string>
diff --git a/core/res/res/values-my-rMM/strings.xml b/core/res/res/values-my-rMM/strings.xml
index e9264af..d7d5902 100644
--- a/core/res/res/values-my-rMM/strings.xml
+++ b/core/res/res/values-my-rMM/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"သိုလှောင်မှုအား ပြုပြင်ခြင်း။"</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android ကိုအဆင့်မြှင့်တင်နေပါသည်"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"အဆင့်မြှင့်တင်ခြင်း မပြီးဆုံးသေးသ၍ အချို့အက်ပ်များကို ကောင်းမွန်စွာအသုံးပြုနိုင်ဦးမည် မဟုတ်ပါ"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_0">%1$d</xliff:g> ထဲက အက်ပ်<xliff:g id="NUMBER_1">%2$d</xliff:g>ကို ဆီလျော်အောင် လုပ်နေ"</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> အားပြင်ဆင်နေသည်။"</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"အက်ပ်များကို စတင်နေ"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 381fc1f..d2e4d71 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Optimaliser lagring."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android oppgraderes"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"Noen apper fungerer kanskje ikke skikkelig før oppgraderingen er fullført"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Optimaliserer app <xliff:g id="NUMBER_0">%1$d</xliff:g> av <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"Forbereder <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Starter apper."</string>
diff --git a/core/res/res/values-ne-rNP/strings.xml b/core/res/res/values-ne-rNP/strings.xml
index 8f382968..b3de0aa 100644
--- a/core/res/res/values-ne-rNP/strings.xml
+++ b/core/res/res/values-ne-rNP/strings.xml
@@ -1030,6 +1030,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"भण्डारण अनुकूलन गर्दै।"</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android को स्तरवृद्धि हुँदैछ"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"स्तरवृद्धि सम्पन्न नभएसम्म केही अनुप्रयोगहरू राम्ररी काम नगर्न सक्छन्"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"अनुप्रयोग अनुकुल हुँदै <xliff:g id="NUMBER_0">%1$d</xliff:g> को <xliff:g id="NUMBER_1">%2$d</xliff:g>।"</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> तयारी गर्दै।"</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"सुरुवात अनुप्रयोगहरू।"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index d43d6c6..f23d046 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Opslagruimte wordt geoptimaliseerd."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android wordt geüpgraded"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"Sommige apps werken mogelijk pas correct nadat de upgrade is voltooid"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"App <xliff:g id="NUMBER_0">%1$d</xliff:g> van <xliff:g id="NUMBER_1">%2$d</xliff:g> optimaliseren."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> voorbereiden."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Apps starten."</string>
diff --git a/core/res/res/values-pa-rIN/strings.xml b/core/res/res/values-pa-rIN/strings.xml
index bea0682..d96b89e 100644
--- a/core/res/res/values-pa-rIN/strings.xml
+++ b/core/res/res/values-pa-rIN/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"ਸਟੋਰੇਜ ਅਨੁਕੂਲ ਕਰ ਰਿਹਾ ਹੈ।"</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android ਅੱਪਗ੍ਰੇਡ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"ਹੋ ਸਕਦਾ ਹੈ ਕਿ ਕੁਝ ਐਪਾਂ ਅੱਪਗ੍ਰੇਡ ਦੇ ਪੂਰੀ ਹੋਣ ਤੱਕ ਸਹੀ ਢੰਗ ਨਾਲ ਕੰਮ ਨਾ ਕਰਨ"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_0">%1$d</xliff:g> <xliff:g id="NUMBER_1">%2$d</xliff:g> ਦਾ ਐਪ ਅਨੁਕੂਲ ਕਰ ਰਿਹਾ ਹੈ।"</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> ਤਿਆਰ ਕਰ ਰਿਹਾ ਹੈ।"</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"ਐਪਸ ਚਾਲੂ ਕਰ ਰਿਹਾ ਹੈ।"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index cff4fe40..dcbf9d04 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -1070,6 +1070,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Optymalizacja pamięci."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android jest uaktualniany"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"Niektóre aplikacje mogą nie działać prawidłowo, dopóki nie zakończy się aktualizacja."</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Optymalizowanie aplikacji <xliff:g id="NUMBER_0">%1$d</xliff:g> z <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"Przygotowuję aplikację <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Uruchamianie aplikacji."</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index f5b2389..6998871 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Otimizando o armazenamento."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"O Android está sendo atualizado"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"Alguns apps podem não funcionar corretamente até que a atualização seja concluída"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Otimizando app <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"Preparando <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Iniciando apps."</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 3079a61..1e96a4d 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"A otimizar o armazenamento."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"O Android está a ser atualizado"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"Algumas aplicações podem não funcionar corretamente enquanto a atualização não for concluída"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"A otimizar a aplicação <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"A preparar o <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"A iniciar aplicações"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index f5b2389..6998871 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Otimizando o armazenamento."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"O Android está sendo atualizado"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"Alguns apps podem não funcionar corretamente até que a atualização seja concluída"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Otimizando app <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"Preparando <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Iniciando apps."</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 0cb12af..0058858 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -1047,6 +1047,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Se optimizează stocarea."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android face upgrade"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"Este posibil ca unele aplicații să nu funcționeze corespunzător până când nu se finalizează upgrade-ul"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Se optimizează aplicația <xliff:g id="NUMBER_0">%1$d</xliff:g> din <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"Se pregătește <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Se pornesc aplicațiile."</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index abd9012..e202854 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1020,7 +1020,7 @@
     <string name="whichEditApplicationLabel" msgid="7183524181625290300">"Изменить"</string>
     <string name="whichSendApplication" msgid="6902512414057341668">"Поделиться с помощью:"</string>
     <string name="whichSendApplicationNamed" msgid="2799370240005424391">"Поделиться через %1$s"</string>
-    <string name="whichSendApplicationLabel" msgid="4579076294675975354">"Открыть доступ"</string>
+    <string name="whichSendApplicationLabel" msgid="4579076294675975354">"Поделиться"</string>
     <string name="whichSendToApplication" msgid="8272422260066642057">"Выберите приложение"</string>
     <string name="whichSendToApplicationNamed" msgid="7768387871529295325">"Отправка с помощью %1$s"</string>
     <string name="whichSendToApplicationLabel" msgid="8878962419005813500">"Отправить"</string>
@@ -1070,6 +1070,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Оптимизация хранилища…"</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Обновление Android"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"Во время обновления возможны неполадки в работе приложений."</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Оптимизация приложения <xliff:g id="NUMBER_0">%1$d</xliff:g> из <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"Подготовка приложения \"<xliff:g id="APPNAME">%1$s</xliff:g>\"..."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Запуск приложений."</string>
diff --git a/core/res/res/values-si-rLK/strings.xml b/core/res/res/values-si-rLK/strings.xml
index c64d1ed..9240212 100644
--- a/core/res/res/values-si-rLK/strings.xml
+++ b/core/res/res/values-si-rLK/strings.xml
@@ -1026,6 +1026,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"ආචයනය ප්‍රශස්තිකරණය කිරීම."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android උත්ශ්‍රේණි කරමින්"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"උත්ශ්‍රේණි කිරීම අවසන් වන තෙක් සමහර යෙදුම් නිසි ලෙස ක්‍රියා නොකළ හැකිය"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_1">%2$d</xliff:g> කින් <xliff:g id="NUMBER_0">%1$d</xliff:g> වැනි යෙදුම ප්‍රශස්ත කරමින්."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> සූදානම් කරමින්."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"යෙදුම් ආරම්භ කරමින්."</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 97180db..e077075 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -1070,6 +1070,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Optimalizuje sa úložisko"</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Prebieha inovácia systému Android"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"Niektoré aplikácie môžu správne fungovať až po dokončení inovácie"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Prebieha optimalizácia aplikácie <xliff:g id="NUMBER_0">%1$d</xliff:g> z <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"Pripravuje sa aplikácia <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Prebieha spúšťanie aplikácií."</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 9653ff8..e1eea81 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -1070,6 +1070,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Optimiziranje shrambe."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Poteka nadgradnja Androida."</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"Nekatere aplikacije morda ne bodo delovale pravilno, dokler ne bo dokončana nadgradnja."</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Optimiranje aplikacije <xliff:g id="NUMBER_0">%1$d</xliff:g> od <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"Pripravljanje aplikacije <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Zagon aplikacij."</string>
diff --git a/core/res/res/values-sq-rAL/strings.xml b/core/res/res/values-sq-rAL/strings.xml
index d9b14dc..5ad7ba4 100644
--- a/core/res/res/values-sq-rAL/strings.xml
+++ b/core/res/res/values-sq-rAL/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Po përshtat ruajtjen."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android po përmirësohet"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"Disa aplikacione mund të mos funksionojnë si duhet deri sa të përfundojë përmirësimi"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Po përshtat aplikacionin <xliff:g id="NUMBER_0">%1$d</xliff:g> nga gjithsej <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"Po përgatit <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Aplikacionet e fillimit."</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index b3fc8ca..7bfc3dd 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -1047,6 +1047,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Меморија се оптимизује."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android се надограђује…"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"Неке апликације можда неће исправно функционисати док се надоградња не доврши"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Оптимизовање апликације <xliff:g id="NUMBER_0">%1$d</xliff:g> од <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"Припрема се <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Покретање апликација."</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 8557f28..8673360 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Lagringsutrymmet optimeras."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android uppgraderas"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"En del appar kanske inte fungerar som de ska innan uppgraderingen har slutförts"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Optimerar app <xliff:g id="NUMBER_0">%1$d</xliff:g> av <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> förbereds."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Appar startas."</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 30f22ff..71d9bf7 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -1022,6 +1022,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Inaboresha hifadhi."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Tunasasisha Android"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"Huenda baadhi ya programu zisifanye kazi vizuri hadi itakapomaliza kusasisha"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Inaboresha programu <xliff:g id="NUMBER_0">%1$d</xliff:g> kutoka <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"Inaandaa <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Programu zinaanza"</string>
diff --git a/core/res/res/values-ta-rIN/strings.xml b/core/res/res/values-ta-rIN/strings.xml
index f606000..823286c 100644
--- a/core/res/res/values-ta-rIN/strings.xml
+++ b/core/res/res/values-ta-rIN/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"சேமிப்பகத்தை உகந்ததாக்குகிறது."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android மேம்படுத்தப்படுகிறது"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"மேம்படுத்துவது முடியும் வரை, சில பயன்பாடுகள் சரியாக வேலைசெய்யாமல் போகக்கூடும்"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_0">%1$d</xliff:g> / <xliff:g id="NUMBER_1">%2$d</xliff:g> பயன்பாட்டை ஒருங்கிணைக்கிறது."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g>ஐத் தயார்செய்கிறது."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"பயன்பாடுகள் தொடங்கப்படுகின்றன."</string>
diff --git a/core/res/res/values-te-rIN/strings.xml b/core/res/res/values-te-rIN/strings.xml
index 56c2eac..6218cdf 100644
--- a/core/res/res/values-te-rIN/strings.xml
+++ b/core/res/res/values-te-rIN/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"నిల్వను అనుకూలపరుస్తోంది."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android అప్‌గ్రేడ్ అవుతోంది"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"అప్‌గ్రేడ్ పూర్తయ్యే వరకు కొన్ని అనువర్తనాలు సరిగ్గా పని చేయకపోవచ్చు"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_1">%2$d</xliff:g>లో <xliff:g id="NUMBER_0">%1$d</xliff:g> అనువర్తనాన్ని అనుకూలీకరిస్తోంది."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g>ని సిద్ధం చేస్తోంది."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"అనువర్తనాలను ప్రారంభిస్తోంది."</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index b64eb8f..2dfd2e7 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"กำลังเพิ่มประสิทธิภาพพื้นที่จัดเก็บข้อมูล"</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android กำลังอัปเกรด"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"แอปบางแอปอาจทำงานไม่ถูกต้องจนกว่าจะอัปเกรดเสร็จ"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"กำลังเพิ่มประสิทธิภาพแอปพลิเคชัน <xliff:g id="NUMBER_0">%1$d</xliff:g> จาก <xliff:g id="NUMBER_1">%2$d</xliff:g> รายการ"</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"กำลังเตรียม <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"กำลังเริ่มต้นแอปพลิเคชัน"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 7c91c68..8553992 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Ino-optimize ang storage."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Nag-a-upgrade ang Android"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"Maaaring hindi gumana nang maayos ang ilang app hangga\'t hindi pa natatapos ang pag-upgrade"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Ino-optimize ang app <xliff:g id="NUMBER_0">%1$d</xliff:g> ng <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"Ihinahanda ang <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Sinisimulan ang apps."</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 805f1d2..1033e11 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Depolama optimize ediliyor."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android yeni sürüme geçiriliyor"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"Yeni sürüme geçiş işlemi tamamlanana kadar bazı uygulamalar düzgün çalışmayabilir"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_0">%1$d</xliff:g>/<xliff:g id="NUMBER_1">%2$d</xliff:g> uygulama optimize ediliyor."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> hazırlanıyor."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Uygulamalar başlatılıyor"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 6694981..21c1e3f 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -1070,6 +1070,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Оптимізація пам’яті."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android оновлюється"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"Деякі додатки можуть не працювати належним чином, доки не завершиться оновлення"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Оптимізація програми <xliff:g id="NUMBER_0">%1$d</xliff:g> з <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"Підготовка додатка <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Запуск програм."</string>
diff --git a/core/res/res/values-ur-rPK/strings.xml b/core/res/res/values-ur-rPK/strings.xml
index 651d9ea..ff99fb0 100644
--- a/core/res/res/values-ur-rPK/strings.xml
+++ b/core/res/res/values-ur-rPK/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"اسٹوریج کو بہترین بنایا جا رہا ہے۔"</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"‏Android اپ گریڈ ہو رہا ہے"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"اپ گریڈ ختم ہونے تک شاید کچھ ایپس ٹھیک طرح سے کام نہ کریں"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"ایپ <xliff:g id="NUMBER_0">%1$d</xliff:g> از <xliff:g id="NUMBER_1">%2$d</xliff:g> کو بہتر بنایا جا رہا ہے۔"</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> تیار ہو رہی ہے۔"</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"ایپس شروع ہو رہی ہیں۔"</string>
diff --git a/core/res/res/values-uz-rUZ/strings.xml b/core/res/res/values-uz-rUZ/strings.xml
index 03d16b7..194b506 100644
--- a/core/res/res/values-uz-rUZ/strings.xml
+++ b/core/res/res/values-uz-rUZ/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Xotira optimallashtirilmoqda."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android yangilanmoqda"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"Yangilanish vaqtida ba’zi ilovalar to‘g‘ri ishlamasligi mumkin"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Ilovalar optimallashtirilmoqda (<xliff:g id="NUMBER_0">%1$d</xliff:g> / <xliff:g id="NUMBER_1">%2$d</xliff:g>)."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> tayyorlanmoqda."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Ilovalar ishga tushirilmoqda."</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index a302ae4..4ce86cf 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Tối ưu hóa lưu trữ."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android đang nâng cấp"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"Một số ứng dụng có thể không hoạt động bình thường cho đến khi nâng cấp xong"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Đang tối ưu hóa ứng dụng <xliff:g id="NUMBER_0">%1$d</xliff:g> trong tổng số <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"Đang chuẩn bị <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Khởi động ứng dụng."</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index b5b87c7..3b2abe7 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"正在优化存储空间。"</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android 正在升级"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"在升级完成之前,部分应用可能无法正常运行"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"正在优化第<xliff:g id="NUMBER_0">%1$d</xliff:g>个应用(共<xliff:g id="NUMBER_1">%2$d</xliff:g>个)。"</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"正在准备升级<xliff:g id="APPNAME">%1$s</xliff:g>。"</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"正在启动应用。"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index d912ce5..5aa4648 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"正在優化儲存空間。"</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"正在升級 Android"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"部分應用程式需要完成升級方可正常運作"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"正在優化第 <xliff:g id="NUMBER_0">%1$d</xliff:g> 個應用程式 (共 <xliff:g id="NUMBER_1">%2$d</xliff:g> 個)。"</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"正在準備 <xliff:g id="APPNAME">%1$s</xliff:g>。"</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"正在啟動應用程式。"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 3c6c2b3..cd3ee3a 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"正在對儲存空間進行最佳化處理。"</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"正在升級 Android"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"升級完成前,部分應用程式可能無法正常運作"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"正在最佳化第 <xliff:g id="NUMBER_0">%1$d</xliff:g> 個應用程式 (共 <xliff:g id="NUMBER_1">%2$d</xliff:g> 個)。"</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"正在準備升級「<xliff:g id="APPNAME">%1$s</xliff:g>」。"</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"正在啟動應用程式。"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index e29b05f..b00b745 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -1024,6 +1024,8 @@
     <string name="android_upgrading_fstrim" msgid="8036718871534640010">"Ikhulisa isitoreji."</string>
     <string name="android_upgrading_notification_title" msgid="1619393112444671028">"I-Android iyathuthukiswa"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"Ezinye izinhlelo zokusebenza kungenzeka zingasebenzi kahle kuze kuqedwe ukuthuthukiswa"</string>
+    <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+    <skip />
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Ukubeka ezingeni eliphezulu <xliff:g id="NUMBER_0">%1$d</xliff:g> uhlelo lokusebenza <xliff:g id="NUMBER_1">%2$d</xliff:g>"</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"Ukulungisela i-<xliff:g id="APPNAME">%1$s</xliff:g>."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Qalisa izinhlelo zokusebenza."</string>
diff --git a/core/tests/coretests/src/android/app/ApplicationErrorReportTest.java b/core/tests/coretests/src/android/app/ApplicationErrorReportTest.java
new file mode 100644
index 0000000..19a390a
--- /dev/null
+++ b/core/tests/coretests/src/android/app/ApplicationErrorReportTest.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2016 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.app;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import android.app.ApplicationErrorReport.CrashInfo;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class ApplicationErrorReportTest {
+
+    @Test
+    public void testHugeStacktraceLeadsToReasonableReport() {
+        Throwable deepStackTrace = deepStackTrace();
+        CrashInfo crashInfo = new CrashInfo(deepStackTrace);
+
+        assertTrue("stack trace is longer than 50'000 characters",
+                crashInfo.stackTrace.length() < 50000);
+    }
+
+    @Test
+    public void testHugeExceptionMessageLeadsToReasonableReport() {
+        StringBuilder msg = new StringBuilder();
+        for (int i = 0; i < 1000000; i++) {
+            msg.append('x');
+        }
+
+        CrashInfo crashInfo = new CrashInfo(new Throwable(msg.toString()));
+
+        assertTrue("message is longer than 50'000 characters",
+                crashInfo.exceptionMessage.length() < 50000);
+    }
+
+    @Test
+    public void testTruncationKeepsStartAndEndIntact() {
+        StringBuilder msg = new StringBuilder("start");
+        for (int i = 0; i < 1000000; i++) {
+            msg.append('x');
+        }
+        msg.append("end");
+
+        CrashInfo crashInfo = new CrashInfo(new Throwable(msg.toString()));
+
+        String exceptionMessage = crashInfo.exceptionMessage;
+        assertEquals("start", exceptionMessage.substring(0, "start".length()));
+        assertEquals("end", exceptionMessage.substring(exceptionMessage.length() - "end".length()));
+    }
+
+    /**
+     * @return a Throwable with a very long stack trace.
+     */
+    private Throwable deepStackTrace() {
+        return stackTraceGenerator__aaaaaaaaa_aaaaaaaaa_aaaaaaaaa_aaaaaaaaa_aaaaaaaaa(1000);
+    }
+
+    private Throwable stackTraceGenerator__aaaaaaaaa_aaaaaaaaa_aaaaaaaaa_aaaaaaaaa_aaaaaaaaa(
+            int d) {
+        if (d > 0) {
+            return stackTraceGenerator__aaaaaaaaa_aaaaaaaaa_aaaaaaaaa_aaaaaaaaa_aaaaaaaaa(d - 1);
+        } else {
+            return new Throwable("here");
+        }
+    }
+}
diff --git a/core/tests/coretests/src/android/text/method/BackspaceTest.java b/core/tests/coretests/src/android/text/method/BackspaceTest.java
index a9fa4dd..fd686b9 100644
--- a/core/tests/coretests/src/android/text/method/BackspaceTest.java
+++ b/core/tests/coretests/src/android/text/method/BackspaceTest.java
@@ -170,10 +170,27 @@
         backspace(state, 0);
         state.assertEquals("|");
 
+        state.setByString("U+1F469 U+200D U+1F373 |");
+        backspace(state, 0);
+        state.assertEquals("|");
+
+        state.setByString("U+1F487 U+200D U+2640 |");
+        backspace(state, 0);
+        state.assertEquals("|");
+
+        state.setByString("U+1F487 U+200D U+2640 U+FE0F |");
+        backspace(state, 0);
+        state.assertEquals("|");
+
         state.setByString("U+1F468 U+200D U+2764 U+FE0F U+200D U+1F48B U+200D U+1F468 |");
         backspace(state, 0);
         state.assertEquals("|");
 
+        // Emoji modifier can be appended to the first emoji.
+        state.setByString("U+1F469 U+1F3FB U+200D U+1F4BC |");
+        backspace(state, 0);
+        state.assertEquals("|");
+
         // End with ZERO WIDTH JOINER
         state.setByString("U+1F441 U+200D |");
         backspace(state, 0);
@@ -445,13 +462,6 @@
         backspace(state, 0);
         state.assertEquals("|");
 
-        // Emoji modifier + ZERO WIDTH JOINER
-        state.setByString("U+1F466 U+1F3FB U+200D U+1F469 |");
-        backspace(state, 0);
-        state.assertEquals("U+1F466 |");
-        backspace(state, 0);
-        state.assertEquals("|");
-
         // Regional indicator symbol + Emoji modifier
         state.setByString("U+1F1FA U+1F3FB |");
         backspace(state, 0);
diff --git a/docs/html-intl/intl/es/preview/download-ota.jd b/docs/html-intl/intl/es/preview/download-ota.jd
index d3e8be9..2b2bcbf 100644
--- a/docs/html-intl/intl/es/preview/download-ota.jd
+++ b/docs/html-intl/intl/es/preview/download-ota.jd
@@ -178,7 +178,7 @@
 <ol>
   <li>Descargar una imagen de dispositivo inalámbrico de la tabla que verás a continuación.</li>
   <li>Reinicia el dispositivo en modo Recuperación. Para leer más información sobre cómo
-    aplicar este modo en dispositivos Nexus, visita la sección 
+    aplicar este modo en dispositivos Nexus, visita la sección
 <a href="https://support.google.com/nexus/answer/4596836">Reset your Nexus
       device to factory settings</a>.
   </li>
@@ -202,65 +202,73 @@
 
   <tr id="bullhead">
     <td>Nexus 5X <br>"bullhead"</td>
-    <td><a href="#top" onclick="onDownload(this)">bullhead-ota-npd35k-b8cfbd80.zip</a><br>
-      MD5: 15fe2eba9b01737374196bdf0a792fe9<br>
-      SHA-1: 5014b2bba77f9e1a680ac3f90729621c85a14283
+    <td><a href="#top" onclick="onDownload(this)"
+      >bullhead-ota-npd90g-0a874807.zip</a><br>
+      MD5: 4b83b803fac1a6eec13f66d0afc6f46e<br>
+      SHA-1: a9920bcc8d475ce322cada097d085448512635e2
     </td>
   </tr>
 
   <tr id="shamu">
     <td>Nexus 6 <br>"shamu"</td>
-    <td><a href="#top" onclick="onDownload(this)">shamu-ota-npd35k-078e6fa5.zip</a><br>
-      MD5: e8b12f7721c53af9a450f7058928a5fc<br>
-      SHA-1: b7a9b756f84a1d2e482ff9c16749d65f6e51425a
+    <td><a href="#top" onclick="onDownload(this)"
+      >shamu-ota-npd90g-06f5d23d.zip</a><br>
+      MD5: 513570bb3a91878c2d1a5807d2340420<br>
+      SHA-1: 2d2f40636c95c132907e6ba0d10b395301e969ed
     </td>
   </tr>
 
   <tr id="angler">
     <td>Nexus 6P <br>"angler"</td>
-    <td><a href="#top" onclick="onDownload(this)">angler-ota-npd35k-88457699.zip</a><br>
-      MD5: 3fac09fef759dde26e57cb80b20b6477<br>
-      SHA-1: 27d6caa786577d8a38b2da5bf94b33b4524a1a1c
+    <td><a href="#top" onclick="onDownload(this)"
+      >angler-ota-npd90g-5baa69c2.zip</a><br>
+      MD5: 096fe26c5d50606a424d2f3326c0477b<br>
+      SHA-1: 468d2e7aea444505513ddc183c85690c00fab0c1
     </td>
   </tr>
 
   <tr id="volantis">
     <td>Nexus 9 <br>"volantis"</td>
-    <td><a href="#top" onclick="onDownload(this)">volantis-ota-npd35k-51dbae76.zip</a><br>
-      MD5: 58312c4a5971818ef5c77a3f446003da<br>
-      SHA-1: aad9005be33d3e2bab480509a6ab74c3c3b9d921
+    <td><a href="#top" onclick="onDownload(this)"
+      >volantis-ota-npd90g-c04785e1.zip</a><br>
+      MD5: 6aecd3b0b3a839c5ce1ce4d12187b03e<br>
+      SHA-1: 31633180635b831e59271a7d904439f278586f49
     </td>
   </tr>
 
   <tr id="volantisg">
     <td>Nexus 9G <br>"volantisg"</td>
-    <td><a href="#top" onclick="onDownload(this)">volantisg-ota-npd35k-834f047f.zip</a><br>
-      MD5: 92b7d1fa252f7394e70f957c72d4aac8<br>
-      SHA-1: b6c057c84d90893630e303cbb60530e20ddb8361
+    <td><a href="#top" onclick="onDownload(this)"
+      >volantisg-ota-npd90g-c56aa1b0.zip</a><br>
+      MD5: 0493fa79763d67bcdde8007299e1888d<br>
+      SHA-1: f709daf81968a1b27ed41fe40d42e0d106f3c494
     </td>
   </tr>
 
   <tr id="fugu">
     <td>Nexus Player <br>"fugu"</td>
-    <td><a href="#top" onclick="onDownload(this)">fugu-ota-npd35k-6ac91298.zip</a><br>
-      MD5: 1461622ad53ea842b2722fa7b49b8172<br>
-      SHA-1: 409c061668ab270774877d7f3eae44fa48d2b931
+    <td><a href="#top" onclick="onDownload(this)"
+      >fugu-ota-npd90g-3a0643ae.zip</a><br>
+      MD5: 9c38b6647fe5a4f2965196b7c409f0f7<br>
+      SHA-1: 77c6fb05191f0c2ae0956bae18f1c80b2f922f05
     </td>
   </tr>
 
   <tr id="ryu">
     <td>Pixel C <br>"ryu"</td>
-    <td><a href="#top" onclick="onDownload(this)">ryu-ota-npd35k-a0b2347f.zip</a><br>
-      MD5: c60117f3640cc6db12386fd632289c7d<br>
-      SHA-1: 87349c767c69efb4172c90ce1d88cf578c3d28b3
+    <td><a href="#top" onclick="onDownload(this)"
+      >ryu-ota-npd90g-ec931914.zip</a><br>
+      MD5: 4c6135498ca156a9cdaf443ddfdcb2ba<br>
+      SHA-1: 297cc9a204685ef5507ec087fc7edf5b34551ce6
     </td>
   </tr>
 
   <tr id="seed">
     <td>General Mobile 4G (Android One) <br>"seed"</td>
-    <td><a href="#top" onclick="onDownload(this)">seed_l8150-ota-npd35k-09897a1d.zip</a><br>
-      MD5: a55cf94f7cce0393ec6c0b35041766b7<br>
-      SHA-1: 6f33742290eb46f2561891f38ca2e754b4e50c6a
+    <td><a href="#top" onclick="onDownload(this)"
+      >seed_l8150-ota-npd90g-dcb0662d.zip</a><br>
+      MD5: f40ea6314a13ea6dd30d0e68098532a2<br>
+      SHA-1: 11af10b621f4480ac63f4e99189d61e1686c0865
     </td>
   </tr>
 
diff --git a/docs/html-intl/intl/es/preview/download.jd b/docs/html-intl/intl/es/preview/download.jd
index d489074..4662d5b 100644
--- a/docs/html-intl/intl/es/preview/download.jd
+++ b/docs/html-intl/intl/es/preview/download.jd
@@ -209,7 +209,7 @@
 <h2 id="device-preview">Configurar un dispositivo de hardware</h2>
 
 <p>
-  En N Developer Preview se ofrecen actualizaciones del sistema para una variedad de dispositivos de hardware 
+  En N Developer Preview se ofrecen actualizaciones del sistema para una variedad de dispositivos de hardware
 que puedes usar para realizarle pruebas a tu aplicación, desde teléfonos hasta tablets y TV.
 </p>
 
@@ -300,65 +300,73 @@
 
   <tr id="bullhead">
     <td>Nexus 5X <br>"bullhead"</td>
-    <td><a href="#top" onclick="onDownload(this)">bullhead-npd35k-factory-5ba40535.tgz</a><br>
-      MD5: b6c5d79a21815ee21db41822dcf61e9f<br>
-      SHA-1: 5ba4053577007d15c96472206e3a79bc80ab194c
+    <td><a href="#top" onclick="onDownload(this)"
+      >bullhead-npd90g-factory-7a0ca1bc.tgz</a><br>
+      MD5: e7a9a3061335c1e0c8be2588f13290af<br>
+      SHA-1: 7a0ca1bcfa51bbefde34243603bc79c7dec214a1
     </td>
   </tr>
 
   <tr id="shamu">
     <td>Nexus 6 <br>"shamu"</td>
-    <td><a href="#top" onclick="onDownload(this)">shamu-npd35k-factory-a33bf20c.tgz</a><br>
-      MD5: e1cf9c57cfb11bebe7f1f5bfbf05d7ab<br>
-      SHA-1: a33bf20c719206bcf08d1edd8da6c0ff9d50f69c
+    <td><a href="#top" onclick="onDownload(this)"
+      >shamu-npd90g-factory-f7a4e3a9.tgz</a><br>
+      MD5: 2fb572ddcfca67bb1d741be97492a9ed<br>
+      SHA-1: f7a4e3a96c797827492998e855c8f9efbfc8559a
     </td>
   </tr>
 
   <tr id="angler">
     <td>Nexus 6P <br>"angler"</td>
-    <td><a href="#top" onclick="onDownload(this)">angler-npd35k-factory-81c341d5.tgz</a><br>
-      MD5: e93de7949433339856124c3729c15ebb<br>
-      SHA-1: 81c341d57ef2cd139569b055d5d59e9e592a7abd
+    <td><a href="#top" onclick="onDownload(this)"
+      >angler-npd90g-factory-cd9ac81e.tgz</a><br>
+      MD5: 2370c30f3ef1d0684c1de5216a5d90fe<br>
+      SHA-1: cd9ac81ec7f4a646ac6054eecbf2ea4c4b89b054
     </td>
   </tr>
 
   <tr id="volantis">
     <td>Nexus 9 <br>"volantis"</td>
-    <td><a href="#top" onclick="onDownload(this)">volantis-npd35k-factory-2b50e19d.tgz</a><br>
-      MD5: 565be87ebb2d5937e2abe1a42645864b<br>
-      SHA-1: 2b50e19dae2667b27f911e3c61ed64860caf43e1
+    <td><a href="#top" onclick="onDownload(this)"
+      >volantis-npd90g-factory-41b55406.tgz</a><br>
+      MD5: cefa78950141da2a7c75e887717e3c8f<br>
+      SHA-1: 41b554060263a7ef16e4be8422cbd6caca26e00f
     </td>
   </tr>
 
   <tr id="volantisg">
     <td>Nexus 9G <br>"volantisg"</td>
-    <td><a href="#top" onclick="onDownload(this)">volantisg-npd35k-factory-2e89ebe6.tgz</a><br>
-      MD5: a8464e15c6683fe2afa378a63e205fda<br>
-      SHA-1: 2e89ebe67a46b2f3beb050746c13341cd11fa678
+    <td><a href="#top" onclick="onDownload(this)"
+      >volantisg-npd90g-factory-610492be.tgz</a><br>
+      MD5: 2f36dc0d0fab02ab78be500677ec239f<br>
+      SHA-1: 610492bedfc4127023040ecb2c89239a78a900ad
     </td>
   </tr>
 
   <tr id="fugu">
     <td>Nexus Player <br>"fugu"</td>
-    <td><a href="#top" onclick="onDownload(this)">fugu-npd35k-factory-1de74874.tgz</a><br>
-      MD5: c0dbb7db671f61b2785da5001cedefcb<br>
-      SHA-1: 1de74874f8d83e14d642f13b5a2130fc2aa55873
+    <td><a href="#top" onclick="onDownload(this)"
+      >fugu-npd90g-factory-0fe95694.tgz</a><br>
+      MD5: f4cb48f919e4c29c631de21416c612e2<br>
+      SHA-1: 0fe95694e7bc41e4c3ac0e4438cd77102a0aa8b4
     </td>
   </tr>
 
   <tr id="ryu">
     <td>Pixel C <br>"ryu"</td>
-    <td><a href="#top" onclick="onDownload(this)">ryu-npd35k-factory-b4eed85d.tgz</a><br>
-      MD5: bdcb6f770e753668b5fadff2a6678e0d<br>
-      SHA-1: b4eed85de0d42c200348a8629084f78e24f72ac2
+    <td><a href="#top" onclick="onDownload(this)"
+      >ryu-npd90g-factory-f4da981c.tgz</a><br>
+      MD5: d9f0e40b6c20d274831e8a7d285fd887<br>
+      SHA-1: f4da981c70576133321e2858e52fe2c990e68a75
     </td>
   </tr>
 
   <tr id="seed">
     <td>General Mobile 4G (Android One) <br>"seed"</td>
-    <td><a href="#top" onclick="onDownload(this)">seed_l8150-npd35k-factory-5ab1212b.tgz</a><br>
-      MD5: 7d34a9774fdd6e025d485ce6cfc23c4c<br>
-      SHA-1: 5ab1212bc9417269d391aacf1e672fff24b4ecc5
+    <td><a href="#top" onclick="onDownload(this)"
+      >seed_l8150-npd90g-factory-48f59c99.tgz</a><br>
+      MD5: 0ed565c509594072822d71c65b48ec8e<br>
+      SHA-1: 48f59c99ac43d1cd2f5656a283bb9868581663a8
     </td>
   </tr>
 
@@ -377,7 +385,7 @@
   Si quieres desinstalar la muestra desde un dispositivo, puedes hacerlo de las
   siguientes maneras: </p>
   <ul>
-    <li><strong>Obtener una imagen de sistema con las especificaciones de fábrica</strong> y luego actualízala de manera manual 
+    <li><strong>Obtener una imagen de sistema con las especificaciones de fábrica</strong> y luego actualízala de manera manual
     para el dispositivo.
       <ul>
           <li>Para <strong>los dispositivos Nexus y Pixel C</strong>, consulta
@@ -466,8 +474,8 @@
 
 <p>
 A fin de garantizar la mejor experiencia en el emulador de Android, verifica que estás utilizando
-Android Studio 2.1 o una versión superior, compatible con el <a href="http://tools.android.com/tech-docs/emulator">emulador de Android 2.0</a>, 
-cuyo rendimiento es mayor si se lo compara con el emulador utilizado en 
+Android Studio 2.1 o una versión superior, compatible con el <a href="http://tools.android.com/tech-docs/emulator">emulador de Android 2.0</a>,
+cuyo rendimiento es mayor si se lo compara con el emulador utilizado en
 Android Studio 1.5.</p>
 
 <p>Para obtener más información sobre la creación de dispositivos virtuales, consulta <a href="{@docRoot}tools/devices/index.html">Administración de dispositivos virtuales</a>.
diff --git a/docs/html-intl/intl/in/preview/download-ota.jd b/docs/html-intl/intl/in/preview/download-ota.jd
index 1efe9b7..4adf9bb 100644
--- a/docs/html-intl/intl/in/preview/download-ota.jd
+++ b/docs/html-intl/intl/in/preview/download-ota.jd
@@ -202,65 +202,73 @@
 
   <tr id="bullhead">
     <td>Nexus 5X <br>"bullhead"</td>
-    <td><a href="#top" onclick="onDownload(this)">bullhead-ota-npd35k-b8cfbd80.zip</a><br>
-      MD5: 15fe2eba9b01737374196bdf0a792fe9<br>
-      SHA-1: 5014b2bba77f9e1a680ac3f90729621c85a14283
+    <td><a href="#top" onclick="onDownload(this)"
+      >bullhead-ota-npd90g-0a874807.zip</a><br>
+      MD5: 4b83b803fac1a6eec13f66d0afc6f46e<br>
+      SHA-1: a9920bcc8d475ce322cada097d085448512635e2
     </td>
   </tr>
 
   <tr id="shamu">
     <td>Nexus 6 <br>"shamu"</td>
-    <td><a href="#top" onclick="onDownload(this)">shamu-ota-npd35k-078e6fa5.zip</a><br>
-      MD5: e8b12f7721c53af9a450f7058928a5fc<br>
-      SHA-1: b7a9b756f84a1d2e482ff9c16749d65f6e51425a
+    <td><a href="#top" onclick="onDownload(this)"
+      >shamu-ota-npd90g-06f5d23d.zip</a><br>
+      MD5: 513570bb3a91878c2d1a5807d2340420<br>
+      SHA-1: 2d2f40636c95c132907e6ba0d10b395301e969ed
     </td>
   </tr>
 
   <tr id="angler">
     <td>Nexus 6P <br>"angler"</td>
-    <td><a href="#top" onclick="onDownload(this)">angler-ota-npd35k-88457699.zip</a><br>
-      MD5: 3fac09fef759dde26e57cb80b20b6477<br>
-      SHA-1: 27d6caa786577d8a38b2da5bf94b33b4524a1a1c
+    <td><a href="#top" onclick="onDownload(this)"
+      >angler-ota-npd90g-5baa69c2.zip</a><br>
+      MD5: 096fe26c5d50606a424d2f3326c0477b<br>
+      SHA-1: 468d2e7aea444505513ddc183c85690c00fab0c1
     </td>
   </tr>
 
   <tr id="volantis">
     <td>Nexus 9 <br>"volantis"</td>
-    <td><a href="#top" onclick="onDownload(this)">volantis-ota-npd35k-51dbae76.zip</a><br>
-      MD5: 58312c4a5971818ef5c77a3f446003da<br>
-      SHA-1: aad9005be33d3e2bab480509a6ab74c3c3b9d921
+    <td><a href="#top" onclick="onDownload(this)"
+      >volantis-ota-npd90g-c04785e1.zip</a><br>
+      MD5: 6aecd3b0b3a839c5ce1ce4d12187b03e<br>
+      SHA-1: 31633180635b831e59271a7d904439f278586f49
     </td>
   </tr>
 
   <tr id="volantisg">
     <td>Nexus 9G <br>"volantisg"</td>
-    <td><a href="#top" onclick="onDownload(this)">volantisg-ota-npd35k-834f047f.zip</a><br>
-      MD5: 92b7d1fa252f7394e70f957c72d4aac8<br>
-      SHA-1: b6c057c84d90893630e303cbb60530e20ddb8361
+    <td><a href="#top" onclick="onDownload(this)"
+      >volantisg-ota-npd90g-c56aa1b0.zip</a><br>
+      MD5: 0493fa79763d67bcdde8007299e1888d<br>
+      SHA-1: f709daf81968a1b27ed41fe40d42e0d106f3c494
     </td>
   </tr>
 
   <tr id="fugu">
     <td>Nexus Player <br>"fugu"</td>
-    <td><a href="#top" onclick="onDownload(this)">fugu-ota-npd35k-6ac91298.zip</a><br>
-      MD5: 1461622ad53ea842b2722fa7b49b8172<br>
-      SHA-1: 409c061668ab270774877d7f3eae44fa48d2b931
+    <td><a href="#top" onclick="onDownload(this)"
+      >fugu-ota-npd90g-3a0643ae.zip</a><br>
+      MD5: 9c38b6647fe5a4f2965196b7c409f0f7<br>
+      SHA-1: 77c6fb05191f0c2ae0956bae18f1c80b2f922f05
     </td>
   </tr>
 
   <tr id="ryu">
     <td>Pixel C <br>"ryu"</td>
-    <td><a href="#top" onclick="onDownload(this)">ryu-ota-npd35k-a0b2347f.zip</a><br>
-      MD5: c60117f3640cc6db12386fd632289c7d<br>
-      SHA-1: 87349c767c69efb4172c90ce1d88cf578c3d28b3
+    <td><a href="#top" onclick="onDownload(this)"
+      >ryu-ota-npd90g-ec931914.zip</a><br>
+      MD5: 4c6135498ca156a9cdaf443ddfdcb2ba<br>
+      SHA-1: 297cc9a204685ef5507ec087fc7edf5b34551ce6
     </td>
   </tr>
 
   <tr id="seed">
     <td>General Mobile 4G (Android One) <br>"seed"</td>
-    <td><a href="#top" onclick="onDownload(this)">seed_l8150-ota-npd35k-09897a1d.zip</a><br>
-      MD5: a55cf94f7cce0393ec6c0b35041766b7<br>
-      SHA-1: 6f33742290eb46f2561891f38ca2e754b4e50c6a
+    <td><a href="#top" onclick="onDownload(this)"
+      >seed_l8150-ota-npd90g-dcb0662d.zip</a><br>
+      MD5: f40ea6314a13ea6dd30d0e68098532a2<br>
+      SHA-1: 11af10b621f4480ac63f4e99189d61e1686c0865
     </td>
   </tr>
 
diff --git a/docs/html-intl/intl/in/preview/download.jd b/docs/html-intl/intl/in/preview/download.jd
index a759a11..abf911d 100644
--- a/docs/html-intl/intl/in/preview/download.jd
+++ b/docs/html-intl/intl/in/preview/download.jd
@@ -300,65 +300,73 @@
 
   <tr id="bullhead">
     <td>Nexus 5X <br>"bullhead"</td>
-    <td><a href="#top" onclick="onDownload(this)">bullhead-npd35k-factory-5ba40535.tgz</a><br>
-      MD5: b6c5d79a21815ee21db41822dcf61e9f<br>
-      SHA-1: 5ba4053577007d15c96472206e3a79bc80ab194c
+    <td><a href="#top" onclick="onDownload(this)"
+      >bullhead-npd90g-factory-7a0ca1bc.tgz</a><br>
+      MD5: e7a9a3061335c1e0c8be2588f13290af<br>
+      SHA-1: 7a0ca1bcfa51bbefde34243603bc79c7dec214a1
     </td>
   </tr>
 
   <tr id="shamu">
     <td>Nexus 6 <br>"shamu"</td>
-    <td><a href="#top" onclick="onDownload(this)">shamu-npd35k-factory-a33bf20c.tgz</a><br>
-      MD5: e1cf9c57cfb11bebe7f1f5bfbf05d7ab<br>
-      SHA-1: a33bf20c719206bcf08d1edd8da6c0ff9d50f69c
+    <td><a href="#top" onclick="onDownload(this)"
+      >shamu-npd90g-factory-f7a4e3a9.tgz</a><br>
+      MD5: 2fb572ddcfca67bb1d741be97492a9ed<br>
+      SHA-1: f7a4e3a96c797827492998e855c8f9efbfc8559a
     </td>
   </tr>
 
   <tr id="angler">
     <td>Nexus 6P <br>"angler"</td>
-    <td><a href="#top" onclick="onDownload(this)">angler-npd35k-factory-81c341d5.tgz</a><br>
-      MD5: e93de7949433339856124c3729c15ebb<br>
-      SHA-1: 81c341d57ef2cd139569b055d5d59e9e592a7abd
+    <td><a href="#top" onclick="onDownload(this)"
+      >angler-npd90g-factory-cd9ac81e.tgz</a><br>
+      MD5: 2370c30f3ef1d0684c1de5216a5d90fe<br>
+      SHA-1: cd9ac81ec7f4a646ac6054eecbf2ea4c4b89b054
     </td>
   </tr>
 
   <tr id="volantis">
     <td>Nexus 9 <br>"volantis"</td>
-    <td><a href="#top" onclick="onDownload(this)">volantis-npd35k-factory-2b50e19d.tgz</a><br>
-      MD5: 565be87ebb2d5937e2abe1a42645864b<br>
-      SHA-1: 2b50e19dae2667b27f911e3c61ed64860caf43e1
+    <td><a href="#top" onclick="onDownload(this)"
+      >volantis-npd90g-factory-41b55406.tgz</a><br>
+      MD5: cefa78950141da2a7c75e887717e3c8f<br>
+      SHA-1: 41b554060263a7ef16e4be8422cbd6caca26e00f
     </td>
   </tr>
 
   <tr id="volantisg">
     <td>Nexus 9G <br>"volantisg"</td>
-    <td><a href="#top" onclick="onDownload(this)">volantisg-npd35k-factory-2e89ebe6.tgz</a><br>
-      MD5: a8464e15c6683fe2afa378a63e205fda<br>
-      SHA-1: 2e89ebe67a46b2f3beb050746c13341cd11fa678
+    <td><a href="#top" onclick="onDownload(this)"
+      >volantisg-npd90g-factory-610492be.tgz</a><br>
+      MD5: 2f36dc0d0fab02ab78be500677ec239f<br>
+      SHA-1: 610492bedfc4127023040ecb2c89239a78a900ad
     </td>
   </tr>
 
   <tr id="fugu">
     <td>Nexus Player <br>"fugu"</td>
-    <td><a href="#top" onclick="onDownload(this)">fugu-npd35k-factory-1de74874.tgz</a><br>
-      MD5: c0dbb7db671f61b2785da5001cedefcb<br>
-      SHA-1: 1de74874f8d83e14d642f13b5a2130fc2aa55873
+    <td><a href="#top" onclick="onDownload(this)"
+      >fugu-npd90g-factory-0fe95694.tgz</a><br>
+      MD5: f4cb48f919e4c29c631de21416c612e2<br>
+      SHA-1: 0fe95694e7bc41e4c3ac0e4438cd77102a0aa8b4
     </td>
   </tr>
 
   <tr id="ryu">
     <td>Pixel C <br>"ryu"</td>
-    <td><a href="#top" onclick="onDownload(this)">ryu-npd35k-factory-b4eed85d.tgz</a><br>
-      MD5: bdcb6f770e753668b5fadff2a6678e0d<br>
-      SHA-1: b4eed85de0d42c200348a8629084f78e24f72ac2
+    <td><a href="#top" onclick="onDownload(this)"
+      >ryu-npd90g-factory-f4da981c.tgz</a><br>
+      MD5: d9f0e40b6c20d274831e8a7d285fd887<br>
+      SHA-1: f4da981c70576133321e2858e52fe2c990e68a75
     </td>
   </tr>
 
   <tr id="seed">
     <td>General Mobile 4G (Android One) <br>"seed"</td>
-    <td><a href="#top" onclick="onDownload(this)">seed_l8150-npd35k-factory-5ab1212b.tgz</a><br>
-      MD5: 7d34a9774fdd6e025d485ce6cfc23c4c<br>
-      SHA-1: 5ab1212bc9417269d391aacf1e672fff24b4ecc5
+    <td><a href="#top" onclick="onDownload(this)"
+      >seed_l8150-npd90g-factory-48f59c99.tgz</a><br>
+      MD5: 0ed565c509594072822d71c65b48ec8e<br>
+      SHA-1: 48f59c99ac43d1cd2f5656a283bb9868581663a8
     </td>
   </tr>
 
@@ -458,7 +466,7 @@
     <strong>x86</strong> ABI), kemudian klik <strong>Next</strong>.
     (Hanya citra sistem x86 yang saat ini didukung dengan Android Emulator
 untuk Android N Preview.)
-  <li>Selesaikan konfigurasi AVD selanjutnya dan klik 
+  <li>Selesaikan konfigurasi AVD selanjutnya dan klik
     <strong>Finish</strong>.</li>
 </ol>
 
diff --git a/docs/html-intl/intl/ja/preview/download-ota.jd b/docs/html-intl/intl/ja/preview/download-ota.jd
index 1107baf..835597b 100644
--- a/docs/html-intl/intl/ja/preview/download-ota.jd
+++ b/docs/html-intl/intl/ja/preview/download-ota.jd
@@ -202,65 +202,73 @@
 
   <tr id="bullhead">
     <td>Nexus 5X <br>"bullhead"</td>
-    <td><a href="#top" onclick="onDownload(this)">bullhead-ota-npd35k-b8cfbd80.zip</a><br>
-      MD5:15fe2eba9b01737374196bdf0a792fe9<br>
-      SHA-1:5014b2bba77f9e1a680ac3f90729621c85a14283
+    <td><a href="#top" onclick="onDownload(this)"
+      >bullhead-ota-npd90g-0a874807.zip</a><br>
+      MD5: 4b83b803fac1a6eec13f66d0afc6f46e<br>
+      SHA-1: a9920bcc8d475ce322cada097d085448512635e2
     </td>
   </tr>
 
   <tr id="shamu">
     <td>Nexus 6 <br>"shamu"</td>
-    <td><a href="#top" onclick="onDownload(this)">shamu-ota-npd35k-078e6fa5.zip</a><br>
-      MD5: e8b12f7721c53af9a450f7058928a5fc<br>
-      SHA-1: b7a9b756f84a1d2e482ff9c16749d65f6e51425a
+    <td><a href="#top" onclick="onDownload(this)"
+      >shamu-ota-npd90g-06f5d23d.zip</a><br>
+      MD5: 513570bb3a91878c2d1a5807d2340420<br>
+      SHA-1: 2d2f40636c95c132907e6ba0d10b395301e969ed
     </td>
   </tr>
 
   <tr id="angler">
     <td>Nexus 6P <br>"angler"</td>
-    <td><a href="#top" onclick="onDownload(this)">angler-ota-npd35k-88457699.zip</a><br>
-      MD5:3fac09fef759dde26e57cb80b20b6477<br>
-      SHA-1:27d6caa786577d8a38b2da5bf94b33b4524a1a1c
+    <td><a href="#top" onclick="onDownload(this)"
+      >angler-ota-npd90g-5baa69c2.zip</a><br>
+      MD5: 096fe26c5d50606a424d2f3326c0477b<br>
+      SHA-1: 468d2e7aea444505513ddc183c85690c00fab0c1
     </td>
   </tr>
 
   <tr id="volantis">
     <td>Nexus 9 <br>"volantis"</td>
-    <td><a href="#top" onclick="onDownload(this)">volantis-ota-npd35k-51dbae76.zip</a><br>
-      MD5:58312c4a5971818ef5c77a3f446003da<br>
-      SHA-1: aad9005be33d3e2bab480509a6ab74c3c3b9d921
+    <td><a href="#top" onclick="onDownload(this)"
+      >volantis-ota-npd90g-c04785e1.zip</a><br>
+      MD5: 6aecd3b0b3a839c5ce1ce4d12187b03e<br>
+      SHA-1: 31633180635b831e59271a7d904439f278586f49
     </td>
   </tr>
 
   <tr id="volantisg">
     <td>Nexus 9G <br>"volantisg"</td>
-    <td><a href="#top" onclick="onDownload(this)">volantisg-ota-npd35k-834f047f.zip</a><br>
-      MD5:92b7d1fa252f7394e70f957c72d4aac8<br>
-      SHA-1: b6c057c84d90893630e303cbb60530e20ddb8361
+    <td><a href="#top" onclick="onDownload(this)"
+      >volantisg-ota-npd90g-c56aa1b0.zip</a><br>
+      MD5: 0493fa79763d67bcdde8007299e1888d<br>
+      SHA-1: f709daf81968a1b27ed41fe40d42e0d106f3c494
     </td>
   </tr>
 
   <tr id="fugu">
     <td>Nexus Player <br>"fugu"</td>
-    <td><a href="#top" onclick="onDownload(this)">fugu-ota-npd35k-6ac91298.zip</a><br>
-      MD5:1461622ad53ea842b2722fa7b49b8172<br>
-      SHA-1:409c061668ab270774877d7f3eae44fa48d2b931
+    <td><a href="#top" onclick="onDownload(this)"
+      >fugu-ota-npd90g-3a0643ae.zip</a><br>
+      MD5: 9c38b6647fe5a4f2965196b7c409f0f7<br>
+      SHA-1: 77c6fb05191f0c2ae0956bae18f1c80b2f922f05
     </td>
   </tr>
 
   <tr id="ryu">
     <td>Pixel C <br>"ryu"</td>
-    <td><a href="#top" onclick="onDownload(this)">ryu-ota-npd35k-a0b2347f.zip</a><br>
-      MD5: c60117f3640cc6db12386fd632289c7d<br>
-      SHA-1:87349c767c69efb4172c90ce1d88cf578c3d28b3
+    <td><a href="#top" onclick="onDownload(this)"
+      >ryu-ota-npd90g-ec931914.zip</a><br>
+      MD5: 4c6135498ca156a9cdaf443ddfdcb2ba<br>
+      SHA-1: 297cc9a204685ef5507ec087fc7edf5b34551ce6
     </td>
   </tr>
 
   <tr id="seed">
-    <td>General Mobile 4G(Android One) <br>"seed"</td>
-    <td><a href="#top" onclick="onDownload(this)">seed_l8150-ota-npd35k-09897a1d.zip</a><br>
-      MD5: a55cf94f7cce0393ec6c0b35041766b7<br>
-      SHA-1:6f33742290eb46f2561891f38ca2e754b4e50c6a
+    <td>General Mobile 4G (Android One) <br>"seed"</td>
+    <td><a href="#top" onclick="onDownload(this)"
+      >seed_l8150-ota-npd90g-dcb0662d.zip</a><br>
+      MD5: f40ea6314a13ea6dd30d0e68098532a2<br>
+      SHA-1: 11af10b621f4480ac63f4e99189d61e1686c0865
     </td>
   </tr>
 
diff --git a/docs/html-intl/intl/ja/preview/download.jd b/docs/html-intl/intl/ja/preview/download.jd
index 52c3c6c..705a90b 100644
--- a/docs/html-intl/intl/ja/preview/download.jd
+++ b/docs/html-intl/intl/ja/preview/download.jd
@@ -300,65 +300,73 @@
 
   <tr id="bullhead">
     <td>Nexus 5X <br>"bullhead"</td>
-    <td><a href="#top" onclick="onDownload(this)">bullhead-npd35k-factory-5ba40535.tgz</a><br>
-      MD5: b6c5d79a21815ee21db41822dcf61e9f<br>
-      SHA-1:5ba4053577007d15c96472206e3a79bc80ab194c
+    <td><a href="#top" onclick="onDownload(this)"
+      >bullhead-npd90g-factory-7a0ca1bc.tgz</a><br>
+      MD5: e7a9a3061335c1e0c8be2588f13290af<br>
+      SHA-1: 7a0ca1bcfa51bbefde34243603bc79c7dec214a1
     </td>
   </tr>
 
   <tr id="shamu">
     <td>Nexus 6 <br>"shamu"</td>
-    <td><a href="#top" onclick="onDownload(this)">shamu-npd35k-factory-a33bf20c.tgz</a><br>
-      MD5: e1cf9c57cfb11bebe7f1f5bfbf05d7ab<br>
-      SHA-1: a33bf20c719206bcf08d1edd8da6c0ff9d50f69c
+    <td><a href="#top" onclick="onDownload(this)"
+      >shamu-npd90g-factory-f7a4e3a9.tgz</a><br>
+      MD5: 2fb572ddcfca67bb1d741be97492a9ed<br>
+      SHA-1: f7a4e3a96c797827492998e855c8f9efbfc8559a
     </td>
   </tr>
 
   <tr id="angler">
     <td>Nexus 6P <br>"angler"</td>
-    <td><a href="#top" onclick="onDownload(this)">angler-npd35k-factory-81c341d5.tgz</a><br>
-      MD5: e93de7949433339856124c3729c15ebb<br>
-      SHA-1:81c341d57ef2cd139569b055d5d59e9e592a7abd
+    <td><a href="#top" onclick="onDownload(this)"
+      >angler-npd90g-factory-cd9ac81e.tgz</a><br>
+      MD5: 2370c30f3ef1d0684c1de5216a5d90fe<br>
+      SHA-1: cd9ac81ec7f4a646ac6054eecbf2ea4c4b89b054
     </td>
   </tr>
 
   <tr id="volantis">
     <td>Nexus 9 <br>"volantis"</td>
-    <td><a href="#top" onclick="onDownload(this)">volantis-npd35k-factory-2b50e19d.tgz</a><br>
-      MD5:565be87ebb2d5937e2abe1a42645864b<br>
-      SHA-1:2b50e19dae2667b27f911e3c61ed64860caf43e1
+    <td><a href="#top" onclick="onDownload(this)"
+      >volantis-npd90g-factory-41b55406.tgz</a><br>
+      MD5: cefa78950141da2a7c75e887717e3c8f<br>
+      SHA-1: 41b554060263a7ef16e4be8422cbd6caca26e00f
     </td>
   </tr>
 
   <tr id="volantisg">
     <td>Nexus 9G <br>"volantisg"</td>
-    <td><a href="#top" onclick="onDownload(this)">volantisg-npd35k-factory-2e89ebe6.tgz</a><br>
-      MD5: a8464e15c6683fe2afa378a63e205fda<br>
-      SHA-1:2e89ebe67a46b2f3beb050746c13341cd11fa678
+    <td><a href="#top" onclick="onDownload(this)"
+      >volantisg-npd90g-factory-610492be.tgz</a><br>
+      MD5: 2f36dc0d0fab02ab78be500677ec239f<br>
+      SHA-1: 610492bedfc4127023040ecb2c89239a78a900ad
     </td>
   </tr>
 
   <tr id="fugu">
     <td>Nexus Player <br>"fugu"</td>
-    <td><a href="#top" onclick="onDownload(this)">fugu-npd35k-factory-1de74874.tgz</a><br>
-      MD5: c0dbb7db671f61b2785da5001cedefcb<br>
-      SHA-1:1de74874f8d83e14d642f13b5a2130fc2aa55873
+    <td><a href="#top" onclick="onDownload(this)"
+      >fugu-npd90g-factory-0fe95694.tgz</a><br>
+      MD5: f4cb48f919e4c29c631de21416c612e2<br>
+      SHA-1: 0fe95694e7bc41e4c3ac0e4438cd77102a0aa8b4
     </td>
   </tr>
 
   <tr id="ryu">
     <td>Pixel C <br>"ryu"</td>
-    <td><a href="#top" onclick="onDownload(this)">ryu-npd35k-factory-b4eed85d.tgz</a><br>
-      MD5: bdcb6f770e753668b5fadff2a6678e0d<br>
-      SHA-1: b4eed85de0d42c200348a8629084f78e24f72ac2
+    <td><a href="#top" onclick="onDownload(this)"
+      >ryu-npd90g-factory-f4da981c.tgz</a><br>
+      MD5: d9f0e40b6c20d274831e8a7d285fd887<br>
+      SHA-1: f4da981c70576133321e2858e52fe2c990e68a75
     </td>
   </tr>
 
   <tr id="seed">
-    <td>General Mobile 4G(Android One) <br>"seed"</td>
-    <td><a href="#top" onclick="onDownload(this)">seed_l8150-npd35k-factory-5ab1212b.tgz</a><br>
-      MD5:7d34a9774fdd6e025d485ce6cfc23c4c<br>
-      SHA-1:5ab1212bc9417269d391aacf1e672fff24b4ecc5
+    <td>General Mobile 4G (Android One) <br>"seed"</td>
+    <td><a href="#top" onclick="onDownload(this)"
+      >seed_l8150-npd90g-factory-48f59c99.tgz</a><br>
+      MD5: 0ed565c509594072822d71c65b48ec8e<br>
+      SHA-1: 48f59c99ac43d1cd2f5656a283bb9868581663a8
     </td>
   </tr>
 
diff --git a/docs/html-intl/intl/ko/preview/download-ota.jd b/docs/html-intl/intl/ko/preview/download-ota.jd
index 886b8a8..ee08846 100644
--- a/docs/html-intl/intl/ko/preview/download-ota.jd
+++ b/docs/html-intl/intl/ko/preview/download-ota.jd
@@ -202,65 +202,73 @@
 
   <tr id="bullhead">
     <td>Nexus 5X <br>"bullhead"</td>
-    <td><a href="#top" onclick="onDownload(this)">bullhead-ota-npd35k-b8cfbd80.zip</a><br>
-      MD5: 15fe2eba9b01737374196bdf0a792fe9<br>
-      SHA-1: 5014b2bba77f9e1a680ac3f90729621c85a14283
+    <td><a href="#top" onclick="onDownload(this)"
+      >bullhead-ota-npd90g-0a874807.zip</a><br>
+      MD5: 4b83b803fac1a6eec13f66d0afc6f46e<br>
+      SHA-1: a9920bcc8d475ce322cada097d085448512635e2
     </td>
   </tr>
 
   <tr id="shamu">
     <td>Nexus 6 <br>"shamu"</td>
-    <td><a href="#top" onclick="onDownload(this)">shamu-ota-npd35k-078e6fa5.zip</a><br>
-      MD5: e8b12f7721c53af9a450f7058928a5fc<br>
-      SHA-1: b7a9b756f84a1d2e482ff9c16749d65f6e51425a
+    <td><a href="#top" onclick="onDownload(this)"
+      >shamu-ota-npd90g-06f5d23d.zip</a><br>
+      MD5: 513570bb3a91878c2d1a5807d2340420<br>
+      SHA-1: 2d2f40636c95c132907e6ba0d10b395301e969ed
     </td>
   </tr>
 
   <tr id="angler">
     <td>Nexus 6P <br>"angler"</td>
-    <td><a href="#top" onclick="onDownload(this)">angler-ota-npd35k-88457699.zip</a><br>
-      MD5: 3fac09fef759dde26e57cb80b20b6477<br>
-      SHA-1: 27d6caa786577d8a38b2da5bf94b33b4524a1a1c
+    <td><a href="#top" onclick="onDownload(this)"
+      >angler-ota-npd90g-5baa69c2.zip</a><br>
+      MD5: 096fe26c5d50606a424d2f3326c0477b<br>
+      SHA-1: 468d2e7aea444505513ddc183c85690c00fab0c1
     </td>
   </tr>
 
   <tr id="volantis">
     <td>Nexus 9 <br>"volantis"</td>
-    <td><a href="#top" onclick="onDownload(this)">volantis-ota-npd35k-51dbae76.zip</a><br>
-      MD5: 58312c4a5971818ef5c77a3f446003da<br>
-      SHA-1: aad9005be33d3e2bab480509a6ab74c3c3b9d921
+    <td><a href="#top" onclick="onDownload(this)"
+      >volantis-ota-npd90g-c04785e1.zip</a><br>
+      MD5: 6aecd3b0b3a839c5ce1ce4d12187b03e<br>
+      SHA-1: 31633180635b831e59271a7d904439f278586f49
     </td>
   </tr>
 
   <tr id="volantisg">
     <td>Nexus 9G <br>"volantisg"</td>
-    <td><a href="#top" onclick="onDownload(this)">volantisg-ota-npd35k-834f047f.zip</a><br>
-      MD5: 92b7d1fa252f7394e70f957c72d4aac8<br>
-      SHA-1: b6c057c84d90893630e303cbb60530e20ddb8361
+    <td><a href="#top" onclick="onDownload(this)"
+      >volantisg-ota-npd90g-c56aa1b0.zip</a><br>
+      MD5: 0493fa79763d67bcdde8007299e1888d<br>
+      SHA-1: f709daf81968a1b27ed41fe40d42e0d106f3c494
     </td>
   </tr>
 
   <tr id="fugu">
     <td>Nexus Player <br>"fugu"</td>
-    <td><a href="#top" onclick="onDownload(this)">fugu-ota-npd35k-6ac91298.zip</a><br>
-      MD5: 1461622ad53ea842b2722fa7b49b8172<br>
-      SHA-1: 409c061668ab270774877d7f3eae44fa48d2b931
+    <td><a href="#top" onclick="onDownload(this)"
+      >fugu-ota-npd90g-3a0643ae.zip</a><br>
+      MD5: 9c38b6647fe5a4f2965196b7c409f0f7<br>
+      SHA-1: 77c6fb05191f0c2ae0956bae18f1c80b2f922f05
     </td>
   </tr>
 
   <tr id="ryu">
     <td>Pixel C <br>"ryu"</td>
-    <td><a href="#top" onclick="onDownload(this)">ryu-ota-npd35k-a0b2347f.zip</a><br>
-      MD5: c60117f3640cc6db12386fd632289c7d<br>
-      SHA-1: 87349c767c69efb4172c90ce1d88cf578c3d28b3
+    <td><a href="#top" onclick="onDownload(this)"
+      >ryu-ota-npd90g-ec931914.zip</a><br>
+      MD5: 4c6135498ca156a9cdaf443ddfdcb2ba<br>
+      SHA-1: 297cc9a204685ef5507ec087fc7edf5b34551ce6
     </td>
   </tr>
 
   <tr id="seed">
-    <td>General Mobile 4G(Android One) <br>"seed"</td>
-    <td><a href="#top" onclick="onDownload(this)">seed_l8150-ota-npd35k-09897a1d.zip</a><br>
-      MD5: a55cf94f7cce0393ec6c0b35041766b7<br>
-      SHA-1: 6f33742290eb46f2561891f38ca2e754b4e50c6a
+    <td>General Mobile 4G (Android One) <br>"seed"</td>
+    <td><a href="#top" onclick="onDownload(this)"
+      >seed_l8150-ota-npd90g-dcb0662d.zip</a><br>
+      MD5: f40ea6314a13ea6dd30d0e68098532a2<br>
+      SHA-1: 11af10b621f4480ac63f4e99189d61e1686c0865
     </td>
   </tr>
 
diff --git a/docs/html-intl/intl/ko/preview/download.jd b/docs/html-intl/intl/ko/preview/download.jd
index 802420b..88c45cd 100644
--- a/docs/html-intl/intl/ko/preview/download.jd
+++ b/docs/html-intl/intl/ko/preview/download.jd
@@ -300,65 +300,73 @@
 
   <tr id="bullhead">
     <td>Nexus 5X <br>"bullhead"</td>
-    <td><a href="#top" onclick="onDownload(this)">bullhead-npd35k-factory-5ba40535.tgz</a><br>
-      MD5: b6c5d79a21815ee21db41822dcf61e9f<br>
-      SHA-1: 5ba4053577007d15c96472206e3a79bc80ab194c
+    <td><a href="#top" onclick="onDownload(this)"
+      >bullhead-npd90g-factory-7a0ca1bc.tgz</a><br>
+      MD5: e7a9a3061335c1e0c8be2588f13290af<br>
+      SHA-1: 7a0ca1bcfa51bbefde34243603bc79c7dec214a1
     </td>
   </tr>
 
   <tr id="shamu">
     <td>Nexus 6 <br>"shamu"</td>
-    <td><a href="#top" onclick="onDownload(this)">shamu-npd35k-factory-a33bf20c.tgz</a><br>
-      MD5: e1cf9c57cfb11bebe7f1f5bfbf05d7ab<br>
-      SHA-1: a33bf20c719206bcf08d1edd8da6c0ff9d50f69c
+    <td><a href="#top" onclick="onDownload(this)"
+      >shamu-npd90g-factory-f7a4e3a9.tgz</a><br>
+      MD5: 2fb572ddcfca67bb1d741be97492a9ed<br>
+      SHA-1: f7a4e3a96c797827492998e855c8f9efbfc8559a
     </td>
   </tr>
 
   <tr id="angler">
     <td>Nexus 6P <br>"angler"</td>
-    <td><a href="#top" onclick="onDownload(this)">angler-npd35k-factory-81c341d5.tgz</a><br>
-      MD5: e93de7949433339856124c3729c15ebb<br>
-      SHA-1: 81c341d57ef2cd139569b055d5d59e9e592a7abd
+    <td><a href="#top" onclick="onDownload(this)"
+      >angler-npd90g-factory-cd9ac81e.tgz</a><br>
+      MD5: 2370c30f3ef1d0684c1de5216a5d90fe<br>
+      SHA-1: cd9ac81ec7f4a646ac6054eecbf2ea4c4b89b054
     </td>
   </tr>
 
   <tr id="volantis">
     <td>Nexus 9 <br>"volantis"</td>
-    <td><a href="#top" onclick="onDownload(this)">volantis-npd35k-factory-2b50e19d.tgz</a><br>
-      MD5: 565be87ebb2d5937e2abe1a42645864b<br>
-      SHA-1: 2b50e19dae2667b27f911e3c61ed64860caf43e1
+    <td><a href="#top" onclick="onDownload(this)"
+      >volantis-npd90g-factory-41b55406.tgz</a><br>
+      MD5: cefa78950141da2a7c75e887717e3c8f<br>
+      SHA-1: 41b554060263a7ef16e4be8422cbd6caca26e00f
     </td>
   </tr>
 
   <tr id="volantisg">
     <td>Nexus 9G <br>"volantisg"</td>
-    <td><a href="#top" onclick="onDownload(this)">volantisg-npd35k-factory-2e89ebe6.tgz</a><br>
-      MD5: a8464e15c6683fe2afa378a63e205fda<br>
-      SHA-1: 2e89ebe67a46b2f3beb050746c13341cd11fa678
+    <td><a href="#top" onclick="onDownload(this)"
+      >volantisg-npd90g-factory-610492be.tgz</a><br>
+      MD5: 2f36dc0d0fab02ab78be500677ec239f<br>
+      SHA-1: 610492bedfc4127023040ecb2c89239a78a900ad
     </td>
   </tr>
 
   <tr id="fugu">
     <td>Nexus Player <br>"fugu"</td>
-    <td><a href="#top" onclick="onDownload(this)">fugu-npd35k-factory-1de74874.tgz</a><br>
-      MD5: c0dbb7db671f61b2785da5001cedefcb<br>
-      SHA-1: 1de74874f8d83e14d642f13b5a2130fc2aa55873
+    <td><a href="#top" onclick="onDownload(this)"
+      >fugu-npd90g-factory-0fe95694.tgz</a><br>
+      MD5: f4cb48f919e4c29c631de21416c612e2<br>
+      SHA-1: 0fe95694e7bc41e4c3ac0e4438cd77102a0aa8b4
     </td>
   </tr>
 
   <tr id="ryu">
     <td>Pixel C <br>"ryu"</td>
-    <td><a href="#top" onclick="onDownload(this)">ryu-npd35k-factory-b4eed85d.tgz</a><br>
-      MD5: bdcb6f770e753668b5fadff2a6678e0d<br>
-      SHA-1: b4eed85de0d42c200348a8629084f78e24f72ac2
+    <td><a href="#top" onclick="onDownload(this)"
+      >ryu-npd90g-factory-f4da981c.tgz</a><br>
+      MD5: d9f0e40b6c20d274831e8a7d285fd887<br>
+      SHA-1: f4da981c70576133321e2858e52fe2c990e68a75
     </td>
   </tr>
 
   <tr id="seed">
-    <td>General Mobile 4G(Android One) <br>"seed"</td>
-    <td><a href="#top" onclick="onDownload(this)">seed_l8150-npd35k-factory-5ab1212b.tgz</a><br>
-      MD5: 7d34a9774fdd6e025d485ce6cfc23c4c<br>
-      SHA-1: 5ab1212bc9417269d391aacf1e672fff24b4ecc5
+    <td>General Mobile 4G (Android One) <br>"seed"</td>
+    <td><a href="#top" onclick="onDownload(this)"
+      >seed_l8150-npd90g-factory-48f59c99.tgz</a><br>
+      MD5: 0ed565c509594072822d71c65b48ec8e<br>
+      SHA-1: 48f59c99ac43d1cd2f5656a283bb9868581663a8
     </td>
   </tr>
 
diff --git a/docs/html-intl/intl/pt-br/preview/download-ota.jd b/docs/html-intl/intl/pt-br/preview/download-ota.jd
index 693aa92..3f817ed 100644
--- a/docs/html-intl/intl/pt-br/preview/download-ota.jd
+++ b/docs/html-intl/intl/pt-br/preview/download-ota.jd
@@ -165,7 +165,7 @@
 <p>
   Esta página fornece links para imagens OTA de dispositivo e descreve
  como aplicar manualmente uma atualização OTA em um dispositivo. Esse procedimento pode ser útil
- para recuperar dispositivos que receberam atualizações OTA usando o programa beta 
+ para recuperar dispositivos que receberam atualizações OTA usando o programa beta
 do Android e não estão ligando após a instalação.
 </p>
 
@@ -179,7 +179,7 @@
   <li>Baixe uma imagem OTA de dispositivo na tabela abaixo.</li>
   <li>Reinicialize o dispositivo para ficar em modo Recovery. Para obter mais informações sobre como colocar
  dispositivos Nexus nesse modo, consulte
- <a href="https://support.google.com/nexus/answer/4596836">Redefinição do 
+ <a href="https://support.google.com/nexus/answer/4596836">Redefinição do
 dispositivo Nexus para voltar à configuração de fábrica</a>.
   </li>
   <li>No dispositivo, selecione <strong>ADB sideload</strong>.</li>
@@ -202,65 +202,73 @@
 
   <tr id="bullhead">
     <td>Nexus 5X <br>"bullhead"</td>
-    <td><a href="#top" onclick="onDownload(this)">bullhead-ota-npd35k-b8cfbd80.zip</a><br>
-      MD5: 15fe2eba9b01737374196bdf0a792fe9<br>
-      SHA-1: 5014b2bba77f9e1a680ac3f90729621c85a14283
+    <td><a href="#top" onclick="onDownload(this)"
+      >bullhead-ota-npd90g-0a874807.zip</a><br>
+      MD5: 4b83b803fac1a6eec13f66d0afc6f46e<br>
+      SHA-1: a9920bcc8d475ce322cada097d085448512635e2
     </td>
   </tr>
 
   <tr id="shamu">
     <td>Nexus 6 <br>"shamu"</td>
-    <td><a href="#top" onclick="onDownload(this)">shamu-ota-npd35k-078e6fa5.zip</a><br>
-      MD5: e8b12f7721c53af9a450f7058928a5fc<br>
-      SHA-1: b7a9b756f84a1d2e482ff9c16749d65f6e51425a
+    <td><a href="#top" onclick="onDownload(this)"
+      >shamu-ota-npd90g-06f5d23d.zip</a><br>
+      MD5: 513570bb3a91878c2d1a5807d2340420<br>
+      SHA-1: 2d2f40636c95c132907e6ba0d10b395301e969ed
     </td>
   </tr>
 
   <tr id="angler">
     <td>Nexus 6P <br>"angler"</td>
-    <td><a href="#top" onclick="onDownload(this)">angler-ota-npd35k-88457699.zip</a><br>
-      MD5: 3fac09fef759dde26e57cb80b20b6477<br>
-      SHA-1: 27d6caa786577d8a38b2da5bf94b33b4524a1a1c
+    <td><a href="#top" onclick="onDownload(this)"
+      >angler-ota-npd90g-5baa69c2.zip</a><br>
+      MD5: 096fe26c5d50606a424d2f3326c0477b<br>
+      SHA-1: 468d2e7aea444505513ddc183c85690c00fab0c1
     </td>
   </tr>
 
   <tr id="volantis">
     <td>Nexus 9 <br>"volantis"</td>
-    <td><a href="#top" onclick="onDownload(this)">volantis-ota-npd35k-51dbae76.zip</a><br>
-      MD5: 58312c4a5971818ef5c77a3f446003da<br>
-      SHA-1: aad9005be33d3e2bab480509a6ab74c3c3b9d921
+    <td><a href="#top" onclick="onDownload(this)"
+      >volantis-ota-npd90g-c04785e1.zip</a><br>
+      MD5: 6aecd3b0b3a839c5ce1ce4d12187b03e<br>
+      SHA-1: 31633180635b831e59271a7d904439f278586f49
     </td>
   </tr>
 
   <tr id="volantisg">
     <td>Nexus 9G <br>"volantisg"</td>
-    <td><a href="#top" onclick="onDownload(this)">volantisg-ota-npd35k-834f047f.zip</a><br>
-      MD5: 92b7d1fa252f7394e70f957c72d4aac8<br>
-      SHA-1: b6c057c84d90893630e303cbb60530e20ddb8361
+    <td><a href="#top" onclick="onDownload(this)"
+      >volantisg-ota-npd90g-c56aa1b0.zip</a><br>
+      MD5: 0493fa79763d67bcdde8007299e1888d<br>
+      SHA-1: f709daf81968a1b27ed41fe40d42e0d106f3c494
     </td>
   </tr>
 
   <tr id="fugu">
     <td>Nexus Player <br>"fugu"</td>
-    <td><a href="#top" onclick="onDownload(this)">fugu-ota-npd35k-6ac91298.zip</a><br>
-      MD5: 1461622ad53ea842b2722fa7b49b8172<br>
-      SHA-1: 409c061668ab270774877d7f3eae44fa48d2b931
+    <td><a href="#top" onclick="onDownload(this)"
+      >fugu-ota-npd90g-3a0643ae.zip</a><br>
+      MD5: 9c38b6647fe5a4f2965196b7c409f0f7<br>
+      SHA-1: 77c6fb05191f0c2ae0956bae18f1c80b2f922f05
     </td>
   </tr>
 
   <tr id="ryu">
     <td>Pixel C <br>"ryu"</td>
-    <td><a href="#top" onclick="onDownload(this)">ryu-ota-npd35k-a0b2347f.zip</a><br>
-      MD5: c60117f3640cc6db12386fd632289c7d<br>
-      SHA-1: 87349c767c69efb4172c90ce1d88cf578c3d28b3
+    <td><a href="#top" onclick="onDownload(this)"
+      >ryu-ota-npd90g-ec931914.zip</a><br>
+      MD5: 4c6135498ca156a9cdaf443ddfdcb2ba<br>
+      SHA-1: 297cc9a204685ef5507ec087fc7edf5b34551ce6
     </td>
   </tr>
 
   <tr id="seed">
     <td>General Mobile 4G (Android One) <br>"seed"</td>
-    <td><a href="#top" onclick="onDownload(this)">seed_l8150-ota-npd35k-09897a1d.zip</a><br>
-      MD5: a55cf94f7cce0393ec6c0b35041766b7<br>
-      SHA-1: 6f33742290eb46f2561891f38ca2e754b4e50c6a
+    <td><a href="#top" onclick="onDownload(this)"
+      >seed_l8150-ota-npd90g-dcb0662d.zip</a><br>
+      MD5: f40ea6314a13ea6dd30d0e68098532a2<br>
+      SHA-1: 11af10b621f4480ac63f4e99189d61e1686c0865
     </td>
   </tr>
 
diff --git a/docs/html-intl/intl/pt-br/preview/download.jd b/docs/html-intl/intl/pt-br/preview/download.jd
index b0f23e5..111c183 100644
--- a/docs/html-intl/intl/pt-br/preview/download.jd
+++ b/docs/html-intl/intl/pt-br/preview/download.jd
@@ -286,7 +286,7 @@
 </p>
 
 <p>
-  Se decidir que deseja obter atualizações por OTA após atualizar um dispositivo manualmente, 
+  Se decidir que deseja obter atualizações por OTA após atualizar um dispositivo manualmente,
 basta inscrevê-lo no <a href="https://g.co/androidbeta">programa beta
  do Android</a>. É possível inscrever dispositivos a qualquer momento para receber a próxima atualização do Preview
  por OTA.
@@ -300,65 +300,73 @@
 
   <tr id="bullhead">
     <td>Nexus 5X <br>"bullhead"</td>
-    <td><a href="#top" onclick="onDownload(this)">bullhead-npd35k-factory-5ba40535.tgz</a><br>
-      MD5: b6c5d79a21815ee21db41822dcf61e9f<br>
-      SHA-1: 5ba4053577007d15c96472206e3a79bc80ab194c
+    <td><a href="#top" onclick="onDownload(this)"
+      >bullhead-npd90g-factory-7a0ca1bc.tgz</a><br>
+      MD5: e7a9a3061335c1e0c8be2588f13290af<br>
+      SHA-1: 7a0ca1bcfa51bbefde34243603bc79c7dec214a1
     </td>
   </tr>
 
   <tr id="shamu">
     <td>Nexus 6 <br>"shamu"</td>
-    <td><a href="#top" onclick="onDownload(this)">shamu-npd35k-factory-a33bf20c.tgz</a><br>
-      MD5: e1cf9c57cfb11bebe7f1f5bfbf05d7ab<br>
-      SHA-1: a33bf20c719206bcf08d1edd8da6c0ff9d50f69c
+    <td><a href="#top" onclick="onDownload(this)"
+      >shamu-npd90g-factory-f7a4e3a9.tgz</a><br>
+      MD5: 2fb572ddcfca67bb1d741be97492a9ed<br>
+      SHA-1: f7a4e3a96c797827492998e855c8f9efbfc8559a
     </td>
   </tr>
 
   <tr id="angler">
     <td>Nexus 6P <br>"angler"</td>
-    <td><a href="#top" onclick="onDownload(this)">angler-npd35k-factory-81c341d5.tgz</a><br>
-      MD5: e93de7949433339856124c3729c15ebb<br>
-      SHA-1: 81c341d57ef2cd139569b055d5d59e9e592a7abd
+    <td><a href="#top" onclick="onDownload(this)"
+      >angler-npd90g-factory-cd9ac81e.tgz</a><br>
+      MD5: 2370c30f3ef1d0684c1de5216a5d90fe<br>
+      SHA-1: cd9ac81ec7f4a646ac6054eecbf2ea4c4b89b054
     </td>
   </tr>
 
   <tr id="volantis">
     <td>Nexus 9 <br>"volantis"</td>
-    <td><a href="#top" onclick="onDownload(this)">volantis-npd35k-factory-2b50e19d.tgz</a><br>
-      MD5: 565be87ebb2d5937e2abe1a42645864b<br>
-      SHA-1: 2b50e19dae2667b27f911e3c61ed64860caf43e1
+    <td><a href="#top" onclick="onDownload(this)"
+      >volantis-npd90g-factory-41b55406.tgz</a><br>
+      MD5: cefa78950141da2a7c75e887717e3c8f<br>
+      SHA-1: 41b554060263a7ef16e4be8422cbd6caca26e00f
     </td>
   </tr>
 
   <tr id="volantisg">
     <td>Nexus 9G <br>"volantisg"</td>
-    <td><a href="#top" onclick="onDownload(this)">volantisg-npd35k-factory-2e89ebe6.tgz</a><br>
-      MD5: a8464e15c6683fe2afa378a63e205fda<br>
-      SHA-1: 2e89ebe67a46b2f3beb050746c13341cd11fa678
+    <td><a href="#top" onclick="onDownload(this)"
+      >volantisg-npd90g-factory-610492be.tgz</a><br>
+      MD5: 2f36dc0d0fab02ab78be500677ec239f<br>
+      SHA-1: 610492bedfc4127023040ecb2c89239a78a900ad
     </td>
   </tr>
 
   <tr id="fugu">
     <td>Nexus Player <br>"fugu"</td>
-    <td><a href="#top" onclick="onDownload(this)">fugu-npd35k-factory-1de74874.tgz</a><br>
-      MD5: c0dbb7db671f61b2785da5001cedefcb<br>
-      SHA-1: 1de74874f8d83e14d642f13b5a2130fc2aa55873
+    <td><a href="#top" onclick="onDownload(this)"
+      >fugu-npd90g-factory-0fe95694.tgz</a><br>
+      MD5: f4cb48f919e4c29c631de21416c612e2<br>
+      SHA-1: 0fe95694e7bc41e4c3ac0e4438cd77102a0aa8b4
     </td>
   </tr>
 
   <tr id="ryu">
     <td>Pixel C <br>"ryu"</td>
-    <td><a href="#top" onclick="onDownload(this)">ryu-npd35k-factory-b4eed85d.tgz</a><br>
-      MD5: bdcb6f770e753668b5fadff2a6678e0d<br>
-      SHA-1: b4eed85de0d42c200348a8629084f78e24f72ac2
+    <td><a href="#top" onclick="onDownload(this)"
+      >ryu-npd90g-factory-f4da981c.tgz</a><br>
+      MD5: d9f0e40b6c20d274831e8a7d285fd887<br>
+      SHA-1: f4da981c70576133321e2858e52fe2c990e68a75
     </td>
   </tr>
 
   <tr id="seed">
     <td>General Mobile 4G (Android One) <br>"seed"</td>
-    <td><a href="#top" onclick="onDownload(this)">seed_l8150-npd35k-factory-5ab1212b.tgz</a><br>
-      MD5: 7d34a9774fdd6e025d485ce6cfc23c4c<br>
-      SHA-1: 5ab1212bc9417269d391aacf1e672fff24b4ecc5
+    <td><a href="#top" onclick="onDownload(this)"
+      >seed_l8150-npd90g-factory-48f59c99.tgz</a><br>
+      MD5: 0ed565c509594072822d71c65b48ec8e<br>
+      SHA-1: 48f59c99ac43d1cd2f5656a283bb9868581663a8
     </td>
   </tr>
 
@@ -390,7 +398,7 @@
       </ul>
     </li>
     <li><strong>Cancele a inscrição do dispositivo no programa beta do Android</strong>. Se o
- dispositivo estiver inscrito no <a href="https://g.co/androidbeta">programa beta 
+ dispositivo estiver inscrito no <a href="https://g.co/androidbeta">programa beta
 do Android</a>, independentemente de qual ele seja, você poderá simplesmente cancelar a inscrição.
   <p>
     O dispositivo receberá uma atualização por OTA para a versão
@@ -465,7 +473,7 @@
 <p>Agora, é possível iniciar o emulador do Android com o AVD Android N Preview.</p>
 
 <p>
-Para ter a melhor experiência possível com o emulador do Android, instale o 
+Para ter a melhor experiência possível com o emulador do Android, instale o
 Android Studio 2.1 ou mais recente, que oferece suporte ao <a href="http://tools.android.com/tech-docs/emulator">Android Emulator 2.0</a>,
 cujo desempenho é muito superior ao do emulador no
 Android Studio 1.5.</p>
diff --git a/docs/html-intl/intl/ru/preview/download.jd b/docs/html-intl/intl/ru/preview/download.jd
index b286cad..3af4a5a 100644
--- a/docs/html-intl/intl/ru/preview/download.jd
+++ b/docs/html-intl/intl/ru/preview/download.jd
@@ -107,7 +107,7 @@
 9.3. Google вправе в любое время прекратить действие настоящего Лицензионного соглашения, отправив предварительное уведомление или без него.
 
 9.4 Действие настоящего Лицензионного соглашения автоматически прекращается без предварительного уведомления или выполнения иных действий сразу после следующего:
-(A) компания Google прекращает предоставление Preview или определенных частей Preview пользователям в той стране, в которой вы проживаете или используете услуги компании; 
+(A) компания Google прекращает предоставление Preview или определенных частей Preview пользователям в той стране, в которой вы проживаете или используете услуги компании;
 (B) компания Google выпускает окончательную версию Android SDK.
 
 9.5 В случае прекращения действия настоящего Лицензионного соглашения прекращается действие лицензии, предоставленной в рамках Лицензионного соглашения, и вам следует незамедлительно прекратить любое использование Preview, тогда как положения, изложенные в разделах 10, 11, 12 и 14 продолжают действовать бессрочно.
@@ -264,7 +264,7 @@
 вручную записать его во флэш-память устройства. См. информацию в следующей таблице, чтобы загрузить системный образ
 для своего тестового устройства. Запись вручную во флэш-память устройства удобна, если требуется
 точное управление средой тестирования или частая переустановка,
-например при автоматическом тестировании. 
+например при автоматическом тестировании.
 </p>
 
 <!-- You can flash by ota or system image --><p>
@@ -289,7 +289,7 @@
   Если вы захотите получить обновления по беспроводной связи после записи на устройство вручную,
 вам нужно просто зарегистрировать устройство в <a href="https://g.co/androidbeta">программе
 бета-тестировании Android</a>. Вы можете зарегистрировать устройство в любое время для получения следующего обновления предварительной версии
-по беспроводной связи. 
+по беспроводной связи.
 </p>
 
 <table>
@@ -300,64 +300,73 @@
 
   <tr id="bullhead">
     <td>Nexus 5X <br>"bullhead"</td>
-    <td><a href="#top" onclick="onDownload(this)">bullhead-npc56p-preview-6c877a3d.tgz</a><br>
-      MD5: b5cf874021023b398f5b983b24913f5d<br>
-      SHA-1: 6c877a3d9fae7ec8a1678448e325b77b7a7b143a
+    <td><a href="#top" onclick="onDownload(this)"
+      >bullhead-npd90g-factory-7a0ca1bc.tgz</a><br>
+      MD5: e7a9a3061335c1e0c8be2588f13290af<br>
+      SHA-1: 7a0ca1bcfa51bbefde34243603bc79c7dec214a1
     </td>
   </tr>
 
   <tr id="shamu">
     <td>Nexus 6 <br>"shamu"</td>
-    <td><a href="#top" onclick="onDownload(this)">shamu-npc56p-preview-54b13c67.tgz</a><br>
-      MD5: af183638cf34e0eb944a1957d7696f60<br>
-      SHA-1: 54b13c6703d369cc79a8fd8728fe4103c6343973
+    <td><a href="#top" onclick="onDownload(this)"
+      >shamu-npd90g-factory-f7a4e3a9.tgz</a><br>
+      MD5: 2fb572ddcfca67bb1d741be97492a9ed<br>
+      SHA-1: f7a4e3a96c797827492998e855c8f9efbfc8559a
     </td>
   </tr>
 
   <tr id="angler">
     <td>Nexus 6P <br>"angler"</td>
-    <td><a href="#top" onclick="onDownload(this)">angler-npc56p-preview-85ffc1b1.tgz</a><br>
-      MD5: bc4934ea7bd325753eee1606d3725a24<br>
-      SHA-1: 85ffc1b1be402b1b96f9ba10929e86bba6c6c588
+    <td><a href="#top" onclick="onDownload(this)"
+      >angler-npd90g-factory-cd9ac81e.tgz</a><br>
+      MD5: 2370c30f3ef1d0684c1de5216a5d90fe<br>
+      SHA-1: cd9ac81ec7f4a646ac6054eecbf2ea4c4b89b054
     </td>
   </tr>
 
   <tr id="volantis">
     <td>Nexus 9 <br>"volantis"</td>
-    <td><a href="#top" onclick="onDownload(this)">volantis-npc56p-preview-0e8ec8ef.tgz</a><br>
-      MD5: c901334c6158351e945f188167ae56f4<br>
-      SHA-1: 0e8ec8ef98c7a8d4f58d15f90afc5176303efca4
+    <td><a href="#top" onclick="onDownload(this)"
+      >volantis-npd90g-factory-41b55406.tgz</a><br>
+      MD5: cefa78950141da2a7c75e887717e3c8f<br>
+      SHA-1: 41b554060263a7ef16e4be8422cbd6caca26e00f
     </td>
   </tr>
 
   <tr id="volantisg">
     <td>Nexus 9G <br>"volantisg"</td>
-    <td><a href="#top" onclick="onDownload(this)">volantisg-npc56p-preview-1bafdbfb.tgz</a><br>
-      MD5: 7bb95bebc478d7257cccb4652899d1b4<br>
-      SHA-1: 1bafdbfb502e979a9fe4c257a379c4c7af8a3ae6
+    <td><a href="#top" onclick="onDownload(this)"
+      >volantisg-npd90g-factory-610492be.tgz</a><br>
+      MD5: 2f36dc0d0fab02ab78be500677ec239f<br>
+      SHA-1: 610492bedfc4127023040ecb2c89239a78a900ad
     </td>
   </tr>
 
   <tr id="fugu">
     <td>Nexus Player <br>"fugu"</td>
-    <td><a href="#top" onclick="onDownload(this)">fugu-npc56r-preview-7027d5b6.tgz</a><br>
-      MD5: f5d3d8f75836ccfe4c70e8162e498be4<br>
-      SHA-1: 7027d5b662bceda4c80a91a0a14ef0e5a7ba795b
+    <td><a href="#top" onclick="onDownload(this)"
+      >fugu-npd90g-factory-0fe95694.tgz</a><br>
+      MD5: f4cb48f919e4c29c631de21416c612e2<br>
+      SHA-1: 0fe95694e7bc41e4c3ac0e4438cd77102a0aa8b4
     </td>
   </tr>
 
   <tr id="ryu">
     <td>Pixel C <br>"ryu"</td>
-    <td><a href="#top" onclick="onDownload(this)">ryu-npc56p-preview-335a86a4.tgz</a><br>
-      MD5: 4e21fb183bbbf467bee91598d587fd2e<br>
-      SHA-1: 335a86a435ee51f18464de343ad2e071c38f0e92
+    <td><a href="#top" onclick="onDownload(this)"
+      >ryu-npd90g-factory-f4da981c.tgz</a><br>
+      MD5: d9f0e40b6c20d274831e8a7d285fd887<br>
+      SHA-1: f4da981c70576133321e2858e52fe2c990e68a75
     </td>
   </tr>
+
   <tr id="seed">
     <td>General Mobile 4G (Android One) <br>"seed"</td>
-    <td><a href="#top" onclick="onDownload(this)">seed_l8150-npc56p-preview-82472ebc.tgz</a><br>
-      MD5: 983e083bc7cd0c4a2d39d6ebaa20202a<br>
-      SHA-1: 82472ebc9a6054a103f53cb400a1351913c95127
+    <td><a href="#top" onclick="onDownload(this)"
+      >seed_l8150-npd90g-factory-48f59c99.tgz</a><br>
+      MD5: 0ed565c509594072822d71c65b48ec8e<br>
+      SHA-1: 48f59c99ac43d1cd2f5656a283bb9868581663a8
     </td>
   </tr>
 
diff --git a/docs/html-intl/intl/vi/preview/download.jd b/docs/html-intl/intl/vi/preview/download.jd
index f6aa7cc..8b2a272 100644
--- a/docs/html-intl/intl/vi/preview/download.jd
+++ b/docs/html-intl/intl/vi/preview/download.jd
@@ -209,7 +209,7 @@
 <h2 id="device-preview">Thiết lập thiết bị phần cứng</h2>
 
 <p>
-  Bản N Developer Preview cung cấp các cập nhật hệ thống cho một loạt các thiết bị phần cứng 
+  Bản N Developer Preview cung cấp các cập nhật hệ thống cho một loạt các thiết bị phần cứng
   mà bạn có thể sử dụng để kiểm thử ứng dụng của bạn, từ điện thoại tới máy tính bảng và TV.
 </p>
 
@@ -220,8 +220,8 @@
 
 <ul>
   <li><strong>Đăng ký cập nhật hệ thống tự động qua vô tuyến cho thiết bị</strong> thông qua
-  <a href="https://g.co/androidbeta">Chương trình Android Beta</a>. Sau khi đăng ký, thiết bị của bạn sẽ nhận được 
-  qua sóng vô tuyến các cập nhật định kỳ về tất cả bản dựng theo mốc trong bản N Developer Preview. Cách tiếp cận này 
+  <a href="https://g.co/androidbeta">Chương trình Android Beta</a>. Sau khi đăng ký, thiết bị của bạn sẽ nhận được
+  qua sóng vô tuyến các cập nhật định kỳ về tất cả bản dựng theo mốc trong bản N Developer Preview. Cách tiếp cận này
   được khuyến khích bởi nó cho phép bạn chuyển tiếp liền mạch từ môi trường hiện tại của bạn
  qua nhiều bản phát hành khác nhau của N Developer Preview.</li>
   <li><strong>Tải xuống ảnh hệ thống của Developer Preview và flash thiết bị</strong>.
@@ -264,7 +264,7 @@
   flash thủ công nó vào thiết bị của bạn. Xem bảng dưới đây để tải xuống ảnh hệ thống
   cho thiết bị kiểm thử của bạn. Việc flash thủ công thiết bị sẽ hữu ích nếu bạn cần
   kiểm soát chính xác môi trường kiểm thử hoặc cần phải cài đặt lại thường xuyên,
-  chẳng hạn như cho kiểm thử tự động. 
+  chẳng hạn như cho kiểm thử tự động.
 </p>
 
 <!-- You can flash by ota or system image --><p>
@@ -286,10 +286,10 @@
 </p>
 
 <p>
-  Nếu bạn quyết định muốn nhận cập nhật qua vô tuyến sau khi đã flash thủ công thiết bị, 
+  Nếu bạn quyết định muốn nhận cập nhật qua vô tuyến sau khi đã flash thủ công thiết bị,
   tất cả những gì bạn cần làm là đăng ký <a href="https://g.co/androidbeta">Chương trình Android
   Beta</a> cho thiết bị. Bạn có thể đăng ký thiết bị bất cứ lúc nào để nhận được
-  bản cập nhật qua vô tuyến tiếp theo của Preview. 
+  bản cập nhật qua vô tuyến tiếp theo của Preview.
 </p>
 
 <table>
@@ -300,64 +300,73 @@
 
   <tr id="bullhead">
     <td>Nexus 5X <br>"bullhead"</td>
-    <td><a href="#top" onclick="onDownload(this)">bullhead-npc56p-preview-6c877a3d.tgz</a><br>
-      MD5: b5cf874021023b398f5b983b24913f5d<br>
-      SHA-1: 6c877a3d9fae7ec8a1678448e325b77b7a7b143a
+    <td><a href="#top" onclick="onDownload(this)"
+      >bullhead-npd90g-factory-7a0ca1bc.tgz</a><br>
+      MD5: e7a9a3061335c1e0c8be2588f13290af<br>
+      SHA-1: 7a0ca1bcfa51bbefde34243603bc79c7dec214a1
     </td>
   </tr>
 
   <tr id="shamu">
     <td>Nexus 6 <br>"shamu"</td>
-    <td><a href="#top" onclick="onDownload(this)">shamu-npc56p-preview-54b13c67.tgz</a><br>
-      MD5: af183638cf34e0eb944a1957d7696f60<br>
-      SHA-1: 54b13c6703d369cc79a8fd8728fe4103c6343973
+    <td><a href="#top" onclick="onDownload(this)"
+      >shamu-npd90g-factory-f7a4e3a9.tgz</a><br>
+      MD5: 2fb572ddcfca67bb1d741be97492a9ed<br>
+      SHA-1: f7a4e3a96c797827492998e855c8f9efbfc8559a
     </td>
   </tr>
 
   <tr id="angler">
     <td>Nexus 6P <br>"angler"</td>
-    <td><a href="#top" onclick="onDownload(this)">angler-npc56p-preview-85ffc1b1.tgz</a><br>
-      MD5: bc4934ea7bd325753eee1606d3725a24<br>
-      SHA-1: 85ffc1b1be402b1b96f9ba10929e86bba6c6c588
+    <td><a href="#top" onclick="onDownload(this)"
+      >angler-npd90g-factory-cd9ac81e.tgz</a><br>
+      MD5: 2370c30f3ef1d0684c1de5216a5d90fe<br>
+      SHA-1: cd9ac81ec7f4a646ac6054eecbf2ea4c4b89b054
     </td>
   </tr>
 
   <tr id="volantis">
     <td>Nexus 9 <br>"volantis"</td>
-    <td><a href="#top" onclick="onDownload(this)">volantis-npc56p-preview-0e8ec8ef.tgz</a><br>
-      MD5: c901334c6158351e945f188167ae56f4<br>
-      SHA-1: 0e8ec8ef98c7a8d4f58d15f90afc5176303efca4
+    <td><a href="#top" onclick="onDownload(this)"
+      >volantis-npd90g-factory-41b55406.tgz</a><br>
+      MD5: cefa78950141da2a7c75e887717e3c8f<br>
+      SHA-1: 41b554060263a7ef16e4be8422cbd6caca26e00f
     </td>
   </tr>
 
   <tr id="volantisg">
     <td>Nexus 9G <br>"volantisg"</td>
-    <td><a href="#top" onclick="onDownload(this)">volantisg-npc56p-preview-1bafdbfb.tgz</a><br>
-      MD5: 7bb95bebc478d7257cccb4652899d1b4<br>
-      SHA-1: 1bafdbfb502e979a9fe4c257a379c4c7af8a3ae6
+    <td><a href="#top" onclick="onDownload(this)"
+      >volantisg-npd90g-factory-610492be.tgz</a><br>
+      MD5: 2f36dc0d0fab02ab78be500677ec239f<br>
+      SHA-1: 610492bedfc4127023040ecb2c89239a78a900ad
     </td>
   </tr>
 
   <tr id="fugu">
     <td>Nexus Player <br>"fugu"</td>
-    <td><a href="#top" onclick="onDownload(this)">fugu-npc56r-preview-7027d5b6.tgz</a><br>
-      MD5: f5d3d8f75836ccfe4c70e8162e498be4<br>
-      SHA-1: 7027d5b662bceda4c80a91a0a14ef0e5a7ba795b
+    <td><a href="#top" onclick="onDownload(this)"
+      >fugu-npd90g-factory-0fe95694.tgz</a><br>
+      MD5: f4cb48f919e4c29c631de21416c612e2<br>
+      SHA-1: 0fe95694e7bc41e4c3ac0e4438cd77102a0aa8b4
     </td>
   </tr>
 
   <tr id="ryu">
     <td>Pixel C <br>"ryu"</td>
-    <td><a href="#top" onclick="onDownload(this)">ryu-npc56p-preview-335a86a4.tgz</a><br>
-      MD5: 4e21fb183bbbf467bee91598d587fd2e<br>
-      SHA-1: 335a86a435ee51f18464de343ad2e071c38f0e92
+    <td><a href="#top" onclick="onDownload(this)"
+      >ryu-npd90g-factory-f4da981c.tgz</a><br>
+      MD5: d9f0e40b6c20d274831e8a7d285fd887<br>
+      SHA-1: f4da981c70576133321e2858e52fe2c990e68a75
     </td>
   </tr>
+
   <tr id="seed">
     <td>General Mobile 4G (Android One) <br>"seed"</td>
-    <td><a href="#top" onclick="onDownload(this)">seed_l8150-npc56p-preview-82472ebc.tgz</a><br>
-      MD5: 983e083bc7cd0c4a2d39d6ebaa20202a<br>
-      SHA-1: 82472ebc9a6054a103f53cb400a1351913c95127
+    <td><a href="#top" onclick="onDownload(this)"
+      >seed_l8150-npd90g-factory-48f59c99.tgz</a><br>
+      MD5: 0ed565c509594072822d71c65b48ec8e<br>
+      SHA-1: 48f59c99ac43d1cd2f5656a283bb9868581663a8
     </td>
   </tr>
 
@@ -423,7 +432,7 @@
 
   <li>Nhấp vào tab <strong>SDK Tools</strong>, rồi chọn
     <strong>Android SDK Build Tools</strong>, <strong>Android SDK
-    Platform-Tools</strong>, và các hộp kiểm <strong>Android SDK Tools</strong> 
+    Platform-Tools</strong>, và các hộp kiểm <strong>Android SDK Tools</strong>
 .
   </li>
 
@@ -464,7 +473,7 @@
 
 <p class="note"><strong>Lưu ý:</strong>
   Nếu bạn hiện đang sử dụng Android Studio 2.0 Beta, một vấn đề đã được biết đến
- sẽ ngăn cản bạn tạo AVD bằng ảnh hệ thống của N Preview, vì vậy 
+ sẽ ngăn cản bạn tạo AVD bằng ảnh hệ thống của N Preview, vì vậy
   hiện bạn cần sử dụng preview của Android Studio 2.1 để tạo các AVD.
 </p>
 
diff --git a/docs/html-intl/intl/zh-cn/preview/download-ota.jd b/docs/html-intl/intl/zh-cn/preview/download-ota.jd
index ab1408f..5d17abc 100644
--- a/docs/html-intl/intl/zh-cn/preview/download-ota.jd
+++ b/docs/html-intl/intl/zh-cn/preview/download-ota.jd
@@ -202,65 +202,73 @@
 
   <tr id="bullhead">
     <td>Nexus 5X <br>"bullhead"</td>
-    <td><a href="#top" onclick="onDownload(this)">bullhead-ota-npd35k-b8cfbd80.zip</a><br>
-      MD5:15fe2eba9b01737374196bdf0a792fe9<br>
-      SHA-1:5014b2bba77f9e1a680ac3f90729621c85a14283
+    <td><a href="#top" onclick="onDownload(this)"
+      >bullhead-ota-npd90g-0a874807.zip</a><br>
+      MD5: 4b83b803fac1a6eec13f66d0afc6f46e<br>
+      SHA-1: a9920bcc8d475ce322cada097d085448512635e2
     </td>
   </tr>
 
   <tr id="shamu">
     <td>Nexus 6 <br>"shamu"</td>
-    <td><a href="#top" onclick="onDownload(this)">shamu-ota-npd35k-078e6fa5.zip</a><br>
-      MD5: e8b12f7721c53af9a450f7058928a5fc<br>
-      SHA-1: b7a9b756f84a1d2e482ff9c16749d65f6e51425a
+    <td><a href="#top" onclick="onDownload(this)"
+      >shamu-ota-npd90g-06f5d23d.zip</a><br>
+      MD5: 513570bb3a91878c2d1a5807d2340420<br>
+      SHA-1: 2d2f40636c95c132907e6ba0d10b395301e969ed
     </td>
   </tr>
 
   <tr id="angler">
     <td>Nexus 6P <br>"angler"</td>
-    <td><a href="#top" onclick="onDownload(this)">angler-ota-npd35k-88457699.zip</a><br>
-      MD5:3fac09fef759dde26e57cb80b20b6477<br>
-      SHA-1:27d6caa786577d8a38b2da5bf94b33b4524a1a1c
+    <td><a href="#top" onclick="onDownload(this)"
+      >angler-ota-npd90g-5baa69c2.zip</a><br>
+      MD5: 096fe26c5d50606a424d2f3326c0477b<br>
+      SHA-1: 468d2e7aea444505513ddc183c85690c00fab0c1
     </td>
   </tr>
 
   <tr id="volantis">
     <td>Nexus 9 <br>"volantis"</td>
-    <td><a href="#top" onclick="onDownload(this)">volantis-ota-npd35k-51dbae76.zip</a><br>
-      MD5:58312c4a5971818ef5c77a3f446003da<br>
-      SHA-1: aad9005be33d3e2bab480509a6ab74c3c3b9d921
+    <td><a href="#top" onclick="onDownload(this)"
+      >volantis-ota-npd90g-c04785e1.zip</a><br>
+      MD5: 6aecd3b0b3a839c5ce1ce4d12187b03e<br>
+      SHA-1: 31633180635b831e59271a7d904439f278586f49
     </td>
   </tr>
 
   <tr id="volantisg">
     <td>Nexus 9G <br>"volantisg"</td>
-    <td><a href="#top" onclick="onDownload(this)">volantisg-ota-npd35k-834f047f.zip</a><br>
-      MD5:92b7d1fa252f7394e70f957c72d4aac8<br>
-      SHA-1: b6c057c84d90893630e303cbb60530e20ddb8361
+    <td><a href="#top" onclick="onDownload(this)"
+      >volantisg-ota-npd90g-c56aa1b0.zip</a><br>
+      MD5: 0493fa79763d67bcdde8007299e1888d<br>
+      SHA-1: f709daf81968a1b27ed41fe40d42e0d106f3c494
     </td>
   </tr>
 
   <tr id="fugu">
     <td>Nexus Player <br>"fugu"</td>
-    <td><a href="#top" onclick="onDownload(this)">fugu-ota-npd35k-6ac91298.zip</a><br>
-      MD5:1461622ad53ea842b2722fa7b49b8172<br>
-      SHA-1:409c061668ab270774877d7f3eae44fa48d2b931
+    <td><a href="#top" onclick="onDownload(this)"
+      >fugu-ota-npd90g-3a0643ae.zip</a><br>
+      MD5: 9c38b6647fe5a4f2965196b7c409f0f7<br>
+      SHA-1: 77c6fb05191f0c2ae0956bae18f1c80b2f922f05
     </td>
   </tr>
 
   <tr id="ryu">
     <td>Pixel C <br>"ryu"</td>
-    <td><a href="#top" onclick="onDownload(this)">ryu-ota-npd35k-a0b2347f.zip</a><br>
-      MD5: c60117f3640cc6db12386fd632289c7d<br>
-      SHA-1:87349c767c69efb4172c90ce1d88cf578c3d28b3
+    <td><a href="#top" onclick="onDownload(this)"
+      >ryu-ota-npd90g-ec931914.zip</a><br>
+      MD5: 4c6135498ca156a9cdaf443ddfdcb2ba<br>
+      SHA-1: 297cc9a204685ef5507ec087fc7edf5b34551ce6
     </td>
   </tr>
 
   <tr id="seed">
     <td>General Mobile 4G (Android One) <br>"seed"</td>
-    <td><a href="#top" onclick="onDownload(this)">seed_l8150-ota-npd35k-09897a1d.zip</a><br>
-      MD5: a55cf94f7cce0393ec6c0b35041766b7<br>
-      SHA-1:6f33742290eb46f2561891f38ca2e754b4e50c6a
+    <td><a href="#top" onclick="onDownload(this)"
+      >seed_l8150-ota-npd90g-dcb0662d.zip</a><br>
+      MD5: f40ea6314a13ea6dd30d0e68098532a2<br>
+      SHA-1: 11af10b621f4480ac63f4e99189d61e1686c0865
     </td>
   </tr>
 
diff --git a/docs/html-intl/intl/zh-cn/preview/download.jd b/docs/html-intl/intl/zh-cn/preview/download.jd
index 0aa115f..06bf2bf 100644
--- a/docs/html-intl/intl/zh-cn/preview/download.jd
+++ b/docs/html-intl/intl/zh-cn/preview/download.jd
@@ -300,65 +300,73 @@
 
   <tr id="bullhead">
     <td>Nexus 5X <br>"bullhead"</td>
-    <td><a href="#top" onclick="onDownload(this)">bullhead-npd35k-factory-5ba40535.tgz</a><br>
-      MD5: b6c5d79a21815ee21db41822dcf61e9f<br>
-      SHA-1:5ba4053577007d15c96472206e3a79bc80ab194c
+    <td><a href="#top" onclick="onDownload(this)"
+      >bullhead-npd90g-factory-7a0ca1bc.tgz</a><br>
+      MD5: e7a9a3061335c1e0c8be2588f13290af<br>
+      SHA-1: 7a0ca1bcfa51bbefde34243603bc79c7dec214a1
     </td>
   </tr>
 
   <tr id="shamu">
     <td>Nexus 6 <br>"shamu"</td>
-    <td><a href="#top" onclick="onDownload(this)">shamu-npd35k-factory-a33bf20c.tgz</a><br>
-      MD5: e1cf9c57cfb11bebe7f1f5bfbf05d7ab<br>
-      SHA-1: a33bf20c719206bcf08d1edd8da6c0ff9d50f69c
+    <td><a href="#top" onclick="onDownload(this)"
+      >shamu-npd90g-factory-f7a4e3a9.tgz</a><br>
+      MD5: 2fb572ddcfca67bb1d741be97492a9ed<br>
+      SHA-1: f7a4e3a96c797827492998e855c8f9efbfc8559a
     </td>
   </tr>
 
   <tr id="angler">
     <td>Nexus 6P <br>"angler"</td>
-    <td><a href="#top" onclick="onDownload(this)">angler-npd35k-factory-81c341d5.tgz</a><br>
-      MD5: e93de7949433339856124c3729c15ebb<br>
-      SHA-1:81c341d57ef2cd139569b055d5d59e9e592a7abd
+    <td><a href="#top" onclick="onDownload(this)"
+      >angler-npd90g-factory-cd9ac81e.tgz</a><br>
+      MD5: 2370c30f3ef1d0684c1de5216a5d90fe<br>
+      SHA-1: cd9ac81ec7f4a646ac6054eecbf2ea4c4b89b054
     </td>
   </tr>
 
   <tr id="volantis">
     <td>Nexus 9 <br>"volantis"</td>
-    <td><a href="#top" onclick="onDownload(this)">volantis-npd35k-factory-2b50e19d.tgz</a><br>
-      MD5:565be87ebb2d5937e2abe1a42645864b<br>
-      SHA-1:2b50e19dae2667b27f911e3c61ed64860caf43e1
+    <td><a href="#top" onclick="onDownload(this)"
+      >volantis-npd90g-factory-41b55406.tgz</a><br>
+      MD5: cefa78950141da2a7c75e887717e3c8f<br>
+      SHA-1: 41b554060263a7ef16e4be8422cbd6caca26e00f
     </td>
   </tr>
 
   <tr id="volantisg">
     <td>Nexus 9G <br>"volantisg"</td>
-    <td><a href="#top" onclick="onDownload(this)">volantisg-npd35k-factory-2e89ebe6.tgz</a><br>
-      MD5: a8464e15c6683fe2afa378a63e205fda<br>
-      SHA-1:2e89ebe67a46b2f3beb050746c13341cd11fa678
+    <td><a href="#top" onclick="onDownload(this)"
+      >volantisg-npd90g-factory-610492be.tgz</a><br>
+      MD5: 2f36dc0d0fab02ab78be500677ec239f<br>
+      SHA-1: 610492bedfc4127023040ecb2c89239a78a900ad
     </td>
   </tr>
 
   <tr id="fugu">
     <td>Nexus Player <br>"fugu"</td>
-    <td><a href="#top" onclick="onDownload(this)">fugu-npd35k-factory-1de74874.tgz</a><br>
-      MD5: c0dbb7db671f61b2785da5001cedefcb<br>
-      SHA-1:1de74874f8d83e14d642f13b5a2130fc2aa55873
+    <td><a href="#top" onclick="onDownload(this)"
+      >fugu-npd90g-factory-0fe95694.tgz</a><br>
+      MD5: f4cb48f919e4c29c631de21416c612e2<br>
+      SHA-1: 0fe95694e7bc41e4c3ac0e4438cd77102a0aa8b4
     </td>
   </tr>
 
   <tr id="ryu">
     <td>Pixel C <br>"ryu"</td>
-    <td><a href="#top" onclick="onDownload(this)">ryu-npd35k-factory-b4eed85d.tgz</a><br>
-      MD5: bdcb6f770e753668b5fadff2a6678e0d<br>
-      SHA-1: b4eed85de0d42c200348a8629084f78e24f72ac2
+    <td><a href="#top" onclick="onDownload(this)"
+      >ryu-npd90g-factory-f4da981c.tgz</a><br>
+      MD5: d9f0e40b6c20d274831e8a7d285fd887<br>
+      SHA-1: f4da981c70576133321e2858e52fe2c990e68a75
     </td>
   </tr>
 
   <tr id="seed">
     <td>General Mobile 4G (Android One) <br>"seed"</td>
-    <td><a href="#top" onclick="onDownload(this)">seed_l8150-npd35k-factory-5ab1212b.tgz</a><br>
-      MD5:7d34a9774fdd6e025d485ce6cfc23c4c<br>
-      SHA-1:5ab1212bc9417269d391aacf1e672fff24b4ecc5
+    <td><a href="#top" onclick="onDownload(this)"
+      >seed_l8150-npd90g-factory-48f59c99.tgz</a><br>
+      MD5: 0ed565c509594072822d71c65b48ec8e<br>
+      SHA-1: 48f59c99ac43d1cd2f5656a283bb9868581663a8
     </td>
   </tr>
 
diff --git a/docs/html-intl/intl/zh-tw/preview/download.jd b/docs/html-intl/intl/zh-tw/preview/download.jd
index a98000a..caa2a55 100644
--- a/docs/html-intl/intl/zh-tw/preview/download.jd
+++ b/docs/html-intl/intl/zh-tw/preview/download.jd
@@ -264,7 +264,7 @@
 
 
 
- 
+
 </p>
 
 <!-- You can flash by ota or system image --><p>
@@ -289,7 +289,7 @@
   如果您決定手動更新裝置後要接收 OTA 更新,您唯一要做的事是在 <a href="https://g.co/androidbeta">Android Beta 計劃</a>中註冊裝置。您可以隨時註冊裝置,以隔空傳輸方式接收下一個「Preview」更新。
 
 
- 
+
 </p>
 
 <table>
@@ -300,64 +300,73 @@
 
   <tr id="bullhead">
     <td>Nexus 5X <br>"bullhead"</td>
-    <td><a href="#top" onclick="onDownload(this)">bullhead-npc56p-preview-6c877a3d.tgz</a><br>
-      MD5:b5cf874021023b398f5b983b24913f5d<br>
-      SHA-1:6c877a3d9fae7ec8a1678448e325b77b7a7b143a
+    <td><a href="#top" onclick="onDownload(this)"
+      >bullhead-npd90g-factory-7a0ca1bc.tgz</a><br>
+      MD5: e7a9a3061335c1e0c8be2588f13290af<br>
+      SHA-1: 7a0ca1bcfa51bbefde34243603bc79c7dec214a1
     </td>
   </tr>
 
   <tr id="shamu">
     <td>Nexus 6 <br>"shamu"</td>
-    <td><a href="#top" onclick="onDownload(this)">shamu-npc56p-preview-54b13c67.tgz</a><br>
-      MD5:af183638cf34e0eb944a1957d7696f60<br>
-      SHA-1:54b13c6703d369cc79a8fd8728fe4103c6343973
+    <td><a href="#top" onclick="onDownload(this)"
+      >shamu-npd90g-factory-f7a4e3a9.tgz</a><br>
+      MD5: 2fb572ddcfca67bb1d741be97492a9ed<br>
+      SHA-1: f7a4e3a96c797827492998e855c8f9efbfc8559a
     </td>
   </tr>
 
   <tr id="angler">
     <td>Nexus 6P <br>"angler"</td>
-    <td><a href="#top" onclick="onDownload(this)">angler-npc56p-preview-85ffc1b1.tgz</a><br>
-      MD5:bc4934ea7bd325753eee1606d3725a24<br>
-      SHA-1:85ffc1b1be402b1b96f9ba10929e86bba6c6c588
+    <td><a href="#top" onclick="onDownload(this)"
+      >angler-npd90g-factory-cd9ac81e.tgz</a><br>
+      MD5: 2370c30f3ef1d0684c1de5216a5d90fe<br>
+      SHA-1: cd9ac81ec7f4a646ac6054eecbf2ea4c4b89b054
     </td>
   </tr>
 
   <tr id="volantis">
     <td>Nexus 9 <br>"volantis"</td>
-    <td><a href="#top" onclick="onDownload(this)">volantis-npc56p-preview-0e8ec8ef.tgz</a><br>
-      MD5:c901334c6158351e945f188167ae56f4<br>
-      SHA-1:0e8ec8ef98c7a8d4f58d15f90afc5176303efca4
+    <td><a href="#top" onclick="onDownload(this)"
+      >volantis-npd90g-factory-41b55406.tgz</a><br>
+      MD5: cefa78950141da2a7c75e887717e3c8f<br>
+      SHA-1: 41b554060263a7ef16e4be8422cbd6caca26e00f
     </td>
   </tr>
 
   <tr id="volantisg">
     <td>Nexus 9G <br>"volantisg"</td>
-    <td><a href="#top" onclick="onDownload(this)">volantisg-npc56p-preview-1bafdbfb.tgz</a><br>
-      MD5:7bb95bebc478d7257cccb4652899d1b4<br>
-      SHA-1:1bafdbfb502e979a9fe4c257a379c4c7af8a3ae6
+    <td><a href="#top" onclick="onDownload(this)"
+      >volantisg-npd90g-factory-610492be.tgz</a><br>
+      MD5: 2f36dc0d0fab02ab78be500677ec239f<br>
+      SHA-1: 610492bedfc4127023040ecb2c89239a78a900ad
     </td>
   </tr>
 
   <tr id="fugu">
     <td>Nexus Player <br>"fugu"</td>
-    <td><a href="#top" onclick="onDownload(this)">fugu-npc56r-preview-7027d5b6.tgz</a><br>
-      MD5:f5d3d8f75836ccfe4c70e8162e498be4<br>
-      SHA-1:7027d5b662bceda4c80a91a0a14ef0e5a7ba795b
+    <td><a href="#top" onclick="onDownload(this)"
+      >fugu-npd90g-factory-0fe95694.tgz</a><br>
+      MD5: f4cb48f919e4c29c631de21416c612e2<br>
+      SHA-1: 0fe95694e7bc41e4c3ac0e4438cd77102a0aa8b4
     </td>
   </tr>
 
   <tr id="ryu">
     <td>Pixel C <br>"ryu"</td>
-    <td><a href="#top" onclick="onDownload(this)">ryu-npc56p-preview-335a86a4.tgz</a><br>
-      MD5:4e21fb183bbbf467bee91598d587fd2e<br>
-      SHA-1:335a86a435ee51f18464de343ad2e071c38f0e92
+    <td><a href="#top" onclick="onDownload(this)"
+      >ryu-npd90g-factory-f4da981c.tgz</a><br>
+      MD5: d9f0e40b6c20d274831e8a7d285fd887<br>
+      SHA-1: f4da981c70576133321e2858e52fe2c990e68a75
     </td>
   </tr>
+
   <tr id="seed">
-    <td>一般行動裝置 4G (Android One) <br>"seed"</td>
-    <td><a href="#top" onclick="onDownload(this)">seed_l8150-npc56p-preview-82472ebc.tgz</a><br>
-      MD5:983e083bc7cd0c4a2d39d6ebaa20202a<br>
-      SHA-1:82472ebc9a6054a103f53cb400a1351913c95127
+    <td>General Mobile 4G (Android One) <br>"seed"</td>
+    <td><a href="#top" onclick="onDownload(this)"
+      >seed_l8150-npd90g-factory-48f59c99.tgz</a><br>
+      MD5: 0ed565c509594072822d71c65b48ec8e<br>
+      SHA-1: 48f59c99ac43d1cd2f5656a283bb9868581663a8
     </td>
   </tr>
 
diff --git a/docs/html/_redirects.yaml b/docs/html/_redirects.yaml
index 4a9cab6..0ee8157 100644
--- a/docs/html/_redirects.yaml
+++ b/docs/html/_redirects.yaml
@@ -1197,3 +1197,5 @@
   to: https://developer.android.com/studio/intro/update.html#sdk-manager
 - from: /r/studio-ui/newjclass.html
   to: /studio/write/index.html
+- from: /r/studio-ui/menu-help.html
+  to: /studio/intro/index.html
diff --git a/docs/html/preview/api-overview.jd b/docs/html/preview/api-overview.jd
index 3373fc4..c7ffb7a 100644
--- a/docs/html/preview/api-overview.jd
+++ b/docs/html/preview/api-overview.jd
@@ -27,6 +27,7 @@
         <li><a href="#multi-locale_languages">Locales and Languages</a></li>
         <li><a href="#emoji">New Emojis</a></li>
         <li><a href="#icu4">ICU4J APIs in Android</a></li>
+        <li><a href="#webview">WebView</a></li>
         <li><a href="#gles_32">OpenGL ES 3.2 API</a></li>
         <li><a href="#android_tv_recording">Android TV Recording</a></li>
         <li><a href="#android_for_work">Android for Work</a></li>
@@ -573,7 +574,85 @@
   "{@docRoot}preview/features/icu4j-framework.html">ICU4J Support</a>.
 </p>
 
+<h2 id="webview">WebView</h2>
 
+<h3>Chrome + WebView, Together</h3>
+
+<p>
+  Starting with Chrome version 51 on Android N and above, the Chrome APK on your device
+  is used to provide and render Android System WebViews. This approach improves memory
+  usage on the device itself and also reduces the bandwidth required to keep
+  WebView up to date (as the standalone WebView APK will no longer be updated
+  as long as Chrome remains enabled).
+</p>
+
+<p>
+  You can choose your WebView provider by enabling Developer Options and
+  selecting <strong>WebView implementation</strong>. You can use any compatible
+  Chrome version (Dev, Beta or Stable) that is installed on your device or the
+  standalone Webview APK to act as the WebView implementation.
+</p>
+
+<h3>Multiprocess</h3>
+
+<p>
+  Starting with Chrome version 51 in Android N, WebView will run web content in a
+  separate sandboxed process when the developer option "Multiprocess WebView"
+  is enabled.
+</p>
+
+<p>
+  We're looking for feedback on compatibility and runtime performance in N
+  before enabling multiprocess WebView in a future version of Android. In this
+  version, regressions in startup time, total memory usage and software
+  rendering performance are expected.
+</p>
+
+<p>
+  If you find unexpected issues in multiprocess mode we’d like to hear about
+  them. Please get in touch with the WebView team on the <a href=
+  "https://bugs.chromium.org/p/chromium/issues/entry?template=Webview%20Bugs"
+  >Chromium bug tracker</a>.
+</p>
+
+<h3>Javascript run before page load</h3>
+<p>
+  Starting with apps targeting Android N, the Javascript context will be reset
+  when a new page is loaded. Currently, the context is carried over for the
+  first page loaded in a new WebView instance.
+</p>
+
+<p>
+  Developers looking to inject Javascript into the WebView should execute the
+  script after the page has started to load.
+</p>
+
+<h3>Geolocation on insecure origins</h3>
+
+<p>
+  Starting with apps targeting Android N, the geolocation API will only be
+  allowed on secure origins (over HTTPS.) This policy is designed to protect
+  users’ private information when they’re using an insecure connection.
+</p>
+
+<h3>Testing with WebView Beta</h3>
+
+<p>
+  WebView is updated regularly, so we recommend that you test compatibility
+  with your app frequently using WebView’s beta channel. To get started testing
+  pre-release versions of WebView on Android N, download and install either
+  Chrome Dev or Chrome Beta, and select it as the WebView implementation under
+  developer options as described above. Please report issues via the <a href=
+  "https://bugs.chromium.org/p/chromium/issues/entry?template=Webview%20Bugs">Chromium
+  bug tracker</a> so that we can fix them before a new version of WebView is
+  released.
+</p>
+
+<p>
+  If you have any other questions or issues, feel free to reach out to the
+  WebView team via our <a href=
+  "https://plus.google.com/communities/105434725573080290360">G+ community</a>.
+</p>
 
 <h2 id="gles_32">OpenGL&trade; ES 3.2 API</h2>
 
@@ -667,8 +746,9 @@
 
 <p>
   Users can also manually set Always on VPN clients that implement
-  <code>VPNService</code> methods in the primary user using
-  <strong>Settings&gt;More&gt;Vpn</strong>.
+  <code>VPNService</code> methods using
+  <strong>Settings&gt;More&gt;Vpn</strong>. The option to enable Always on VPN
+  from Settings is available only if VPN client targets API level 24.
 </p>
 
 <h3 id="custom_provisioning">Customized provisioning</h3>
@@ -755,6 +835,20 @@
   on the device.
 </p>
 
+<p class="note">
+  <strong>Note: </strong>Only a small number of devices running Android N
+  support hardware-level key attestation; all other devices running Android N
+  use software-level key attestation instead. Before you verify the properties
+  of a device's hardware-backed keys in a production-level environment, you
+  should make sure that the device supports hardware-level key attestation. To
+  do so, you should check that the attestation certificate chain contains a root
+  certificate that is signed by the Google attestation root key and that the
+  <code>attestationSecurityLevel</code> element within the <a
+  href="{@docRoot}preview/features/key-attestation.html#certificate_schema_keydescription">key
+  description</a> data structure is set to the TrustedEnvironment security
+  level.
+</p>
+
 <p>
   For more information, see the
   <a href="{@docRoot}preview/features/key-attestation.html">Key Attestation</a>
diff --git a/docs/html/preview/behavior-changes.jd b/docs/html/preview/behavior-changes.jd
index 3a37295..48dc053 100644
--- a/docs/html/preview/behavior-changes.jd
+++ b/docs/html/preview/behavior-changes.jd
@@ -748,6 +748,23 @@
   to the trusted credentials storage via Settings UI separately, with a
   DER-encoded format under a .crt or .cer file extension.
   </li>
+
+  <li>Starting in Android N, fingerprint enrollment and storage are managed per user.
+  If a profile owner’s Device Policy Client (DPC) targets pre-N on an N device,
+  the user is still able to set fingerprint on the device, but work
+  applications cannot access device fingerprint. When the DPC targets N and
+  above, the user can set fingerprint specifically for work profile by going to
+  <strong>Settings &gt; Security &gt; Work profile security</strong>.
+  </li>
+
+  <li>A new encryption status <code>ENCRYPTION_STATUS_ACTIVE_PER_USER</code> is
+  returned by <code>DevicePolicyManager.getStorageEncryptionStatus()</code>, to
+  indicate that encryption is active and the encryption key is tied to the
+  user. The new status is only returned if DPC targets API Level 24 and above.
+  For apps targeting earlier API levels, <code>ENCRYPTION_STATUS_ACTIVE</code>
+  is returned, even if the encryption key is specific to the user or profile.
+  </li>
+
 </ul>
 
 <p>
diff --git a/docs/html/preview/download-ota.jd b/docs/html/preview/download-ota.jd
index 18f3e8d..65f7f9f 100644
--- a/docs/html/preview/download-ota.jd
+++ b/docs/html/preview/download-ota.jd
@@ -203,72 +203,72 @@
   <tr id="bullhead">
     <td>Nexus 5X <br>"bullhead"</td>
     <td><a href="#top" onclick="onDownload(this)"
-      >bullhead-ota-npd56n-dd5c12ee.zip</a><br>
-      MD5: af9a82e9a78925ca9c1c7f5f6fb851ec<br>
-      SHA-1: e4aabd5634b7ebdeffa877cd9e49244c0be326e4
+      >bullhead-ota-npd90g-0a874807.zip</a><br>
+      MD5: 4b83b803fac1a6eec13f66d0afc6f46e<br>
+      SHA-1: a9920bcc8d475ce322cada097d085448512635e2
     </td>
   </tr>
 
   <tr id="shamu">
     <td>Nexus 6 <br>"shamu"</td>
     <td><a href="#top" onclick="onDownload(this)"
-      >shamu-ota-npd56n-2818fd62.zip</a><br>
-      MD5: d8df396b187a8667889260e5464bd676<br>
-      SHA-1: c03c8ef8be587a574565855d4faa526254794e03
+      >shamu-ota-npd90g-06f5d23d.zip</a><br>
+      MD5: 513570bb3a91878c2d1a5807d2340420<br>
+      SHA-1: 2d2f40636c95c132907e6ba0d10b395301e969ed
     </td>
   </tr>
 
   <tr id="angler">
     <td>Nexus 6P <br>"angler"</td>
     <td><a href="#top" onclick="onDownload(this)"
-      >angler-ota-npd56n-d2f2611c.zip</a><br>
-      MD5: c3c206892d414d4fc7da892ff840eada<br>
-      SHA-1: 2bdc79409ace5e163ef014ae51977d0a71b83df5
+      >angler-ota-npd90g-5baa69c2.zip</a><br>
+      MD5: 096fe26c5d50606a424d2f3326c0477b<br>
+      SHA-1: 468d2e7aea444505513ddc183c85690c00fab0c1
     </td>
   </tr>
 
   <tr id="volantis">
     <td>Nexus 9 <br>"volantis"</td>
     <td><a href="#top" onclick="onDownload(this)"
-      >volantis-ota-npd56n-42228a60.zip</a><br>
-      MD5: c80cf483d8b3c014fc7b27f80957a158<br>
-      SHA-1: f437829320f47ea3aa5f8b70ce2f0bb3d30b3f4f
+      >volantis-ota-npd90g-c04785e1.zip</a><br>
+      MD5: 6aecd3b0b3a839c5ce1ce4d12187b03e<br>
+      SHA-1: 31633180635b831e59271a7d904439f278586f49
     </td>
   </tr>
 
   <tr id="volantisg">
     <td>Nexus 9G <br>"volantisg"</td>
     <td><a href="#top" onclick="onDownload(this)"
-      >volantisg-ota-npd56n-9b4dbaac.zip</a><br>
-      MD5: 9e55ac1650e4f07a662bafa7f082e91c<br>
-      SHA-1: b9982be56c2817d122664869a1fbe9b13e9c72f7
+      >volantisg-ota-npd90g-c56aa1b0.zip</a><br>
+      MD5: 0493fa79763d67bcdde8007299e1888d<br>
+      SHA-1: f709daf81968a1b27ed41fe40d42e0d106f3c494
     </td>
   </tr>
 
   <tr id="fugu">
     <td>Nexus Player <br>"fugu"</td>
     <td><a href="#top" onclick="onDownload(this)"
-      >fugu-ota-npd56n-b305968a.zip</a><br>
-      MD5: dfc980acad6772d8473ccaa9cbbb681a<br>
-      SHA-1: d7bf8192649dea970afda165d181b4eea07abd7d
+      >fugu-ota-npd90g-3a0643ae.zip</a><br>
+      MD5: 9c38b6647fe5a4f2965196b7c409f0f7<br>
+      SHA-1: 77c6fb05191f0c2ae0956bae18f1c80b2f922f05
     </td>
   </tr>
 
   <tr id="ryu">
     <td>Pixel C <br>"ryu"</td>
     <td><a href="#top" onclick="onDownload(this)"
-      >ryu-ota-npd56n-5bf2fd66.zip</a><br>
-      MD5: 1699e4bacfbef16a75ae6cf3f2e3d886<br>
-      SHA-1: e20f3a8e43fcdd6acef21da80894afc8f9474e33
+      >ryu-ota-npd90g-ec931914.zip</a><br>
+      MD5: 4c6135498ca156a9cdaf443ddfdcb2ba<br>
+      SHA-1: 297cc9a204685ef5507ec087fc7edf5b34551ce6
     </td>
   </tr>
 
   <tr id="seed">
     <td>General Mobile 4G (Android One) <br>"seed"</td>
     <td><a href="#top" onclick="onDownload(this)"
-      >seed_l8150-ota-npd56n-a322696c.zip</a><br>
-      MD5: afc0e363ad2fd7418423e189a339a8e9<br>
-      SHA-1: fc4d818878df51894eac29932dd0e9f6511329c6
+      >seed_l8150-ota-npd90g-dcb0662d.zip</a><br>
+      MD5: f40ea6314a13ea6dd30d0e68098532a2<br>
+      SHA-1: 11af10b621f4480ac63f4e99189d61e1686c0865
     </td>
   </tr>
 
diff --git a/docs/html/preview/download.jd b/docs/html/preview/download.jd
index ad82211..a60cbfaa 100644
--- a/docs/html/preview/download.jd
+++ b/docs/html/preview/download.jd
@@ -219,14 +219,26 @@
 </p>
 
 <ul>
-  <li><strong>Enroll the device in automatic OTA system updates</strong> through the
-  <a href="https://g.co/androidbeta">Android Beta Program</a>. Once enrolled, your device will receive regular
-  over-the-air (OTA) updates of all milestone builds in the N Developer Preview. This
-  approach is recommended because it lets you seamlessly transition from your current
-  environment through the various releases of the N Developer Preview.</li>
-  <li><strong>Download a Developer Preview system image and flash the device</strong>.
-  OTA updates are not provided automatically for devices that you flash manually, but
-  you can enroll those devices in Android Beta Program to get OTA updates. </li>
+  <li>
+    <strong>Enroll the device in automatic OTA system updates</strong> through
+    the <a href="https://g.co/androidbeta">Android Beta Program</a>. Once
+    enrolled, your device will receive regular over-the-air (OTA) updates of
+    all milestone builds in the N Developer Preview. When the next version of
+    Android is released, your device will automatically update to the final
+    version. This approach is recommended because it lets you seamlessly
+    transition from your current environment, through the various releases of
+    the N Developer Preview, to the release version.
+  </li>
+
+  <li>
+    <strong>Download a Developer Preview system image and flash the
+    device</strong>. OTA updates are not provided automatically for devices
+    that you flash manually, but you can enroll those devices in Android Beta
+    Program to get OTA updates. When the next version of Android is released,
+    you can download the final device image from the <a href=
+    "https://developers.google.com/android/nexus/images" type=
+    "external-link">factory images</a> page.
+  </li>
 </ul>
 
 <h3 id="ota">Enroll the device in automatic OTA updates</h3>
@@ -234,9 +246,11 @@
 <p>
   If you have access to a supported device (see the list in the Downloads
   table), you can receive over-the-air updates to preview versions of Android
-  by enrolling that device in the <a href="https://g.co/androidbeta">Android Beta Program</a>. These updates are
-  automatically downloaded and will update your device just like official
-  system updates.
+  by enrolling that device in the <a href="https://g.co/androidbeta">Android
+  Beta Program</a>. These updates are automatically downloaded and will update
+  your device just like official system updates. When the next version of
+  Android is released, the device will automatically update to the production
+  version.
 </p>
 
 <p>
@@ -282,7 +296,8 @@
 <p>
   Manually flashed system images <strong>do not
   automatically receive OTA updates</strong> to later Developer Preview
-  milestone builds. Make sure to keep your environment up-to-date and flash a
+  milestone builds or the final, production version. Make sure to keep your
+  environment up-to-date and flash a
   new system image at each Developer Preview milestone.
 </p>
 
@@ -302,72 +317,72 @@
   <tr id="bullhead">
     <td>Nexus 5X <br>"bullhead"</td>
     <td><a href="#top" onclick="onDownload(this)"
-      >bullhead-npd56n-factory-996cac57.tgz</a><br>
-      MD5: 5aadba91f60de00d58dc6198ef5cc3ba<br>
-      SHA-1: 996cac575d83bde573315290da8f52cecc4127d2
+      >bullhead-npd90g-factory-7a0ca1bc.tgz</a><br>
+      MD5: e7a9a3061335c1e0c8be2588f13290af<br>
+      SHA-1: 7a0ca1bcfa51bbefde34243603bc79c7dec214a1
     </td>
   </tr>
 
   <tr id="shamu">
     <td>Nexus 6 <br>"shamu"</td>
     <td><a href="#top" onclick="onDownload(this)"
-      >shamu-npd56n-factory-7936bf75.tgz</a><br>
-      MD5: b7ed0db569f3bc2d6655fe8d8cea0e13<br>
-      SHA-1: 7936bf75e6bfb771bd14485211a319b246311b96
+      >shamu-npd90g-factory-f7a4e3a9.tgz</a><br>
+      MD5: 2fb572ddcfca67bb1d741be97492a9ed<br>
+      SHA-1: f7a4e3a96c797827492998e855c8f9efbfc8559a
     </td>
   </tr>
 
   <tr id="angler">
     <td>Nexus 6P <br>"angler"</td>
     <td><a href="#top" onclick="onDownload(this)"
-      >angler-npd56n-factory-1ce5ccad.tgz</a><br>
-      MD5: f296eccaed4e2526d6435df8cf0e8df1<br>
-      SHA-1: 1ce5ccad8a3eae143e0ecd9c7afbb1be2f1d41cc
+      >angler-npd90g-factory-cd9ac81e.tgz</a><br>
+      MD5: 2370c30f3ef1d0684c1de5216a5d90fe<br>
+      SHA-1: cd9ac81ec7f4a646ac6054eecbf2ea4c4b89b054
     </td>
   </tr>
 
   <tr id="volantis">
     <td>Nexus 9 <br>"volantis"</td>
     <td><a href="#top" onclick="onDownload(this)"
-      >volantis-npd56n-factory-8b9f997e.tgz</a><br>
-      MD5: 111c2fe5777dd6aae71fb8ef35dda9d3<br>
-      SHA-1: 8b9f997ea39fdaf505527536bd346948ae1bae30
+      >volantis-npd90g-factory-41b55406.tgz</a><br>
+      MD5: cefa78950141da2a7c75e887717e3c8f<br>
+      SHA-1: 41b554060263a7ef16e4be8422cbd6caca26e00f
     </td>
   </tr>
 
   <tr id="volantisg">
     <td>Nexus 9G <br>"volantisg"</td>
     <td><a href="#top" onclick="onDownload(this)"
-      >volantisg-npd56n-factory-ef05106a.tgz</a><br>
-      MD5: 3a6f4d47b385966347bd26b7a922cd6e<br>
-      SHA-1: ef05106a9e3becea5673ea67d6c0cc21a2ec09d4
+      >volantisg-npd90g-factory-610492be.tgz</a><br>
+      MD5: 2f36dc0d0fab02ab78be500677ec239f<br>
+      SHA-1: 610492bedfc4127023040ecb2c89239a78a900ad
     </td>
   </tr>
 
   <tr id="fugu">
     <td>Nexus Player <br>"fugu"</td>
     <td><a href="#top" onclick="onDownload(this)"
-      >fugu-npd56n-factory-a51674a1.tgz</a><br>
-      MD5: b75dc745a64848ea24124db8fa9252ed<br>
-      SHA-1: a51674a1303b17fec0405d513f9c0fe9f225780f
+      >fugu-npd90g-factory-0fe95694.tgz</a><br>
+      MD5: f4cb48f919e4c29c631de21416c612e2<br>
+      SHA-1: 0fe95694e7bc41e4c3ac0e4438cd77102a0aa8b4
     </td>
   </tr>
 
   <tr id="ryu">
     <td>Pixel C <br>"ryu"</td>
     <td><a href="#top" onclick="onDownload(this)"
-      >ryu-npd56n-factory-e36c49b1.tgz</a><br>
-      MD5: 0a2d660b09e19614a5b3573487b88066<br>
-      SHA-1: e36c49b184843cdfe10278aebc04ce50b6d670b6
+      >ryu-npd90g-factory-f4da981c.tgz</a><br>
+      MD5: d9f0e40b6c20d274831e8a7d285fd887<br>
+      SHA-1: f4da981c70576133321e2858e52fe2c990e68a75
     </td>
   </tr>
 
   <tr id="seed">
     <td>General Mobile 4G (Android One) <br>"seed"</td>
     <td><a href="#top" onclick="onDownload(this)"
-      >seed_l8150-npd56n-factory-dd5d4fd2.tgz</a><br>
-      MD5: 3420581b969af777753141dacc7f73b9<br>
-      SHA-1: dd5d4fd203f9c5dad658434c0ff370c411b78835
+      >seed_l8150-npd90g-factory-48f59c99.tgz</a><br>
+      MD5: 0ed565c509594072822d71c65b48ec8e<br>
+      SHA-1: 48f59c99ac43d1cd2f5656a283bb9868581663a8
     </td>
   </tr>
 
diff --git a/docs/html/preview/features/direct-boot.jd b/docs/html/preview/features/direct-boot.jd
index 8351f4b..60f6141 100644
--- a/docs/html/preview/features/direct-boot.jd
+++ b/docs/html/preview/features/direct-boot.jd
@@ -14,6 +14,7 @@
     <li><a href="#notification">Getting Notified of User Unlock</a></li>
     <li><a href="#migrating">Migrating Existing Data</a></li>
     <li><a href="#testing">Testing Your Encryption Aware App</a></li>
+    <li><a href="#dpm">Checking Device Policy Encryption Status</a></li>
   </ol>
 </div>
 </div>
@@ -186,3 +187,34 @@
 </pre>
 
 <p>Using these commands causes the device to reboot.</p>
+
+<h2 id="dpm">Checking Device Policy Encryption Status</h2>
+
+<p>Device administration apps can use
+{@link android.app.admin.DevicePolicyManager#getStorageEncryptionStatus
+DevicePolicyManager.getStorageEncryptionStatus()} to check the current
+encryption status of the device. If your app is targeting an API level
+lower than Android N,
+{@link android.app.admin.DevicePolicyManager#getStorageEncryptionStatus
+getStorageEncryptionStatus()} will return
+{@link android.app.admin.DevicePolicyManager#ENCRYPTION_STATUS_ACTIVE
+ENCRYPTION_STATUS_ACTIVE} if the device is either using full-disk encryption,
+or file-based encryption with Direct Boot. In both of these cases, data is
+always stored encrypted at rest. If your app is targeting an API level of
+Android N or higher,
+{@link android.app.admin.DevicePolicyManager#getStorageEncryptionStatus
+getStorageEncryptionStatus()} will return
+{@link android.app.admin.DevicePolicyManager#ENCRYPTION_STATUS_ACTIVE
+ENCRYPTION_STATUS_ACTIVE} if the device is using full-disk encryption. It will
+return
+{@link android.app.admin.DevicePolicyManager#ENCRYPTION_STATUS_ACTIVE_PER_USER
+ENCRYPTION_STATUS_ACTIVE_PER_USER} if the device is using file-based encryption
+with Direct Boot.</p>
+
+<p>If you build a device administration app
+that targets Android N, make sure to check for both
+{@link android.app.admin.DevicePolicyManager#ENCRYPTION_STATUS_ACTIVE
+ENCRYPTION_STATUS_ACTIVE} and
+{@link android.app.admin.DevicePolicyManager#ENCRYPTION_STATUS_ACTIVE_PER_USER
+ENCRYPTION_STATUS_ACTIVE_PER_USER} to determine if the device is
+encrypted.</p>
diff --git a/docs/html/preview/features/key-attestation.jd b/docs/html/preview/features/key-attestation.jd
index 98b8340..5be6dfa 100644
--- a/docs/html/preview/features/key-attestation.jd
+++ b/docs/html/preview/features/key-attestation.jd
@@ -21,6 +21,19 @@
   interpret the schema of the attestation certificate's extension data.
 </p>
 
+<p class="note">
+  <strong>Note: </strong>Only a small number of devices running Android N
+  support hardware-level key attestation; all other devices running Android N
+  use software-level key attestation instead. Before you verify the properties
+  of a device's hardware-backed keys in a production-level environment, you
+  should make sure that the device supports hardware-level key attestation. To
+  do so, you should check that the attestation certificate chain contains a root
+  certificate that is signed by the Google attestation root key and that the
+  <code>attestationSecurityLevel</code> element within the <a
+  href="#certificate_schema_keydescription">key description</a> data structure
+  is set to the TrustedEnvironment security level.
+</p>
+
 <h2 id="verifying">
   Retrieving and Verifying a Hardware-backed Key Pair
 </h2>
@@ -227,8 +240,8 @@
       level</a> of the attestation.
     </p>
 
-    <p class="note">
-      <strong>Note:</strong> Although it is possible to attest keys that are
+    <p class="caution">
+      <strong>Warning:</strong> Although it is possible to attest keys that are
       stored in the Android system&mdash;that is, if the
       <code>attestationSecurity</code> value is set to Software&mdash;you
       cannot trust these attestations if the Android system becomes compromised.
diff --git a/docs/html/preview/support.jd b/docs/html/preview/support.jd
index ef8a652..234c21f 100644
--- a/docs/html/preview/support.jd
+++ b/docs/html/preview/support.jd
@@ -12,14 +12,14 @@
 <h2>In this document</h2>
 
 <ul>
-  <li><a href="#dp4">Developer Preview 4</a>
+  <li><a href="#dp5">Developer Preview 5</a>
     <ul>
       <li><a href="#general">General advisories</a></li>
-      <li><a href="#new">New in DP4</a></li>
+      <li><a href="#new">New in DP5</a></li>
       <li><a href="#ki">Known issues</a></li>
-      <li><a href="#upgrade-notes">Notes on publishing apps that target API 24</a></li>
     </ul>
   </li>
+  <li><a href="#dp4">Developer Preview 4</a></li>
   <li><a href="#dp3">Developer Preview 3</a></li>
   <li><a href="#dp2">Developer Preview 2</a></li>
   <li><a href="#dp1">Developer Preview 1</a></li>
@@ -50,6 +50,123 @@
   community</a>.
 </p>
 
+<h2 id="dp5">Developer Preview 5</h2>
+
+<div class="wrap">
+  <div class="cols">
+    <div class="col-6of12">
+      <p>
+        <em>Date: July 2016<br>
+        Build: NPD90G<br>
+        Emulator support: x86 &amp; ARM (32/64-bit)<br>
+        Google Play services: 8.4</em>
+      </p>
+    </div>
+  </div>
+</div>
+
+<h3 id="general">General advisories</h3>
+
+<p>
+  This Developer Preview release is for <strong>app developers and other early
+  adopters</strong> and is available for daily use, development, or
+  compatibility testing. Please be aware of these general notes about the
+  release:
+</p>
+
+<ul>
+  <li>This release may have various <strong>stability issues</strong> on
+  supported devices.
+  </li>
+
+  <li>Some apps <strong>may not function as expected</strong> on the new
+  platform version. This includes Google’s apps as well as other apps.
+  </li>
+
+  <li>Developer Preview 5 is <strong>Compatibility Test Suite (CTS)
+  approved</strong> on these devices: Nexus 5X, Nexus 6, Nexus 6P, and
+  Pixel C. Apps that depend on CTS approved builds should work normally
+  on these devices (Android Pay for example).
+  </li>
+
+  <li>Developer Preview 4 is <strong>available on all supported
+  devices:</strong> Nexus 5X, Nexus 6, Nexus 6P, Nexus 9, Nexus Player,
+  Pixel C, General Mobile 4G (Android One), as well as Sony Xperia Z3
+  (D6603 and D6653 models).
+  </li>
+</ul>
+
+
+<h3 id="new">New in DP5</h3>
+
+<h4>Updated system images for supported devices and emulator</h4>
+
+<p>
+  Developer Preview 5 includes <a href=
+  "{@docRoot}preview/download.html"><strong>near-final system
+  images</strong></a> for supported devices and the Android emulator. The
+  images include the final APIs (API level 24) for the upcoming Android N
+  platform. When you are done testing, you can publish app using API level 24
+  to Google Play, in alpha, beta, and production release channels.
+</p>
+
+
+<!--
+
+<h4 id="api-changes">Feature and API changes</h4>
+
+<ul>
+  <li>TODO</li>
+</ul>
+
+-->
+
+<h3 id="ki">Known Issues</h3>
+
+<h4>Stability</h4>
+
+<ul>
+  <li>Users may encounter system instability (such as kernel panics and
+  crashes).
+  </li>
+</ul>
+
+<!-- TBA, if any
+<h4>Device-specific issues</h4>
+
+<dl>
+  <dt>
+    <strong>Device Name</strong>
+  </dt>
+
+  <dd>
+    Issue 1
+  </dd>
+
+  <dd>
+    Issue 2
+  </dd>
+</dl>
+
+-->
+<!-- TBA, if any
+
+<h4 id="dp5-fixes">Fixes for issues reported by developers</h4>
+
+<p>
+  A number of issues reported by developers have been fixed, including:
+</p>
+
+<ul>
+  <li>TODO</li>
+</ul>
+
+-->
+
+
+
+<!-- DP4 Release Notes Archive -->
+
 <h2 id="dp4">Developer Preview 4</h2>
 
 <div class="wrap">
@@ -280,7 +397,7 @@
   </li>
 </ul>
 
-<h4 id="">Android Auto</h4>
+<h4>Android Auto</h4>
 
 <p>
   The version of Google Maps included in Developer Preview 4 (9.30) crashes
diff --git a/docs/html/wear/preview/_book.yaml b/docs/html/wear/preview/_book.yaml
index 3bea2fd..a231fb5 100644
--- a/docs/html/wear/preview/_book.yaml
+++ b/docs/html/wear/preview/_book.yaml
@@ -30,5 +30,8 @@
 - title: License Agreement
   path: /wear/preview/license.html
 
+- title: Behavior Changes
+  path: /wear/preview/behavior-changes.html
+
 - title: Support and Release Notes
   path: /wear/preview/support.html
diff --git a/docs/html/wear/preview/behavior-changes.jd b/docs/html/wear/preview/behavior-changes.jd
new file mode 100644
index 0000000..0214622
--- /dev/null
+++ b/docs/html/wear/preview/behavior-changes.jd
@@ -0,0 +1,63 @@
+page.title=Behavior Changes
+meta.keywords="preview", "wear"
+page.tags="preview", "developer preview"
+
+@jd:body
+
+<p>
+  Along with new features, Android Wear 2.0 includes a variety of behavior
+  changes. This document highlights some of the key changes to
+  account for in your apps.
+</p>
+
+<p>
+  If you have previously published an app for Android Wear, be aware that
+  your app might be affected by these changes in the platform.
+</p>
+
+<div id="qv-wrapper">
+<div id="qv">
+
+<h2>In this document</h2>
+
+<ul>
+  <li><a href="#activity-dismissal">Activity Dismissal</a></li>
+</ul>
+
+</div>
+</div>
+
+<h2 id="activity-dismissal">Activity Dismissal</h2>
+
+<p>
+  Starting in <a href="{@docRoot}wear/preview/index.html">Android Wear 2.0</a>,
+  users dismiss apps and activities by using
+  the power (stem) button on the watch.
+  Long-pressing to dismiss an app is no longer suggested.
+  Additionally, developers should not implement the
+  long-press for dismissing
+  <a href="{@docRoot}training/wearables/ui/exit.html">full screen</a>
+  activities (panning or immersive activities such as Google Maps).
+</p>
+
+<p>
+  In Android Wear 2.0, the power button of the watch is used
+  to navigate back in the
+  <a href="{@docRoot}guide/components/tasks-and-back-stack.html">back stack</a>,
+  including for full-screen panning activities.
+  Before Android Wear 2.0, the <code>DismissOverlayView</code> class was
+  used to implement the long-press for a user to dismiss an app.
+  (The <code>DismissOverlayView</code> class was added to a layout
+  for full-screen drawing and to draw over the other views.)
+  Developers should test the power button for going back
+  between an app's activities and for exiting an app.
+</p>
+
+<p>
+  Additionally, swipe for exiting an app or activity is not available.
+  Developers can consider how their user interfaces
+  can be enhanced with swipe-left and swipe-right,
+  in a way similar to the functionality described for
+  <a href="{@docRoot}wear/preview/features/ui-nav-actions.html">navigation
+  drawers</a>.
+</p>
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index 4f6368c..dc1d18f 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -235,7 +235,7 @@
     private final Rect mTmpBounds = new Rect();
 
     public VectorDrawable() {
-        this(new VectorDrawableState(), null);
+        this(new VectorDrawableState(null), null);
     }
 
     /**
@@ -830,7 +830,8 @@
 
         private static final int NATIVE_ALLOCATION_SIZE = 316;
 
-        // Deep copy for mutate() or implicitly mutate.
+        // If copy is not null, deep copy the given VectorDrawableState. Otherwise, create a
+        // native vector drawable tree with an empty root group.
         public VectorDrawableState(VectorDrawableState copy) {
             if (copy != null) {
                 mThemeAttrs = copy.mThemeAttrs;
@@ -851,8 +852,11 @@
                 if (copy.mRootName != null) {
                     mVGTargetsMap.put(copy.mRootName, this);
                 }
-                onTreeConstructionFinished();
+            } else {
+                mRootGroup = new VGroup();
+                createNativeTree(mRootGroup);
             }
+            onTreeConstructionFinished();
         }
 
         private void createNativeTree(VGroup rootGroup) {
@@ -870,7 +874,8 @@
             VMRuntime.getRuntime().registerNativeAllocation(NATIVE_ALLOCATION_SIZE);
         }
 
-
+        // This should be called every time after a new RootGroup and all its subtrees are created
+        // (i.e. in constructors of VectorDrawableState and in inflate).
         void onTreeConstructionFinished() {
             mRootGroup.setTree(mNativeTree);
             mAllocationOfAllNodes = mRootGroup.getNativeSize();
@@ -918,11 +923,6 @@
                     || super.canApplyTheme();
         }
 
-        public VectorDrawableState() {
-            mRootGroup = new VGroup();
-            createNativeTree(mRootGroup);
-        }
-
         @Override
         public Drawable newDrawable() {
             return new VectorDrawable(this, null);
diff --git a/libs/hwui/ClipArea.cpp b/libs/hwui/ClipArea.cpp
index 39b8d3d..84451ba 100644
--- a/libs/hwui/ClipArea.cpp
+++ b/libs/hwui/ClipArea.cpp
@@ -530,14 +530,14 @@
 }
 
 void ClipArea::applyTransformToRegion(const Matrix4& transform, SkRegion* region) {
-    if (transform.isSimple() && !transform.isPureTranslate()) {
+    if (transform.rectToRect() && !transform.isPureTranslate()) {
         // handle matrices with scale manually by mapping each rect
         SkRegion other;
         SkRegion::Iterator it(*region);
         while (!it.done()) {
             Rect rect(it.rect());
             transform.mapRect(rect);
-            rect.roundOut();
+            rect.snapGeometryToPixelBoundaries(true);
             other.op(rect.left, rect.top, rect.right, rect.bottom, SkRegion::kUnion_Op);
             it.next();
         }
diff --git a/libs/hwui/tests/unit/ClipAreaTests.cpp b/libs/hwui/tests/unit/ClipAreaTests.cpp
index afabd35..d4d7919 100644
--- a/libs/hwui/tests/unit/ClipAreaTests.cpp
+++ b/libs/hwui/tests/unit/ClipAreaTests.cpp
@@ -334,5 +334,14 @@
     EXPECT_EQ(SkIRect::MakeLTRB(12, 26, 16, 32), region.getBounds());
 }
 
+TEST(ClipArea, applyTransformToRegion_rotate90) {
+    SkRegion region(SkIRect::MakeLTRB(1, 2, 3, 4));
+    Matrix4 transform;
+    transform.loadRotate(90);
+    ClipArea::applyTransformToRegion(transform, &region);
+    EXPECT_TRUE(region.isRect());
+    EXPECT_EQ(SkIRect::MakeLTRB(-4, 1, -2, 3), region.getBounds());
+}
+
 } // namespace uirenderer
 } // namespace android
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 542dced..264944f 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -133,9 +133,10 @@
  <p class=note>
  Note that on some devices the slice-height is advertised as 0. This could mean either that the
  slice-height is the same as the frame height, or that the slice-height is the frame height
- aligned to some value (usually a power of 2). Unfortunately, there is no way to tell the actual
- slice height in this case. Furthermore, the vertical stride of the {@code U} plane in planar
- formats is also not specified or defined, though usually it is half of the slice height.
+ aligned to some value (usually a power of 2). Unfortunately, there is no standard and simple way
+ to tell the actual slice height in this case. Furthermore, the vertical stride of the {@code U}
+ plane in planar formats is also not specified or defined, though usually it is half of the slice
+ height.
  <p>
  The {@link MediaFormat#KEY_WIDTH} and {@link MediaFormat#KEY_HEIGHT} keys specify the size of the
  video frames; however, for most encondings the video (picture) only occupies a portion of the
@@ -620,8 +621,9 @@
  mode} will be automatically applied with one exception:
  <p class=note>
  Prior to the {@link android.os.Build.VERSION_CODES#M} release, software decoders may not
- have applied the rotation when being rendered onto a Surface. Unfortunately, there is no way to
- identify software decoders, or if they apply the rotation other than by trying it out.
+ have applied the rotation when being rendered onto a Surface. Unfortunately, there is no standard
+ and simple way to identify software decoders, or if they apply the rotation other than by trying
+ it out.
  <p>
  There are also some caveats.
  <p class=note>
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index d7a18d9..d74aa81 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -49,12 +49,18 @@
  * <tr><td>{@link #KEY_FRAME_RATE}</td><td>Integer or Float</td><td>required for <b>encoders</b>,
  *         optional for <b>decoders</b></td></tr>
  * <tr><td>{@link #KEY_CAPTURE_RATE}</td><td>Integer</td><td></td></tr>
- * <tr><td>{@link #KEY_I_FRAME_INTERVAL}</td><td>Integer</td><td><b>encoder-only</b></td></tr>
+ * <tr><td>{@link #KEY_I_FRAME_INTERVAL}</td><td>Integer (or Float)</td><td><b>encoder-only</b>,
+ *         time-interval between key frames.
+ *         Float support added in {@link android.os.Build.VERSION_CODES#N_MR1}</td></tr>
  * <tr><td>{@link #KEY_INTRA_REFRESH_PERIOD}</td><td>Integer</td><td><b>encoder-only</b>, optional</td></tr>
  * <tr><td>{@link #KEY_MAX_WIDTH}</td><td>Integer</td><td><b>decoder-only</b>, optional, max-resolution width</td></tr>
  * <tr><td>{@link #KEY_MAX_HEIGHT}</td><td>Integer</td><td><b>decoder-only</b>, optional, max-resolution height</td></tr>
- * <tr><td>{@link #KEY_REPEAT_PREVIOUS_FRAME_AFTER}</td><td>Long</td><td><b>video encoder in surface-mode only</b></td></tr>
- * <tr><td>{@link #KEY_PUSH_BLANK_BUFFERS_ON_STOP}</td><td>Integer(1)</td><td><b>video decoder rendering to a surface only</b></td></tr>
+ * <tr><td>{@link #KEY_REPEAT_PREVIOUS_FRAME_AFTER}</td><td>Long</td><td><b>encoder in surface-mode
+ *         only</b>, optional</td></tr>
+ * <tr><td>{@link #KEY_PUSH_BLANK_BUFFERS_ON_STOP}</td><td>Integer(1)</td><td><b>decoder rendering
+ *         to a surface only</b>, optional</td></tr>
+ * <tr><td>{@link #KEY_TEMPORAL_LAYERING}</td><td>String</td><td><b>encoder only</b>, optional,
+ *         temporal-layering schema</td></tr>
  * </table>
  * Specify both {@link #KEY_MAX_WIDTH} and {@link #KEY_MAX_HEIGHT} to enable
  * adaptive playback (seamless resolution change) for a video decoder that
@@ -258,9 +264,20 @@
     public static final String KEY_CAPTURE_RATE = "capture-rate";
 
     /**
-     * A key describing the frequency of I frames expressed in secs
-     * between I frames.
-     * The associated value is an integer.
+     * A key describing the frequency of key frames expressed in seconds between key frames.
+     * <p>
+     * This key is used by video encoders.
+     * A negative value means no key frames are requested after the first frame.
+     * A zero value means a stream containing all key frames is requested.
+     * <p class=note>
+     * Most video encoders will convert this value of the number of non-key-frames between
+     * key-frames, using the {@linkplain #KEY_FRAME_RATE frame rate} information; therefore,
+     * if the actual frame rate differs (e.g. input frames are dropped or the frame rate
+     * changes), the <strong>time interval</strong> between key frames will not be the
+     * configured value.
+     * <p>
+     * The associated value is an integer (or float since
+     * {@link android.os.Build.VERSION_CODES#N_MR1}).
      */
     public static final String KEY_I_FRAME_INTERVAL = "i-frame-interval";
 
@@ -280,12 +297,18 @@
 
    /**
      * A key describing the temporal layering schema.  This is an optional parameter
-     * that applies only to video encoders.  Use {@link MediaCodec#getInputFormat}
+     * that applies only to video encoders.  Use {@link MediaCodec#getOutputFormat}
      * after {@link MediaCodec#configure configure} to query if the encoder supports
-     * the desired schema. Supported values are {@code webrtc.vp8.1-layer},
-     * {@code webrtc.vp8.2-layer}, {@code webrtc.vp8.3-layer}, and {@code none}.
-     * If the encoder does not support temporal layering, the input format will
-     * not have an entry with this key.
+     * the desired schema. Supported values are {@code webrtc.vp8.N-layer},
+     * {@code android.generic.N}, {@code android.generic.N+M} and {@code none}, where
+     * {@code N} denotes the total number of non-bidirectional layers (which must be at least 1)
+     * and {@code M} denotes the total number of bidirectional layers (which must be non-negative).
+     * <p class=note>{@code android.generic.*} schemas have been added in {@link
+     * android.os.Build.VERSION_CODES#N_MR1}.
+     * <p>
+     * The encoder may support fewer temporal layers, in which case the output format
+     * will contain the configured schema. If the encoder does not support temporal
+     * layering, the output format will not have an entry with this key.
      * The associated value is a string.
      */
     public static final String KEY_TEMPORAL_LAYERING = "ts-schema";
diff --git a/packages/DocumentsUI/AndroidManifest.xml b/packages/DocumentsUI/AndroidManifest.xml
index 69912ab..a3edae3 100644
--- a/packages/DocumentsUI/AndroidManifest.xml
+++ b/packages/DocumentsUI/AndroidManifest.xml
@@ -11,6 +11,7 @@
     <application
         android:name=".DocumentsApplication"
         android:label="@string/app_label"
+        android:icon="@mipmap/ic_app_icon"
         android:supportsRtl="true">
 
         <activity
diff --git a/packages/DocumentsUI/res/mipmap-hdpi/ic_app_icon.png b/packages/DocumentsUI/res/mipmap-hdpi/ic_app_icon.png
new file mode 100644
index 0000000..cd3a037
--- /dev/null
+++ b/packages/DocumentsUI/res/mipmap-hdpi/ic_app_icon.png
Binary files differ
diff --git a/packages/DocumentsUI/res/mipmap-mdpi/ic_app_icon.png b/packages/DocumentsUI/res/mipmap-mdpi/ic_app_icon.png
new file mode 100644
index 0000000..8d08e9b
--- /dev/null
+++ b/packages/DocumentsUI/res/mipmap-mdpi/ic_app_icon.png
Binary files differ
diff --git a/packages/DocumentsUI/res/mipmap-xhdpi/ic_app_icon.png b/packages/DocumentsUI/res/mipmap-xhdpi/ic_app_icon.png
new file mode 100644
index 0000000..f3bacb7
--- /dev/null
+++ b/packages/DocumentsUI/res/mipmap-xhdpi/ic_app_icon.png
Binary files differ
diff --git a/packages/DocumentsUI/res/mipmap-xxhdpi/ic_app_icon.png b/packages/DocumentsUI/res/mipmap-xxhdpi/ic_app_icon.png
new file mode 100644
index 0000000..5156171
--- /dev/null
+++ b/packages/DocumentsUI/res/mipmap-xxhdpi/ic_app_icon.png
Binary files differ
diff --git a/packages/DocumentsUI/res/mipmap-xxxhdpi/ic_app_icon.png b/packages/DocumentsUI/res/mipmap-xxxhdpi/ic_app_icon.png
new file mode 100644
index 0000000..6dc2f76
--- /dev/null
+++ b/packages/DocumentsUI/res/mipmap-xxxhdpi/ic_app_icon.png
Binary files differ
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index a3070bd..78b9927 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -484,6 +484,8 @@
     @Override
     public void deleteDocument(String docId) throws FileNotFoundException {
         final File file = getFileForDocId(docId);
+        final File visibleFile = getFileForDocId(docId, true);
+
         final boolean isDirectory = file.isDirectory();
         if (isDirectory) {
             FileUtils.deleteContents(file);
@@ -492,7 +494,6 @@
             throw new IllegalStateException("Failed to delete " + file);
         }
 
-        final File visibleFile = getFileForDocId(docId, true);
         if (visibleFile != null) {
             final ContentResolver resolver = getContext().getContentResolver();
             final Uri externalUri = MediaStore.Files.getContentUri("external");
diff --git a/packages/Keyguard/res/values-my-rMM/dimens.xml b/packages/Keyguard/res/values-my-rMM/dimens.xml
new file mode 100644
index 0000000..21b2a46
--- /dev/null
+++ b/packages/Keyguard/res/values-my-rMM/dimens.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2016 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
+  -->
+<resources>
+    <dimen name="bottom_text_spacing_digital">4dp</dimen>
+</resources>
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java
index 9d1df26..e1657c7 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java
@@ -127,6 +127,11 @@
         super.onConfigurationChanged(newConfig);
         mClockView.setTextSize(TypedValue.COMPLEX_UNIT_PX,
                 getResources().getDimensionPixelSize(R.dimen.widget_big_font_size));
+        // Some layouts like burmese have a different margin for the clock
+        MarginLayoutParams layoutParams = (MarginLayoutParams) mClockView.getLayoutParams();
+        layoutParams.bottomMargin = getResources().getDimensionPixelSize(
+                R.dimen.bottom_text_spacing_digital);
+        mClockView.setLayoutParams(layoutParams);
         mDateView.setTextSize(TypedValue.COMPLEX_UNIT_PX,
                 getResources().getDimensionPixelSize(R.dimen.widget_label_font_size));
         mOwnerInfo.setTextSize(TypedValue.COMPLEX_UNIT_PX,
diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java
index 548ddf8..e049079 100644
--- a/packages/SettingsLib/src/com/android/settingslib/Utils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java
@@ -169,7 +169,7 @@
      * Determine whether a package is a "system package", in which case certain things (like
      * disabling notifications or disabling the package altogether) should be disallowed.
      */
-    public static boolean isSystemPackage(PackageManager pm, PackageInfo pkg) {
+    public static boolean isSystemPackage(Resources resources, PackageManager pm, PackageInfo pkg) {
         if (sSystemSignature == null) {
             sSystemSignature = new Signature[]{ getSystemSignature(pm) };
         }
@@ -187,7 +187,8 @@
                 || pkg.packageName.equals(sPermissionControllerPackageName)
                 || pkg.packageName.equals(sServicesSystemSharedLibPackageName)
                 || pkg.packageName.equals(sSharedSystemSharedLibPackageName)
-                || pkg.packageName.equals(PrintManager.PRINT_SPOOLER_PACKAGE_NAME);
+                || pkg.packageName.equals(PrintManager.PRINT_SPOOLER_PACKAGE_NAME)
+                || isDeviceProvisioningPackage(resources, pkg.packageName);
     }
 
     private static Signature getFirstSignature(PackageInfo pkg) {
@@ -205,4 +206,14 @@
         }
         return null;
     }
+
+    /**
+     * Returns {@code true} if the supplied package is the device provisioning app. Otherwise,
+     * returns {@code false}.
+     */
+    public static boolean isDeviceProvisioningPackage(Resources resources, String packageName) {
+        String deviceProvisioningPackage = resources.getString(
+                com.android.internal.R.string.config_deviceProvisioningPackage);
+        return deviceProvisioningPackage != null && deviceProvisioningPackage.equals(packageName);
+    }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
index 7392453..16bfc56 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
@@ -582,10 +582,10 @@
         public ArrayList<AppEntry> rebuild(AppFilter filter, Comparator<AppEntry> comparator,
                 boolean foreground) {
             synchronized (mRebuildSync) {
-                synchronized (mEntriesMap) {
+                synchronized (mRebuildingSessions) {
                     mRebuildingSessions.add(this);
                     mRebuildRequested = true;
-                    mRebuildAsync = false;
+                    mRebuildAsync = true;
                     mRebuildFilter = filter;
                     mRebuildComparator = comparator;
                     mRebuildForeground = foreground;
@@ -597,23 +597,7 @@
                     }
                 }
 
-                // We will wait for .25s for the list to be built.
-                long waitend = SystemClock.uptimeMillis()+250;
-
-                while (mRebuildResult == null) {
-                    long now = SystemClock.uptimeMillis();
-                    if (now >= waitend) {
-                        break;
-                    }
-                    try {
-                        mRebuildSync.wait(waitend - now);
-                    } catch (InterruptedException e) {
-                    }
-                }
-
-                mRebuildAsync = true;
-
-                return mRebuildResult;
+                return null;
             }
         }
 
@@ -776,7 +760,7 @@
         public void handleMessage(Message msg) {
             // Always try rebuilding list first thing, if needed.
             ArrayList<Session> rebuildingSessions = null;
-            synchronized (mEntriesMap) {
+            synchronized (mRebuildingSessions) {
                 if (mRebuildingSessions.size() > 0) {
                     rebuildingSessions = new ArrayList<Session>(mRebuildingSessions);
                     mRebuildingSessions.clear();
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
index b79ce80..bf48e5d 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
@@ -247,7 +247,6 @@
                 return Settings.Secure.getInt(mContext.getContentResolver(), name, 0) != 0;
             case Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES:
             case Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES:
-            case Settings.Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX:
             case Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER:
             case Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE:
                 return !TextUtils.isEmpty(Settings.Secure.getString(
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_4g_plus.xml b/packages/SystemUI/res/drawable/ic_qs_signal_4g_plus.xml
index 258bd0f..4d7f325 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_4g_plus.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_4g_plus.xml
@@ -1,37 +1,30 @@
 <!--
-     Copyright (C) 2016 The Android Open Source Project
+    Copyright (C) 2016 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
+    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
 
-     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.
+         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.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="18.0dp"
-    android:height="24dp"
-    android:viewportWidth="36.0"
-    android:viewportHeight="36.0">
-
+        android:width="24.0dp"
+        android:height="24.0dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
     <path
-        android:fillColor="#FFFFFF"
-        android:pathData="M6.797,13.334h1.231v1.522H6.797v2.509h-1.62v-2.509H1.101l-0.039-1.157l4.069-7.643h1.666V13.334z
-M2.648,13.334h2.53V8.721L5.137,8.713L4.984,9.148L2.648,13.334z" />
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M4.6,7.8l0.7,0.0l0.0,1.3L4.6,9.1L4.6,11.0L3.0,11.0L3.0,9.2L0.1,9.2L0.0,8.2l3.0,-5.7l1.7,0.0L4.6,7.8L4.6,7.8zM1.7,7.8L3.0,7.8l0.0,-3.0L2.9,5.0L1.7,7.8z"/>
     <path
-        android:fillColor="#FFFFFF"
-        android:pathData="M16.155,15.836c-0.269,0.439-0.695,0.832-1.282,1.177c-0.587,0.344-1.344,0.517-2.271,0.517
-c-1.151,0-2.098-0.432-2.841-1.294c-0.744-0.862-1.115-1.978-1.115-3.345v-2.36c0-1.367,0.359-2.481,1.077-3.343
-c0.719-0.863,1.643-1.293,2.772-1.293c1.132,0,2.017,0.331,2.649,0.994c0.633,0.663,0.941,1.528,0.924,2.594l-0.021,0.047h-1.545
-c0-0.638-0.171-1.15-0.513-1.538c-0.341-0.389-0.831-0.583-1.469-0.583c-0.674,0-1.217,0.292-1.63,0.877
-c-0.413,0.585-0.619,1.328-0.619,2.229v2.375c0,0.912,0.215,1.662,0.645,2.25c0.431,0.587,0.992,0.881,1.684,0.881
-c0.522,0,0.935-0.068,1.238-0.205c0.304-0.138,0.533-0.305,0.688-0.502v-2.338h-2.041v-1.413h3.668V15.836z" />
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M11.9,9.9c-0.2,0.4 -0.6,0.7 -1.0,0.9s-1.0,0.4 -1.8,0.4c-0.9,0.0 -1.7,-0.3 -2.2,-0.8S6.1,9.0 6.1,7.9L6.1,5.6c0.0,-1.1 0.3,-1.9 0.8,-2.4S8.2,2.4 9.0,2.4c1.0,0.0 1.7,0.2 2.1,0.7s0.7,1.2 0.7,2.1l-1.6,0.0c0.0,-0.5 -0.1,-0.9 -0.2,-1.1S9.5,3.7 9.0,3.7c-0.4,0.0 -0.7,0.2 -0.9,0.5S7.8,5.0 7.8,5.6l0.0,2.3c0.0,0.7 0.1,1.1 0.3,1.4c0.2,0.3 0.6,0.5 1.0,0.5c0.3,0.0 0.6,0.0 0.7,-0.1s0.3,-0.2 0.4,-0.3L10.2,7.8L9.0,7.8L9.0,6.6l2.9,0.0L11.9,9.9z"/>
     <path
-        android:fillColor="#FFFFFF"
-        android:pathData="M19.366,14.701v-2.232h-2.25v-1.541h2.25V8.695h1.5v2.232h2.256v1.541h-2.256v2.232H19.366z" />
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M17.7,4.4l-1.900001,0.0 0.0,-1.9 -1.2,0.0 0.0,1.9 -1.900001,0.0 0.0,1.2 1.900001,0.0 0.0,1.9 1.2,0.0 0.0,-1.9 1.900001,0.0z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_lte_plus.xml b/packages/SystemUI/res/drawable/ic_qs_signal_lte_plus.xml
new file mode 100644
index 0000000..3af0629
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_lte_plus.xml
@@ -0,0 +1,33 @@
+<!--
+    Copyright (C) 2016 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24.0dp"
+        android:height="24.0dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M2.0,9.7l2.0,0.0L4.0,11.0L0.4,11.0L0.4,2.5L2.0,2.5L2.0,9.7z"/>
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M8.3,3.8L7.0,3.8L7.0,11.0L5.4,11.0L5.4,3.8L4.0,3.8L4.0,2.5l4.3,0.0L8.3,3.8z"/>
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M12.4,7.3l-1.7,0.0l0.0,2.4l2.1,0.0L12.799999,11.0L9.0,11.0L9.0,2.5l3.7,0.0l0.0,1.3l-2.1,0.0l0.0,2.1l1.7,0.0L12.4,7.3L12.4,7.3z"/>
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M18.4,4.4l-1.9,0.0 0.0,-1.9 -1.2,0.0 0.0,1.9 -1.900001,0.0 0.0,1.2 1.900001,0.0 0.0,1.9 1.2,0.0 0.0,-1.9 1.9,0.0z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_4g_plus.xml b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_4g_plus.xml
index 17a4394..3cdd3e1 100644
--- a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_4g_plus.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_4g_plus.xml
@@ -1,37 +1,30 @@
 <!--
-     Copyright (C) 2016 The Android Open Source Project
+    Copyright (C) 2016 The Android Open Source Project
 
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
 
-     http://www.apache.org/licenses/LICENSE-2.0
+         http://www.apache.org/licenses/LICENSE-2.0
 
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
+    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.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="15dp"
-    android:height="20dp"
-    android:viewportWidth="36"
-    android:viewportHeight="36">
-
+        android:width="17.0dp"
+        android:height="17.0dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
     <path
-        android:fillColor="#FFFFFF"
-        android:pathData="M6.797,13.334h1.231v1.522H6.797v2.509h-1.62v-2.509H1.101l-0.039-1.157l4.069-7.643h1.666V13.334z
-M2.648,13.334h2.53V8.721L5.137,8.713L4.984,9.148L2.648,13.334z" />
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M4.6,7.8l0.7,0.0l0.0,1.3L4.6,9.1L4.6,11.0L3.0,11.0L3.0,9.2L0.1,9.2L0.0,8.2l3.0,-5.7l1.7,0.0L4.6,7.8L4.6,7.8zM1.7,7.8L3.0,7.8l0.0,-3.0L2.9,5.0L1.7,7.8z"/>
     <path
-        android:fillColor="#FFFFFF"
-        android:pathData="M16.155,15.836c-0.269,0.439-0.695,0.832-1.282,1.177c-0.587,0.344-1.344,0.517-2.271,0.517
-c-1.151,0-2.098-0.432-2.841-1.294c-0.744-0.862-1.115-1.978-1.115-3.345v-2.36c0-1.367,0.359-2.481,1.077-3.343
-c0.719-0.863,1.643-1.293,2.772-1.293c1.132,0,2.017,0.331,2.649,0.994c0.633,0.663,0.941,1.528,0.924,2.594l-0.021,0.047h-1.545
-c0-0.638-0.171-1.15-0.513-1.538c-0.341-0.389-0.831-0.583-1.469-0.583c-0.674,0-1.217,0.292-1.63,0.877
-c-0.413,0.585-0.619,1.328-0.619,2.229v2.375c0,0.912,0.215,1.662,0.645,2.25c0.431,0.587,0.992,0.881,1.684,0.881
-c0.522,0,0.935-0.068,1.238-0.205c0.304-0.138,0.533-0.305,0.688-0.502v-2.338h-2.041v-1.413h3.668V15.836z" />
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M11.9,9.9c-0.2,0.4 -0.6,0.7 -1.0,0.9s-1.0,0.4 -1.8,0.4c-0.9,0.0 -1.7,-0.3 -2.2,-0.8S6.1,9.0 6.1,7.9L6.1,5.6c0.0,-1.1 0.3,-1.9 0.8,-2.4S8.2,2.4 9.0,2.4c1.0,0.0 1.7,0.2 2.1,0.7s0.7,1.2 0.7,2.1l-1.6,0.0c0.0,-0.5 -0.1,-0.9 -0.2,-1.1S9.5,3.7 9.0,3.7c-0.4,0.0 -0.7,0.2 -0.9,0.5S7.8,5.0 7.8,5.6l0.0,2.3c0.0,0.7 0.1,1.1 0.3,1.4c0.2,0.3 0.6,0.5 1.0,0.5c0.3,0.0 0.6,0.0 0.7,-0.1s0.3,-0.2 0.4,-0.3L10.2,7.8L9.0,7.8L9.0,6.6l2.9,0.0L11.9,9.9z"/>
     <path
-        android:fillColor="#FFFFFF"
-        android:pathData="M19.366,14.701v-2.232h-2.25v-1.541h2.25V8.695h1.5v2.232h2.256v1.541h-2.256v2.232H19.366z" />
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M17.7,4.4l-1.900001,0.0 0.0,-1.9 -1.2,0.0 0.0,1.9 -1.900001,0.0 0.0,1.2 1.900001,0.0 0.0,1.9 1.2,0.0 0.0,-1.9 1.900001,0.0z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_lte_plus.xml b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_lte_plus.xml
new file mode 100644
index 0000000..db18fad
--- /dev/null
+++ b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_lte_plus.xml
@@ -0,0 +1,33 @@
+<!--
+    Copyright (C) 2016 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="17.0dp"
+        android:height="17.0dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M2.0,9.7l2.0,0.0L4.0,11.0L0.4,11.0L0.4,2.5L2.0,2.5L2.0,9.7z"/>
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M8.3,3.8L7.0,3.8L7.0,11.0L5.4,11.0L5.4,3.8L4.0,3.8L4.0,2.5l4.3,0.0L8.3,3.8z"/>
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M12.4,7.3l-1.7,0.0l0.0,2.4l2.1,0.0L12.799999,11.0L9.0,11.0L9.0,2.5l3.7,0.0l0.0,1.3l-2.1,0.0l0.0,2.1l1.7,0.0L12.4,7.3L12.4,7.3z"/>
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M18.4,4.4l-1.9,0.0 0.0,-1.9 -1.2,0.0 0.0,1.9 -1.900001,0.0 0.0,1.2 1.900001,0.0 0.0,1.9 1.2,0.0 0.0,-1.9 1.9,0.0z"/>
+</vector>
diff --git a/packages/SystemUI/res/layout/qs_detail.xml b/packages/SystemUI/res/layout/qs_detail.xml
index 63390e2..967db26 100644
--- a/packages/SystemUI/res/layout/qs_detail.xml
+++ b/packages/SystemUI/res/layout/qs_detail.xml
@@ -47,11 +47,12 @@
     <com.android.systemui.qs.NonInterceptingScrollView
         android:layout_width="match_parent"
         android:layout_height="0dp"
-        android:layout_weight="1">
+        android:layout_weight="1"
+        android:fillViewport="true">
         <FrameLayout
             android:id="@android:id/content"
             android:layout_width="match_parent"
-            android:layout_height="wrap_content" />
+            android:layout_height="match_parent"/>
     </com.android.systemui.qs.NonInterceptingScrollView>
 
     <include layout="@layout/qs_detail_buttons" />
diff --git a/packages/SystemUI/res/layout/qs_detail_items.xml b/packages/SystemUI/res/layout/qs_detail_items.xml
index f1a8d63..c94a972 100644
--- a/packages/SystemUI/res/layout/qs_detail_items.xml
+++ b/packages/SystemUI/res/layout/qs_detail_items.xml
@@ -15,7 +15,8 @@
      limitations under the License.
 -->
 <!-- extends FrameLayout -->
-<com.android.systemui.qs.QSDetailItems xmlns:android="http://schemas.android.com/apk/res/android"
+<com.android.systemui.qs.QSDetailItems
+    xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:sysui="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
@@ -28,26 +29,26 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:orientation="vertical"
-        sysui:itemHeight="@dimen/qs_detail_item_height" />
+        sysui:itemHeight="@dimen/qs_detail_item_height"/>
 
     <LinearLayout
         android:id="@android:id/empty"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
         android:layout_gravity="center"
-        android:gravity="center_horizontal"
-        android:orientation="vertical" >
+        android:gravity="center"
+        android:orientation="vertical">
 
         <ImageView
             android:id="@android:id/icon"
             android:layout_width="56dp"
-            android:layout_height="56dp" />
+            android:layout_height="56dp"/>
 
         <TextView
             android:id="@android:id/title"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_marginTop="20dp"
-            android:textAppearance="@style/TextAppearance.QS.DetailEmpty" />
+            android:textAppearance="@style/TextAppearance.QS.DetailEmpty"/>
     </LinearLayout>
 </com.android.systemui.qs.QSDetailItems>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 134388f..fa30f49 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -224,9 +224,25 @@
     <!-- Doze: duration to avoid false pickup gestures triggered by notification vibrations -->
     <integer name="doze_pickup_vibration_threshold">2000</integer>
 
-    <!-- Doze: can we assume the pickup sensor includes a proximity check? -->
+    <!-- Doze: can we assume the pickup sensor includes a proximity check?
+         This is ignored if doze_pickup_subtype_performs_proximity_check is not empty.
+         @deprecated: use doze_pickup_subtype_performs_proximity_check instead.-->
     <bool name="doze_pickup_performs_proximity_check">false</bool>
 
+    <!-- Doze: a list of pickup sensor subtypes that perform a proximity check before they trigger.
+               If not empty, either * or !* must appear to specify the default.
+               If empty, falls back to doze_pickup_performs_proximity_check.
+
+               Examples: 1,2,3,!* -> subtypes 1,2 and 3 perform the check, all others don't.
+                         !1,!2,*  -> subtypes 1 and 2 don't perform the check, all others do.
+                         !8,*     -> subtype 8 does not perform the check, all others do
+                         1,1,*    -> illegal, every item may only appear once
+                         1,!1,*   -> illegal, no contradictions allowed
+                         1,2      -> illegal, need either * or !*
+                         1,,4a3   -> illegal, no empty or non-numeric terms allowed
+    -->
+    <string name="doze_pickup_subtype_performs_proximity_check"></string>
+
     <!-- Doze: pulse parameter - how long does it take to fade in? -->
     <integer name="doze_pulse_duration_in">900</integer>
 
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 5324968..a0cb61a 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -354,6 +354,9 @@
     <!-- Content description of the data connection type LTE for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_data_connection_lte">LTE</string>
 
+    <!-- Content description of the data connection type LTE+ for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_data_connection_lte_plus">LTE+</string>
+
     <!-- Content description of the data connection type CDMA for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_data_connection_cdma">CDMA</string>
 
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index 39a3412..52b5a54 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -55,7 +55,8 @@
             com.android.systemui.media.RingtonePlayer.class,
             com.android.systemui.keyboard.KeyboardUI.class,
             com.android.systemui.tv.pip.PipUI.class,
-            com.android.systemui.shortcut.ShortcutKeyDispatcher.class
+            com.android.systemui.shortcut.ShortcutKeyDispatcher.class,
+            com.android.systemui.VendorServices.class
     };
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/VendorServices.java b/packages/SystemUI/src/com/android/systemui/VendorServices.java
new file mode 100644
index 0000000..0be6b12
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/VendorServices.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2016 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.systemui;
+
+/**
+ * Placeholder for any vendor-specific services.
+ */
+public class VendorServices extends SystemUI {
+
+    @Override
+    public void start() {
+        // no-op
+    }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
index 5f1b042..661b347 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
@@ -214,6 +214,10 @@
     }
 
     private void requestPulse(final int reason) {
+        requestPulse(reason, false /* performedProxCheck */);
+    }
+
+    private void requestPulse(final int reason, boolean performedProxCheck) {
         if (mHost != null && mDreaming && !mPulsing) {
             // Let the host know we want to pulse.  Wait for it to be ready, then
             // turn the screen on.  When finished, turn the screen off again.
@@ -226,10 +230,9 @@
                 return;
             }
             final long start = SystemClock.uptimeMillis();
-            final boolean nonBlocking = reason == DozeLog.PULSE_REASON_SENSOR_PICKUP
-                    && mDozeParameters.getPickupPerformsProxCheck();
-            if (nonBlocking) {
-                // proximity check is only done to capture statistics, continue pulsing
+            if (performedProxCheck) {
+                // the caller already performed a successful proximity check; we'll only do one to
+                // capture statistics, continue pulsing immediately.
                 continuePulsing(reason);
             }
             // perform a proximity check
@@ -239,7 +242,7 @@
                     final boolean isNear = result == RESULT_NEAR;
                     final long end = SystemClock.uptimeMillis();
                     DozeLog.traceProximityResult(mContext, isNear, end - start, reason);
-                    if (nonBlocking) {
+                    if (performedProxCheck) {
                         // we already continued
                         return;
                     }
@@ -540,9 +543,12 @@
             mWakeLock.acquire();
             try {
                 if (DEBUG) Log.d(mTag, "onTrigger: " + triggerEventToString(event));
+                boolean sensorPerformsProxCheck = false;
                 if (mSensor.getType() == Sensor.TYPE_PICK_UP_GESTURE) {
                     int subType = (int) event.values[0];
                     MetricsLogger.action(mContext, MetricsEvent.ACTION_AMBIENT_GESTURE, subType);
+                    sensorPerformsProxCheck = mDozeParameters.getPickupSubtypePerformsProxCheck(
+                            subType);
                 }
                 if (mDebugVibrate) {
                     final Vibrator v = (Vibrator) mContext.getSystemService(
@@ -555,7 +561,7 @@
                 }
 
                 mRegistered = false;
-                requestPulse(mPulseReason);
+                requestPulse(mPulseReason, sensorPerformsProxCheck);
                 updateListener();  // reregister, this sensor only fires once
 
                 // reset the notification pulse schedule, but only if we think we were not triggered
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
index c63be9c..6206cef9 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
@@ -67,6 +67,8 @@
     private boolean mTriggeredExpand;
     private int mOpenX;
     private int mOpenY;
+    private boolean mAnimating;
+    private boolean mSwitchState;
 
     public QSDetail(Context context, @Nullable AttributeSet attrs) {
         super(context, attrs);
@@ -158,7 +160,7 @@
                 mQsDetailHeader.setClickable(false);
             } else {
                 mQsDetailHeaderSwitch.setVisibility(VISIBLE);
-                mQsDetailHeaderSwitch.setChecked(toggleState);
+                handleToggleStateChanged(toggleState);
                 mQsDetailHeader.setClickable(true);
                 mQsDetailHeader.setOnClickListener(new OnClickListener() {
                     @Override
@@ -228,6 +230,7 @@
         }
         sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
         if (visibleDiff) {
+            mAnimating = true;
             if (mFullyExpanded || mDetailAdapter != null) {
                 setAlpha(1);
                 mClipper.animateCircularClip(x, y, mDetailAdapter != null, listener);
@@ -241,6 +244,10 @@
     }
 
     private void handleToggleStateChanged(boolean state) {
+        mSwitchState = state;
+        if (mAnimating) {
+            return;
+        }
         mQsDetailHeaderSwitch.setChecked(state);
     }
 
@@ -257,6 +264,10 @@
         }
     }
 
+    private void checkPendingAnimations() {
+        handleToggleStateChanged(mSwitchState);
+    }
+
     private final QSPanel.Callback mQsPanelCallback = new QSPanel.Callback() {
         @Override
         public void onToggleStateChanged(final boolean state) {
@@ -294,6 +305,8 @@
             // If we have been cancelled, remove the listener so that onAnimationEnd doesn't get
             // called, this will avoid accidentally turning off the grid when we don't want to.
             animation.removeListener(this);
+            mAnimating = false;
+            checkPendingAnimations();
         };
 
         @Override
@@ -303,6 +316,8 @@
                 mQsPanel.setGridContentVisibility(false);
                 mHeader.setVisibility(View.INVISIBLE);
             }
+            mAnimating = false;
+            checkPendingAnimations();
         }
     };
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
index 569a567..b36221d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
@@ -71,7 +71,7 @@
         super(host);
         mWindowManager = WindowManagerGlobal.getWindowManagerService();
         mComponent = ComponentName.unflattenFromString(action);
-        mTile = new Tile(mComponent);
+        mTile = new Tile();
         setTileIcon();
         mServiceManager = host.getTileServices().getTileWrapper(this);
         mService = mServiceManager.getTileService();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/QSTileServiceWrapper.java b/packages/SystemUI/src/com/android/systemui/qs/external/QSTileServiceWrapper.java
index 407453c..451e1f6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/QSTileServiceWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/QSTileServiceWrapper.java
@@ -94,4 +94,8 @@
             return false;
         }
     }
+
+    public IQSTileService getService() {
+        return mService;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
index 79f9de6..681005c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
@@ -26,6 +26,7 @@
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ServiceInfo;
 import android.net.Uri;
+import android.os.Binder;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.RemoteException;
@@ -37,6 +38,7 @@
 import android.support.annotation.VisibleForTesting;
 import android.util.ArraySet;
 import android.util.Log;
+
 import libcore.util.Objects;
 
 import java.util.Set;
@@ -67,6 +69,7 @@
     private final Handler mHandler;
     private final Intent mIntent;
     private final UserHandle mUser;
+    private final IBinder mToken = new Binder();
 
     private Set<Integer> mQueuedMessages = new ArraySet<>();
     private QSTileServiceWrapper mWrapper;
@@ -88,7 +91,7 @@
         mHandler = handler;
         mIntent = intent;
         mIntent.putExtra(TileService.EXTRA_SERVICE, service.asBinder());
-        mIntent.putExtra(TileService.EXTRA_COMPONENT, intent.getComponent());
+        mIntent.putExtra(TileService.EXTRA_TOKEN, mToken);
         mUser = user;
         if (DEBUG) Log.d(TAG, "Creating " + mIntent + " " + mUser);
     }
@@ -396,6 +399,10 @@
         handleDeath();
     }
 
+    public IBinder getToken() {
+        return mToken;
+    }
+
     public interface TileChangeListener {
         void onTileChanged(ComponentName tile);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
index 3d030f9..f3e4d60 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
@@ -25,6 +25,7 @@
 import android.content.pm.ResolveInfo;
 import android.net.Uri;
 import android.os.Handler;
+import android.os.IBinder;
 import android.os.UserHandle;
 import android.service.quicksettings.IQSTileService;
 import android.service.quicksettings.Tile;
@@ -32,6 +33,7 @@
 import android.support.annotation.VisibleForTesting;
 import android.util.Log;
 
+import com.android.systemui.qs.customize.TileQueryHelper.TileStateListener;
 import com.android.systemui.qs.external.TileLifecycleManager.TileChangeListener;
 
 import java.util.List;
@@ -106,6 +108,10 @@
         return mStateManager;
     }
 
+    public IBinder getToken() {
+        return mStateManager.getToken();
+    }
+
     public void setBindRequested(boolean bindRequested) {
         if (mBindRequested == bindRequested) return;
         mBindRequested = bindRequested;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
index 6f0bed2..575f198 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
@@ -25,10 +25,12 @@
 import android.graphics.drawable.Icon;
 import android.os.Binder;
 import android.os.Handler;
+import android.os.IBinder;
 import android.os.Looper;
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.service.quicksettings.IQSService;
+import android.service.quicksettings.IQSTileService;
 import android.service.quicksettings.Tile;
 import android.service.quicksettings.TileService;
 import android.util.ArrayMap;
@@ -52,6 +54,7 @@
 
     private final ArrayMap<CustomTile, TileServiceManager> mServices = new ArrayMap<>();
     private final ArrayMap<ComponentName, CustomTile> mTiles = new ArrayMap<>();
+    private final ArrayMap<IBinder, CustomTile> mTokenMap = new ArrayMap<>();
     private final Context mContext;
     private final Handler mHandler;
     private final Handler mMainHandler;
@@ -82,6 +85,7 @@
         synchronized (mServices) {
             mServices.put(tile, service);
             mTiles.put(component, tile);
+            mTokenMap.put(service.getToken(), tile);
         }
         return service;
     }
@@ -95,6 +99,7 @@
             service.setBindAllowed(false);
             service.handleDestroy();
             mServices.remove(tile);
+            mTokenMap.remove(service.getToken());
             mTiles.remove(tile.getComponent());
             final String slot = tile.getComponent().getClassName();
             mMainHandler.post(new Runnable() {
@@ -138,8 +143,9 @@
         }
     }
 
-    private void verifyCaller(String packageName) {
+    private void verifyCaller(CustomTile tile) {
         try {
+            String packageName = tile.getComponent().getPackageName();
             int uid = mContext.getPackageManager().getPackageUidAsUser(packageName,
                     Binder.getCallingUserHandle().getIdentifier());
             if (Binder.getCallingUid() != uid) {
@@ -170,10 +176,9 @@
     }
 
     @Override
-    public void updateQsTile(Tile tile) {
-        ComponentName componentName = tile.getComponentName();
-        verifyCaller(componentName.getPackageName());
-        CustomTile customTile = getTileForComponent(componentName);
+    public void updateQsTile(Tile tile, IBinder token) {
+        CustomTile customTile = getTileForToken(token);
+        verifyCaller(customTile);
         if (customTile != null) {
             synchronized (mServices) {
                 final TileServiceManager tileServiceManager = mServices.get(customTile);
@@ -186,10 +191,9 @@
     }
 
     @Override
-    public void onStartSuccessful(Tile tile) {
-        ComponentName componentName = tile.getComponentName();
-        verifyCaller(componentName.getPackageName());
-        CustomTile customTile = getTileForComponent(componentName);
+    public void onStartSuccessful(IBinder token) {
+        CustomTile customTile = getTileForToken(token);
+        verifyCaller(customTile);
         if (customTile != null) {
             synchronized (mServices) {
                 final TileServiceManager tileServiceManager = mServices.get(customTile);
@@ -200,10 +204,9 @@
     }
 
     @Override
-    public void onShowDialog(Tile tile) {
-        ComponentName componentName = tile.getComponentName();
-        verifyCaller(componentName.getPackageName());
-        CustomTile customTile = getTileForComponent(componentName);
+    public void onShowDialog(IBinder token) {
+        CustomTile customTile = getTileForToken(token);
+        verifyCaller(customTile);
         if (customTile != null) {
             customTile.onDialogShown();
             mHost.collapsePanels();
@@ -212,10 +215,9 @@
     }
 
     @Override
-    public void onDialogHidden(Tile tile) {
-        ComponentName componentName = tile.getComponentName();
-        verifyCaller(componentName.getPackageName());
-        CustomTile customTile = getTileForComponent(componentName);
+    public void onDialogHidden(IBinder token) {
+        CustomTile customTile = getTileForToken(token);
+        verifyCaller(customTile);
         if (customTile != null) {
             mServices.get(customTile).setShowingDialog(false);
             customTile.onDialogHidden();
@@ -223,23 +225,22 @@
     }
 
     @Override
-    public void onStartActivity(Tile tile) {
-        ComponentName componentName = tile.getComponentName();
-        verifyCaller(componentName.getPackageName());
-        CustomTile customTile = getTileForComponent(componentName);
+    public void onStartActivity(IBinder token) {
+        CustomTile customTile = getTileForToken(token);
+        verifyCaller(customTile);
         if (customTile != null) {
             mHost.collapsePanels();
         }
     }
 
     @Override
-    public void updateStatusIcon(Tile tile, Icon icon, String contentDescription) {
-        final ComponentName componentName = tile.getComponentName();
-        String packageName = componentName.getPackageName();
-        verifyCaller(packageName);
-        CustomTile customTile = getTileForComponent(componentName);
+    public void updateStatusIcon(IBinder token, Icon icon, String contentDescription) {
+        CustomTile customTile = getTileForToken(token);
+        verifyCaller(customTile);
         if (customTile != null) {
             try {
+                ComponentName componentName = customTile.getComponent();
+                String packageName = componentName.getPackageName();
                 UserHandle userHandle = getCallingUserHandle();
                 PackageInfo info = mContext.getPackageManager().getPackageInfoAsUser(packageName, 0,
                         userHandle.getIdentifier());
@@ -263,9 +264,9 @@
     }
 
     @Override
-    public Tile getTile(ComponentName componentName) {
-        verifyCaller(componentName.getPackageName());
-        CustomTile customTile = getTileForComponent(componentName);
+    public Tile getTile(IBinder token) {
+        CustomTile customTile = getTileForToken(token);
+        verifyCaller(customTile);
         if (customTile != null) {
             return customTile.getQsTile();
         }
@@ -273,10 +274,9 @@
     }
 
     @Override
-    public void startUnlockAndRun(Tile tile) {
-        ComponentName componentName = tile.getComponentName();
-        verifyCaller(componentName.getPackageName());
-        CustomTile customTile = getTileForComponent(componentName);
+    public void startUnlockAndRun(IBinder token) {
+        CustomTile customTile = getTileForToken(token);
+        verifyCaller(customTile);
         if (customTile != null) {
             customTile.startUnlockAndRun();
         }
@@ -294,6 +294,12 @@
         return keyguardMonitor.isSecure() && keyguardMonitor.isShowing();
     }
 
+    private CustomTile getTileForToken(IBinder token) {
+        synchronized (mServices) {
+            return mTokenMap.get(token);
+        }
+    }
+
     private CustomTile getTileForComponent(ComponentName component) {
         synchronized (mServices) {
             return mTiles.get(component);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
index 7a23910..794610e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -90,11 +90,11 @@
             mHost.startActivityDismissingKeyguard(new Intent(Settings.ACTION_BLUETOOTH_SETTINGS));
             return;
         }
+        showDetail(true);
         if (!mState.value) {
             mState.value = true;
             mController.setBluetoothEnabled(true);
         }
-        showDetail(true);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
index 04cb553..91821ba 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
@@ -122,9 +122,9 @@
         if (mState.value) {
             mController.setZen(Global.ZEN_MODE_OFF, null, TAG);
         } else {
+            showDetail(true);
             int zen = Prefs.getInt(mContext, Prefs.Key.DND_FAVORITE_ZEN, Global.ZEN_MODE_ALARMS);
             mController.setZen(zen, null, TAG);
-            showDetail(true);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index 661212c..9ce1f31 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -113,11 +113,11 @@
             mHost.startActivityDismissingKeyguard(new Intent(Settings.ACTION_WIFI_SETTINGS));
             return;
         }
+        showDetail(true);
         if (!mState.value) {
             mController.setWifiEnabled(true);
             mState.value = true;
         }
-        showDetail(true);
     }
 
     @Override
@@ -368,5 +368,5 @@
             }
             mItems.setItems(items);
         }
-    };
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
index b66a4fb..c497cfd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
@@ -186,7 +186,7 @@
         try {
             final PackageInfo info =
                     pm.getPackageInfo(sbn.getPackageName(), PackageManager.GET_SIGNATURES);
-            systemApp = Utils.isSystemPackage(pm, info);
+            systemApp = Utils.isSystemPackage(getResources(), pm, info);
         } catch (PackageManager.NameNotFoundException e) {
             // unlikely.
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
index 1d890d0..9b3ed33 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
@@ -21,6 +21,7 @@
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.MathUtils;
+import android.util.SparseBooleanArray;
 
 import com.android.systemui.R;
 
@@ -39,6 +40,8 @@
 
     private static PulseSchedule sPulseSchedule;
 
+    private static IntInOutMatcher sPickupSubtypePerformsProxMatcher;
+
     public DozeParameters(Context context) {
         mContext = context;
     }
@@ -61,7 +64,20 @@
         pw.print("    getPulseSchedule(): "); pw.println(getPulseSchedule());
         pw.print("    getPulseScheduleResets(): "); pw.println(getPulseScheduleResets());
         pw.print("    getPickupVibrationThreshold(): "); pw.println(getPickupVibrationThreshold());
-        pw.print("    getPickupPerformsProxCheck(): "); pw.println(getPickupPerformsProxCheck());
+        pw.print("    getPickupSubtypePerformsProxCheck(): ");pw.println(
+                dumpPickupSubtypePerformsProxCheck());
+    }
+
+    private String dumpPickupSubtypePerformsProxCheck() {
+        // Refresh sPickupSubtypePerformsProxMatcher
+        getPickupSubtypePerformsProxCheck(0);
+
+        if (sPickupSubtypePerformsProxMatcher == null) {
+            return "fallback: " + mContext.getResources().getBoolean(
+                    R.bool.doze_pickup_performs_proximity_check);
+        } else {
+            return "spec: " + sPickupSubtypePerformsProxMatcher.mSpec;
+        }
     }
 
     public boolean getDisplayStateSupported() {
@@ -106,10 +122,6 @@
         return getBoolean("doze.pulse.proxcheck", R.bool.doze_proximity_check_before_pulse);
     }
 
-    public boolean getPickupPerformsProxCheck() {
-        return getBoolean("doze.pickup.proxcheck", R.bool.doze_pickup_performs_proximity_check);
-    }
-
     public boolean getPulseOnNotifications() {
         return getBoolean("doze.pulse.notifications", R.bool.doze_pulse_on_notifications);
     }
@@ -143,6 +155,101 @@
         return SystemProperties.get(propName, mContext.getString(resId));
     }
 
+    public boolean getPickupSubtypePerformsProxCheck(int subType) {
+        String spec = getString("doze.pickup.proxcheck",
+                R.string.doze_pickup_subtype_performs_proximity_check);
+
+        if (TextUtils.isEmpty(spec)) {
+            // Fall back to non-subtype based property.
+            return mContext.getResources().getBoolean(R.bool.doze_pickup_performs_proximity_check);
+        }
+
+        if (sPickupSubtypePerformsProxMatcher == null
+                || !TextUtils.equals(spec, sPickupSubtypePerformsProxMatcher.mSpec)) {
+            sPickupSubtypePerformsProxMatcher = new IntInOutMatcher(spec);
+        }
+
+        return sPickupSubtypePerformsProxMatcher.isIn(subType);
+    }
+
+
+    /**
+     * Parses a spec of the form `1,2,3,!5,*`. The resulting object will match numbers that are
+     * listed, will not match numbers that are listed with a ! prefix, and will match / not match
+     * unlisted numbers depending on whether * or !* is present.
+     *
+     * *  -> match any numbers that are not explicitly listed
+     * !* -> don't match any numbers that are not explicitly listed
+     * 2  -> match 2
+     * !3 -> don't match 3
+     *
+     * It is illegal to specify:
+     * - an empty spec
+     * - a spec containing that are empty, or a lone !
+     * - a spec for anything other than numbers or *
+     * - multiple terms for the same number / multiple *s
+     */
+    public static class IntInOutMatcher {
+        private static final String WILDCARD = "*";
+        private static final char OUT_PREFIX = '!';
+
+        private final SparseBooleanArray mIsIn;
+        private final boolean mDefaultIsIn;
+        final String mSpec;
+
+        public IntInOutMatcher(String spec) {
+            if (TextUtils.isEmpty(spec)) {
+                throw new IllegalArgumentException("Spec must not be empty");
+            }
+
+            boolean defaultIsIn = false;
+            boolean foundWildcard = false;
+
+            mSpec = spec;
+            mIsIn = new SparseBooleanArray();
+
+            for (String itemPrefixed : spec.split(",", -1)) {
+                if (itemPrefixed.length() == 0) {
+                    throw new IllegalArgumentException(
+                            "Illegal spec, must not have zero-length items: `" + spec + "`");
+                }
+                boolean isIn = itemPrefixed.charAt(0) != OUT_PREFIX;
+                String item = isIn ? itemPrefixed : itemPrefixed.substring(1);
+
+                if (itemPrefixed.length() == 0) {
+                    throw new IllegalArgumentException(
+                            "Illegal spec, must not have zero-length items: `" + spec + "`");
+                }
+
+                if (WILDCARD.equals(item)) {
+                    if (foundWildcard) {
+                        throw new IllegalArgumentException("Illegal spec, `" + WILDCARD +
+                                "` must not appear multiple times in `" + spec + "`");
+                    }
+                    defaultIsIn = isIn;
+                    foundWildcard = true;
+                } else {
+                    int key = Integer.parseInt(item);
+                    if (mIsIn.indexOfKey(key) >= 0) {
+                        throw new IllegalArgumentException("Illegal spec, `" + key +
+                                "` must not appear multiple times in `" + spec + "`");
+                    }
+                    mIsIn.put(key, isIn);
+                }
+            }
+
+            if (!foundWildcard) {
+                throw new IllegalArgumentException("Illegal spec, must specify either * or !*");
+            }
+
+            mDefaultIsIn = defaultIsIn;
+        }
+
+        public boolean isIn(int value) {
+            return (mIsIn.get(value, mDefaultIsIn));
+        }
+    }
+
     public static class PulseSchedule {
         private static final Pattern PATTERN = Pattern.compile("(\\d+?)s", 0);
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 4b82279..64f205d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -58,6 +58,7 @@
 import com.android.systemui.statusbar.KeyguardAffordanceView;
 import com.android.systemui.statusbar.NotificationData;
 import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.notification.NotificationUtils;
 import com.android.systemui.statusbar.policy.HeadsUpManager;
 import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
 import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
@@ -78,7 +79,6 @@
     private static final int CAP_HEIGHT = 1456;
     private static final int FONT_HEIGHT = 2163;
 
-    private static final float HEADER_RUBBERBAND_FACTOR = 2.05f;
     private static final float LOCK_ICON_ACTIVE_SCALE = 1.2f;
 
     private static final String COUNTER_PANEL_OPEN = "panel_open";
@@ -1376,8 +1376,7 @@
         int min = mStatusBarMinHeight;
         if (mStatusBar.getBarState() != StatusBarState.KEYGUARD
                 && mNotificationStackScroller.getNotGoneChildCount() == 0) {
-            int minHeight = (int) ((mQsMinExpansionHeight + getOverExpansionAmount())
-                    * HEADER_RUBBERBAND_FACTOR);
+            int minHeight = (int) (mQsMinExpansionHeight + getOverExpansionAmount());
             min = Math.max(min, minHeight);
         }
         int maxHeight;
@@ -1552,15 +1551,8 @@
         if (mStatusBar.getBarState() == StatusBarState.KEYGUARD) {
             return 0;
         }
-        if (mNotificationStackScroller.getNotGoneChildCount() == 0) {
-            return Math.min(0, mExpandedHeight / HEADER_RUBBERBAND_FACTOR - mQsMinExpansionHeight);
-        }
-        float stackTranslation = mNotificationStackScroller.getStackTranslation();
-        float translation = stackTranslation / HEADER_RUBBERBAND_FACTOR;
-        if (mHeadsUpManager.hasPinnedHeadsUp() || mIsExpansionFromHeadsUp) {
-            translation = mNotificationStackScroller.getTopPadding() + stackTranslation
-                    - mQsMinExpansionHeight;
-        }
+        float translation = NotificationUtils.interpolate(-mQsMinExpansionHeight, 0,
+                mNotificationStackScroller.getAppearFraction(mExpandedHeight));
         return Math.min(0, translation);
     }
 
@@ -1968,7 +1960,7 @@
         if (mNotificationStackScroller.getNotGoneChildCount() > 0) {
             return mNotificationStackScroller.getPeekHeight();
         } else {
-            return mQsMinExpansionHeight * HEADER_RUBBERBAND_FACTOR;
+            return mQsMinExpansionHeight;
         }
     }
 
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 fb7afc5..482c698 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -2586,7 +2586,7 @@
     @Override
     public void handleSystemNavigationKey(int key) {
         if (SPEW) Log.d(TAG, "handleSystemNavigationKey: " + key);
-        if (!panelsEnabled()) {
+        if (!panelsEnabled() || !mKeyguardMonitor.isDeviceInteractive()) {
             return;
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
index 15e235d..405ccd6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
@@ -400,7 +400,7 @@
                 ComponentName component = CustomTile.getComponentFromSpec(tileSpec);
                 Intent intent = new Intent().setComponent(component);
                 TileLifecycleManager lifecycleManager = new TileLifecycleManager(new Handler(),
-                        mContext, mServices, new Tile(component), intent,
+                        mContext, mServices, new Tile(), intent,
                         new UserHandle(ActivityManager.getCurrentUser()));
                 lifecycleManager.onStopListening();
                 lifecycleManager.onTileRemoved();
@@ -414,7 +414,7 @@
                 ComponentName component = CustomTile.getComponentFromSpec(tileSpec);
                 Intent intent = new Intent().setComponent(component);
                 TileLifecycleManager lifecycleManager = new TileLifecycleManager(new Handler(),
-                        mContext, mServices, new Tile(component), intent,
+                        mContext, mServices, new Tile(), intent,
                         new UserHandle(ActivityManager.getCurrentUser()));
                 lifecycleManager.onTileAdded();
                 lifecycleManager.flushMessagesAndUnbind();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
index 970fed0..c175180 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
@@ -112,6 +112,10 @@
         notifyKeyguardChanged();
     }
 
+    public boolean isDeviceInteractive() {
+        return mKeyguardUpdateMonitor.isDeviceInteractive();
+    }
+
     private void updateCanSkipBouncerState() {
         mCanSkipBouncer = mKeyguardUpdateMonitor.getUserCanSkipBouncer(mCurrentUser);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index ac3246d..8178bda 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -201,7 +201,7 @@
                 TelephonyIcons.FOUR_G_PLUS);
         } else {
             mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE, TelephonyIcons.LTE);
-            mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE_CA, TelephonyIcons.LTE);
+            mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE_CA, TelephonyIcons.LTE_PLUS);
         }
         mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_IWLAN, TelephonyIcons.WFC);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index 7a042af..a31bc04 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -786,6 +786,7 @@
                             datatype.equals("g") ? TelephonyIcons.G :
                             datatype.equals("h") ? TelephonyIcons.H :
                             datatype.equals("lte") ? TelephonyIcons.LTE :
+                            datatype.equals("lte+") ? TelephonyIcons.LTE_PLUS :
                             datatype.equals("roam") ? TelephonyIcons.ROAMING :
                             TelephonyIcons.UNKNOWN;
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
index d91b332..ed8c7ff 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
@@ -208,10 +208,12 @@
     };
 
     static final int QS_DATA_LTE = R.drawable.ic_qs_signal_lte;
+    static final int QS_DATA_LTE_PLUS = R.drawable.ic_qs_signal_lte_plus;
 
     static final int FLIGHT_MODE_ICON = R.drawable.stat_sys_airplane_mode;
     static final int ROAMING_ICON = R.drawable.stat_sys_data_fully_connected_roam;
     static final int ICON_LTE = R.drawable.stat_sys_data_fully_connected_lte;
+    static final int ICON_LTE_PLUS = R.drawable.stat_sys_data_fully_connected_lte_plus;
     static final int ICON_G = R.drawable.stat_sys_data_fully_connected_g;
     static final int ICON_E = R.drawable.stat_sys_data_fully_connected_e;
     static final int ICON_H = R.drawable.stat_sys_data_fully_connected_h;
@@ -393,6 +395,21 @@
             TelephonyIcons.QS_DATA_LTE
             );
 
+    static final MobileIconGroup LTE_PLUS = new MobileIconGroup(
+            "LTE+",
+            TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH,
+            TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
+            0, 0,
+            TelephonyIcons.TELEPHONY_NO_NETWORK,
+            TelephonyIcons.QS_TELEPHONY_NO_NETWORK,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
+            R.string.accessibility_data_connection_lte_plus,
+            TelephonyIcons.ICON_LTE_PLUS,
+            true,
+            TelephonyIcons.QS_DATA_LTE_PLUS
+            );
+
     static final MobileIconGroup ROAMING = new MobileIconGroup(
             "Roaming",
             TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH_ROAMING,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index e00674a..71b349f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -668,30 +668,74 @@
     public void setStackHeight(float height) {
         mLastSetStackHeight = height;
         setIsExpanded(height > 0.0f);
-        int newStackHeight = (int) height;
-        int minStackHeight = getLayoutMinHeight();
         int stackHeight;
-        float paddingOffset;
-        boolean trackingHeadsUp = mTrackingHeadsUp || mHeadsUpManager.hasPinnedHeadsUp();
-        int normalUnfoldPositionStart = trackingHeadsUp
-                ? mHeadsUpManager.getTopHeadsUpPinnedHeight()
-                : minStackHeight;
-        if (newStackHeight - mTopPadding - mTopPaddingOverflow >= normalUnfoldPositionStart
-                || getNotGoneChildCount() == 0) {
-            paddingOffset = mTopPaddingOverflow;
-            stackHeight = newStackHeight;
+        float translationY;
+        float appearEndPosition = getAppearEndPosition();
+        float appearStartPosition = getAppearStartPosition();
+        if (height >= appearEndPosition) {
+            translationY = mTopPaddingOverflow;
+            stackHeight = (int) height;
         } else {
-            int translationY;
-            translationY = newStackHeight - normalUnfoldPositionStart;
-            paddingOffset = translationY - mTopPadding;
-            stackHeight = (int) (height - (translationY - mTopPadding));
+            float appearFraction = getAppearFraction(height);
+            if (appearFraction >= 0) {
+                translationY = NotificationUtils.interpolate(getExpandTranslationStart(), 0,
+                        appearFraction);
+            } else {
+                // This may happen when pushing up a heads up. We linearly push it up from the
+                // start
+                translationY = height - appearStartPosition + getExpandTranslationStart();
+            }
+            stackHeight = (int) (height - translationY);
         }
         if (stackHeight != mCurrentStackHeight) {
             mCurrentStackHeight = stackHeight;
             updateAlgorithmHeightAndPadding();
             requestChildrenUpdate();
         }
-        setStackTranslation(paddingOffset);
+        setStackTranslation(translationY);
+    }
+
+    /**
+     * @return The translation at the beginning when expanding.
+     *         Measured relative to the resting position.
+     */
+    private float getExpandTranslationStart() {
+        int startPosition = mTrackingHeadsUp || mHeadsUpManager.hasPinnedHeadsUp()
+                ? 0 : -getFirstChildMinHeight();
+        return startPosition - mTopPadding;
+    }
+
+    /**
+     * @return the position from where the appear transition starts when expanding.
+     *         Measured in absolute height.
+     */
+    private float getAppearStartPosition() {
+        return mTrackingHeadsUp
+                ? mHeadsUpManager.getTopHeadsUpPinnedHeight()
+                : 0;
+    }
+
+    /**
+     * @return the position from where the appear transition ends when expanding.
+     *         Measured in absolute height.
+     */
+    private float getAppearEndPosition() {
+        int firstItemHeight = mTrackingHeadsUp || mHeadsUpManager.hasPinnedHeadsUp()
+                ? mHeadsUpManager.getTopHeadsUpPinnedHeight() + mBottomStackPeekSize
+                        + mBottomStackSlowDownHeight
+                : getLayoutMinHeight();
+        return firstItemHeight + mTopPadding + mTopPaddingOverflow;
+    }
+
+    /**
+     * @param height the height of the panel
+     * @return the fraction of the appear animation that has been performed
+     */
+    public float getAppearFraction(float height) {
+        float appearEndPosition = getAppearEndPosition();
+        float appearStartPosition = getAppearStartPosition();
+        return (height - appearStartPosition)
+                / (appearEndPosition - appearStartPosition);
     }
 
     public float getStackTranslation() {
@@ -2096,6 +2140,12 @@
     }
 
     public int getLayoutMinHeight() {
+        int firstChildMinHeight = getFirstChildMinHeight();
+        return Math.min(firstChildMinHeight + mBottomStackPeekSize + mBottomStackSlowDownHeight,
+                mMaxLayoutHeight - mTopPadding);
+    }
+
+    private int getFirstChildMinHeight() {
         final ExpandableView firstChild = getFirstChildNotGone();
         int firstChildMinHeight = firstChild != null
                 ? firstChild.getIntrinsicHeight()
@@ -2105,8 +2155,7 @@
         if (mOwnScrollY > 0) {
             firstChildMinHeight = Math.max(firstChildMinHeight - mOwnScrollY, mCollapsedSize);
         }
-        return Math.min(firstChildMinHeight + mBottomStackPeekSize + mBottomStackSlowDownHeight,
-                mMaxLayoutHeight - mTopPadding);
+        return firstChildMinHeight;
     }
 
     public float getTopPaddingOverflow() {
@@ -2605,6 +2654,10 @@
                 type = row.wasJustClicked()
                         ? AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR_CLICK
                         : AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR;
+                if (row.isChildInGroup()) {
+                    // We can otherwise get stuck in there if it was just isolated
+                    row.setHeadsupDisappearRunning(false);
+                }
             } else {
                 StackViewState viewState = mCurrentStackScrollState.getViewStateForView(row);
                 if (viewState == null) {
@@ -3101,7 +3154,13 @@
         for (int i = 0; i < getChildCount(); i++) {
             View view = getChildAt(i);
             if (view instanceof ExpandableNotificationRow) {
-                ((ExpandableNotificationRow) view).setHeadsupDisappearRunning(false);
+                ExpandableNotificationRow row = (ExpandableNotificationRow) view;
+                row.setHeadsupDisappearRunning(false);
+                if (row.isSummaryWithChildren()) {
+                    for (ExpandableNotificationRow child : row.getNotificationChildren()) {
+                        child.setHeadsupDisappearRunning(false);
+                    }
+                }
             }
         }
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/phone/DozeParametersTests.java b/packages/SystemUI/tests/src/com/android/systemui/phone/DozeParametersTests.java
new file mode 100644
index 0000000..07334f3
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/phone/DozeParametersTests.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2016 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.systemui.phone;
+
+import com.android.systemui.statusbar.phone.DozeParameters.IntInOutMatcher;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+@SmallTest
+public class DozeParametersTests extends AndroidTestCase {
+
+    public void test_inOutMatcher_defaultIn() {
+        IntInOutMatcher intInOutMatcher = new IntInOutMatcher("*");
+
+        assertTrue(intInOutMatcher.isIn(1));
+        assertTrue(intInOutMatcher.isIn(-1));
+        assertTrue(intInOutMatcher.isIn(0));
+    }
+
+    public void test_inOutMatcher_defaultOut() {
+        IntInOutMatcher intInOutMatcher = new IntInOutMatcher("!*");
+
+        assertFalse(intInOutMatcher.isIn(1));
+        assertFalse(intInOutMatcher.isIn(-1));
+        assertFalse(intInOutMatcher.isIn(0));
+    }
+
+    public void test_inOutMatcher_someIn() {
+        IntInOutMatcher intInOutMatcher = new IntInOutMatcher("1,2,3,!*");
+
+        assertTrue(intInOutMatcher.isIn(1));
+        assertTrue(intInOutMatcher.isIn(2));
+        assertTrue(intInOutMatcher.isIn(3));
+
+        assertFalse(intInOutMatcher.isIn(0));
+        assertFalse(intInOutMatcher.isIn(4));
+    }
+
+    public void test_inOutMatcher_someOut() {
+        IntInOutMatcher intInOutMatcher = new IntInOutMatcher("!1,!2,!3,*");
+
+        assertFalse(intInOutMatcher.isIn(1));
+        assertFalse(intInOutMatcher.isIn(2));
+        assertFalse(intInOutMatcher.isIn(3));
+
+        assertTrue(intInOutMatcher.isIn(0));
+        assertTrue(intInOutMatcher.isIn(4));
+    }
+
+    public void test_inOutMatcher_mixed() {
+        IntInOutMatcher intInOutMatcher = new IntInOutMatcher("!1,2,!3,*");
+
+        assertFalse(intInOutMatcher.isIn(1));
+        assertTrue(intInOutMatcher.isIn(2));
+        assertFalse(intInOutMatcher.isIn(3));
+
+        assertTrue(intInOutMatcher.isIn(0));
+        assertTrue(intInOutMatcher.isIn(4));
+    }
+
+    public void test_inOutMatcher_failEmpty() {
+        try {
+            new IntInOutMatcher("");
+            fail("Expected IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+    }
+
+    public void test_inOutMatcher_failNull() {
+        try {
+            new IntInOutMatcher(null);
+            fail("Expected IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+    }
+
+    public void test_inOutMatcher_failEmptyClause() {
+        try {
+            new IntInOutMatcher("!1,*,");
+            fail("Expected IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+    }
+
+    public void test_inOutMatcher_failDuplicate() {
+        try {
+            new IntInOutMatcher("!1,*,!1");
+            fail("Expected IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+    }
+
+    public void test_inOutMatcher_failDuplicateDefault() {
+        try {
+            new IntInOutMatcher("!1,*,*");
+            fail("Expected IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+    }
+
+    public void test_inOutMatcher_failMalformedNot() {
+        try {
+            new IntInOutMatcher("!,*");
+            fail("Expected IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+    }
+
+    public void test_inOutMatcher_failText() {
+        try {
+            new IntInOutMatcher("!abc,*");
+            fail("Expected IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+    }
+
+    public void test_inOutMatcher_failContradiction() {
+        try {
+            new IntInOutMatcher("1,!1,*");
+            fail("Expected IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+    }
+
+    public void test_inOutMatcher_failContradictionDefault() {
+        try {
+            new IntInOutMatcher("1,*,!*");
+            fail("Expected IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+    }
+
+    public void test_inOutMatcher_failMissingDefault() {
+        try {
+            new IntInOutMatcher("1");
+            fail("Expected IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTests.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTests.java
index c93377a..7703c58 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTests.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTests.java
@@ -58,7 +58,7 @@
         mHandler = new Handler(mThread.getLooper());
         ComponentName component = new ComponentName(mContext, FakeTileService.class);
         mStateManager = new TileLifecycleManager(mHandler, getContext(),
-                Mockito.mock(IQSService.class), new Tile(component),
+                Mockito.mock(IQSService.class), new Tile(),
                 new Intent().setComponent(component),
                 new UserHandle(UserHandle.myUserId()));
         mCallbacks.clear();
diff --git a/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java b/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java
index 97efed0..05207b9 100644
--- a/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java
+++ b/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java
@@ -114,13 +114,17 @@
                 imageStage.delete();
                 lockImageStage.delete();
 
-                Os.link(mWallpaperInfo.getCanonicalPath(), infoStage.getCanonicalPath());
-                fullBackupFile(infoStage, data);
-                Os.link(mWallpaperFile.getCanonicalPath(), imageStage.getCanonicalPath());
-                fullBackupFile(imageStage, data);
+                if (mWallpaperInfo.exists()) {
+                    Os.link(mWallpaperInfo.getCanonicalPath(), infoStage.getCanonicalPath());
+                    fullBackupFile(infoStage, data);
+                }
+                if (mWallpaperFile.exists()) {
+                    Os.link(mWallpaperFile.getCanonicalPath(), imageStage.getCanonicalPath());
+                    fullBackupFile(imageStage, data);
+                }
 
                 // Don't try to store the lock image if we overran our quota last time
-                if (!mQuotaExceeded) {
+                if (mLockWallpaperFile.exists() && !mQuotaExceeded) {
                     Os.link(mLockWallpaperFile.getCanonicalPath(), lockImageStage.getCanonicalPath());
                     fullBackupFile(lockImageStage, data);
                 }
@@ -130,7 +134,7 @@
                 }
             }
         } catch (Exception e) {
-            Slog.e(TAG, "Unable to back up wallpaper: " + e.getMessage());
+            Slog.e(TAG, "Unable to back up wallpaper", e);
         } finally {
             if (DEBUG) {
                 Slog.v(TAG, "Removing backup stage links");
@@ -173,6 +177,9 @@
         final File lockImageStage = new File (filesDir, LOCK_IMAGE_STAGE);
 
         try {
+            // First off, revert to the factory state
+            mWm.clear(WallpaperManager.FLAG_SYSTEM | WallpaperManager.FLAG_LOCK);
+
             // It is valid for the imagery to be absent; it means that we were not permitted
             // to back up the original image on the source device, or there was no user-supplied
             // wallpaper image present.
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 60d3339..7ebc150 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -1422,7 +1422,8 @@
         updateTouchExplorationLocked(userState);
         updatePerformGesturesLocked(userState);
         updateEnhancedWebAccessibilityLocked(userState);
-        updateDisplayColorAdjustmentSettingsLocked(userState);
+        updateDisplayDaltonizerLocked(userState);
+        updateDisplayInversionLocked(userState);
         updateMagnificationLocked(userState);
         updateSoftKeyboardShowModeLocked(userState);
         scheduleUpdateInputFilter(userState);
@@ -1539,7 +1540,6 @@
         somethingChanged |= readEnhancedWebAccessibilityEnabledChangedLocked(userState);
         somethingChanged |= readDisplayMagnificationEnabledSettingLocked(userState);
         somethingChanged |= readAutoclickEnabledSettingLocked(userState);
-        somethingChanged |= readDisplayColorAdjustmentSettingsLocked(userState);
 
         return somethingChanged;
     }
@@ -1602,18 +1602,6 @@
          return false;
     }
 
-    private boolean readDisplayColorAdjustmentSettingsLocked(UserState userState) {
-        final boolean displayAdjustmentsEnabled = DisplayAdjustmentUtils.hasAdjustments(mContext,
-                userState.mUserId);
-        if (displayAdjustmentsEnabled != userState.mHasDisplayColorAdjustment) {
-            userState.mHasDisplayColorAdjustment = displayAdjustmentsEnabled;
-            return true;
-        }
-        // If display adjustment is enabled, always assume there was a change in
-        // the adjustment settings.
-        return displayAdjustmentsEnabled;
-    }
-
     private boolean readHighTextContrastEnabledSettingLocked(UserState userState) {
         final boolean highTextContrastEnabled = Settings.Secure.getIntForUser(
                 mContext.getContentResolver(),
@@ -1730,8 +1718,12 @@
         return false;
     }
 
-    private void updateDisplayColorAdjustmentSettingsLocked(UserState userState) {
-        DisplayAdjustmentUtils.applyAdjustments(mContext, userState.mUserId);
+    private void updateDisplayDaltonizerLocked(UserState userState) {
+        DisplayAdjustmentUtils.applyDaltonizerSetting(mContext, userState.mUserId);
+    }
+
+    private void updateDisplayInversionLocked(UserState userState) {
+        DisplayAdjustmentUtils.applyInversionSetting(mContext, userState.mUserId);
     }
 
     private void updateMagnificationLocked(UserState userState) {
@@ -4184,7 +4176,6 @@
         public boolean mIsAutoclickEnabled;
         public boolean mIsPerformGesturesEnabled;
         public boolean mIsFilterKeyEventsEnabled;
-        public boolean mHasDisplayColorAdjustment;
         public boolean mAccessibilityFocusOnlyInActiveWindow;
 
         private Service mUiAutomationService;
@@ -4300,9 +4291,6 @@
         private final Uri mDisplayDaltonizerUri = Settings.Secure.getUriFor(
                 Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER);
 
-        private final Uri mDisplayColorMatrixUri = Settings.Secure.getUriFor(
-                Settings.Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX);
-
         private final Uri mHighTextContrastUri = Settings.Secure.getUriFor(
                 Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED);
 
@@ -4334,8 +4322,6 @@
             contentResolver.registerContentObserver(
                     mDisplayDaltonizerUri, false, this, UserHandle.USER_ALL);
             contentResolver.registerContentObserver(
-                    mDisplayColorMatrixUri, false, this, UserHandle.USER_ALL);
-            contentResolver.registerContentObserver(
                     mHighTextContrastUri, false, this, UserHandle.USER_ALL);
             contentResolver.registerContentObserver(
                     mAccessibilitySoftKeyboardModeUri, false, this, UserHandle.USER_ALL);
@@ -4377,14 +4363,11 @@
                     if (readEnhancedWebAccessibilityEnabledChangedLocked(userState)) {
                         onUserStateChangedLocked(userState);
                     }
-                } else if (mDisplayInversionEnabledUri.equals(uri)
-                        || mDisplayDaltonizerEnabledUri.equals(uri)
+                } else if (mDisplayDaltonizerEnabledUri.equals(uri)
                         || mDisplayDaltonizerUri.equals(uri)) {
-                    if (readDisplayColorAdjustmentSettingsLocked(userState)) {
-                        updateDisplayColorAdjustmentSettingsLocked(userState);
-                    }
-                } else if (mDisplayColorMatrixUri.equals(uri)) {
-                    updateDisplayColorAdjustmentSettingsLocked(userState);
+                    updateDisplayDaltonizerLocked(userState);
+                } else if (mDisplayInversionEnabledUri.equals(uri)) {
+                    updateDisplayInversionLocked(userState);
                 } else if (mHighTextContrastUri.equals(uri)) {
                     if (readHighTextContrastEnabledSettingLocked(userState)) {
                         onUserStateChangedLocked(userState);
diff --git a/services/accessibility/java/com/android/server/accessibility/DisplayAdjustmentUtils.java b/services/accessibility/java/com/android/server/accessibility/DisplayAdjustmentUtils.java
index e1f3cd8..1532946 100644
--- a/services/accessibility/java/com/android/server/accessibility/DisplayAdjustmentUtils.java
+++ b/services/accessibility/java/com/android/server/accessibility/DisplayAdjustmentUtils.java
@@ -18,23 +18,23 @@
 
 import android.content.ContentResolver;
 import android.content.Context;
-import android.opengl.Matrix;
-import android.os.IBinder;
-import android.os.Parcel;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.provider.Settings;
-import android.util.Slog;
+import android.provider.Settings.Secure;
 import android.view.accessibility.AccessibilityManager;
 
+import com.android.server.LocalServices;
+import com.android.server.display.DisplayTransformManager;
+
 /**
  * Utility methods for performing accessibility display adjustments.
  */
 class DisplayAdjustmentUtils {
-    private static final String LOG_TAG = DisplayAdjustmentUtils.class.getSimpleName();
+
+    /** Default inversion mode for display color correction. */
+    private static final int DEFAULT_DISPLAY_DALTONIZER =
+            AccessibilityManager.DALTONIZER_CORRECT_DEUTERANOMALY;
 
     /** Matrix and offset used for converting color to gray-scale. */
-    private static final float[] GRAYSCALE_MATRIX = new float[] {
+    private static final float[] MATRIX_GRAYSCALE = new float[] {
         .2126f, .2126f, .2126f, 0,
         .7152f, .7152f, .7152f, 0,
         .0722f, .0722f, .0722f, 0,
@@ -48,150 +48,44 @@
      * represents a non-multiplied addition, see surfaceflinger's ProgramCache
      * for full implementation details.
      */
-    private static final float[] INVERSION_MATRIX_VALUE_ONLY = new float[] {
+    private static final float[] MATRIX_INVERT_COLOR = new float[] {
         0.402f, -0.598f, -0.599f, 0,
        -1.174f, -0.174f, -1.175f, 0,
        -0.228f, -0.228f,  0.772f, 0,
              1,       1,       1, 1
     };
 
-    /** Default inversion mode for display color correction. */
-    private static final int DEFAULT_DISPLAY_DALTONIZER =
-            AccessibilityManager.DALTONIZER_CORRECT_DEUTERANOMALY;
-
-    /**
-     * Returns whether the specified user with has any display color
-     * adjustments.
-     */
-    public static boolean hasAdjustments(Context context, int userId) {
+    public static void applyDaltonizerSetting(Context context, int userId) {
         final ContentResolver cr = context.getContentResolver();
+        final DisplayTransformManager dtm = LocalServices.getService(DisplayTransformManager.class);
 
-        if (Settings.Secure.getIntForUser(cr,
-                Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, 0, userId) != 0) {
-            return true;
+        int daltonizerMode = AccessibilityManager.DALTONIZER_DISABLED;
+        if (Secure.getIntForUser(cr,
+                Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED, 0, userId) != 0) {
+            daltonizerMode = Secure.getIntForUser(cr,
+                    Secure.ACCESSIBILITY_DISPLAY_DALTONIZER, DEFAULT_DISPLAY_DALTONIZER, userId);
         }
 
-        if (Settings.Secure.getIntForUser(cr,
-                Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED, 0, userId) != 0) {
-            return true;
+        float[] grayscaleMatrix = null;
+        if (daltonizerMode == AccessibilityManager.DALTONIZER_SIMULATE_MONOCHROMACY) {
+            // Monochromacy isn't supported by the native Daltonizer.
+            grayscaleMatrix = MATRIX_GRAYSCALE;
+            daltonizerMode = AccessibilityManager.DALTONIZER_DISABLED;
         }
-
-        return false;
+        dtm.setColorMatrix(DisplayTransformManager.LEVEL_COLOR_MATRIX_GRAYSCALE, grayscaleMatrix);
+        dtm.setDaltonizerMode(daltonizerMode);
     }
 
     /**
      * Applies the specified user's display color adjustments.
      */
-    public static void applyAdjustments(Context context, int userId) {
+    public static void applyInversionSetting(Context context, int userId) {
         final ContentResolver cr = context.getContentResolver();
-        float[] colorMatrix = null;
+        final DisplayTransformManager dtm = LocalServices.getService(DisplayTransformManager.class);
 
-        if (Settings.Secure.getIntForUser(cr,
-                Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, 0, userId) != 0) {
-            colorMatrix = multiply(colorMatrix, INVERSION_MATRIX_VALUE_ONLY);
-        }
-
-        if (Settings.Secure.getIntForUser(cr,
-                Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED, 0, userId) != 0) {
-            final int daltonizerMode = Settings.Secure.getIntForUser(cr,
-                    Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER, DEFAULT_DISPLAY_DALTONIZER,
-                    userId);
-            // Monochromacy isn't supported by the native Daltonizer.
-            if (daltonizerMode == AccessibilityManager.DALTONIZER_SIMULATE_MONOCHROMACY) {
-                colorMatrix = multiply(colorMatrix, GRAYSCALE_MATRIX);
-                setDaltonizerMode(AccessibilityManager.DALTONIZER_DISABLED);
-            } else {
-                setDaltonizerMode(daltonizerMode);
-            }
-        } else {
-            setDaltonizerMode(AccessibilityManager.DALTONIZER_DISABLED);
-        }
-
-        String matrix = Settings.Secure.getStringForUser(cr,
-                Settings.Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX, userId);
-        if (matrix != null) {
-            final float[] userMatrix = get4x4Matrix(matrix);
-            if (userMatrix != null) {
-                colorMatrix = multiply(colorMatrix, userMatrix);
-            }
-        }
-
-        setColorTransform(colorMatrix);
+        final boolean invertColors = Secure.getIntForUser(cr,
+                Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, 0, userId) != 0;
+        dtm.setColorMatrix(DisplayTransformManager.LEVEL_COLOR_MATRIX_INVERT_COLOR,
+                invertColors ? MATRIX_INVERT_COLOR : null);
     }
-
-    private static float[] get4x4Matrix(String matrix) {
-        String[] strValues = matrix.split(",");
-        if (strValues.length != 16) {
-            return null;
-        }
-        float[] values = new float[strValues.length];
-        try {
-            for (int i = 0; i < values.length; i++) {
-                values[i] = Float.parseFloat(strValues[i]);
-            }
-        } catch (java.lang.NumberFormatException ex) {
-            return null;
-        }
-        return values;
-    }
-
-    private static float[] multiply(float[] matrix, float[] other) {
-        if (matrix == null) {
-            return other;
-        }
-        float[] result = new float[16];
-        Matrix.multiplyMM(result, 0, matrix, 0, other, 0);
-        return result;
-    }
-
-    /**
-     * Sets the surface flinger's Daltonization mode. This adjusts the color
-     * space to correct for or simulate various types of color blindness.
-     *
-     * @param mode new Daltonization mode
-     */
-    private static void setDaltonizerMode(int mode) {
-        try {
-            final IBinder flinger = ServiceManager.getService("SurfaceFlinger");
-            if (flinger != null) {
-                final Parcel data = Parcel.obtain();
-                data.writeInterfaceToken("android.ui.ISurfaceComposer");
-                data.writeInt(mode);
-                flinger.transact(1014, data, null, 0);
-                data.recycle();
-            }
-        } catch (RemoteException ex) {
-            Slog.e(LOG_TAG, "Failed to set Daltonizer mode", ex);
-        }
-    }
-
-    /**
-     * Sets the surface flinger's color transformation as a 4x4 matrix. If the
-     * matrix is null, color transformations are disabled.
-     *
-     * @param m the float array that holds the transformation matrix, or null to
-     *            disable transformation
-     */
-    private static void setColorTransform(float[] m) {
-        try {
-            final IBinder flinger = ServiceManager.getService("SurfaceFlinger");
-            if (flinger != null) {
-                final Parcel data = Parcel.obtain();
-                data.writeInterfaceToken("android.ui.ISurfaceComposer");
-                if (m != null) {
-                    data.writeInt(1);
-                    for (int i = 0; i < 16; i++) {
-                        data.writeFloat(m[i]);
-                    }
-                } else {
-                    data.writeInt(0);
-                }
-                flinger.transact(1015, data, null, 0);
-                data.recycle();
-            }
-        } catch (RemoteException ex) {
-            Slog.e(LOG_TAG, "Failed to set color transform", ex);
-        }
-    }
-
 }
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 5ce8c9e..497eac9 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -5501,11 +5501,11 @@
 
                         // If the policy is satisfied, go ahead and set up to pipe the
                         // data to the agent.
-                        if (DEBUG && okay && mAgent != null) {
+                        if (MORE_DEBUG && okay && mAgent != null) {
                             Slog.i(TAG, "Reusing existing agent instance");
                         }
                         if (okay && mAgent == null) {
-                            if (DEBUG) Slog.d(TAG, "Need to launch agent for " + pkg);
+                            if (MORE_DEBUG) Slog.d(TAG, "Need to launch agent for " + pkg);
 
                             try {
                                 mTargetApp = mPackageManager.getApplicationInfo(pkg, 0);
@@ -5707,16 +5707,21 @@
         }
 
         void tearDownPipes() {
-            if (mPipes != null) {
-                try {
-                    mPipes[0].close();
-                    mPipes[0] = null;
-                    mPipes[1].close();
-                    mPipes[1] = null;
-                } catch (IOException e) {
-                    Slog.w(TAG, "Couldn't close agent pipes", e);
+            // Teardown might arise from the inline restore processing or from the asynchronous
+            // timeout mechanism, and these might race.  Make sure we don't try to close and
+            // null out the pipes twice.
+            synchronized (this) {
+                if (mPipes != null) {
+                    try {
+                        mPipes[0].close();
+                        mPipes[0] = null;
+                        mPipes[1].close();
+                        mPipes[1] = null;
+                    } catch (IOException e) {
+                        Slog.w(TAG, "Couldn't close agent pipes", e);
+                    }
+                    mPipes = null;
                 }
-                mPipes = null;
             }
         }
 
diff --git a/services/core/java/com/android/server/GestureLauncherService.java b/services/core/java/com/android/server/GestureLauncherService.java
index 5a90488..553cb07 100644
--- a/services/core/java/com/android/server/GestureLauncherService.java
+++ b/services/core/java/com/android/server/GestureLauncherService.java
@@ -33,6 +33,7 @@
 import android.os.PowerManager.WakeLock;
 import android.os.SystemClock;
 import android.os.SystemProperties;
+import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.MutableBoolean;
 import android.util.Slog;
@@ -284,8 +285,8 @@
      * @return true if camera was launched, false otherwise.
      */
     private boolean handleCameraLaunchGesture(boolean useWakelock, int source) {
-        boolean userSetupComplete = Settings.Secure.getInt(mContext.getContentResolver(),
-                Settings.Secure.USER_SETUP_COMPLETE, 0) != 0;
+        boolean userSetupComplete = Settings.Secure.getIntForUser(mContext.getContentResolver(),
+                Settings.Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0;
         if (!userSetupComplete) {
             if (DBG) Slog.d(TAG, String.format(
                     "userSetupComplete = %s, ignoring camera launch gesture.",
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index e28fa73..0cce2a2 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -584,6 +584,18 @@
                         Slog.e(TAG, "Invalid tied profile lock type: " + quality);
                     }
                 }
+                try {
+                    final String alias = LockPatternUtils.PROFILE_KEY_NAME_ENCRYPT + userInfo.id;
+                    java.security.KeyStore keyStore =
+                            java.security.KeyStore.getInstance("AndroidKeyStore");
+                    keyStore.load(null);
+                    if (keyStore.containsAlias(alias)) {
+                        keyStore.deleteEntry(alias);
+                    }
+                } catch (KeyStoreException | NoSuchAlgorithmException |
+                        CertificateException | IOException e) {
+                    Slog.e(TAG, "Unable to remove tied profile key", e);
+                }
             }
         } catch (RemoteException re) {
             Slog.e(TAG, "Unable to migrate old data", re);
@@ -1027,37 +1039,38 @@
             KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES);
             keyGenerator.init(new SecureRandom());
             SecretKey secretKey = keyGenerator.generateKey();
-
             java.security.KeyStore keyStore = java.security.KeyStore.getInstance("AndroidKeyStore");
             keyStore.load(null);
-            keyStore.setEntry(
-                    LockPatternUtils.PROFILE_KEY_NAME_ENCRYPT + userId,
-                    new java.security.KeyStore.SecretKeyEntry(secretKey),
-                    new KeyProtection.Builder(KeyProperties.PURPOSE_ENCRYPT)
-                            .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
-                            .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
-                            .build());
-            keyStore.setEntry(
-                    LockPatternUtils.PROFILE_KEY_NAME_DECRYPT + userId,
-                    new java.security.KeyStore.SecretKeyEntry(secretKey),
-                    new KeyProtection.Builder(KeyProperties.PURPOSE_DECRYPT)
-                            .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
-                            .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
-                            .setUserAuthenticationRequired(true)
-                            .setUserAuthenticationValidityDurationSeconds(30)
-                            .build());
-
-            // Key imported, obtain a reference to it.
-            SecretKey keyStoreEncryptionKey = (SecretKey) keyStore.getKey(
-                    LockPatternUtils.PROFILE_KEY_NAME_ENCRYPT + userId, null);
-            // The original key can now be discarded.
-
-            Cipher cipher = Cipher.getInstance(
-                    KeyProperties.KEY_ALGORITHM_AES + "/" + KeyProperties.BLOCK_MODE_GCM + "/"
-                            + KeyProperties.ENCRYPTION_PADDING_NONE);
-            cipher.init(Cipher.ENCRYPT_MODE, keyStoreEncryptionKey);
-            encryptionResult = cipher.doFinal(randomLockSeed);
-            iv = cipher.getIV();
+            try {
+                keyStore.setEntry(
+                        LockPatternUtils.PROFILE_KEY_NAME_ENCRYPT + userId,
+                        new java.security.KeyStore.SecretKeyEntry(secretKey),
+                        new KeyProtection.Builder(KeyProperties.PURPOSE_ENCRYPT)
+                                .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
+                                .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
+                                .build());
+                keyStore.setEntry(
+                        LockPatternUtils.PROFILE_KEY_NAME_DECRYPT + userId,
+                        new java.security.KeyStore.SecretKeyEntry(secretKey),
+                        new KeyProtection.Builder(KeyProperties.PURPOSE_DECRYPT)
+                                .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
+                                .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
+                                .setUserAuthenticationRequired(true)
+                                .setUserAuthenticationValidityDurationSeconds(30)
+                                .build());
+                // Key imported, obtain a reference to it.
+                SecretKey keyStoreEncryptionKey = (SecretKey) keyStore.getKey(
+                        LockPatternUtils.PROFILE_KEY_NAME_ENCRYPT + userId, null);
+                Cipher cipher = Cipher.getInstance(
+                        KeyProperties.KEY_ALGORITHM_AES + "/" + KeyProperties.BLOCK_MODE_GCM + "/"
+                                + KeyProperties.ENCRYPTION_PADDING_NONE);
+                cipher.init(Cipher.ENCRYPT_MODE, keyStoreEncryptionKey);
+                encryptionResult = cipher.doFinal(randomLockSeed);
+                iv = cipher.getIV();
+            } finally {
+                // The original key can now be discarded.
+                keyStore.deleteEntry(LockPatternUtils.PROFILE_KEY_NAME_ENCRYPT + userId);
+            }
         } catch (CertificateException | UnrecoverableKeyException
                 | IOException | BadPaddingException | IllegalBlockSizeException | KeyStoreException
                 | NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException e) {
diff --git a/services/core/java/com/android/server/PinnerService.java b/services/core/java/com/android/server/PinnerService.java
index eaf317a..7ea8f1f 100644
--- a/services/core/java/com/android/server/PinnerService.java
+++ b/services/core/java/com/android/server/PinnerService.java
@@ -41,6 +41,7 @@
 import com.android.internal.app.ResolverActivity;
 import com.android.internal.os.BackgroundThread;
 
+import dalvik.system.DexFile;
 import dalvik.system.VMRuntime;
 
 import java.util.ArrayList;
@@ -240,12 +241,6 @@
         }
         mPinnedCameraFiles.add(pf);
 
-        //find the location of the odex based on the location of the APK
-        int lastPeriod = camAPK.lastIndexOf('.');
-        int lastSlash = camAPK.lastIndexOf('/', lastPeriod);
-        String base = camAPK.substring(0, lastSlash);
-        String appName = camAPK.substring(lastSlash + 1, lastPeriod);
-
         // determine the ABI from either ApplicationInfo or Build
         String arch = "arm";
         if (cameraInfo.primaryCpuAbi != null
@@ -256,8 +251,18 @@
                 arch = arch + "64";
             }
         }
-        String odex = base + "/oat/" + arch + "/" + appName + ".odex";
-        //not all apps have odex files, so not pinning the odex is not a fatal error
+
+        // get the path to the odex or oat file
+        String baseCodePath = cameraInfo.getBaseCodePath();
+        String odex = null;
+        try {
+            odex = DexFile.getDexFileOutputPath(baseCodePath, arch);
+        } catch (IOException ioe) {}
+        if (odex == null) {
+            return true;
+        }
+
+        //not pinning the oat/odex is not a fatal error
         pf = pinFile(odex, 0, 0, MAX_CAMERA_PIN_SIZE);
         if (pf != null) {
             mPinnedCameraFiles.add(pf);
@@ -265,6 +270,7 @@
                 Slog.i(TAG, "Pinned " + pf.mFilename);
             }
         }
+
         return true;
     }
 
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index f7bd04b..577cada 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -1225,11 +1225,13 @@
             } finally {
                 db.endTransaction();
             }
-            sendAccountsChangedBroadcast(accounts.userId);
         }
         if (getUserManager().getUserInfo(accounts.userId).canHaveProfile()) {
             addAccountToLinkedRestrictedUsers(account, accounts.userId);
         }
+
+        // Only send LOGIN_ACCOUNTS_CHANGED when the database changed.
+        sendAccountsChangedBroadcast(accounts.userId);
         return true;
     }
 
@@ -1412,7 +1414,6 @@
         synchronized (accounts.cacheLock) {
             final SQLiteDatabase db = accounts.openHelper.getWritableDatabaseUserIsUnlocked();
             db.beginTransaction();
-            boolean isSuccessful = false;
             Account renamedAccount = new Account(newName, accountToRename.type);
             try {
                 final long accountId = getAccountIdLocked(db, accountToRename);
@@ -1425,54 +1426,51 @@
                     values.put(ACCOUNTS_PREVIOUS_NAME, accountToRename.name);
                     db.update(TABLE_ACCOUNTS, values, ACCOUNTS_ID + "=?", argsAccountId);
                     db.setTransactionSuccessful();
-                    isSuccessful = true;
                     logRecord(db, DebugDbHelper.ACTION_ACCOUNT_RENAME, TABLE_ACCOUNTS, accountId,
                             accounts);
                 }
             } finally {
                 db.endTransaction();
-                if (isSuccessful) {
-                    /*
-                     * Database transaction was successful. Clean up cached
-                     * data associated with the account in the user profile.
-                     */
-                    insertAccountIntoCacheLocked(accounts, renamedAccount);
-                    /*
-                     * Extract the data and token caches before removing the
-                     * old account to preserve the user data associated with
-                     * the account.
-                     */
-                    HashMap<String, String> tmpData = accounts.userDataCache.get(accountToRename);
-                    HashMap<String, String> tmpTokens = accounts.authTokenCache.get(accountToRename);
-                    removeAccountFromCacheLocked(accounts, accountToRename);
-                    /*
-                     * Update the cached data associated with the renamed
-                     * account.
-                     */
-                    accounts.userDataCache.put(renamedAccount, tmpData);
-                    accounts.authTokenCache.put(renamedAccount, tmpTokens);
-                    accounts.previousNameCache.put(
-                          renamedAccount,
-                          new AtomicReference<String>(accountToRename.name));
-                    resultAccount = renamedAccount;
+            }
+            /*
+             * Database transaction was successful. Clean up cached
+             * data associated with the account in the user profile.
+             */
+            insertAccountIntoCacheLocked(accounts, renamedAccount);
+            /*
+             * Extract the data and token caches before removing the
+             * old account to preserve the user data associated with
+             * the account.
+             */
+            HashMap<String, String> tmpData = accounts.userDataCache.get(accountToRename);
+            HashMap<String, String> tmpTokens = accounts.authTokenCache.get(accountToRename);
+            removeAccountFromCacheLocked(accounts, accountToRename);
+            /*
+             * Update the cached data associated with the renamed
+             * account.
+             */
+            accounts.userDataCache.put(renamedAccount, tmpData);
+            accounts.authTokenCache.put(renamedAccount, tmpTokens);
+            accounts.previousNameCache.put(
+                    renamedAccount,
+                    new AtomicReference<String>(accountToRename.name));
+            resultAccount = renamedAccount;
 
-                    int parentUserId = accounts.userId;
-                    if (canHaveProfile(parentUserId)) {
-                        /*
-                         * Owner or system user account was renamed, rename the account for
-                         * those users with which the account was shared.
-                         */
-                        List<UserInfo> users = getUserManager().getUsers(true);
-                        for (UserInfo user : users) {
-                            if (user.isRestricted()
-                                    && (user.restrictedProfileParentId == parentUserId)) {
-                                renameSharedAccountAsUser(accountToRename, newName, user.id);
-                            }
-                        }
+            int parentUserId = accounts.userId;
+            if (canHaveProfile(parentUserId)) {
+                /*
+                 * Owner or system user account was renamed, rename the account for
+                 * those users with which the account was shared.
+                 */
+                List<UserInfo> users = getUserManager().getUsers(true);
+                for (UserInfo user : users) {
+                    if (user.isRestricted()
+                            && (user.restrictedProfileParentId == parentUserId)) {
+                        renameSharedAccountAsUser(accountToRename, newName, user.id);
                     }
-                    sendAccountsChangedBroadcast(accounts.userId);
                 }
             }
+            sendAccountsChangedBroadcast(accounts.userId);
         }
         return resultAccount;
     }
@@ -1653,7 +1651,7 @@
     }
 
     private boolean removeAccountInternal(UserAccounts accounts, Account account, int callingUid) {
-        int deleted;
+        boolean isChanged = false;
         boolean userUnlocked = isLocalUnlockedUser(accounts.userId);
         if (!userUnlocked) {
             Slog.i(TAG, "Removing account " + account + " while user "+ accounts.userId
@@ -1663,25 +1661,38 @@
             final SQLiteDatabase db = userUnlocked
                     ? accounts.openHelper.getWritableDatabaseUserIsUnlocked()
                     : accounts.openHelper.getWritableDatabase();
-            final long accountId = getAccountIdLocked(db, account);
             db.beginTransaction();
+            // Set to a dummy value, this will only be used if the database
+            // transaction succeeds.
+            long accountId = -1;
             try {
-                deleted = db.delete(TABLE_ACCOUNTS, ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE
-                                + "=?", new String[]{account.name, account.type});
-                if (userUnlocked) {
-                    // Delete from CE table
-                    deleted = db.delete(CE_TABLE_ACCOUNTS, ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE
-                            + "=?", new String[]{account.name, account.type});
+                accountId = getAccountIdLocked(db, account);
+                if (accountId >= 0) {
+                    db.delete(
+                            TABLE_ACCOUNTS,
+                            ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE + "=?",
+                            new String[]{ account.name, account.type });
+                    if (userUnlocked) {
+                        // Delete from CE table
+                        db.delete(
+                                CE_TABLE_ACCOUNTS,
+                                ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE + "=?",
+                                new String[]{ account.name, account.type });
+                    }
+                    db.setTransactionSuccessful();
+                    isChanged = true;
                 }
-                db.setTransactionSuccessful();
             } finally {
                 db.endTransaction();
             }
-            removeAccountFromCacheLocked(accounts, account);
-            sendAccountsChangedBroadcast(accounts.userId);
-            String action = userUnlocked ? DebugDbHelper.ACTION_ACCOUNT_REMOVE
-                    : DebugDbHelper.ACTION_ACCOUNT_REMOVE_DE;
-            logRecord(db, action, TABLE_ACCOUNTS, accountId, accounts);
+            if (isChanged) {
+                removeAccountFromCacheLocked(accounts, account);
+                // Only broadcast LOGIN_ACCOUNTS_CHANGED if a change occured.
+                sendAccountsChangedBroadcast(accounts.userId);
+                String action = userUnlocked ? DebugDbHelper.ACTION_ACCOUNT_REMOVE
+                        : DebugDbHelper.ACTION_ACCOUNT_REMOVE_DE;
+                logRecord(db, action, TABLE_ACCOUNTS, accountId, accounts);
+            }
         }
         long id = Binder.clearCallingIdentity();
         try {
@@ -1698,7 +1709,7 @@
         } finally {
             Binder.restoreCallingIdentity(id);
         }
-        return (deleted > 0);
+        return isChanged;
     }
 
     @Override
@@ -1922,6 +1933,7 @@
         if (account == null) {
             return;
         }
+        boolean isChanged = false;
         synchronized (accounts.cacheLock) {
             final SQLiteDatabase db = accounts.openHelper.getWritableDatabaseUserIsUnlocked();
             db.beginTransaction();
@@ -1931,12 +1943,17 @@
                 final long accountId = getAccountIdLocked(db, account);
                 if (accountId >= 0) {
                     final String[] argsAccountId = {String.valueOf(accountId)};
-                    db.update(CE_TABLE_ACCOUNTS, values, ACCOUNTS_ID + "=?", argsAccountId);
-                    db.delete(CE_TABLE_AUTHTOKENS, AUTHTOKENS_ACCOUNTS_ID + "=?", argsAccountId);
+                    db.update(
+                            CE_TABLE_ACCOUNTS, values, ACCOUNTS_ID + "=?", argsAccountId);
+                    db.delete(
+                            CE_TABLE_AUTHTOKENS, AUTHTOKENS_ACCOUNTS_ID + "=?", argsAccountId);
                     accounts.authTokenCache.remove(account);
                     accounts.accountTokenCaches.remove(account);
                     db.setTransactionSuccessful();
-
+                    // If there is an account whose password will be updated and the database
+                    // transactions succeed, then we say that a change has occured. Even if the
+                    // new password is the same as the old and there were no authtokens to delete.
+                    isChanged = true;
                     String action = (password == null || password.length() == 0) ?
                             DebugDbHelper.ACTION_CLEAR_PASSWORD
                             : DebugDbHelper.ACTION_SET_PASSWORD;
@@ -1944,8 +1961,11 @@
                 }
             } finally {
                 db.endTransaction();
+                if (isChanged) {
+                    // Send LOGIN_ACCOUNTS_CHANGED only if the something changed.
+                    sendAccountsChangedBroadcast(accounts.userId);
+                }
             }
-            sendAccountsChangedBroadcast(accounts.userId);
         }
     }
 
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 1f0dbfe..8716811 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -140,7 +140,6 @@
 import android.content.pm.ProviderInfo;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
-import android.content.pm.ShortcutServiceInternal;
 import android.content.pm.UserInfo;
 import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
@@ -644,30 +643,41 @@
         return mShowDialogs && !mSleeping && !mShuttingDown;
     }
 
-    // it's a semaphore; boost when 0->1, reset when 1->0
-    static ThreadLocal<Integer> sIsBoosted = new ThreadLocal<Integer>() {
-        @Override protected Integer initialValue() {
-            return 0;
+    private static final class PriorityState {
+        // Acts as counter for number of synchronized region that needs to acquire 'this' as a lock
+        // the current thread is currently in. When it drops down to zero, we will no longer boost
+        // the thread's priority.
+        private int regionCounter = 0;
+
+        // The thread's previous priority before boosting.
+        private int prevPriority = Integer.MIN_VALUE;
+    }
+
+    static ThreadLocal<PriorityState> sThreadPriorityState = new ThreadLocal<PriorityState>() {
+        @Override protected PriorityState initialValue() {
+            return new PriorityState();
         }
     };
 
     static void boostPriorityForLockedSection() {
-        if (sIsBoosted.get() == 0) {
-            // boost to prio 118 while holding a global lock
-            Process.setThreadPriority(Process.myTid(), -2);
-            //Log.e(TAG, "PRIORITY BOOST:  set priority on TID " + Process.myTid());
+        int tid = Process.myTid();
+        int prevPriority = Process.getThreadPriority(tid);
+        PriorityState state = sThreadPriorityState.get();
+        if (state.regionCounter == 0 && prevPriority > -2) {
+            state.prevPriority = prevPriority;
+            Process.setThreadPriority(tid, -2);
         }
-        int cur = sIsBoosted.get();
-        sIsBoosted.set(cur + 1);
+        state.regionCounter++;
     }
 
     static void resetPriorityAfterLockedSection() {
-        sIsBoosted.set(sIsBoosted.get() - 1);
-        if (sIsBoosted.get() == 0) {
-            //Log.e(TAG, "PRIORITY BOOST:  reset priority on TID " + Process.myTid());
-            Process.setThreadPriority(Process.myTid(), 0);
+        PriorityState state = sThreadPriorityState.get();
+        state.regionCounter--;
+        if (state.regionCounter == 0 && state.prevPriority > -2) {
+            Process.setThreadPriority(Process.myTid(), state.prevPriority);
         }
     }
+
     public class PendingAssistExtras extends Binder implements Runnable {
         public final ActivityRecord activity;
         public final Bundle extras;
@@ -18865,15 +18875,6 @@
                         null, AppOpsManager.OP_NONE, null, false, false,
                         MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
                 if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {
-                    // Tell the shortcut manager that the system locale changed.  It needs to know
-                    // it before any other apps receive ACTION_LOCALE_CHANGED, which is why
-                    // we "push" from here, rather than having the service listen to the broadcast.
-                    final ShortcutServiceInternal shortcutService =
-                            LocalServices.getService(ShortcutServiceInternal.class);
-                    if (shortcutService != null) {
-                        shortcutService.onSystemLocaleChangedNoLock();
-                    }
-
                     intent = new Intent(Intent.ACTION_LOCALE_CHANGED);
                     intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
                     if (!mProcessesReady) {
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index a4fc251..c16fc62 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -3074,7 +3074,7 @@
         final boolean nowVisible = allResumedActivitiesVisible();
         for (int activityNdx = mStoppingActivities.size() - 1; activityNdx >= 0; --activityNdx) {
             ActivityRecord s = mStoppingActivities.get(activityNdx);
-            final boolean waitingVisible = mWaitingVisibleActivities.contains(s);
+            boolean waitingVisible = mWaitingVisibleActivities.contains(s);
             if (DEBUG_STATES) Slog.v(TAG, "Stopping " + s + ": nowVisible=" + nowVisible
                     + " waitingVisible=" + waitingVisible + " finishing=" + s.finishing);
             if (waitingVisible && nowVisible) {
@@ -3087,6 +3087,7 @@
                     // hidden by the activities in front of it.
                     if (DEBUG_STATES) Slog.v(TAG, "Before stopping, can hide: " + s);
                     mWindowManager.setAppVisibility(s.appToken, false);
+                    waitingVisible = false;
                 }
             }
             if ((!waitingVisible || mService.isSleepingOrShuttingDownLocked()) && remove) {
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index 12310e3..b6c8d5d 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -450,8 +450,6 @@
 
     private int setWifiTethering(final boolean enable) {
         synchronized (mPublicSync) {
-            // Note that we're maintaining a predicate that mWifiTetherRequested always matches
-            // our last request to WifiManager re: its AP enabled status.
             mWifiTetherRequested = enable;
             final WifiManager wifiManager =
                     (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
@@ -794,10 +792,6 @@
                 }
             } else if (action.equals(WifiManager.WIFI_AP_STATE_CHANGED_ACTION)) {
                 synchronized (Tethering.this.mPublicSync) {
-                    if (!mWifiTetherRequested) {
-                        // We only care when we're trying to tether via our WiFi interface.
-                        return;
-                    }
                     int curState =  intent.getIntExtra(WifiManager.EXTRA_WIFI_AP_STATE,
                             WifiManager.WIFI_AP_STATE_DISABLED);
                     switch (curState) {
@@ -805,8 +799,10 @@
                             // We can see this state on the way to both enabled and failure states.
                             break;
                         case WifiManager.WIFI_AP_STATE_ENABLED:
-                            // Tell an appropriate interface state machine that it should tether.
-                            tetherMatchingInterfaces(true, ConnectivityManager.TETHERING_WIFI);
+                            // When the AP comes up and we've been requested to tether it, do so.
+                            if (mWifiTetherRequested) {
+                                tetherMatchingInterfaces(true, ConnectivityManager.TETHERING_WIFI);
+                            }
                             break;
                         case WifiManager.WIFI_AP_STATE_DISABLED:
                         case WifiManager.WIFI_AP_STATE_DISABLING:
@@ -816,10 +812,20 @@
                                 Log.d(TAG, "Canceling WiFi tethering request - AP_STATE=" +
                                     curState);
                             }
-                            // Tell an appropriate interface state machine that
-                            // it needs to tear itself down.
-                            tetherMatchingInterfaces(false, ConnectivityManager.TETHERING_WIFI);
-                            setWifiTethering(false);
+                            // Tell appropriate interface state machines that they should tear
+                            // themselves down.
+                            for (int i = 0; i < mTetherStates.size(); i++) {
+                                TetherInterfaceStateMachine tism =
+                                        mTetherStates.valueAt(i).mStateMachine;
+                                if (tism.interfaceType() == ConnectivityManager.TETHERING_WIFI) {
+                                    tism.sendMessage(
+                                            TetherInterfaceStateMachine.CMD_TETHER_UNREQUESTED);
+                                    break;  // There should be at most one of these.
+                                }
+                            }
+                            // Regardless of whether we requested this transition, the AP has gone
+                            // down.  Don't try to tether again unless we're requested to do so.
+                            mWifiTetherRequested = false;
                             break;
                     }
                 }
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 6a6570b..fec7ed1 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -244,6 +244,7 @@
         publishBinderService(Context.DISPLAY_SERVICE, new BinderService(),
                 true /*allowIsolated*/);
         publishLocalService(DisplayManagerInternal.class, new LocalService());
+        publishLocalService(DisplayTransformManager.class, new DisplayTransformManager());
     }
 
     @Override
diff --git a/services/core/java/com/android/server/display/DisplayTransformManager.java b/services/core/java/com/android/server/display/DisplayTransformManager.java
new file mode 100644
index 0000000..cfeae7b
--- /dev/null
+++ b/services/core/java/com/android/server/display/DisplayTransformManager.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2016 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.server.display;
+
+import android.opengl.Matrix;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Slog;
+import android.util.SparseArray;
+
+/**
+ * Manager for applying color transformations to the display.
+ */
+public class DisplayTransformManager {
+
+    private static final String TAG = "DisplayTransformManager";
+
+    /**
+     * Color transform level used by Night display to tint the display red.
+     */
+    public static final int LEVEL_COLOR_MATRIX_NIGHT_DISPLAY = 100;
+    /**
+     * Color transform level used by A11y services to make the display monochromatic.
+     */
+    public static final int LEVEL_COLOR_MATRIX_GRAYSCALE = 200;
+    /**
+     * Color transform level used by A11y services to invert the display colors.
+     */
+    public static final int LEVEL_COLOR_MATRIX_INVERT_COLOR = 300;
+
+    private final SparseArray<float[]> mColorMatrix = new SparseArray<>(3);
+
+    private int mDaltonizerMode = -1;
+
+    /* package */ DisplayTransformManager() {
+    }
+
+    /**
+     * Returns the color transform matrix set for a given level.
+     */
+    public float[] getColorMatrix(int key) {
+        synchronized (mColorMatrix) {
+            return mColorMatrix.get(key);
+        }
+    }
+
+    /**
+     * Sets and applies a current color transform matrix for a given level.
+     * <p>
+     * Note: all color transforms are first composed to a single matrix in ascending order based
+     * on level before being applied to the display.
+     *
+     * @param key   the level used to identify and compose the color transform (low -> high)
+     * @param value the 4x4 color transform matrix (in column-major order), or {@code null} to
+     *              remove the color transform matrix associated with the provided level
+     */
+    public void setColorMatrix(int key, float[] value) {
+        if (value != null && value.length != 16) {
+            throw new IllegalArgumentException("Expected length: 16 (4x4 matrix)"
+                    + ", actual length: " + value.length);
+        }
+
+        synchronized (mColorMatrix) {
+            if (value != null) {
+                mColorMatrix.put(key, value);
+            } else {
+                mColorMatrix.remove(key);
+            }
+
+            // Update the current color transform.
+            applyColorMatrix(computeColorMatrix());
+        }
+    }
+
+    /**
+     * Returns the composition of all current color matrices, or {@code null} if there are none.
+     */
+    private float[] computeColorMatrix() {
+        synchronized (mColorMatrix) {
+            final int count = mColorMatrix.size();
+            if (count == 0) {
+                return null;
+            }
+
+            final float[][] result = new float[2][16];
+            Matrix.setIdentityM(result[0], 0);
+            for (int i = 0; i < count; i++) {
+                float[] rhs = mColorMatrix.valueAt(i);
+                Matrix.multiplyMM(result[(i + 1) % 2], 0, result[i % 2], 0, rhs, 0);
+            }
+            return result[count % 2];
+        }
+    }
+
+    /**
+     * Returns the current Daltonization mode.
+     */
+    public int getDaltonizerMode() {
+        return mDaltonizerMode;
+    }
+
+    /**
+     * Sets the current Daltonization mode. This adjusts the color space to correct for or simulate
+     * various types of color blindness.
+     *
+     * @param mode the new Daltonization mode, or -1 to disable
+     */
+    public void setDaltonizerMode(int mode) {
+        if (mDaltonizerMode != mode) {
+            mDaltonizerMode = mode;
+            applyDaltonizerMode(mode);
+        }
+    }
+
+    /**
+     * Propagates the provided color transformation matrix to the SurfaceFlinger.
+     */
+    private static void applyColorMatrix(float[] m) {
+        final IBinder flinger = ServiceManager.getService("SurfaceFlinger");
+        if (flinger != null) {
+            final Parcel data = Parcel.obtain();
+            data.writeInterfaceToken("android.ui.ISurfaceComposer");
+            if (m != null) {
+                data.writeInt(1);
+                for (int i = 0; i < 16; i++) {
+                    data.writeFloat(m[i]);
+                }
+            } else {
+                data.writeInt(0);
+            }
+            try {
+                flinger.transact(1015, data, null, 0);
+            } catch (RemoteException ex) {
+                Slog.e(TAG, "Failed to set color transform", ex);
+            } finally {
+                data.recycle();
+            }
+        }
+    }
+
+    /**
+     * Propagates the provided Daltonization mode to the SurfaceFlinger.
+     */
+    private static void applyDaltonizerMode(int mode) {
+        final IBinder flinger = ServiceManager.getService("SurfaceFlinger");
+        if (flinger != null) {
+            final Parcel data = Parcel.obtain();
+            data.writeInterfaceToken("android.ui.ISurfaceComposer");
+            data.writeInt(mode);
+            try {
+                flinger.transact(1014, data, null, 0);
+            } catch (RemoteException ex) {
+                Slog.e(TAG, "Failed to set Daltonizer mode", ex);
+            } finally {
+                data.recycle();
+            }
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/display/NightDisplayService.java b/services/core/java/com/android/server/display/NightDisplayService.java
index 27abd1e..1f4ee9b 100644
--- a/services/core/java/com/android/server/display/NightDisplayService.java
+++ b/services/core/java/com/android/server/display/NightDisplayService.java
@@ -22,6 +22,8 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.database.ContentObserver;
+import android.net.Uri;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.UserHandle;
@@ -47,11 +49,19 @@
     private static final boolean DEBUG = false;
 
     /**
-     * Night mode ~= 3400 K.
+     * Night display ~= 3400 K.
      */
-    private static final String MATRIX_NIGHT = "1,0,0,0,0,.754,0,0,0,0,.516,0,0,0,0,1";
+    private static final float[] MATRIX_NIGHT = new float[] {
+        1,      0,      0, 0,
+        0, 0.754f,      0, 0,
+        0,      0, 0.516f, 0,
+        0,      0,      0, 1
+    };
+
+    private final Handler mHandler;
 
     private int mCurrentUser = UserHandle.USER_NULL;
+    private ContentObserver mUserSetupObserver;
     private boolean mBootCompleted;
 
     private NightDisplayController mController;
@@ -60,6 +70,7 @@
 
     public NightDisplayService(Context context) {
         super(context);
+        mHandler = new Handler(Looper.getMainLooper());
     }
 
     @Override
@@ -68,15 +79,23 @@
     }
 
     @Override
+    public void onBootPhase(int phase) {
+        if (phase == PHASE_BOOT_COMPLETED) {
+            mBootCompleted = true;
+
+            // Register listeners now that boot is complete.
+            if (mCurrentUser != UserHandle.USER_NULL && mUserSetupObserver == null) {
+                setUp();
+            }
+        }
+    }
+
+    @Override
     public void onStartUser(int userHandle) {
         super.onStartUser(userHandle);
 
-        // Register listeners for the new user.
         if (mCurrentUser == UserHandle.USER_NULL) {
-            mCurrentUser = userHandle;
-            if (mBootCompleted) {
-                setUpNightMode();
-            }
+            onUserChanged(userHandle);
         }
     }
 
@@ -84,44 +103,60 @@
     public void onSwitchUser(int userHandle) {
         super.onSwitchUser(userHandle);
 
-        // Unregister listeners for the old user.
-        if (mBootCompleted && mCurrentUser != UserHandle.USER_NULL) {
-            tearDownNightMode();
-        }
-
-        // Register listeners for the new user.
-        mCurrentUser = userHandle;
-        if (mBootCompleted) {
-            setUpNightMode();
-        }
+        onUserChanged(userHandle);
     }
 
     @Override
     public void onStopUser(int userHandle) {
         super.onStopUser(userHandle);
 
-        // Unregister listeners for the old user.
         if (mCurrentUser == userHandle) {
-            if (mBootCompleted) {
-                tearDownNightMode();
-            }
-            mCurrentUser = UserHandle.USER_NULL;
+            onUserChanged(UserHandle.USER_NULL);
         }
     }
 
-    @Override
-    public void onBootPhase(int phase) {
-        if (phase == PHASE_BOOT_COMPLETED) {
-            mBootCompleted = true;
+    private void onUserChanged(int userHandle) {
+        final ContentResolver cr = getContext().getContentResolver();
 
-            // Register listeners now that boot is complete.
-            if (mCurrentUser != UserHandle.USER_NULL) {
-                setUpNightMode();
+        if (mCurrentUser != UserHandle.USER_NULL) {
+            if (mUserSetupObserver != null) {
+                cr.unregisterContentObserver(mUserSetupObserver);
+                mUserSetupObserver = null;
+            } else if (mBootCompleted) {
+                tearDown();
+            }
+        }
+
+        mCurrentUser = userHandle;
+
+        if (mCurrentUser != UserHandle.USER_NULL) {
+            if (!isUserSetupCompleted(cr, mCurrentUser)) {
+                mUserSetupObserver = new ContentObserver(mHandler) {
+                    @Override
+                    public void onChange(boolean selfChange, Uri uri) {
+                        if (isUserSetupCompleted(cr, mCurrentUser)) {
+                            cr.unregisterContentObserver(this);
+                            mUserSetupObserver = null;
+
+                            if (mBootCompleted) {
+                                setUp();
+                            }
+                        }
+                    }
+                };
+                cr.registerContentObserver(Secure.getUriFor(Secure.USER_SETUP_COMPLETE),
+                        false /* notifyForDescendents */, mUserSetupObserver, mCurrentUser);
+            } else if (mBootCompleted) {
+                setUp();
             }
         }
     }
 
-    private void setUpNightMode() {
+    private static boolean isUserSetupCompleted(ContentResolver cr, int userHandle) {
+        return Secure.getIntForUser(cr, Secure.USER_SETUP_COMPLETE, 0, userHandle) == 1;
+    }
+
+    private void setUp() {
         // Create a new controller for the current user and start listening for changes.
         mController = new NightDisplayController(getContext(), mCurrentUser);
         mController.setListener(this);
@@ -135,8 +170,11 @@
         }
     }
 
-    private void tearDownNightMode() {
-        mController.setListener(null);
+    private void tearDown() {
+        if (mController != null) {
+            mController.setListener(null);
+            mController = null;
+        }
 
         if (mAutoMode != null) {
             mAutoMode.onStop();
@@ -144,7 +182,6 @@
         }
 
         mIsActivated = null;
-        mController = null;
     }
 
     @Override
@@ -159,9 +196,9 @@
             }
 
             // Update the current color matrix.
-            final ContentResolver cr = getContext().getContentResolver();
-            Secure.putStringForUser(cr, Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX,
-                    activated ? MATRIX_NIGHT : null, mCurrentUser);
+            final DisplayTransformManager dtm = getLocalService(DisplayTransformManager.class);
+            dtm.setColorMatrix(DisplayTransformManager.LEVEL_COLOR_MATRIX_NIGHT_DISPLAY,
+                    activated ? MATRIX_NIGHT : null);
         }
     }
 
@@ -319,13 +356,11 @@
     private class TwilightAutoMode extends AutoMode implements TwilightListener {
 
         private final TwilightManager mTwilightManager;
-        private final Handler mHandler;
 
         private boolean mIsNight;
 
         public TwilightAutoMode() {
             mTwilightManager = getLocalService(TwilightManager.class);
-            mHandler = new Handler(Looper.getMainLooper());
         }
 
         private void updateActivated() {
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index 8589de1..8f212db 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -1556,6 +1556,11 @@
                 }
             }
 
+            if ((job.getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0) {
+                getContext().enforceCallingOrSelfPermission(
+                        android.Manifest.permission.CONNECTIVITY_INTERNAL, TAG);
+            }
+
             long ident = Binder.clearCallingIdentity();
             try {
                 return JobSchedulerService.this.schedule(job, uid);
diff --git a/services/core/java/com/android/server/job/controllers/JobStatus.java b/services/core/java/com/android/server/job/controllers/JobStatus.java
index 552c990..0947554 100644
--- a/services/core/java/com/android/server/job/controllers/JobStatus.java
+++ b/services/core/java/com/android/server/job/controllers/JobStatus.java
@@ -486,6 +486,7 @@
                 + ":[" + job.getService()
                 + ",jId=" + job.getId()
                 + ",u" + getUserId()
+                + ",suid=" + getSourceUid()
                 + ",R=(" + formatRunTime(earliestRunTimeElapsedMillis, NO_EARLIEST_RUNTIME)
                 + "," + formatRunTime(latestRunTimeElapsedMillis, NO_LATEST_RUNTIME) + ")"
                 + ",N=" + job.getNetworkType() + ",C=" + job.isRequireCharging()
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 8d19a24..cbd0769 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -58,7 +58,6 @@
 import android.app.NotificationManager;
 import android.app.NotificationManager.Policy;
 import android.app.PendingIntent;
-import android.app.RemoteInput;
 import android.app.StatusBarManager;
 import android.app.backup.BackupManager;
 import android.app.usage.UsageEvents;
@@ -93,7 +92,6 @@
 import android.os.IInterface;
 import android.os.Looper;
 import android.os.Message;
-import android.os.Parcelable;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.SystemClock;
@@ -122,6 +120,8 @@
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.Xml;
+import android.view.WindowManager;
+import android.view.WindowManagerInternal;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
 import android.widget.Toast;
@@ -232,6 +232,7 @@
     @Nullable StatusBarManagerInternal mStatusBar;
     Vibrator mVibrator;
     private VrManagerInternal mVrManagerInternal;
+    private WindowManagerInternal mWindowManagerInternal;
 
     final IBinder mForegroundToken = new Binder();
     private Handler mHandler;
@@ -452,13 +453,15 @@
         final String pkg;
         final ITransientNotification callback;
         int duration;
+        Binder token;
 
-        ToastRecord(int pid, String pkg, ITransientNotification callback, int duration)
-        {
+        ToastRecord(int pid, String pkg, ITransientNotification callback, int duration,
+                    Binder token) {
             this.pid = pid;
             this.pkg = pkg;
             this.callback = callback;
             this.duration = duration;
+            this.token = token;
         }
 
         void update(int duration) {
@@ -1125,6 +1128,7 @@
             mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
             mAudioManagerInternal = getLocalService(AudioManagerInternal.class);
             mVrManagerInternal = getLocalService(VrManagerInternal.class);
+            mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
             mZenModeHelper.onSystemReady();
         } else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
             // This observer will force an update when observe is called, causing us to
@@ -1325,10 +1329,13 @@
                             }
                         }
 
-                        record = new ToastRecord(callingPid, pkg, callback, duration);
+                        Binder token = new Binder();
+                        mWindowManagerInternal.addWindowToken(token,
+                                WindowManager.LayoutParams.TYPE_TOAST);
+                        record = new ToastRecord(callingPid, pkg, callback, duration, token);
                         mToastQueue.add(record);
                         index = mToastQueue.size() - 1;
-                        keepProcessAliveLocked(callingPid);
+                        keepProcessAliveIfNeededLocked(callingPid);
                     }
                     // If it's at index 0, it's the current toast.  It doesn't matter if it's
                     // new or just been updated.  Call back and tell it to show itself.
@@ -2987,7 +2994,7 @@
         while (record != null) {
             if (DBG) Slog.d(TAG, "Show pkg=" + record.pkg + " callback=" + record.callback);
             try {
-                record.callback.show();
+                record.callback.show(record.token);
                 scheduleTimeoutLocked(record);
                 return;
             } catch (RemoteException e) {
@@ -2998,7 +3005,7 @@
                 if (index >= 0) {
                     mToastQueue.remove(index);
                 }
-                keepProcessAliveLocked(record.pid);
+                keepProcessAliveIfNeededLocked(record.pid);
                 if (mToastQueue.size() > 0) {
                     record = mToastQueue.get(0);
                 } else {
@@ -3018,8 +3025,11 @@
             // don't worry about this, we're about to remove it from
             // the list anyway
         }
-        mToastQueue.remove(index);
-        keepProcessAliveLocked(record.pid);
+
+        ToastRecord lastToast = mToastQueue.remove(index);
+        mWindowManagerInternal.removeWindowToken(lastToast.token, true);
+
+        keepProcessAliveIfNeededLocked(record.pid);
         if (mToastQueue.size() > 0) {
             // Show the next one. If the callback fails, this will remove
             // it from the list, so don't assume that the list hasn't changed
@@ -3063,7 +3073,7 @@
     }
 
     // lock on mToastQueue
-    void keepProcessAliveLocked(int pid)
+    void keepProcessAliveIfNeededLocked(int pid)
     {
         int toastCount = 0; // toasts from this pid
         ArrayList<ToastRecord> list = mToastQueue;
diff --git a/services/core/java/com/android/server/pm/AbstractStatsBase.java b/services/core/java/com/android/server/pm/AbstractStatsBase.java
new file mode 100644
index 0000000..612c476
--- /dev/null
+++ b/services/core/java/com/android/server/pm/AbstractStatsBase.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2016 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.server.pm;
+
+import android.os.Environment;
+import android.os.SystemClock;
+import android.util.AtomicFile;
+
+import java.io.File;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * A simple base class for statistics that need to be saved/restored from a dedicated file. This
+ * class provides a base implementation that:
+ * <ul>
+ * <li>Provide an AtomicFile to the actual read/write code
+ * <li>A background-thread write and a synchronous write
+ * <li>Write-limiting for the background-thread (by default writes are at least 30 minutes apart)
+ * <li>Can lock on the provided data object before writing
+ * </ul>
+ * For completion, a subclass needs to implement actual {@link #writeInternal(Object) writing} and
+ * {@link #readInternal(Object) reading}.
+ */
+public abstract class AbstractStatsBase<T> {
+
+    private static final int WRITE_INTERVAL_MS =
+            (PackageManagerService.DEBUG_DEXOPT) ? 0 : 30*60*1000;
+    private final Object mFileLock = new Object();
+    private final AtomicLong mLastTimeWritten = new AtomicLong(0);
+    private final AtomicBoolean mBackgroundWriteRunning = new AtomicBoolean(false);
+    private final String mFileName;
+    private final String mBackgroundThreadName;
+    private final boolean mLock;
+
+    protected AbstractStatsBase(String fileName, String threadName, boolean lock) {
+        mFileName = fileName;
+        mBackgroundThreadName = threadName;
+        mLock = lock;
+    }
+
+    protected AtomicFile getFile() {
+        File dataDir = Environment.getDataDirectory();
+        File systemDir = new File(dataDir, "system");
+        File fname = new File(systemDir, mFileName);
+        return new AtomicFile(fname);
+    }
+
+    void writeNow(final T data) {
+        writeImpl(data);
+        mLastTimeWritten.set(SystemClock.elapsedRealtime());
+    }
+
+    boolean maybeWriteAsync(final T data) {
+        if (SystemClock.elapsedRealtime() - mLastTimeWritten.get() < WRITE_INTERVAL_MS
+            && !PackageManagerService.DEBUG_DEXOPT) {
+            return false;
+        }
+
+        if (mBackgroundWriteRunning.compareAndSet(false, true)) {
+            new Thread(mBackgroundThreadName) {
+                @Override
+                public void run() {
+                    try {
+                        writeImpl(data);
+                        mLastTimeWritten.set(SystemClock.elapsedRealtime());
+                    } finally {
+                        mBackgroundWriteRunning.set(false);
+                    }
+                }
+            }.start();
+            return true;
+        }
+
+        return false;
+    }
+
+    private void writeImpl(T data) {
+        if (mLock) {
+            synchronized (data) {
+                synchronized (mFileLock) {
+                    writeInternal(data);
+                }
+            }
+        } else {
+            synchronized (mFileLock) {
+                writeInternal(data);
+            }
+        }
+    }
+
+    protected abstract void writeInternal(T data);
+
+    void read(T data) {
+        if (mLock) {
+            synchronized (data) {
+                synchronized (mFileLock) {
+                    readInternal(data);
+                }
+            }
+        } else {
+            synchronized (mFileLock) {
+                readInternal(data);
+            }
+        }
+        // We use the current time as last-written. read() is called on system server startup
+        // (current situation), and we want to postpone I/O at boot.
+        mLastTimeWritten.set(SystemClock.elapsedRealtime());
+    }
+
+    protected abstract void readInternal(T data);
+}
diff --git a/services/core/java/com/android/server/pm/CompilerStats.java b/services/core/java/com/android/server/pm/CompilerStats.java
new file mode 100644
index 0000000..8c2fc3e
--- /dev/null
+++ b/services/core/java/com/android/server/pm/CompilerStats.java
@@ -0,0 +1,295 @@
+/*
+ * Copyright (C) 2016 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.server.pm;
+
+import android.util.ArrayMap;
+import android.util.AtomicFile;
+import android.util.Log;
+
+import com.android.internal.util.FastPrintWriter;
+import com.android.internal.util.IndentingPrintWriter;
+
+import libcore.io.IoUtils;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
+import java.io.Writer;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A class that collects, serializes and deserializes compiler-related statistics on a
+ * per-package per-code-path basis.
+ *
+ * Currently used to track compile times.
+ */
+class CompilerStats extends AbstractStatsBase<Void> {
+
+    private final static String COMPILER_STATS_VERSION_HEADER = "PACKAGE_MANAGER__COMPILER_STATS__";
+    private final static int COMPILER_STATS_VERSION = 1;
+
+    /**
+     * Class to collect all stats pertaining to one package.
+     */
+    static class PackageStats {
+
+        private final String packageName;
+
+        /**
+         * This map stores compile-times for all code paths in the package. The value
+         * is in milliseconds.
+         */
+        private final Map<String, Long> compileTimePerCodePath;
+
+        /**
+         * @param packageName
+         */
+        public PackageStats(String packageName) {
+            this.packageName = packageName;
+            // We expect at least one element in here, but let's make it minimal.
+            compileTimePerCodePath = new ArrayMap<>(2);
+        }
+
+        public String getPackageName() {
+            return packageName;
+        }
+
+        /**
+         * Return the recorded compile time for a given code path. Returns
+         * 0 if there is no recorded time.
+         */
+        public long getCompileTime(String codePath) {
+            String storagePath = getStoredPathFromCodePath(codePath);
+            synchronized (compileTimePerCodePath) {
+                Long l = compileTimePerCodePath.get(storagePath);
+                if (l == null) {
+                    return 0;
+                }
+                return l;
+            }
+        }
+
+        public void setCompileTime(String codePath, long compileTimeInMs) {
+            String storagePath = getStoredPathFromCodePath(codePath);
+            synchronized (compileTimePerCodePath) {
+                if (compileTimeInMs <= 0) {
+                    compileTimePerCodePath.remove(storagePath);
+                } else {
+                    compileTimePerCodePath.put(storagePath, compileTimeInMs);
+                }
+            }
+        }
+
+        private static String getStoredPathFromCodePath(String codePath) {
+            int lastSlash = codePath.lastIndexOf(File.separatorChar);
+            return codePath.substring(lastSlash + 1);
+        }
+
+        public void dump(IndentingPrintWriter ipw) {
+            synchronized (compileTimePerCodePath) {
+                if (compileTimePerCodePath.size() == 0) {
+                    ipw.println("(No recorded stats)");
+                } else {
+                    for (Map.Entry<String, Long> e : compileTimePerCodePath.entrySet()) {
+                        ipw.println(" " + e.getKey() + " - " + e.getValue());
+                    }
+                }
+            }
+        }
+    }
+
+    private final Map<String, PackageStats> packageStats;
+
+    public CompilerStats() {
+        super("package-cstats.list", "CompilerStats_DiskWriter", /* lock */ false);
+        packageStats = new HashMap<>();
+    }
+
+    public PackageStats getPackageStats(String packageName) {
+        synchronized (packageStats) {
+            return packageStats.get(packageName);
+        }
+    }
+
+    public void setPackageStats(String packageName, PackageStats stats) {
+        synchronized (packageStats) {
+            packageStats.put(packageName, stats);
+        }
+    }
+
+    public PackageStats createPackageStats(String packageName) {
+        synchronized (packageStats) {
+            PackageStats newStats = new PackageStats(packageName);
+            packageStats.put(packageName, newStats);
+            return newStats;
+        }
+    }
+
+    public PackageStats getOrCreatePackageStats(String packageName) {
+        synchronized (packageStats) {
+            PackageStats existingStats = packageStats.get(packageName);
+            if (existingStats != null) {
+                return existingStats;
+            }
+
+            return createPackageStats(packageName);
+        }
+    }
+
+    public void deletePackageStats(String packageName) {
+        synchronized (packageStats) {
+            packageStats.remove(packageName);
+        }
+    }
+
+    // I/O
+
+    // The encoding is simple:
+    //
+    // 1) The first line is a line consisting of the version header and the version number.
+    //
+    // 2) The rest of the file is package data.
+    // 2.1) A package is started by any line not starting with "-";
+    // 2.2) Any line starting with "-" is code path data. The format is:
+    //      '-'{code-path}':'{compile-time}
+
+    public void write(Writer out) {
+        @SuppressWarnings("resource")
+        FastPrintWriter fpw = new FastPrintWriter(out);
+
+        fpw.print(COMPILER_STATS_VERSION_HEADER);
+        fpw.println(COMPILER_STATS_VERSION);
+
+        synchronized (packageStats) {
+            for (PackageStats pkg : packageStats.values()) {
+                synchronized (pkg.compileTimePerCodePath) {
+                    if (!pkg.compileTimePerCodePath.isEmpty()) {
+                        fpw.println(pkg.getPackageName());
+
+                        for (Map.Entry<String, Long> e : pkg.compileTimePerCodePath.entrySet()) {
+                            fpw.println("-" + e.getKey() + ":" + e.getValue());
+                        }
+                    }
+                }
+            }
+        }
+
+        fpw.flush();
+    }
+
+    public boolean read(Reader r) {
+        synchronized (packageStats) {
+            // TODO: Could make this a final switch, then we wouldn't have to synchronize over
+            //       the whole reading.
+            packageStats.clear();
+
+            try {
+                BufferedReader in = new BufferedReader(r);
+
+                // Read header, do version check.
+                String versionLine = in.readLine();
+                if (versionLine == null) {
+                    throw new IllegalArgumentException("No version line found.");
+                } else {
+                    if (!versionLine.startsWith(COMPILER_STATS_VERSION_HEADER)) {
+                        throw new IllegalArgumentException("Invalid version line: " + versionLine);
+                    }
+                    int version = Integer.parseInt(
+                            versionLine.substring(COMPILER_STATS_VERSION_HEADER.length()));
+                    if (version != COMPILER_STATS_VERSION) {
+                        // TODO: Upgrade older formats? For now, just reject and regenerate.
+                        throw new IllegalArgumentException("Unexpected version: " + version);
+                    }
+                }
+
+                // For simpler code, we ignore any data lines before the first package. We
+                // collect it in a fake package.
+                PackageStats currentPackage = new PackageStats("fake package");
+
+                String s = null;
+                while ((s = in.readLine()) != null) {
+                    if (s.startsWith("-")) {
+                        int colonIndex = s.indexOf(':');
+                        if (colonIndex == -1 || colonIndex == 1) {
+                            throw new IllegalArgumentException("Could not parse data " + s);
+                        }
+                        String codePath = s.substring(1, colonIndex);
+                        long time = Long.parseLong(s.substring(colonIndex + 1));
+                        currentPackage.setCompileTime(codePath, time);
+                    } else {
+                        currentPackage = getOrCreatePackageStats(s);
+                    }
+                }
+            } catch (Exception e) {
+                Log.e(PackageManagerService.TAG, "Error parsing compiler stats", e);
+                return false;
+            }
+
+            return true;
+        }
+    }
+
+    void writeNow() {
+        writeNow(null);
+    }
+
+    boolean maybeWriteAsync() {
+        return maybeWriteAsync(null);
+    }
+
+    @Override
+    protected void writeInternal(Void data) {
+        AtomicFile file = getFile();
+        FileOutputStream f = null;
+
+        try {
+            f = file.startWrite();
+            OutputStreamWriter osw = new OutputStreamWriter(f);
+            write(osw);
+            osw.flush();
+            file.finishWrite(f);
+        } catch (IOException e) {
+            if (f != null) {
+                file.failWrite(f);
+            }
+            Log.e(PackageManagerService.TAG, "Failed to write compiler stats", e);
+        }
+    }
+
+    void read() {
+        read((Void)null);
+    }
+
+    @Override
+    protected void readInternal(Void data) {
+        AtomicFile file = getFile();
+        BufferedReader in = null;
+        try {
+            in = new BufferedReader(new InputStreamReader(file.openRead()));
+            read(in);
+        } catch (FileNotFoundException expected) {
+        } finally {
+            IoUtils.closeQuietly(in);
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java
index 02c6472..77c69c9 100644
--- a/services/core/java/com/android/server/pm/OtaDexoptService.java
+++ b/services/core/java/com/android/server/pm/OtaDexoptService.java
@@ -225,7 +225,8 @@
 
         optimizer.performDexOpt(nextPackage, nextPackage.usesLibraryFiles,
                 null /* ISAs */, false /* checkProfiles */,
-                getCompilerFilterForReason(compilationReason));
+                getCompilerFilterForReason(compilationReason),
+                null /* CompilerStats.PackageStats */);
 
         mCommandsForCurrentPackage = collectingConnection.commands;
         if (mCommandsForCurrentPackage.isEmpty()) {
@@ -271,7 +272,8 @@
                 mPackageManagerService.mInstaller, mPackageManagerService.mInstallLock, mContext);
         optimizer.performDexOpt(nextPackage, nextPackage.usesLibraryFiles, null /* ISAs */,
                 false /* checkProfiles */,
-                getCompilerFilterForReason(PackageManagerService.REASON_AB_OTA));
+                getCompilerFilterForReason(PackageManagerService.REASON_AB_OTA),
+                mPackageManagerService.getOrCreateCompilerPackageStats(nextPackage));
     }
 
     private void moveAbArtifacts(Installer installer) {
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index 26a840d..19b1201 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -90,7 +90,8 @@
      * synchronized on {@link #mInstallLock}.
      */
     int performDexOpt(PackageParser.Package pkg, String[] sharedLibraries,
-            String[] instructionSets, boolean checkProfiles, String targetCompilationFilter) {
+            String[] instructionSets, boolean checkProfiles, String targetCompilationFilter,
+            CompilerStats.PackageStats packageStats) {
         synchronized (mInstallLock) {
             final boolean useLock = mSystemReady;
             if (useLock) {
@@ -99,7 +100,7 @@
             }
             try {
                 return performDexOptLI(pkg, sharedLibraries, instructionSets, checkProfiles,
-                        targetCompilationFilter);
+                        targetCompilationFilter, packageStats);
             } finally {
                 if (useLock) {
                     mDexoptWakeLock.release();
@@ -150,7 +151,8 @@
     }
 
     private int performDexOptLI(PackageParser.Package pkg, String[] sharedLibraries,
-            String[] targetInstructionSets, boolean checkProfiles, String targetCompilerFilter) {
+            String[] targetInstructionSets, boolean checkProfiles, String targetCompilerFilter,
+            CompilerStats.PackageStats packageStats) {
         final String[] instructionSets = targetInstructionSets != null ?
                 targetInstructionSets : getAppDexInstructionSets(pkg.applicationInfo);
 
@@ -254,10 +256,17 @@
                         | DEXOPT_BOOTCOMPLETE);
 
                 try {
+                    long startTime = System.currentTimeMillis();
+
                     mInstaller.dexopt(path, sharedGid, pkg.packageName, dexCodeInstructionSet,
                             dexoptNeeded, oatDir, dexFlags, targetCompilerFilter, pkg.volumeUuid,
                             sharedLibrariesPath);
                     performedDexOpt = true;
+
+                    if (packageStats != null) {
+                        long endTime = System.currentTimeMillis();
+                        packageStats.setCompileTime(path, (int)(endTime - startTime));
+                    }
                 } catch (InstallerException e) {
                     Slog.w(TAG, "Failed to dexopt", e);
                     successfulDexOpt = false;
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 78fa3a3..7fc0f36 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -76,8 +76,6 @@
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static android.content.pm.PackageParser.PARSE_IS_PRIVILEGED;
 import static android.content.pm.PackageParser.isApkFile;
-import static android.os.Process.PACKAGE_INFO_GID;
-import static android.os.Process.SYSTEM_UID;
 import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
 import static android.system.OsConstants.O_CREAT;
 import static android.system.OsConstants.O_RDWR;
@@ -208,7 +206,6 @@
 import android.text.format.DateUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
-import android.util.AtomicFile;
 import android.util.DisplayMetrics;
 import android.util.EventLog;
 import android.util.ExceptionUtils;
@@ -267,7 +264,6 @@
 import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlSerializer;
 
-import java.io.BufferedInputStream;
 import java.io.BufferedOutputStream;
 import java.io.BufferedReader;
 import java.io.ByteArrayInputStream;
@@ -280,7 +276,6 @@
 import java.io.FileReader;
 import java.io.FilenameFilter;
 import java.io.IOException;
-import java.io.InputStream;
 import java.io.PrintWriter;
 import java.nio.charset.StandardCharsets;
 import java.security.DigestInputStream;
@@ -307,7 +302,6 @@
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicLong;
 
 /**
  * Keep track of all those APKs everywhere.
@@ -1131,204 +1125,7 @@
     final @NonNull String mSharedSystemSharedLibraryPackageName;
 
     private final PackageUsage mPackageUsage = new PackageUsage();
-
-    private class PackageUsage {
-        private static final int WRITE_INTERVAL
-            = (DEBUG_DEXOPT) ? 0 : 30*60*1000; // 30m in ms
-
-        private final Object mFileLock = new Object();
-        private final AtomicLong mLastWritten = new AtomicLong(0);
-        private final AtomicBoolean mBackgroundWriteRunning = new AtomicBoolean(false);
-
-        private boolean mIsHistoricalPackageUsageAvailable = true;
-
-        boolean isHistoricalPackageUsageAvailable() {
-            return mIsHistoricalPackageUsageAvailable;
-        }
-
-        void write(boolean force) {
-            if (force) {
-                writeInternal();
-                return;
-            }
-            if (SystemClock.elapsedRealtime() - mLastWritten.get() < WRITE_INTERVAL
-                && !DEBUG_DEXOPT) {
-                return;
-            }
-            if (mBackgroundWriteRunning.compareAndSet(false, true)) {
-                new Thread("PackageUsage_DiskWriter") {
-                    @Override
-                    public void run() {
-                        try {
-                            writeInternal();
-                        } finally {
-                            mBackgroundWriteRunning.set(false);
-                        }
-                    }
-                }.start();
-            }
-        }
-
-        private void writeInternal() {
-            synchronized (mPackages) {
-                synchronized (mFileLock) {
-                    AtomicFile file = getFile();
-                    FileOutputStream f = null;
-                    try {
-                        f = file.startWrite();
-                        BufferedOutputStream out = new BufferedOutputStream(f);
-                        FileUtils.setPermissions(file.getBaseFile().getPath(),
-                                0640, SYSTEM_UID, PACKAGE_INFO_GID);
-                        StringBuilder sb = new StringBuilder();
-
-                        sb.append(USAGE_FILE_MAGIC_VERSION_1);
-                        sb.append('\n');
-                        out.write(sb.toString().getBytes(StandardCharsets.US_ASCII));
-
-                        for (PackageParser.Package pkg : mPackages.values()) {
-                            if (pkg.getLatestPackageUseTimeInMills() == 0L) {
-                                continue;
-                            }
-                            sb.setLength(0);
-                            sb.append(pkg.packageName);
-                            for (long usageTimeInMillis : pkg.mLastPackageUsageTimeInMills) {
-                                sb.append(' ');
-                                sb.append(usageTimeInMillis);
-                            }
-                            sb.append('\n');
-                            out.write(sb.toString().getBytes(StandardCharsets.US_ASCII));
-                        }
-                        out.flush();
-                        file.finishWrite(f);
-                    } catch (IOException e) {
-                        if (f != null) {
-                            file.failWrite(f);
-                        }
-                        Log.e(TAG, "Failed to write package usage times", e);
-                    }
-                }
-            }
-            mLastWritten.set(SystemClock.elapsedRealtime());
-        }
-
-        void readLP() {
-            synchronized (mFileLock) {
-                AtomicFile file = getFile();
-                BufferedInputStream in = null;
-                try {
-                    in = new BufferedInputStream(file.openRead());
-                    StringBuffer sb = new StringBuffer();
-
-                    String firstLine = readLine(in, sb);
-                    if (firstLine == null) {
-                        // Empty file. Do nothing.
-                    } else if (USAGE_FILE_MAGIC_VERSION_1.equals(firstLine)) {
-                        readVersion1LP(in, sb);
-                    } else {
-                        readVersion0LP(in, sb, firstLine);
-                    }
-                } catch (FileNotFoundException expected) {
-                    mIsHistoricalPackageUsageAvailable = false;
-                } catch (IOException e) {
-                    Log.w(TAG, "Failed to read package usage times", e);
-                } finally {
-                    IoUtils.closeQuietly(in);
-                }
-            }
-            mLastWritten.set(SystemClock.elapsedRealtime());
-        }
-
-        private void readVersion0LP(InputStream in, StringBuffer sb, String firstLine)
-                throws IOException {
-            // Initial version of the file had no version number and stored one
-            // package-timestamp pair per line.
-            // Note that the first line has already been read from the InputStream.
-            for (String line = firstLine; line != null; line = readLine(in, sb)) {
-                String[] tokens = line.split(" ");
-                if (tokens.length != 2) {
-                    throw new IOException("Failed to parse " + line +
-                            " as package-timestamp pair.");
-                }
-
-                String packageName = tokens[0];
-                PackageParser.Package pkg = mPackages.get(packageName);
-                if (pkg == null) {
-                    continue;
-                }
-
-                long timestamp = parseAsLong(tokens[1]);
-                for (int reason = 0;
-                        reason < PackageManager.NOTIFY_PACKAGE_USE_REASONS_COUNT;
-                        reason++) {
-                    pkg.mLastPackageUsageTimeInMills[reason] = timestamp;
-                }
-            }
-        }
-
-        private void readVersion1LP(InputStream in, StringBuffer sb) throws IOException {
-            // Version 1 of the file started with the corresponding version
-            // number and then stored a package name and eight timestamps per line.
-            String line;
-            while ((line = readLine(in, sb)) != null) {
-                String[] tokens = line.split(" ");
-                if (tokens.length != PackageManager.NOTIFY_PACKAGE_USE_REASONS_COUNT + 1) {
-                    throw new IOException("Failed to parse " + line + " as a timestamp array.");
-                }
-
-                String packageName = tokens[0];
-                PackageParser.Package pkg = mPackages.get(packageName);
-                if (pkg == null) {
-                    continue;
-                }
-
-                for (int reason = 0;
-                        reason < PackageManager.NOTIFY_PACKAGE_USE_REASONS_COUNT;
-                        reason++) {
-                    pkg.mLastPackageUsageTimeInMills[reason] = parseAsLong(tokens[reason + 1]);
-                }
-            }
-        }
-
-        private long parseAsLong(String token) throws IOException {
-            try {
-                return Long.parseLong(token);
-            } catch (NumberFormatException e) {
-                throw new IOException("Failed to parse " + token + " as a long.", e);
-            }
-        }
-
-        private String readLine(InputStream in, StringBuffer sb) throws IOException {
-            return readToken(in, sb, '\n');
-        }
-
-        private String readToken(InputStream in, StringBuffer sb, char endOfToken)
-                throws IOException {
-            sb.setLength(0);
-            while (true) {
-                int ch = in.read();
-                if (ch == -1) {
-                    if (sb.length() == 0) {
-                        return null;
-                    }
-                    throw new IOException("Unexpected EOF");
-                }
-                if (ch == endOfToken) {
-                    return sb.toString();
-                }
-                sb.append((char)ch);
-            }
-        }
-
-        private AtomicFile getFile() {
-            File dataDir = Environment.getDataDirectory();
-            File systemDir = new File(dataDir, "system");
-            File fname = new File(systemDir, "package-usage.list");
-            return new AtomicFile(fname);
-        }
-
-        private static final String USAGE_FILE_MAGIC = "PACKAGE_USAGE__VERSION_";
-        private static final String USAGE_FILE_MAGIC_VERSION_1 = USAGE_FILE_MAGIC + "1";
-    }
+    private final CompilerStats mCompilerStats = new CompilerStats();
 
     class PackageHandler extends Handler {
         private boolean mBound = false;
@@ -2709,7 +2506,8 @@
 
             // Now that we know all the packages we are keeping,
             // read and update their last usage times.
-            mPackageUsage.readLP();
+            mPackageUsage.read(mPackages);
+            mCompilerStats.read();
 
             EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
                     SystemClock.uptimeMillis());
@@ -7477,7 +7275,8 @@
                 // Package could not be found. Report failure.
                 return PackageDexOptimizer.DEX_OPT_FAILED;
             }
-            mPackageUsage.write(false);
+            mPackageUsage.maybeWriteAsync(mPackages);
+            mCompilerStats.maybeWriteAsync();
         }
         long callingId = Binder.clearCallingIdentity();
         try {
@@ -7522,11 +7321,12 @@
                 // Currently this will do a full compilation of the library by default.
                 pdo.performDexOpt(depPackage, null /* sharedLibraries */, instructionSets,
                         false /* checkProfiles */,
-                        getCompilerFilterForReason(REASON_NON_SYSTEM_LIBRARY));
+                        getCompilerFilterForReason(REASON_NON_SYSTEM_LIBRARY),
+                        getOrCreateCompilerPackageStats(depPackage));
             }
         }
         return pdo.performDexOpt(p, p.usesLibraryFiles, instructionSets, checkProfiles,
-                targetCompilerFilter);
+                targetCompilerFilter, getOrCreateCompilerPackageStats(p));
     }
 
     Collection<PackageParser.Package> findSharedNonSystemLibraries(PackageParser.Package p) {
@@ -7580,7 +7380,8 @@
     }
 
     public void shutdown() {
-        mPackageUsage.write(true);
+        mPackageUsage.writeNow(mPackages);
+        mCompilerStats.writeNow();
     }
 
     @Override
@@ -15226,7 +15027,8 @@
             // Also, don't fail application installs if the dexopt step fails.
             mPackageDexOptimizer.performDexOpt(pkg, pkg.usesLibraryFiles,
                     null /* instructionSets */, false /* checkProfiles */,
-                    getCompilerFilterForReason(REASON_INSTALL));
+                    getCompilerFilterForReason(REASON_INSTALL),
+                    getOrCreateCompilerPackageStats(pkg));
             Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
 
             // Notify BackgroundDexOptService that the package has been changed.
@@ -16886,9 +16688,28 @@
             filter.dump(new LogPrinter(Log.INFO, TAG), "  ");
             pir.addFilter(new PreferredActivity(filter, match, set, activity, always));
             scheduleWritePackageRestrictionsLocked(userId);
+            postPreferredActivityChangedBroadcast(userId);
         }
     }
 
+    private void postPreferredActivityChangedBroadcast(int userId) {
+        mHandler.post(() -> {
+            final IActivityManager am = ActivityManagerNative.getDefault();
+            if (am == null) {
+                return;
+            }
+
+            final Intent intent = new Intent(Intent.ACTION_PREFERRED_ACTIVITY_CHANGED);
+            intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
+            try {
+                am.broadcastIntent(null, intent, null, null,
+                        0, null, null, null, android.app.AppOpsManager.OP_NONE,
+                        null, false, false, userId);
+            } catch (RemoteException e) {
+            }
+        });
+    }
+
     @Override
     public void replacePreferredActivity(IntentFilter filter, int match,
             ComponentName[] set, ComponentName activity, int userId) {
@@ -17040,6 +16861,9 @@
                 changed = true;
             }
         }
+        if (changed) {
+            postPreferredActivityChangedBroadcast(userId);
+        }
         return changed;
     }
 
@@ -17153,6 +16977,7 @@
             mSettings.editPersistentPreferredActivitiesLPw(userId).addFilter(
                     new PersistentPreferredActivity(filter, activity));
             scheduleWritePackageRestrictionsLocked(userId);
+            postPreferredActivityChangedBroadcast(userId);
         }
     }
 
@@ -17195,6 +17020,7 @@
 
             if (changed) {
                 scheduleWritePackageRestrictionsLocked(userId);
+                postPreferredActivityChangedBroadcast(userId);
             }
         }
     }
@@ -18187,6 +18013,7 @@
         public static final int DUMP_DOMAIN_PREFERRED = 1 << 18;
         public static final int DUMP_FROZEN = 1 << 19;
         public static final int DUMP_DEXOPT = 1 << 20;
+        public static final int DUMP_COMPILER_STATS = 1 << 21;
 
         public static final int OPTION_SHOW_FILTERS = 1 << 0;
 
@@ -18304,6 +18131,7 @@
                 pw.println("    installs: details about install sessions");
                 pw.println("    check-permission <permission> <package> [<user>]: does pkg hold perm?");
                 pw.println("    dexopt: dump dexopt state");
+                pw.println("    compiler-stats: dump compiler statistics");
                 pw.println("    <package.name>: info about given package");
                 return;
             } else if ("--checkin".equals(opt)) {
@@ -18425,6 +18253,8 @@
                 dumpState.setDump(DumpState.DUMP_FROZEN);
             } else if ("dexopt".equals(cmd)) {
                 dumpState.setDump(DumpState.DUMP_DEXOPT);
+            } else if ("compiler-stats".equals(cmd)) {
+                dumpState.setDump(DumpState.DUMP_COMPILER_STATS);
             } else if ("write".equals(cmd)) {
                 synchronized (mPackages) {
                     mSettings.writeLPr();
@@ -18787,6 +18617,11 @@
                 dumpDexoptStateLPr(pw, packageName);
             }
 
+            if (!checkin && dumpState.isDumping(DumpState.DUMP_COMPILER_STATS)) {
+                if (dumpState.onTitlePrinted()) pw.println();
+                dumpCompilerStatsLPr(pw, packageName);
+            }
+
             if (!checkin && dumpState.isDumping(DumpState.DUMP_MESSAGES) && packageName == null) {
                 if (dumpState.onTitlePrinted()) pw.println();
                 mSettings.dumpReadMessagesLPr(pw, dumpState);
@@ -18851,6 +18686,38 @@
         }
     }
 
+    private void dumpCompilerStatsLPr(PrintWriter pw, String packageName) {
+        final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ", 120);
+        ipw.println();
+        ipw.println("Compiler stats:");
+        ipw.increaseIndent();
+        Collection<PackageParser.Package> packages = null;
+        if (packageName != null) {
+            PackageParser.Package targetPackage = mPackages.get(packageName);
+            if (targetPackage != null) {
+                packages = Collections.singletonList(targetPackage);
+            } else {
+                ipw.println("Unable to find package: " + packageName);
+                return;
+            }
+        } else {
+            packages = mPackages.values();
+        }
+
+        for (PackageParser.Package pkg : packages) {
+            ipw.println("[" + pkg.packageName + "]");
+            ipw.increaseIndent();
+
+            CompilerStats.PackageStats stats = getCompilerPackageStats(pkg.packageName);
+            if (stats == null) {
+                ipw.println("(No recorded stats)");
+            } else {
+                stats.dump(ipw);
+            }
+            ipw.decreaseIndent();
+        }
+    }
+
     private String dumpDomainString(String packageName) {
         List<IntentFilterVerificationInfo> iviList = getIntentFilterVerifications(packageName)
                 .getList();
@@ -21012,4 +20879,20 @@
         msg.setData(data);
         mProcessLoggingHandler.sendMessage(msg);
     }
+
+    public CompilerStats.PackageStats getCompilerPackageStats(String pkgName) {
+        return mCompilerStats.getPackageStats(pkgName);
+    }
+
+    public CompilerStats.PackageStats getOrCreateCompilerPackageStats(PackageParser.Package pkg) {
+        return getOrCreateCompilerPackageStats(pkg.packageName);
+    }
+
+    public CompilerStats.PackageStats getOrCreateCompilerPackageStats(String pkgName) {
+        return mCompilerStats.getOrCreatePackageStats(pkgName);
+    }
+
+    public void deleteCompilerPackageStats(String pkgName) {
+        mCompilerStats.deletePackageStats(pkgName);
+    }
 }
diff --git a/services/core/java/com/android/server/pm/PackageUsage.java b/services/core/java/com/android/server/pm/PackageUsage.java
new file mode 100644
index 0000000..ac1f739
--- /dev/null
+++ b/services/core/java/com/android/server/pm/PackageUsage.java
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2016 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.server.pm;
+
+import static android.os.Process.PACKAGE_INFO_GID;
+import static android.os.Process.SYSTEM_UID;
+
+import android.content.pm.PackageManager;
+import android.content.pm.PackageParser;
+import android.os.FileUtils;
+import android.util.AtomicFile;
+import android.util.Log;
+
+import libcore.io.IoUtils;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.Map;
+
+class PackageUsage extends AbstractStatsBase<Map<String, PackageParser.Package>> {
+
+    private static final String USAGE_FILE_MAGIC = "PACKAGE_USAGE__VERSION_";
+    private static final String USAGE_FILE_MAGIC_VERSION_1 = USAGE_FILE_MAGIC + "1";
+
+    private boolean mIsHistoricalPackageUsageAvailable = true;
+
+    PackageUsage() {
+        super("package-usage.list", "PackageUsage_DiskWriter", /* lock */ true);
+    }
+
+    boolean isHistoricalPackageUsageAvailable() {
+        return mIsHistoricalPackageUsageAvailable;
+    }
+
+    @Override
+    protected void writeInternal(Map<String, PackageParser.Package> packages) {
+        AtomicFile file = getFile();
+        FileOutputStream f = null;
+        try {
+            f = file.startWrite();
+            BufferedOutputStream out = new BufferedOutputStream(f);
+            FileUtils.setPermissions(file.getBaseFile().getPath(),
+                    0640, SYSTEM_UID, PACKAGE_INFO_GID);
+            StringBuilder sb = new StringBuilder();
+
+            sb.append(USAGE_FILE_MAGIC_VERSION_1);
+            sb.append('\n');
+            out.write(sb.toString().getBytes(StandardCharsets.US_ASCII));
+
+            for (PackageParser.Package pkg : packages.values()) {
+                if (pkg.getLatestPackageUseTimeInMills() == 0L) {
+                    continue;
+                }
+                sb.setLength(0);
+                sb.append(pkg.packageName);
+                for (long usageTimeInMillis : pkg.mLastPackageUsageTimeInMills) {
+                    sb.append(' ');
+                    sb.append(usageTimeInMillis);
+                }
+                sb.append('\n');
+                out.write(sb.toString().getBytes(StandardCharsets.US_ASCII));
+            }
+            out.flush();
+            file.finishWrite(f);
+        } catch (IOException e) {
+            if (f != null) {
+                file.failWrite(f);
+            }
+            Log.e(PackageManagerService.TAG, "Failed to write package usage times", e);
+        }
+    }
+
+    @Override
+    protected void readInternal(Map<String, PackageParser.Package> packages) {
+        AtomicFile file = getFile();
+        BufferedInputStream in = null;
+        try {
+            in = new BufferedInputStream(file.openRead());
+            StringBuffer sb = new StringBuffer();
+
+            String firstLine = readLine(in, sb);
+            if (firstLine == null) {
+                // Empty file. Do nothing.
+            } else if (USAGE_FILE_MAGIC_VERSION_1.equals(firstLine)) {
+                readVersion1LP(packages, in, sb);
+            } else {
+                readVersion0LP(packages, in, sb, firstLine);
+            }
+        } catch (FileNotFoundException expected) {
+            mIsHistoricalPackageUsageAvailable = false;
+        } catch (IOException e) {
+            Log.w(PackageManagerService.TAG, "Failed to read package usage times", e);
+        } finally {
+            IoUtils.closeQuietly(in);
+        }
+    }
+
+    private void readVersion0LP(Map<String, PackageParser.Package> packages, InputStream in,
+            StringBuffer sb, String firstLine)
+            throws IOException {
+        // Initial version of the file had no version number and stored one
+        // package-timestamp pair per line.
+        // Note that the first line has already been read from the InputStream.
+        for (String line = firstLine; line != null; line = readLine(in, sb)) {
+            String[] tokens = line.split(" ");
+            if (tokens.length != 2) {
+                throw new IOException("Failed to parse " + line +
+                        " as package-timestamp pair.");
+            }
+
+            String packageName = tokens[0];
+            PackageParser.Package pkg = packages.get(packageName);
+            if (pkg == null) {
+                continue;
+            }
+
+            long timestamp = parseAsLong(tokens[1]);
+            for (int reason = 0;
+                    reason < PackageManager.NOTIFY_PACKAGE_USE_REASONS_COUNT;
+                    reason++) {
+                pkg.mLastPackageUsageTimeInMills[reason] = timestamp;
+            }
+        }
+    }
+
+    private void readVersion1LP(Map<String, PackageParser.Package> packages, InputStream in,
+            StringBuffer sb) throws IOException {
+        // Version 1 of the file started with the corresponding version
+        // number and then stored a package name and eight timestamps per line.
+        String line;
+        while ((line = readLine(in, sb)) != null) {
+            String[] tokens = line.split(" ");
+            if (tokens.length != PackageManager.NOTIFY_PACKAGE_USE_REASONS_COUNT + 1) {
+                throw new IOException("Failed to parse " + line + " as a timestamp array.");
+            }
+
+            String packageName = tokens[0];
+            PackageParser.Package pkg = packages.get(packageName);
+            if (pkg == null) {
+                continue;
+            }
+
+            for (int reason = 0;
+                    reason < PackageManager.NOTIFY_PACKAGE_USE_REASONS_COUNT;
+                    reason++) {
+                pkg.mLastPackageUsageTimeInMills[reason] = parseAsLong(tokens[reason + 1]);
+            }
+        }
+    }
+
+    private long parseAsLong(String token) throws IOException {
+        try {
+            return Long.parseLong(token);
+        } catch (NumberFormatException e) {
+            throw new IOException("Failed to parse " + token + " as a long.", e);
+        }
+    }
+
+    private String readLine(InputStream in, StringBuffer sb) throws IOException {
+        return readToken(in, sb, '\n');
+    }
+
+    private String readToken(InputStream in, StringBuffer sb, char endOfToken)
+            throws IOException {
+        sb.setLength(0);
+        while (true) {
+            int ch = in.read();
+            if (ch == -1) {
+                if (sb.length() == 0) {
+                    return null;
+                }
+                throw new IOException("Unexpected EOF");
+            }
+            if (ch == endOfToken) {
+                return sb.toString();
+            }
+            sb.append((char)ch);
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index b94d0f0..3c18198 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -34,6 +34,7 @@
 import com.android.internal.util.Preconditions;
 import com.android.internal.util.XmlUtils;
 import com.android.server.pm.ShortcutService.ShortcutOperation;
+import com.android.server.pm.ShortcutService.Stats;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -437,8 +438,6 @@
      * locale changes.
      */
     public int getApiCallCount() {
-        mShortcutUser.resetThrottlingIfNeeded();
-
         final ShortcutService s = mShortcutUser.mService;
 
         // Reset the counter if:
@@ -598,7 +597,37 @@
     }
 
     /**
-     * Called when the package is updated or added.
+     * @return false if any of the target activities are no longer enabled.
+     */
+    private boolean areAllActivitiesStillEnabled() {
+        if (mShortcuts.size() == 0) {
+            return true;
+        }
+        final ShortcutService s = mShortcutUser.mService;
+
+        // Normally the number of target activities is 1 or so, so no need to use a complex
+        // structure like a set.
+        final ArrayList<ComponentName> checked = new ArrayList<>(4);
+
+        for (int i = mShortcuts.size() - 1; i >= 0; i--) {
+            final ShortcutInfo si = mShortcuts.valueAt(i);
+            final ComponentName activity = si.getActivity();
+
+            if (checked.contains(activity)) {
+                continue; // Already checked.
+            }
+            checked.add(activity);
+
+            if (!s.injectIsActivityEnabledAndExported(activity, getOwnerUserId())) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Called when the package may be added or updated, or its activities may be disabled, and
+     * if so, rescan the package and do the necessary stuff.
      *
      * Add case:
      * - Publish manifest shortcuts.
@@ -606,23 +635,35 @@
      * Update case:
      * - Re-publish manifest shortcuts.
      * - If there are shortcuts with resources (icons or strings), update their timestamps.
+     * - Disable shortcuts whose target activities are disabled.
      *
      * @return TRUE if any shortcuts have been changed.
      */
-    public boolean handlePackageAddedOrUpdated(boolean isNewApp, boolean forceRescan) {
-        final PackageInfo pi = mShortcutUser.mService.getPackageInfo(
-                getPackageName(), getPackageUserId());
-        if (pi == null) {
-            return false; // Shouldn't happen.
-        }
+    public boolean rescanPackageIfNeeded(boolean isNewApp, boolean forceRescan) {
+        final ShortcutService s = mShortcutUser.mService;
+        final long start = s.injectElapsedRealtime();
 
-        if (!isNewApp && !forceRescan) {
-            // Make sure the version code or last update time has changed.
-            // Otherwise, nothing to do.
-            if (getPackageInfo().getVersionCode() >= pi.versionCode
-                    && getPackageInfo().getLastUpdateTime() >= pi.lastUpdateTime) {
-                return false;
+        final PackageInfo pi;
+        try {
+            pi = mShortcutUser.mService.getPackageInfo(
+                    getPackageName(), getPackageUserId());
+            if (pi == null) {
+                return false; // Shouldn't happen.
             }
+
+            if (!isNewApp && !forceRescan) {
+                // Return if the package hasn't changed, ie:
+                // - version code hasn't change
+                // - lastUpdateTime hasn't change
+                // - all target activities are still enabled.
+                if ((getPackageInfo().getVersionCode() >= pi.versionCode)
+                        && (getPackageInfo().getLastUpdateTime() >= pi.lastUpdateTime)
+                        && areAllActivitiesStillEnabled()) {
+                    return false;
+                }
+            }
+        } finally {
+            s.logDurationStat(Stats.PACKAGE_UPDATE_CHECK, start);
         }
 
         // Now prepare to publish manifest shortcuts.
@@ -654,8 +695,6 @@
 
         getPackageInfo().updateVersionInfo(pi);
 
-        final ShortcutService s = mShortcutUser.mService;
-
         boolean changed = false;
 
         // For existing shortcuts, update timestamps if they have any resources.
@@ -1001,7 +1040,7 @@
             }
         }
         if (changed) {
-            s.scheduleSaveUser(getPackageUserId());
+            s.packageShortcutsChanged(getPackageName(), getPackageUserId());
         }
     }
 
diff --git a/services/core/java/com/android/server/pm/ShortcutPackageItem.java b/services/core/java/com/android/server/pm/ShortcutPackageItem.java
index 757dd19..26b52e9 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackageItem.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackageItem.java
@@ -48,6 +48,10 @@
         mPackageInfo = Preconditions.checkNotNull(packageInfo);
     }
 
+    public ShortcutUser getUser() {
+        return mShortcutUser;
+    }
+
     /**
      * ID of the user who actually has this package running on.  For {@link ShortcutPackage},
      * this is the same thing as {@link #getOwnerUserId}, but if it's a {@link ShortcutLauncher} and
diff --git a/services/core/java/com/android/server/pm/ShortcutParser.java b/services/core/java/com/android/server/pm/ShortcutParser.java
index 0762c0b..3f302d6 100644
--- a/services/core/java/com/android/server/pm/ShortcutParser.java
+++ b/services/core/java/com/android/server/pm/ShortcutParser.java
@@ -29,6 +29,7 @@
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.Slog;
+import android.util.TypedValue;
 import android.util.Xml;
 
 import com.android.internal.R;
@@ -260,7 +261,12 @@
         final TypedArray sa = service.mContext.getResources().obtainAttributes(attrs,
                 R.styleable.ShortcutCategories);
         try {
-            return sa.getString(R.styleable.ShortcutCategories_name);
+            if (sa.getType(R.styleable.ShortcutCategories_name) == TypedValue.TYPE_STRING) {
+                return sa.getNonResourceString(R.styleable.ShortcutCategories_name);
+            } else {
+                Log.w(TAG, "android:name for shortcut category must be string literal.");
+                return null;
+            }
         } finally {
             sa.recycle();
         }
@@ -272,7 +278,11 @@
         final TypedArray sa = service.mContext.getResources().obtainAttributes(attrs,
                 R.styleable.Shortcut);
         try {
-            final String id = sa.getString(R.styleable.Shortcut_shortcutId);
+            if (sa.getType(R.styleable.Shortcut_shortcutId) != TypedValue.TYPE_STRING) {
+                Log.w(TAG, "android:shortcutId must be string literal. activity=" + activity);
+                return null;
+            }
+            final String id = sa.getNonResourceString(R.styleable.Shortcut_shortcutId);
             final boolean enabled = sa.getBoolean(R.styleable.Shortcut_enabled, true);
             final int iconResId = sa.getResourceId(R.styleable.Shortcut_icon, 0);
             final int titleResId = sa.getResourceId(R.styleable.Shortcut_shortcutShortLabel, 0);
@@ -281,11 +291,11 @@
                     R.styleable.Shortcut_shortcutDisabledMessage, 0);
 
             if (TextUtils.isEmpty(id)) {
-                Slog.w(TAG, "Shortcut ID must be provided. activity=" + activity);
+                Log.w(TAG, "android:shortcutId must be provided. activity=" + activity);
                 return null;
             }
             if (titleResId == 0) {
-                Slog.w(TAG, "Shortcut title must be provided. activity=" + activity);
+                Log.w(TAG, "android:shortcutShortLabel must be provided. activity=" + activity);
                 return null;
             }
 
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 730217d..10f1b4b 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -24,9 +24,11 @@
 import android.app.AppGlobals;
 import android.app.IUidObserver;
 import android.app.usage.UsageStatsManagerInternal;
+import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
@@ -49,10 +51,12 @@
 import android.graphics.Canvas;
 import android.graphics.RectF;
 import android.graphics.drawable.Icon;
+import android.net.Uri;
 import android.os.Binder;
 import android.os.Environment;
 import android.os.FileUtils;
 import android.os.Handler;
+import android.os.LocaleList;
 import android.os.Looper;
 import android.os.ParcelFileDescriptor;
 import android.os.PersistableBundle;
@@ -116,15 +120,11 @@
 import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicLong;
 import java.util.function.Consumer;
 import java.util.function.Predicate;
 
 /**
  * TODO:
- * - Deal with the async nature of PACKAGE_ADD.  Basically when a publisher does anything after
- *   it's upgraded, the manager should make sure the upgrade process has been executed.
- *
  * - getIconMaxWidth()/getIconMaxHeight() should use xdpi and ydpi.
  *   -> But TypedValue.applyDimension() doesn't differentiate x and y..?
  *
@@ -179,7 +179,6 @@
 
     private static final String TAG_ROOT = "root";
     private static final String TAG_LAST_RESET_TIME = "last_reset_time";
-    private static final String TAG_LOCALE_CHANGE_SEQUENCE_NUMBER = "locale_seq_no";
 
     private static final String ATTR_VALUE = "value";
 
@@ -292,16 +291,6 @@
     @GuardedBy("mLock")
     private List<Integer> mDirtyUserIds = new ArrayList<>();
 
-    /**
-     * A counter that increments every time the system locale changes.  We keep track of it to
-     * reset
-     * throttling counters on the first call from each package after the last locale change.
-     *
-     * We need this mechanism because we can't do much in the locale change callback, which is
-     * {@link ShortcutServiceInternal#onSystemLocaleChangedNoLock()}.
-     */
-    private final AtomicLong mLocaleChangeSequenceNumber = new AtomicLong();
-
     private final AtomicBoolean mBootCompleted = new AtomicBoolean();
 
     private static final int PACKAGE_MATCH_FLAGS =
@@ -326,8 +315,9 @@
         int GET_LAUNCHER_ACTIVITY = 11;
         int CHECK_LAUNCHER_ACTIVITY = 12;
         int IS_ACTIVITY_ENABLED = 13;
+        int PACKAGE_UPDATE_CHECK = 14;
 
-        int COUNT = IS_ACTIVITY_ENABLED + 1;
+        int COUNT = PACKAGE_UPDATE_CHECK + 1;
     }
 
     final Object mStatLock = new Object();
@@ -381,7 +371,31 @@
             return; // Don't do anything further.  For unit tests only.
         }
 
-        mPackageMonitor.register(context, looper, UserHandle.ALL, /* externalStorage= */ false);
+        // Register receivers.
+
+        // We need to set a priority, so let's just not use PackageMonitor for now.
+        // TODO Refactor PackageMonitor to support priorities.
+        final IntentFilter packageFilter = new IntentFilter();
+        packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
+        packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+        packageFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
+        packageFilter.addAction(Intent.ACTION_PACKAGE_DATA_CLEARED);
+        packageFilter.addDataScheme("package");
+        packageFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
+        mContext.registerReceiverAsUser(mPackageMonitor, UserHandle.ALL,
+                packageFilter, null, mHandler);
+
+        final IntentFilter preferedActivityFilter = new IntentFilter();
+        preferedActivityFilter.addAction(Intent.ACTION_PREFERRED_ACTIVITY_CHANGED);
+        preferedActivityFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
+        mContext.registerReceiverAsUser(mPackageMonitor, UserHandle.ALL,
+                preferedActivityFilter, null, mHandler);
+
+        final IntentFilter localeFilter = new IntentFilter();
+        localeFilter.addAction(Intent.ACTION_LOCALE_CHANGED);
+        localeFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
+        mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL,
+                localeFilter, null, mHandler);
 
         injectRegisterUidObserver(mUidObserver, ActivityManager.UID_OBSERVER_PROCSTATE
                 | ActivityManager.UID_OBSERVER_GONE);
@@ -394,8 +408,9 @@
         }
     }
 
-    public long getLocaleChangeSequenceNumber() {
-        return mLocaleChangeSequenceNumber.get();
+    public String injectGetLocaleTagsForUser(@UserIdInt int userId) {
+        // TODO This should get the per-user locale.  b/30123329 b/30119489
+        return LocaleList.getDefault().toLanguageTags();
     }
 
     final private IUidObserver mUidObserver = new IUidObserver.Stub() {
@@ -504,8 +519,11 @@
             Slog.d(TAG, "handleUnlockUser: user=" + userId);
         }
         synchronized (mLock) {
-            // Preload
-            getUserShortcutsLocked(userId);
+            // Preload the user's shortcuts.
+            // Also see if the locale has changed.
+            // Note as of nyc, the locale is per-user, so the locale shouldn't change
+            // when the user is locked.  However due to b/30119489 it still happens.
+            getUserShortcutsLocked(userId).detectLocaleChange();
 
             checkPackageChanges(userId);
         }
@@ -751,8 +769,6 @@
 
             // Body.
             writeTagValue(out, TAG_LAST_RESET_TIME, mRawLastResetTime);
-            writeTagValue(out, TAG_LOCALE_CHANGE_SEQUENCE_NUMBER,
-                    mLocaleChangeSequenceNumber.get());
 
             // Epilogue.
             out.endTag(null, TAG_ROOT);
@@ -797,9 +813,6 @@
                     case TAG_LAST_RESET_TIME:
                         mRawLastResetTime = parseLongAttribute(parser, ATTR_VALUE);
                         break;
-                    case TAG_LOCALE_CHANGE_SEQUENCE_NUMBER:
-                        mLocaleChangeSequenceNumber.set(parseLongAttribute(parser, ATTR_VALUE));
-                        break;
                     default:
                         Slog.e(TAG, "Invalid tag: " + tag);
                         break;
@@ -1501,6 +1514,7 @@
 
         synchronized (mLock) {
             final ShortcutPackage ps = getPackageShortcutsLocked(packageName, userId);
+            ps.getUser().onCalledByPublisher(packageName);
 
             ps.ensureImmutableShortcutsNotIncluded(newShortcuts);
 
@@ -1550,6 +1564,7 @@
 
         synchronized (mLock) {
             final ShortcutPackage ps = getPackageShortcutsLocked(packageName, userId);
+            ps.getUser().onCalledByPublisher(packageName);
 
             ps.ensureImmutableShortcutsNotIncluded(newShortcuts);
 
@@ -1628,6 +1643,7 @@
 
         synchronized (mLock) {
             final ShortcutPackage ps = getPackageShortcutsLocked(packageName, userId);
+            ps.getUser().onCalledByPublisher(packageName);
 
             ps.ensureImmutableShortcutsNotIncluded(newShortcuts);
 
@@ -1675,6 +1691,7 @@
 
         synchronized (mLock) {
             final ShortcutPackage ps = getPackageShortcutsLocked(packageName, userId);
+            ps.getUser().onCalledByPublisher(packageName);
 
             ps.ensureImmutableShortcutsNotIncludedWithIds((List<String>) shortcutIds);
 
@@ -1702,6 +1719,7 @@
 
         synchronized (mLock) {
             final ShortcutPackage ps = getPackageShortcutsLocked(packageName, userId);
+            ps.getUser().onCalledByPublisher(packageName);
 
             ps.ensureImmutableShortcutsNotIncludedWithIds((List<String>) shortcutIds);
 
@@ -1722,6 +1740,7 @@
 
         synchronized (mLock) {
             final ShortcutPackage ps = getPackageShortcutsLocked(packageName, userId);
+            ps.getUser().onCalledByPublisher(packageName);
 
             ps.ensureImmutableShortcutsNotIncludedWithIds((List<String>) shortcutIds);
 
@@ -1743,7 +1762,9 @@
         verifyCaller(packageName, userId);
 
         synchronized (mLock) {
-            getPackageShortcutsLocked(packageName, userId).deleteAllDynamicShortcuts();
+            final ShortcutPackage ps = getPackageShortcutsLocked(packageName, userId);
+            ps.getUser().onCalledByPublisher(packageName);
+            ps.deleteAllDynamicShortcuts();
         }
         packageShortcutsChanged(packageName, userId);
 
@@ -1788,7 +1809,9 @@
 
         final ArrayList<ShortcutInfo> ret = new ArrayList<>();
 
-        getPackageShortcutsLocked(packageName, userId).findAll(ret, query, cloneFlags);
+        final ShortcutPackage ps = getPackageShortcutsLocked(packageName, userId);
+        ps.getUser().onCalledByPublisher(packageName);
+        ps.findAll(ret, query, cloneFlags);
 
         return new ParceledListSlice<>(ret);
     }
@@ -1806,8 +1829,9 @@
         verifyCaller(packageName, userId);
 
         synchronized (mLock) {
-            return mMaxUpdatesPerInterval
-                    - getPackageShortcutsLocked(packageName, userId).getApiCallCount();
+            final ShortcutPackage ps = getPackageShortcutsLocked(packageName, userId);
+            ps.getUser().onCalledByPublisher(packageName);
+            return mMaxUpdatesPerInterval - ps.getApiCallCount();
         }
     }
 
@@ -1842,6 +1866,8 @@
 
         synchronized (mLock) {
             final ShortcutPackage ps = getPackageShortcutsLocked(packageName, userId);
+            ps.getUser().onCalledByPublisher(packageName);
+
             if (ps.findShortcutById(shortcutId) == null) {
                 Log.w(TAG, String.format("reportShortcutUsed: package %s doesn't have shortcut %s",
                         packageName, shortcutId));
@@ -1903,7 +1929,12 @@
 
     // We override this method in unit tests to do a simpler check.
     boolean hasShortcutHostPermission(@NonNull String callingPackage, int userId) {
-        return hasShortcutHostPermissionInner(callingPackage, userId);
+        final long start = injectElapsedRealtime();
+        try {
+            return hasShortcutHostPermissionInner(callingPackage, userId);
+        } finally {
+            logDurationStat(Stats.LAUNCHER_PERMISSION_CHECK, start);
+        }
     }
 
     // This method is extracted so we can directly call this method from unit tests,
@@ -1911,15 +1942,22 @@
     @VisibleForTesting
     boolean hasShortcutHostPermissionInner(@NonNull String callingPackage, int userId) {
         synchronized (mLock) {
-            final long start = injectElapsedRealtime();
-
             final ShortcutUser user = getUserShortcutsLocked(userId);
 
+            // Always trust the in-memory cache.
+            final ComponentName cached = user.getCachedLauncher();
+            if (cached != null) {
+                if (cached.getPackageName().equals(callingPackage)) {
+                    return true;
+                }
+            }
+            // If the cached one doesn't match, then go ahead
+
             final List<ResolveInfo> allHomeCandidates = new ArrayList<>();
 
             // Default launcher from package manager.
             final long startGetHomeActivitiesAsUser = injectElapsedRealtime();
-            final ComponentName defaultLauncher = injectPackageManagerInternal()
+            final ComponentName defaultLauncher = mPackageManagerInternal
                     .getHomeActivitiesAsUser(allHomeCandidates, userId);
             logDurationStat(Stats.GET_DEFAULT_HOME, startGetHomeActivitiesAsUser);
 
@@ -1930,7 +1968,7 @@
                     Slog.v(TAG, "Default launcher from PM: " + detected);
                 }
             } else {
-                detected = user.getDefaultLauncherComponent();
+                detected = user.getLastKnownLauncher();
 
                 if (detected != null) {
                     if (injectIsActivityEnabledAndExported(detected, userId)) {
@@ -1940,7 +1978,7 @@
                     } else {
                         Slog.w(TAG, "Cached launcher " + detected + " no longer exists");
                         detected = null;
-                        user.setDefaultLauncherComponent(null);
+                        user.clearLauncher();
                     }
                 }
             }
@@ -1971,13 +2009,13 @@
                     lastPriority = ri.priority;
                 }
             }
-            logDurationStat(Stats.LAUNCHER_PERMISSION_CHECK, start);
 
+            // Update the cache.
+            user.setLauncher(detected);
             if (detected != null) {
                 if (DEBUG) {
                     Slog.v(TAG, "Detected launcher: " + detected);
                 }
-                user.setDefaultLauncherComponent(detected);
                 return detected.getPackageName().equals(callingPackage);
             } else {
                 // Default launcher not found.
@@ -2039,7 +2077,7 @@
         if (appStillExists && (packageUserId == owningUserId)) {
             // This will do the notification and save when needed, so do it after the above
             // notifyListeners.
-            user.handlePackageAddedOrUpdated(packageName, /* forceRescan=*/ true);
+            user.rescanPackageIfNeeded(packageName, /* forceRescan=*/ true);
         }
 
         if (!wasUserLoaded) {
@@ -2282,36 +2320,19 @@
                 @NonNull String callingPackage) {
             return ShortcutService.this.hasShortcutHostPermission(callingPackage, launcherUserId);
         }
+    }
 
-        /**
-         * Called by AM when the system locale changes *within the AM lock.  ABSOLUTELY do not take
-         * any locks in this method.
-         */
+    final BroadcastReceiver mReceiver = new BroadcastReceiver() {
         @Override
-        public void onSystemLocaleChangedNoLock() {
-            // DO NOT HOLD ANY LOCKS HERE.
-
-            // We want to reset throttling for all packages for all users.  But we can't just do so
-            // here because:
-            // - We can't load/save users that are locked.
-            // - Even for loaded users, resetting the counters would require us to hold mLock.
-            //
-            // So we use a "pull" model instead.  In here, we just increment the "locale change
-            // sequence number".  Each ShortcutUser has the "last known locale change sequence".
-            //
-            // This allows ShortcutUser's to detect the system locale change, so they can reset
-            // counters.
-
-            // Ignore all callback during system boot.
-            if (mBootCompleted.get()) {
-                mLocaleChangeSequenceNumber.incrementAndGet();
-                if (DEBUG) {
-                    Slog.d(TAG, "onSystemLocaleChangedNoLock: " + mLocaleChangeSequenceNumber.get());
-                }
-                injectPostToHandler(() -> handleLocaleChanged());
+        public void onReceive(Context context, Intent intent) {
+            if (!mBootCompleted.get()) {
+                return; // Boot not completed, ignore the broadcast.
+            }
+            if (Intent.ACTION_LOCALE_CHANGED.equals(intent.getAction())) {
+                handleLocaleChanged();
             }
         }
-    }
+    };
 
     void handleLocaleChanged() {
         if (DEBUG) {
@@ -2321,7 +2342,7 @@
 
         final long token = injectClearCallingIdentity();
         try {
-            forEachLoadedUserLocked(u -> u.forAllPackages(p -> p.resolveResourceStrings()));
+            forEachLoadedUserLocked(user -> user.detectLocaleChange());
         } finally {
             injectRestoreCallingIdentity(token);
         }
@@ -2331,53 +2352,76 @@
      * Package event callbacks.
      */
     @VisibleForTesting
-    final PackageMonitor mPackageMonitor = new PackageMonitor() {
-
-        private boolean isUserUnlocked() {
-            return mUserManager.isUserUnlocked(getChangingUserId());
-        }
-
+    final BroadcastReceiver mPackageMonitor = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
-            // clearCallingIdentity is not needed normally, but need to do it for the unit test.
+            final int userId  = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
+            if (userId == UserHandle.USER_NULL) {
+                Slog.w(TAG, "Intent broadcast does not contain user handle: " + intent);
+                return;
+            }
+
+            final String action = intent.getAction();
+
+            // This is normally called on Handler, so clearCallingIdentity() isn't needed,
+            // but we still check it in unit tests.
             final long token = injectClearCallingIdentity();
             try {
-                super.onReceive(context, intent);
+
+                if (!mUserManager.isUserUnlocked(userId)) {
+                    if (DEBUG) {
+                        Slog.d(TAG, "Ignoring package broadcast " + action
+                                + " for locked/stopped user " + userId);
+                    }
+                    return;
+                }
+
+                // Whenever we get one of those package broadcasts, or get
+                // ACTION_PREFERRED_ACTIVITY_CHANGED, we purge the default launcher cache.
+                synchronized (mLock) {
+                    final ShortcutUser user = getUserShortcutsLocked(userId);
+                    user.clearLauncher();
+                }
+                if (Intent.ACTION_PREFERRED_ACTIVITY_CHANGED.equals(action)) {
+                    // Nothing farther to do.
+                    return;
+                }
+
+                final Uri intentUri = intent.getData();
+                final String packageName = (intentUri != null) ? intentUri.getSchemeSpecificPart()
+                        : null;
+                if (packageName == null) {
+                    Slog.w(TAG, "Intent broadcast does not contain package name: " + intent);
+                    return;
+                }
+
+                final boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
+
+                switch (action) {
+                    case Intent.ACTION_PACKAGE_ADDED:
+                        if (replacing) {
+                            handlePackageUpdateFinished(packageName, userId);
+                        } else {
+                            handlePackageAdded(packageName, userId);
+                        }
+                        break;
+                    case Intent.ACTION_PACKAGE_REMOVED:
+                        if (!replacing) {
+                            handlePackageRemoved(packageName, userId);
+                        }
+                        break;
+                    case Intent.ACTION_PACKAGE_CHANGED:
+                        handlePackageChanged(packageName, userId);
+
+                        break;
+                    case Intent.ACTION_PACKAGE_DATA_CLEARED:
+                        handlePackageDataCleared(packageName, userId);
+                        break;
+                }
             } finally {
                 injectRestoreCallingIdentity(token);
             }
         }
-
-        @Override
-        public void onPackageAdded(String packageName, int uid) {
-            if (!isUserUnlocked()) return;
-            handlePackageAdded(packageName, getChangingUserId());
-        }
-
-        @Override
-        public void onPackageUpdateFinished(String packageName, int uid) {
-            if (!isUserUnlocked()) return;
-            handlePackageUpdateFinished(packageName, getChangingUserId());
-        }
-
-        @Override
-        public void onPackageRemoved(String packageName, int uid) {
-            if (!isUserUnlocked()) return;
-            handlePackageRemoved(packageName, getChangingUserId());
-        }
-
-        @Override
-        public void onPackageDataCleared(String packageName, int uid) {
-            if (!isUserUnlocked()) return;
-            handlePackageDataCleared(packageName, getChangingUserId());
-        }
-
-        @Override
-        public boolean onPackageChanged(String packageName, int uid, String[] components) {
-            if (!isUserUnlocked()) return false;
-            handlePackageChanged(packageName, getChangingUserId());
-            return false; // We don't need to receive onSomePackagesChanged(), so just false.
-        }
     };
 
     /**
@@ -2427,7 +2471,7 @@
 
                 // Then for each installed app, publish manifest shortcuts when needed.
                 forUpdatedPackages(ownerUserId, user.getLastAppScanTime(), ai -> {
-                    user.handlePackageAddedOrUpdated(ai.packageName, /* forceRescan=*/ false);
+                    user.rescanPackageIfNeeded(ai.packageName, /* forceRescan=*/ false);
                 });
 
                 // Write the time just before the scan, because there may be apps that have just
@@ -2448,7 +2492,7 @@
         synchronized (mLock) {
             final ShortcutUser user = getUserShortcutsLocked(userId);
             user.attemptToRestoreIfNeededAndSave(this, packageName, userId);
-            user.handlePackageAddedOrUpdated(packageName, /* forceRescan=*/ false);
+            user.rescanPackageIfNeeded(packageName, /* forceRescan=*/ false);
         }
         verifyStates();
     }
@@ -2463,7 +2507,7 @@
             user.attemptToRestoreIfNeededAndSave(this, packageName, userId);
 
             if (isPackageInstalled(packageName, userId)) {
-                user.handlePackageAddedOrUpdated(packageName, /* forceRescan=*/ false);
+                user.rescanPackageIfNeeded(packageName, /* forceRescan=*/ false);
             }
         }
         verifyStates();
@@ -2499,7 +2543,7 @@
         synchronized (mLock) {
             final ShortcutUser user = getUserShortcutsLocked(packageUserId);
 
-            user.handlePackageAddedOrUpdated(packageName, /* forceRescan=*/ true);
+            user.rescanPackageIfNeeded(packageName, /* forceRescan=*/ true);
         }
 
         verifyStates();
@@ -2975,10 +3019,6 @@
             pw.print("] ");
             pw.print(formatTime(next));
 
-            pw.print("  Locale change seq#: ");
-            pw.print(mLocaleChangeSequenceNumber.get());
-            pw.println();
-
             pw.print("  Config:");
             pw.print("    Max icon dim: ");
             pw.println(mMaxIconDimension);
@@ -3014,6 +3054,7 @@
                 dumpStatLS(pw, p, Stats.GET_LAUNCHER_ACTIVITY, "getLauncherActivity");
                 dumpStatLS(pw, p, Stats.CHECK_LAUNCHER_ACTIVITY, "checkLauncherActivity");
                 dumpStatLS(pw, p, Stats.IS_ACTIVITY_ENABLED, "isActivityEnabled");
+                dumpStatLS(pw, p, Stats.PACKAGE_UPDATE_CHECK, "packageUpdateCheck");
             }
 
             pw.println();
@@ -3248,7 +3289,7 @@
 
         private void clearLauncher() {
             synchronized (mLock) {
-                getUserShortcutsLocked(mUserId).setDefaultLauncherComponent(null);
+                getUserShortcutsLocked(mUserId).forceClearLauncher();
             }
         }
 
@@ -3258,7 +3299,7 @@
                 hasShortcutHostPermissionInner("-", mUserId);
 
                 getOutPrintWriter().println("Launcher: "
-                        + getUserShortcutsLocked(mUserId).getDefaultLauncherComponent());
+                        + getUserShortcutsLocked(mUserId).getLastKnownLauncher());
             }
         }
 
@@ -3382,11 +3423,6 @@
         }
     }
 
-    @VisibleForTesting
-    PackageManagerInternal injectPackageManagerInternal() {
-        return mPackageManagerInternal;
-    }
-
     File getUserBitmapFilePath(@UserIdInt int userId) {
         return new File(injectUserDataPath(userId), DIRECTORY_BITMAPS);
     }
@@ -3470,7 +3506,7 @@
     }
 
     private void verifyStatesInner() {
-        synchronized (this) {
+        synchronized (mLock) {
             forEachLoadedUserLocked(u -> u.forAllPackageItems(ShortcutPackageItem::verifyStates));
         }
     }
diff --git a/services/core/java/com/android/server/pm/ShortcutUser.java b/services/core/java/com/android/server/pm/ShortcutUser.java
index 7ea89c9..3a43ece 100644
--- a/services/core/java/com/android/server/pm/ShortcutUser.java
+++ b/services/core/java/com/android/server/pm/ShortcutUser.java
@@ -19,6 +19,8 @@
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.content.ComponentName;
+import android.content.pm.ShortcutManager;
+import android.text.TextUtils;
 import android.text.format.Formatter;
 import android.util.ArrayMap;
 import android.util.Slog;
@@ -51,7 +53,7 @@
     private static final String TAG_LAUNCHER = "launcher";
 
     private static final String ATTR_VALUE = "value";
-    private static final String ATTR_KNOWN_LOCALE_CHANGE_SEQUENCE_NUMBER = "locale-seq-no";
+    private static final String ATTR_KNOWN_LOCALES = "locales";
     private static final String ATTR_LAST_APP_SCAN_TIME = "last-app-scan-time";
 
     static final class PackageWithUser {
@@ -101,10 +103,17 @@
 
     private final ArrayMap<PackageWithUser, ShortcutLauncher> mLaunchers = new ArrayMap<>();
 
-    /** Default launcher that can access the launcher apps APIs. */
-    private ComponentName mDefaultLauncherComponent;
+    /**
+     * Last known launcher.  It's used when the default launcher isn't set in PM -- i.e.
+     * when getHomeActivitiesAsUser() return null.  We need it so that in this situation the
+     * previously default launcher can still access shortcuts.
+     */
+    private ComponentName mLastKnownLauncher;
 
-    private long mKnownLocaleChangeSequenceNumber;
+    /** In-memory-cached default launcher. */
+    private ComponentName mCachedLauncher;
+
+    private String mKnownLocales;
 
     private long mLastAppScanTime;
 
@@ -225,29 +234,62 @@
     }
 
     /**
-     * Reset all throttling counters for all packages, if there has been a system locale change.
+     * Must be called at any entry points on {@link ShortcutManager} APIs to make sure the
+     * information on the package is up-to-date.
+     *
+     * We use broadcasts to handle locale changes and package changes, but because broadcasts
+     * are asynchronous, there's a chance a publisher calls getXxxShortcuts() after a certain event
+     * (e.g. system locale change) but shortcut manager hasn't finished processing the broadcast.
+     *
+     * So we call this method at all entry points from publishers to make sure we update all
+     * relevant information.
+     *
+     * Similar inconsistencies can happen when the launcher fetches shortcut information, but
+     * that's a less of an issue because for the launcher we report shortcut changes with
+     * callbacks.
      */
-    public void resetThrottlingIfNeeded() {
-        final long currentNo = mService.getLocaleChangeSequenceNumber();
-        if (mKnownLocaleChangeSequenceNumber < currentNo) {
-            if (ShortcutService.DEBUG) {
-                Slog.d(TAG, "LocaleChange detected for user " + mUserId);
-            }
-
-            mKnownLocaleChangeSequenceNumber = currentNo;
-
-            forAllPackages(p -> p.resetRateLimiting());
-
-            mService.scheduleSaveUser(mUserId);
-        }
+    public void onCalledByPublisher(@NonNull String packageName) {
+        detectLocaleChange();
+        rescanPackageIfNeeded(packageName, /*forceRescan=*/ false);
     }
 
-    public void handlePackageAddedOrUpdated(@NonNull String packageName, boolean forceRescan) {
+    private String getKnownLocales() {
+        if (TextUtils.isEmpty(mKnownLocales)) {
+            mKnownLocales = mService.injectGetLocaleTagsForUser(mUserId);
+            mService.scheduleSaveUser(mUserId);
+        }
+        return mKnownLocales;
+    }
+
+    /**
+     * Check to see if the system locale has changed, and if so, reset throttling
+     * and update resource strings.
+     */
+    public void detectLocaleChange() {
+        final String currentLocales = mService.injectGetLocaleTagsForUser(mUserId);
+        if (getKnownLocales().equals(currentLocales)) {
+            return;
+        }
+        if (ShortcutService.DEBUG) {
+            Slog.d(TAG, "Locale changed from " + currentLocales + " to " + mKnownLocales
+                    + " for user " + mUserId);
+        }
+        mKnownLocales = currentLocales;
+
+        forAllPackages(pkg -> {
+            pkg.resetRateLimiting();
+            pkg.resolveResourceStrings();
+        });
+
+        mService.scheduleSaveUser(mUserId);
+    }
+
+    public void rescanPackageIfNeeded(@NonNull String packageName, boolean forceRescan) {
         final boolean isNewApp = !mPackages.containsKey(packageName);
 
         final ShortcutPackage shortcutPackage = getPackageShortcuts(packageName);
 
-        if (!shortcutPackage.handlePackageAddedOrUpdated(isNewApp, forceRescan)) {
+        if (!shortcutPackage.rescanPackageIfNeeded(isNewApp, forceRescan)) {
             if (isNewApp) {
                 mPackages.remove(packageName);
             }
@@ -265,13 +307,11 @@
             throws IOException, XmlPullParserException {
         out.startTag(null, TAG_ROOT);
 
-        ShortcutService.writeAttr(out, ATTR_KNOWN_LOCALE_CHANGE_SEQUENCE_NUMBER,
-                mKnownLocaleChangeSequenceNumber);
+        ShortcutService.writeAttr(out, ATTR_KNOWN_LOCALES, mKnownLocales);
         ShortcutService.writeAttr(out, ATTR_LAST_APP_SCAN_TIME,
                 mLastAppScanTime);
 
-        ShortcutService.writeTagValue(out, TAG_LAUNCHER,
-                mDefaultLauncherComponent);
+        ShortcutService.writeTagValue(out, TAG_LAUNCHER, mLastKnownLauncher);
 
         // Can't use forEachPackageItem due to the checked exceptions.
         {
@@ -307,8 +347,8 @@
             boolean fromBackup) throws IOException, XmlPullParserException {
         final ShortcutUser ret = new ShortcutUser(s, userId);
 
-        ret.mKnownLocaleChangeSequenceNumber = ShortcutService.parseLongAttribute(parser,
-                ATTR_KNOWN_LOCALE_CHANGE_SEQUENCE_NUMBER);
+        ret.mKnownLocales = ShortcutService.parseStringAttribute(parser,
+                ATTR_KNOWN_LOCALES);
 
         // If lastAppScanTime is in the future, that means the clock went backwards.
         // Just scan all apps again.
@@ -330,7 +370,7 @@
             if (depth == outerDepth + 1) {
                 switch (tag) {
                     case TAG_LAUNCHER: {
-                        ret.mDefaultLauncherComponent = ShortcutService.parseComponentNameAttribute(
+                        ret.mLastKnownLauncher = ShortcutService.parseComponentNameAttribute(
                                 parser, ATTR_VALUE);
                         continue;
                     }
@@ -355,18 +395,44 @@
         return ret;
     }
 
-    public ComponentName getDefaultLauncherComponent() {
-        return mDefaultLauncherComponent;
+    public ComponentName getLastKnownLauncher() {
+        return mLastKnownLauncher;
     }
 
-    public void setDefaultLauncherComponent(ComponentName launcherComponent) {
-        if (Objects.equal(mDefaultLauncherComponent, launcherComponent)) {
+    public void setLauncher(ComponentName launcherComponent) {
+        setLauncher(launcherComponent, /* allowPurgeLastKnown */ false);
+    }
+
+    /** Clears the launcher information without clearing the last known one */
+    public void clearLauncher() {
+        setLauncher(null);
+    }
+
+    /**
+     * Clears the launcher information *with(* clearing the last known one; we do this witl
+     * "cmd shortcut clear-default-launcher".
+     */
+    public void forceClearLauncher() {
+        setLauncher(null, /* allowPurgeLastKnown */ true);
+    }
+
+    private void setLauncher(ComponentName launcherComponent, boolean allowPurgeLastKnown) {
+        mCachedLauncher = launcherComponent; // Always update the in-memory cache.
+
+        if (Objects.equal(mLastKnownLauncher, launcherComponent)) {
             return;
         }
-        mDefaultLauncherComponent = launcherComponent;
+        if (!allowPurgeLastKnown && launcherComponent == null) {
+            return;
+        }
+        mLastKnownLauncher = launcherComponent;
         mService.scheduleSaveUser(mUserId);
     }
 
+    public ComponentName getCachedLauncher() {
+        return mCachedLauncher;
+    }
+
     public void resetThrottling() {
         for (int i = mPackages.size() - 1; i >= 0; i--) {
             mPackages.valueAt(i).resetThrottling();
@@ -377,8 +443,8 @@
         pw.print(prefix);
         pw.print("User: ");
         pw.print(mUserId);
-        pw.print("  Known locale seq#: ");
-        pw.print(mKnownLocaleChangeSequenceNumber);
+        pw.print("  Known locales: ");
+        pw.print(mKnownLocales);
         pw.print("  Last app scan: [");
         pw.print(mLastAppScanTime);
         pw.print("] ");
@@ -388,8 +454,13 @@
         prefix += prefix + "  ";
 
         pw.print(prefix);
-        pw.print("Default launcher: ");
-        pw.print(mDefaultLauncherComponent);
+        pw.print("Cached launcher: ");
+        pw.print(mCachedLauncher);
+        pw.println();
+
+        pw.print(prefix);
+        pw.print("Last known launcher: ");
+        pw.print(mLastKnownLauncher);
         pw.println();
 
         for (int i = 0; i < mLaunchers.size(); i++) {
diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java
index 5fefd4c..7d20931 100644
--- a/services/core/java/com/android/server/vr/VrManagerService.java
+++ b/services/core/java/com/android/server/vr/VrManagerService.java
@@ -403,107 +403,6 @@
 
         publishLocalService(VrManagerInternal.class, new LocalService());
         publishBinderService(VR_MANAGER_BINDER_SERVICE, mVrManager.asBinder());
-
-        // If there are no VR packages installed on the device, then disable VR
-        // components, otherwise, enable them.
-        setEnabledStatusOfVrComponents();
-    }
-
-    private void setEnabledStatusOfVrComponents() {
-        ArraySet<ComponentName> vrComponents = SystemConfig.getInstance().getDefaultVrComponents();
-        if (vrComponents == null) {
-           return;
-        }
-
-        // We only want to enable VR components if there is a VR package installed on the device.
-        // The VR components themselves do not quality as a VR package, so exclude them.
-        ArraySet<String> vrComponentPackageNames = new ArraySet<>();
-        for (ComponentName componentName : vrComponents) {
-            vrComponentPackageNames.add(componentName.getPackageName());
-        }
-
-        // Check to see if there are any packages on the device, other than the VR component
-        // packages.
-        PackageManager pm = mContext.getPackageManager();
-        List<PackageInfo> packageInfos = pm.getInstalledPackages(
-                PackageManager.GET_CONFIGURATIONS);
-        boolean vrModeIsUsed = false;
-        for (PackageInfo packageInfo : packageInfos) {
-            if (packageInfo != null && packageInfo.packageName != null &&
-                    pm.getApplicationEnabledSetting(packageInfo.packageName) ==
-                            PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
-                vrModeIsUsed = enableVrComponentsIfVrModeUsed(pm, packageInfo,
-                        vrComponentPackageNames, vrComponents);
-                if (vrModeIsUsed) {
-                    break;
-                }
-            }
-        }
-
-        if (!vrModeIsUsed) {
-            Slog.i(TAG, "No VR packages found, disabling VR components");
-            setVrComponentsEnabledOrDisabled(vrComponents, false);
-
-            // Register to receive an intent when a new package is installed, in case that package
-            // requires VR components.
-            IntentFilter intentFilter = new IntentFilter();
-            intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
-            intentFilter.addDataScheme("package");
-            mContext.registerReceiver(new BroadcastReceiver() {
-                @Override
-                public void onReceive(Context context, Intent intent) {
-                    PackageManager pm = context.getPackageManager();
-                    final String packageName = intent.getData().getSchemeSpecificPart();
-                    if (packageName != null) {
-                        try {
-                            PackageInfo packageInfo = pm.getPackageInfo(packageName,
-                                    PackageManager.GET_CONFIGURATIONS);
-                            enableVrComponentsIfVrModeUsed(pm, packageInfo,
-                                    vrComponentPackageNames, vrComponents);
-                        } catch (NameNotFoundException e) {
-                        }
-                    }
-                };
-            }, intentFilter);
-        }
-    }
-
-    private void setVrComponentsEnabledOrDisabled(ArraySet<ComponentName> vrComponents,
-            boolean enabled) {
-        int state = enabled ?
-                PackageManager.COMPONENT_ENABLED_STATE_ENABLED :
-                PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
-        PackageManager pm = mContext.getPackageManager();
-        for (ComponentName componentName : vrComponents) {
-            try {
-                // Note that we must first check for the existance of the package before trying
-                // to set its enabled state.  This is to prevent PackageManager from throwing
-                // an excepton if the package is not found (not just a NameNotFoundException
-                // exception).
-                PackageInfo packageInfo = pm.getPackageInfo(componentName.getPackageName(),
-                        PackageManager.GET_CONFIGURATIONS);
-                pm.setApplicationEnabledSetting(componentName.getPackageName(), state , 0);
-            } catch (NameNotFoundException e) {
-            }
-        }
-    }
-
-    private boolean enableVrComponentsIfVrModeUsed(PackageManager pm, PackageInfo packageInfo,
-            ArraySet<String> vrComponentPackageNames, ArraySet<ComponentName> vrComponents) {
-        boolean isVrComponent = vrComponents != null &&
-                vrComponentPackageNames.contains(packageInfo.packageName);
-        if (packageInfo != null && packageInfo.reqFeatures != null && !isVrComponent) {
-            for (FeatureInfo featureInfo : packageInfo.reqFeatures) {
-                if (featureInfo.name != null &&
-                    (featureInfo.name.equals(PackageManager.FEATURE_VR_MODE) ||
-                     featureInfo.name.equals(PackageManager.FEATURE_VR_MODE_HIGH_PERFORMANCE))) {
-                    Slog.i(TAG, "VR package found, enabling VR components");
-                    setVrComponentsEnabledOrDisabled(vrComponents, true);
-                    return true;
-                }
-            }
-        }
-        return false;
     }
 
     @Override
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 4b58a3b..f7a92fe 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -1470,19 +1470,27 @@
     }
 
     @Override
-    public void setWallpaperComponentChecked(ComponentName name, String callingPackage) {
+    public void setWallpaperComponentChecked(ComponentName name, String callingPackage,
+            int userId) {
+
         if (isWallpaperSupported(callingPackage) && isSetWallpaperAllowed(callingPackage)) {
-            setWallpaperComponent(name);
+            setWallpaperComponent(name, userId);
         }
     }
 
     // ToDo: Remove this version of the function
     @Override
     public void setWallpaperComponent(ComponentName name) {
+        setWallpaperComponent(name, UserHandle.getCallingUserId());
+    }
+
+    private void setWallpaperComponent(ComponentName name, int userId) {
+        userId = ActivityManager.handleIncomingUser(getCallingPid(), getCallingUid(), userId,
+                false /* all */, true /* full */, "changing live wallpaper", null /* pkg */);
         checkPermission(android.Manifest.permission.SET_WALLPAPER_COMPONENT);
+
         synchronized (mLock) {
             if (DEBUG) Slog.v(TAG, "setWallpaperComponent name=" + name);
-            int userId = UserHandle.getCallingUserId();
             WallpaperData wallpaper = mWallpaperMap.get(userId);
             if (wallpaper == null) {
                 throw new IllegalStateException("Wallpaper not yet initialized for user " + userId);
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 84788cf..f357cd0 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -200,6 +200,7 @@
 import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION;
 import static android.view.WindowManager.LayoutParams.TYPE_QS_DIALOG;
 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
+import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
 import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
 import static android.view.WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY;
@@ -1950,6 +1951,11 @@
                             + attrs.token + ".  Aborting.");
                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                 }
+                if (type == TYPE_TOAST) {
+                    Slog.w(TAG_WM, "Attempted to add a toast window with unknown token "
+                            + attrs.token + ".  Aborting.");
+                    return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
+                }
                 token = new WindowToken(this, attrs.token, -1, false);
                 addToken = true;
             } else if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
@@ -1999,6 +2005,12 @@
                             + attrs.token + ".  Aborting.");
                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                 }
+            } else if (type == TYPE_TOAST) {
+                if (token.windowType != TYPE_TOAST) {
+                    Slog.w(TAG_WM, "Attempted to add a toast window with bad token "
+                            + attrs.token + ".  Aborting.");
+                    return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
+                }
             } else if (type == TYPE_QS_DIALOG) {
                 if (token.windowType != TYPE_QS_DIALOG) {
                     Slog.w(TAG_WM, "Attempted to add QS dialog window with bad token "
@@ -2907,9 +2919,23 @@
                     }
                     result |= RELAYOUT_RES_SURFACE_CHANGED;
                 }
+                final WindowSurfaceController surfaceController = winAnimator.mSurfaceController;
+                if (viewVisibility == View.VISIBLE && surfaceController != null) {
+                    // We already told the client to go invisible, but the message may not be
+                    // handled yet, or it might want to draw a last frame. If we already have a
+                    // surface, let the client use that, but don't create new surface at this point.
+                    surfaceController.getSurface(outSurface);
+                } else {
+                    if (DEBUG_VISIBILITY) Slog.i(TAG_WM, "Releasing surface in: " + win);
 
-                outSurface.release();
-                if (DEBUG_VISIBILITY) Slog.i(TAG_WM, "Releasing surface in: " + win);
+                    try {
+                        Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmReleaseOutSurface_"
+                                + win.mAttrs.getTitle());
+                        outSurface.release();
+                    } finally {
+                        Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
+                    }
+                }
             }
 
             if (focusMayChange) {
@@ -3044,6 +3070,7 @@
         } else {
             // For some reason there isn't a surface.  Clear the
             // caller's object so they see the same state.
+            Slog.w(TAG_WM, "Failed to create surface control for " + win);
             outSurface.release();
         }
         return result;
diff --git a/services/net/java/android/net/apf/ApfFilter.java b/services/net/java/android/net/apf/ApfFilter.java
index 57f784a..0f812ac 100644
--- a/services/net/java/android/net/apf/ApfFilter.java
+++ b/services/net/java/android/net/apf/ApfFilter.java
@@ -180,6 +180,7 @@
     private static final int IPV4_FRAGMENT_OFFSET_MASK = 0x1fff;
     private static final int IPV4_PROTOCOL_OFFSET = ETH_HEADER_LEN + 9;
     private static final int IPV4_DEST_ADDR_OFFSET = ETH_HEADER_LEN + 16;
+    private static final int IPV4_ANY_HOST_ADDRESS = 0;
 
     private static final int IPV6_NEXT_HEADER_OFFSET = ETH_HEADER_LEN + 6;
     private static final int IPV6_SRC_ADDR_OFFSET = ETH_HEADER_LEN + 8;
@@ -201,12 +202,14 @@
     private static final int DHCP_CLIENT_MAC_OFFSET = ETH_HEADER_LEN + UDP_HEADER_LEN + 28;
 
     private static final int ARP_HEADER_OFFSET = ETH_HEADER_LEN;
-    private static final byte[] ARP_IPV4_REQUEST_HEADER = new byte[]{
+    private static final int ARP_OPCODE_OFFSET = ARP_HEADER_OFFSET + 6;
+    private static final short ARP_OPCODE_REQUEST = 1;
+    private static final short ARP_OPCODE_REPLY = 2;
+    private static final byte[] ARP_IPV4_HEADER = new byte[]{
             0, 1, // Hardware type: Ethernet (1)
             8, 0, // Protocol type: IP (0x0800)
             6,    // Hardware size: 6
             4,    // Protocol size: 4
-            0, 1  // Opcode: request (1)
     };
     private static final int ARP_TARGET_IP_ADDRESS_OFFSET = ETH_HEADER_LEN + 24;
 
@@ -667,23 +670,48 @@
     private void generateArpFilterLocked(ApfGenerator gen) throws IllegalInstructionException {
         // Here's a basic summary of what the ARP filter program does:
         //
-        // if interface has IPv4 address:
-        //   if it's not an ARP IPv4 request:
-        //     pass
-        //   if it's not a request for our IPv4 address:
-        //     drop
+        // if not ARP IPv4
+        //   pass
+        // if not ARP IPv4 reply or request
+        //   pass
+        // if unicast ARP reply
+        //   pass
+        // if interface has no IPv4 address
+        //   if target ip is 0.0.0.0
+        //      drop
+        // else
+        //   if target ip is not the interface ip
+        //      drop
         // pass
 
-        if (mIPv4Address != null) {
-            // if it's not an ARP IPv4 request, pass
-            gen.addLoadImmediate(Register.R0, ARP_HEADER_OFFSET);
-            gen.addJumpIfBytesNotEqual(Register.R0, ARP_IPV4_REQUEST_HEADER, gen.PASS_LABEL);
-            // if it's not a request for our IPv4 address, drop
+        final String checkTargetIPv4 = "checkTargetIPv4";
+
+        // Pass if not ARP IPv4.
+        gen.addLoadImmediate(Register.R0, ARP_HEADER_OFFSET);
+        gen.addJumpIfBytesNotEqual(Register.R0, ARP_IPV4_HEADER, gen.PASS_LABEL);
+
+        // Pass if unknown ARP opcode.
+        gen.addLoad16(Register.R0, ARP_OPCODE_OFFSET);
+        gen.addJumpIfR0Equals(ARP_OPCODE_REQUEST, checkTargetIPv4); // Skip to unicast check
+        gen.addJumpIfR0NotEquals(ARP_OPCODE_REPLY, gen.PASS_LABEL);
+
+        // Pass if unicast reply.
+        gen.addLoadImmediate(Register.R0, ETH_DEST_ADDR_OFFSET);
+        gen.addJumpIfBytesNotEqual(Register.R0, ETH_BROADCAST_MAC_ADDRESS, gen.PASS_LABEL);
+
+        // Either a unicast request, a unicast reply, or a broadcast reply.
+        gen.defineLabel(checkTargetIPv4);
+        if (mIPv4Address == null) {
+            // When there is no IPv4 address, drop GARP replies (b/29404209).
+            gen.addLoad32(Register.R0, ARP_TARGET_IP_ADDRESS_OFFSET);
+            gen.addJumpIfR0Equals(IPV4_ANY_HOST_ADDRESS, gen.DROP_LABEL);
+        } else {
+            // When there is an IPv4 address, drop unicast/broadcast requests
+            // and broadcast replies with a different target IPv4 address.
             gen.addLoadImmediate(Register.R0, ARP_TARGET_IP_ADDRESS_OFFSET);
             gen.addJumpIfBytesNotEqual(Register.R0, mIPv4Address, gen.DROP_LABEL);
         }
 
-        // Otherwise, pass
         gen.addJump(gen.PASS_LABEL);
     }
 
diff --git a/services/tests/servicestests/res/xml/shortcut_error_3.xml b/services/tests/servicestests/res/xml/shortcut_error_3.xml
index a7b9b84..24ee024 100644
--- a/services/tests/servicestests/res/xml/shortcut_error_3.xml
+++ b/services/tests/servicestests/res/xml/shortcut_error_3.xml
@@ -19,6 +19,10 @@
         android:shortcutShortLabel="@string/shortcut_title1"
     />
     <shortcut
+        android:shortcutId="@string/shortcut_title1"
+        android:shortcutShortLabel="@string/shortcut_title1"
+    />
+    <shortcut
         android:shortcutId="x3"
         android:shortcutShortLabel="@string/shortcut_title1"
         >
@@ -26,5 +30,7 @@
             android:action="android.intent.action.VIEW"
             >
         </intent>
+        <categories android:name="@string/shortcut_title1" />
+        <categories android:name="cat2" />
     </shortcut>
 </shortcuts>
diff --git a/services/tests/servicestests/src/android/net/apf/ApfTest.java b/services/tests/servicestests/src/android/net/apf/ApfTest.java
index 815133a..bd76118 100644
--- a/services/tests/servicestests/src/android/net/apf/ApfTest.java
+++ b/services/tests/servicestests/src/android/net/apf/ApfTest.java
@@ -580,7 +580,7 @@
 
         public TestApfFilter(IpManager.Callback ipManagerCallback, boolean multicastFilter,
                 IpConnectivityLog log) throws Exception {
-            super(new ApfCapabilities(2, 1000, ARPHRD_ETHER), NetworkInterface.getByName("lo"),
+            super(new ApfCapabilities(2, 1536, ARPHRD_ETHER), NetworkInterface.getByName("lo"),
                     ipManagerCallback, multicastFilter, log);
         }
 
@@ -618,6 +618,7 @@
     }
 
     private static final int ETH_HEADER_LEN = 14;
+    private static final int ETH_DEST_ADDR_OFFSET = 0;
     private static final int ETH_ETHERTYPE_OFFSET = 12;
     private static final byte[] ETH_BROADCAST_MAC_ADDRESS = new byte[]{
         (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff };
@@ -676,9 +677,18 @@
             4,    // Protocol size: 4
             0, 1  // Opcode: request (1)
     };
+    private static final byte[] ARP_IPV4_REPLY_HEADER = new byte[]{
+            0, 1, // Hardware type: Ethernet (1)
+            8, 0, // Protocol type: IP (0x0800)
+            6,    // Hardware size: 6
+            4,    // Protocol size: 4
+            0, 2  // Opcode: reply (2)
+    };
     private static final int ARP_TARGET_IP_ADDRESS_OFFSET = ETH_HEADER_LEN + 24;
 
     private static final byte[] MOCK_IPV4_ADDR = new byte[]{10, 0, 0, 1};
+    private static final byte[] ANOTHER_IPV4_ADDR = new byte[]{10, 0, 0, 2};
+    private static final byte[] IPV4_ANY_HOST_ADDR = new byte[]{0, 0, 0, 0};
 
     @LargeTest
     public void testApfFilterIPv4() throws Exception {
@@ -801,51 +811,81 @@
         apfFilter.shutdown();
     }
 
-    private void verifyArpFilter(MockIpManagerCallback ipManagerCallback, ApfFilter apfFilter,
-            LinkProperties linkProperties, int filterResult) {
-        ipManagerCallback.resetApfProgramWait();
-        apfFilter.setLinkProperties(linkProperties);
-        byte[] program = ipManagerCallback.getApfProgram();
-        ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
-        packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_ARP);
-        assertPass(program, packet.array(), 0);
-        packet.position(ARP_HEADER_OFFSET);
-        packet.put(ARP_IPV4_REQUEST_HEADER);
-        assertVerdict(filterResult, program, packet.array(), 0);
-        packet.position(ARP_TARGET_IP_ADDRESS_OFFSET);
-        packet.put(MOCK_IPV4_ADDR);
-        assertPass(program, packet.array(), 0);
+    private byte[] getProgram(MockIpManagerCallback cb, ApfFilter filter, LinkProperties lp) {
+        cb.resetApfProgramWait();
+        filter.setLinkProperties(lp);
+        return cb.getApfProgram();
+    }
+
+    private void verifyArpFilter(byte[] program, int filterResult) {
+        // Verify ARP request packet
+        assertPass(program, arpRequestBroadcast(MOCK_IPV4_ADDR), 0);
+        assertVerdict(filterResult, program, arpRequestBroadcast(ANOTHER_IPV4_ADDR), 0);
+        assertDrop(program, arpRequestBroadcast(IPV4_ANY_HOST_ADDR), 0);
+
+        // Verify unicast ARP reply packet is always accepted.
+        assertPass(program, arpReplyUnicast(MOCK_IPV4_ADDR), 0);
+        assertPass(program, arpReplyUnicast(ANOTHER_IPV4_ADDR), 0);
+        assertPass(program, arpReplyUnicast(IPV4_ANY_HOST_ADDR), 0);
+
+        // Verify GARP reply packets are always filtered
+        assertDrop(program, garpReply(), 0);
     }
 
     @LargeTest
     public void testApfFilterArp() throws Exception {
         MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
         ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST, mLog);
-        byte[] program = ipManagerCallback.getApfProgram();
 
-        // Verify initially ARP filter is off
-        ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
-        packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_ARP);
-        assertPass(program, packet.array(), 0);
-        packet.position(ARP_HEADER_OFFSET);
-        packet.put(ARP_IPV4_REQUEST_HEADER);
-        assertPass(program, packet.array(), 0);
-        packet.position(ARP_TARGET_IP_ADDRESS_OFFSET);
-        packet.put(MOCK_IPV4_ADDR);
-        assertPass(program, packet.array(), 0);
+        // Verify initially ARP request filter is off, and GARP filter is on.
+        verifyArpFilter(ipManagerCallback.getApfProgram(), PASS);
 
         // Inform ApfFilter of our address and verify ARP filtering is on
+        LinkAddress linkAddress = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 24);
         LinkProperties lp = new LinkProperties();
-        assertTrue(lp.addLinkAddress(
-                new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 24)));
-        verifyArpFilter(ipManagerCallback, apfFilter, lp, DROP);
+        assertTrue(lp.addLinkAddress(linkAddress));
+        verifyArpFilter(getProgram(ipManagerCallback, apfFilter, lp), DROP);
 
         // Inform ApfFilter of loss of IP and verify ARP filtering is off
-        verifyArpFilter(ipManagerCallback, apfFilter, new LinkProperties(), PASS);
+        verifyArpFilter(getProgram(ipManagerCallback, apfFilter, new LinkProperties()), PASS);
 
         apfFilter.shutdown();
     }
 
+    private static byte[] arpRequestBroadcast(byte[] tip) {
+        ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
+        packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_ARP);
+        packet.position(ETH_DEST_ADDR_OFFSET);
+        packet.put(ETH_BROADCAST_MAC_ADDRESS);
+        packet.position(ARP_HEADER_OFFSET);
+        packet.put(ARP_IPV4_REQUEST_HEADER);
+        packet.position(ARP_TARGET_IP_ADDRESS_OFFSET);
+        packet.put(tip);
+        return packet.array();
+    }
+
+    private static byte[] arpReplyUnicast(byte[] tip) {
+        ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
+        packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_ARP);
+        packet.position(ARP_HEADER_OFFSET);
+        packet.put(ARP_IPV4_REPLY_HEADER);
+        packet.position(ARP_TARGET_IP_ADDRESS_OFFSET);
+        packet.put(tip);
+        return packet.array();
+    }
+
+    private static byte[] garpReply() {
+        ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
+        packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_ARP);
+        packet.position(ETH_DEST_ADDR_OFFSET);
+        packet.put(ETH_BROADCAST_MAC_ADDRESS);
+        packet.position(ARP_HEADER_OFFSET);
+        packet.put(ARP_IPV4_REPLY_HEADER);
+        packet.position(ARP_TARGET_IP_ADDRESS_OFFSET);
+        packet.put(IPV4_ANY_HOST_ADDR);
+        return packet.array();
+    }
+
     // Verify that the last program pushed to the IpManager.Callback properly filters the
     // given packet for the given lifetime.
     private void verifyRaLifetime(MockIpManagerCallback ipManagerCallback, ByteBuffer packet,
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index 1be57bc..037b24e 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -110,13 +110,14 @@
 public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
     protected static final String TAG = "ShortcutManagerTest";
 
+    protected static final boolean DUMP_IN_TEARDOWN = false; // DO NOT SUBMIT WITH true
+
     /**
      * Whether to enable dump or not.  Should be only true when debugging to avoid bugs where
      * dump affecting the behavior.
      */
-    protected static final boolean ENABLE_DUMP = false; // DO NOT SUBMIT WITH true
-
-    protected static final boolean DUMP_IN_TEARDOWN = false; // DO NOT SUBMIT WITH true
+    protected static final boolean ENABLE_DUMP = false // DO NOT SUBMIT WITH true
+            || DUMP_IN_TEARDOWN || ShortcutService.DEBUG;
 
     protected static final String[] EMPTY_STRINGS = new String[0]; // Just for readability.
 
@@ -154,6 +155,11 @@
             // ignore.
             return null;
         }
+
+        @Override
+        public void unregisterReceiver(BroadcastReceiver receiver) {
+            // ignore.
+        }
     }
 
     /** Context used in the client side */
@@ -212,6 +218,11 @@
         }
 
         @Override
+        public String injectGetLocaleTagsForUser(@UserIdInt int userId) {
+            return mInjectedLocale.toLanguageTag();
+        }
+
+        @Override
         boolean injectShouldPerformVerification() {
             return true; // Always verify during unit tests.
         }
@@ -292,11 +303,6 @@
         }
 
         @Override
-        PackageManagerInternal injectPackageManagerInternal() {
-            return mMockPackageManagerInternal;
-        }
-
-        @Override
         boolean hasShortcutHostPermission(@NonNull String callingPackage, int userId) {
             return mDefaultLauncherChecker.test(callingPackage, userId);
         }
@@ -715,11 +721,6 @@
         // Start the service.
         initService();
         setCaller(CALLING_PACKAGE_1);
-
-        // In order to complicate the situation, we set mLocaleChangeSequenceNumber to 1 by
-        // calling this.  Running test with mLocaleChangeSequenceNumber == 0 might make us miss
-        // some edge cases.
-        mInternal.onSystemLocaleChangedNoLock();
     }
 
     /**
@@ -837,12 +838,6 @@
         // Send boot sequence events.
         mService.onBootPhase(SystemService.PHASE_LOCK_SETTINGS_READY);
 
-        // Make sure a call to onSystemLocaleChangedNoLock() before PHASE_BOOT_COMPLETED will be
-        // ignored.
-        final long origSequenceNumber = mService.getLocaleChangeSequenceNumber();
-        mInternal.onSystemLocaleChangedNoLock();
-        assertEquals(origSequenceNumber, mService.getLocaleChangeSequenceNumber());
-
         mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index bf6c2ff..55fa625f 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -3131,7 +3131,7 @@
             assertEquals(2, mManager.getRemainingCallCount());
         });
 
-        mService.getShortcutsForTest().get(UserHandle.USER_SYSTEM).setDefaultLauncherComponent(
+        mService.getShortcutsForTest().get(UserHandle.USER_SYSTEM).setLauncher(
                 new ComponentName("pkg1", "class"));
 
         // Restore.
@@ -3165,7 +3165,7 @@
         });
 
         assertEquals("pkg1", mService.getShortcutsForTest().get(UserHandle.USER_SYSTEM)
-                .getDefaultLauncherComponent().getPackageName());
+                .getLastKnownLauncher().getPackageName());
 
         // Start another user
         mService.handleUnlockUser(USER_10);
@@ -3181,7 +3181,7 @@
             assertEquals("title10-1-1", getCallerShortcut("s1").getTitle());
             assertEquals("title10-1-2", getCallerShortcut("s2").getTitle());
         });
-        assertNull(mService.getShortcutsForTest().get(USER_10).getDefaultLauncherComponent());
+        assertNull(mService.getShortcutsForTest().get(USER_10).getLastKnownLauncher());
 
         // Try stopping the user
         mService.handleCleanupUser(USER_10);
@@ -5730,21 +5730,24 @@
         mRunningUsers.put(USER_10, false);
         mUnlockedUsers.put(USER_10, false);
 
-                mService.mPackageMonitor.onReceive(getTestContext(),
+        mService.mPackageMonitor.onReceive(getTestContext(),
                 genPackageAddIntent(CALLING_PACKAGE_2, USER_10));
         runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
-            assertEmpty(mManager.getManifestShortcuts());
-            assertEmpty(mManager.getPinnedShortcuts());
+            // Don't use the mManager APIs to get shortcuts, because they'll trigger the package
+            // update check.
+            // So look the internal data directly using getCallerShortcuts().
+            assertEmpty(getCallerShortcuts());
         });
 
         // Try again, but the user is locked, so still ignored.
         mRunningUsers.put(USER_10, true);
-
                 mService.mPackageMonitor.onReceive(getTestContext(),
                 genPackageAddIntent(CALLING_PACKAGE_2, USER_10));
         runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
-            assertEmpty(mManager.getManifestShortcuts());
-            assertEmpty(mManager.getPinnedShortcuts());
+            // Don't use the mManager APIs to get shortcuts, because they'll trigger the package
+            // update check.
+            // So look the internal data directly using getCallerShortcuts().
+            assertEmpty(getCallerShortcuts());
         });
 
         // Unlock the user, now it should work.
@@ -5856,9 +5859,11 @@
 
         // Only the valid one is published.
         runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
-            assertShortcutIds(assertAllManifest(assertAllImmutable(assertAllEnabled(
-                    mManager.getManifestShortcuts()))),
-                    "x1");
+            assertWith(getCallerShortcuts())
+                    .areAllManifest()
+                    .areAllImmutable()
+                    .areAllEnabled()
+                    .haveIds("x1");
         });
 
         // Package 1 updated, which has one valid manifest shortcut and one invalid.
@@ -5871,9 +5876,11 @@
 
         // Only the valid one is published.
         runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
-            assertShortcutIds(assertAllManifest(assertAllImmutable(assertAllEnabled(
-                    mManager.getManifestShortcuts()))),
-                    "x2");
+            assertWith(getCallerShortcuts())
+                    .areAllManifest()
+                    .areAllImmutable()
+                    .areAllEnabled()
+                    .haveIds("x2");
         });
 
         // Package 1 updated, which has one valid manifest shortcut and one invalid.
@@ -5886,9 +5893,14 @@
 
         // Only the valid one is published.
         runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
-            assertShortcutIds(assertAllManifest(assertAllImmutable(assertAllEnabled(
-                    mManager.getManifestShortcuts()))),
-                    "x3");
+            assertWith(getCallerShortcuts())
+                    .areAllManifest()
+                    .areAllImmutable()
+                    .areAllEnabled()
+                    .haveIds("x3")
+                    .forShortcutWithId("x3", si -> {
+                        assertEquals(set("cat2"), si.getCategories());
+                     });
         });
     }
 
@@ -6108,7 +6120,7 @@
         });
     }
 
-    public void testManifestShortcuts_localeChange() {
+    public void testManifestShortcuts_localeChange() throws InterruptedException {
         mService.handleUnlockUser(USER_0);
 
         // Package 1 updated, which has one valid manifest shortcut and one invalid.
@@ -6164,8 +6176,15 @@
 
         mInjectedCurrentTimeMillis++;
 
+        // Change the locale and send the broadcast, make sure the launcher gets a callback too.
         mInjectedLocale = Locale.JAPANESE;
-        mInternal.onSystemLocaleChangedNoLock();
+
+        setCaller(LAUNCHER_1, USER_0);
+
+        assertForLauncherCallback(mLauncherApps, () -> {
+            mService.mReceiver.onReceive(mServiceContext, new Intent(Intent.ACTION_LOCALE_CHANGED));
+        }).assertCallbackCalledForPackageAndUser(CALLING_PACKAGE_1, HANDLE_USER_0)
+                .haveIds("ms1", "ms2", "s1");
 
         runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
             // check first shortcut.
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
index d546092..bd413be 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
@@ -47,6 +47,8 @@
 import com.android.frameworks.servicestests.R;
 import com.android.server.pm.ShortcutService.ConfigConstants;
 
+import java.util.Locale;
+
 /**
  * Tests for ShortcutService and ShortcutManager.
  *
@@ -1357,13 +1359,12 @@
         mService.saveDirtyInfo();
         initService();
 
-        final long origSequenceNumber = mService.getLocaleChangeSequenceNumber();
-
-        mInternal.onSystemLocaleChangedNoLock();
-        assertEquals(origSequenceNumber + 1, mService.getLocaleChangeSequenceNumber());
+        mInjectedLocale = Locale.CHINA;
+        mService.mReceiver.onReceive(mServiceContext, new Intent(Intent.ACTION_LOCALE_CHANGED));
 
         // Note at this point only user-0 is loaded, and the counters are reset for this user,
-        // but it will work for other users too, because we persist when
+        // but it will work for other users too because we check the locale change at any
+        // API entry point.
 
         runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
             assertEquals(3, mManager.getRemainingCallCount());
@@ -1384,11 +1385,28 @@
             assertEquals(3, mManager.getRemainingCallCount());
         });
 
+        // Make sure even if we receive ACTION_LOCALE_CHANGED, if the locale hasn't actually
+        // changed, we don't reset throttling.
+        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+            mManager.updateShortcuts(list());
+            assertEquals(2, mManager.getRemainingCallCount());
+        });
+
+        mService.mReceiver.onReceive(mServiceContext, new Intent(Intent.ACTION_LOCALE_CHANGED));
+
+        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+            assertEquals(2, mManager.getRemainingCallCount()); // Still 2.
+        });
+
         mService.saveDirtyInfo();
         initService();
 
-        // Make sure the counter is persisted.
-        assertEquals(origSequenceNumber + 1, mService.getLocaleChangeSequenceNumber());
+        // The locale should be persisted, so it still shouldn't reset throttling.
+        mService.mReceiver.onReceive(mServiceContext, new Intent(Intent.ACTION_LOCALE_CHANGED));
+
+        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+            assertEquals(2, mManager.getRemainingCallCount()); // Still 2.
+        });
     }
 
     public void testThrottling_foreground() throws Exception {
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest6.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest6.java
new file mode 100644
index 0000000..ffb2953
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest6.java
@@ -0,0 +1,317 @@
+/*
+ * Copyright (C) 2016 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.server.pm;
+
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.list;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doAnswer;
+
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.ResolveInfo;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import java.util.List;
+
+/**
+ * Tests for {@link ShortcutService#hasShortcutHostPermissionInner}.
+ */
+@SmallTest
+public class ShortcutManagerTest6 extends BaseShortcutManagerTest {
+
+    private static final String PACKAGE_SYSTEM_LAUNCHER = "com.android.systemlauncher";
+    private static final String PACKAGE_SYSTEM_LAUNCHER_NAME = "systemlauncher_name";
+    private static final int PACKAGE_SYSTEM_LAUNCHER_PRIORITY = 0;
+
+    private static final String PACKAGE_FALLBACK_LAUNCHER = "com.android.settings";
+    private static final String PACKAGE_FALLBACK_LAUNCHER_NAME = "fallback";
+    private static final int PACKAGE_FALLBACK_LAUNCHER_PRIORITY = -999;
+
+    private void prepareGetHomeActivitiesAsUser(ComponentName preferred,
+            List<ResolveInfo> candidates, int userId) {
+        doAnswer(inv -> {
+            ((List) inv.getArguments()[0]).addAll(candidates);
+            return preferred;
+        }).when(mMockPackageManagerInternal).getHomeActivitiesAsUser(any(List.class), eq(userId));
+    }
+
+    private static ComponentName cn(String packageName, String name) {
+        return new ComponentName(packageName, name);
+    }
+
+    private static ResolveInfo ri(String packageName, String name, boolean isSystem, int priority) {
+        final ResolveInfo ri = new ResolveInfo();
+        ri.activityInfo = new ActivityInfo();
+        ri.activityInfo.applicationInfo = new ApplicationInfo();
+
+        ri.activityInfo.packageName = packageName;
+        ri.activityInfo.name = name;
+        if (isSystem) {
+            ri.activityInfo.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
+        }
+        ri.priority = priority;
+        return ri;
+    }
+
+    private static ResolveInfo getSystemLauncher() {
+        return ri(PACKAGE_SYSTEM_LAUNCHER, PACKAGE_SYSTEM_LAUNCHER_NAME, true,
+                PACKAGE_SYSTEM_LAUNCHER_PRIORITY);
+    }
+
+    private static ResolveInfo getFallbackLauncher() {
+        return ri(PACKAGE_FALLBACK_LAUNCHER, PACKAGE_FALLBACK_LAUNCHER_NAME, true,
+                PACKAGE_FALLBACK_LAUNCHER_PRIORITY);
+    }
+
+    public void testHasShortcutHostPermissionInner_systemLauncherOnly() {
+        // Preferred isn't set, use the system launcher.
+        prepareGetHomeActivitiesAsUser(
+                /* preferred */ null,
+                list(getSystemLauncher(), getFallbackLauncher()),
+                USER_0);
+        assertTrue(mService.hasShortcutHostPermissionInner(PACKAGE_SYSTEM_LAUNCHER, USER_0));
+        assertFalse(mService.hasShortcutHostPermissionInner(PACKAGE_FALLBACK_LAUNCHER, USER_0));
+        assertFalse(mService.hasShortcutHostPermissionInner(CALLING_PACKAGE_1, USER_0));
+        assertFalse(mService.hasShortcutHostPermissionInner(CALLING_PACKAGE_2, USER_0));
+
+        // Should be cached.
+        assertEquals(cn(PACKAGE_SYSTEM_LAUNCHER, PACKAGE_SYSTEM_LAUNCHER_NAME),
+                mService.getUserShortcutsLocked(USER_0).getLastKnownLauncher());
+        assertEquals(cn(PACKAGE_SYSTEM_LAUNCHER, PACKAGE_SYSTEM_LAUNCHER_NAME),
+                mService.getUserShortcutsLocked(USER_0).getCachedLauncher());
+
+        // Also make sure the last known is saved, but the cached is not.
+
+        initService();
+
+        assertEquals(cn(PACKAGE_SYSTEM_LAUNCHER, PACKAGE_SYSTEM_LAUNCHER_NAME),
+                mService.getUserShortcutsLocked(USER_0).getLastKnownLauncher());
+        assertEquals(null,
+                mService.getUserShortcutsLocked(USER_0).getCachedLauncher());
+    }
+
+    public void testHasShortcutHostPermissionInner_with3pLauncher() {
+        // Preferred isn't set, still use the system launcher.
+        prepareGetHomeActivitiesAsUser(
+                /* preferred */ null,
+                list(getSystemLauncher(), getFallbackLauncher(),
+                        ri(CALLING_PACKAGE_1, "name", false, 0),
+                        ri(CALLING_PACKAGE_2, "name", false, 0)
+                ),
+                USER_0);
+        assertTrue(mService.hasShortcutHostPermissionInner(PACKAGE_SYSTEM_LAUNCHER, USER_0));
+        assertFalse(mService.hasShortcutHostPermissionInner(PACKAGE_FALLBACK_LAUNCHER, USER_0));
+        assertFalse(mService.hasShortcutHostPermissionInner(CALLING_PACKAGE_1, USER_0));
+        assertFalse(mService.hasShortcutHostPermissionInner(CALLING_PACKAGE_2, USER_0));
+
+        // Should be cached.
+        assertEquals(cn(PACKAGE_SYSTEM_LAUNCHER, PACKAGE_SYSTEM_LAUNCHER_NAME),
+                mService.getUserShortcutsLocked(USER_0).getLastKnownLauncher());
+        assertEquals(cn(PACKAGE_SYSTEM_LAUNCHER, PACKAGE_SYSTEM_LAUNCHER_NAME),
+                mService.getUserShortcutsLocked(USER_0).getCachedLauncher());
+    }
+
+    public void testHasShortcutHostPermissionInner_with3pLauncher_complicated() {
+        // Preferred is set.  That's the default launcher.
+        prepareGetHomeActivitiesAsUser(
+                /* preferred */ cn(CALLING_PACKAGE_2, "name"),
+                list(getSystemLauncher(), getFallbackLauncher(),
+                        ri(CALLING_PACKAGE_1, "name", false, 0),
+                        ri(CALLING_PACKAGE_2, "name", false, 0)
+                ),
+                USER_0);
+        assertFalse(mService.hasShortcutHostPermissionInner(PACKAGE_SYSTEM_LAUNCHER, USER_0));
+        assertFalse(mService.hasShortcutHostPermissionInner(PACKAGE_FALLBACK_LAUNCHER, USER_0));
+        assertFalse(mService.hasShortcutHostPermissionInner(CALLING_PACKAGE_1, USER_0));
+        assertTrue(mService.hasShortcutHostPermissionInner(CALLING_PACKAGE_2, USER_0));
+
+        // Should be cached.
+        assertEquals(cn(CALLING_PACKAGE_2, "name"),
+                mService.getUserShortcutsLocked(USER_0).getLastKnownLauncher());
+        assertEquals(cn(CALLING_PACKAGE_2, "name"),
+                mService.getUserShortcutsLocked(USER_0).getCachedLauncher());
+
+
+        // Once set, even after the preferred launcher is cleared, SM still allows it to access
+        // shortcuts.
+        prepareGetHomeActivitiesAsUser(
+                /* preferred */ null,
+                list(getSystemLauncher(), getFallbackLauncher(),
+                        ri(CALLING_PACKAGE_1, "name", false, 0),
+                        ri(CALLING_PACKAGE_2, "name", false, 0)
+                ),
+                USER_0);
+
+        assertFalse(mService.hasShortcutHostPermissionInner(PACKAGE_SYSTEM_LAUNCHER, USER_0));
+        assertFalse(mService.hasShortcutHostPermissionInner(PACKAGE_FALLBACK_LAUNCHER, USER_0));
+        assertFalse(mService.hasShortcutHostPermissionInner(CALLING_PACKAGE_1, USER_0));
+        assertTrue(mService.hasShortcutHostPermissionInner(CALLING_PACKAGE_2, USER_0));
+
+        // Should be cached.
+        assertEquals(cn(CALLING_PACKAGE_2, "name"),
+                mService.getUserShortcutsLocked(USER_0).getLastKnownLauncher());
+        assertEquals(cn(CALLING_PACKAGE_2, "name"),
+                mService.getUserShortcutsLocked(USER_0).getCachedLauncher());
+
+        // However, if the component has been disabled, then we'll recalculate it.
+        mEnabledActivityChecker = (comp, user) -> false;
+
+        assertTrue(mService.hasShortcutHostPermissionInner(PACKAGE_SYSTEM_LAUNCHER, USER_0));
+        assertFalse(mService.hasShortcutHostPermissionInner(PACKAGE_FALLBACK_LAUNCHER, USER_0));
+        assertFalse(mService.hasShortcutHostPermissionInner(CALLING_PACKAGE_1, USER_0));
+        assertFalse(mService.hasShortcutHostPermissionInner(CALLING_PACKAGE_2, USER_0));
+
+        mEnabledActivityChecker = (comp, user) -> true;
+
+        // Now the preferred changed.
+        prepareGetHomeActivitiesAsUser(
+                /* preferred */ cn(CALLING_PACKAGE_1, "xyz"),
+                list(getSystemLauncher(), getFallbackLauncher(),
+                        ri(CALLING_PACKAGE_1, "name", false, 0),
+                        ri(CALLING_PACKAGE_2, "name", false, 0)
+                ),
+                USER_0);
+
+        assertTrue(mService.hasShortcutHostPermissionInner(CALLING_PACKAGE_1, USER_0));
+
+        // Should be cached.
+        assertEquals(cn(CALLING_PACKAGE_1, "xyz"),
+                mService.getUserShortcutsLocked(USER_0).getLastKnownLauncher());
+        assertEquals(cn(CALLING_PACKAGE_1, "xyz"),
+                mService.getUserShortcutsLocked(USER_0).getCachedLauncher());
+
+
+        // As long as there's the cached launcher set, even if getHomeActivitiesAsUser()
+        // returns different values, the cached one is still the default.
+        prepareGetHomeActivitiesAsUser(
+                /* preferred */ getSystemLauncher().activityInfo.getComponentName(),
+                list(getSystemLauncher(), getFallbackLauncher()),
+                USER_0);
+
+        assertTrue(mService.hasShortcutHostPermissionInner(CALLING_PACKAGE_1, USER_0));
+
+        // Cached ones haven't changed.
+        assertEquals(cn(CALLING_PACKAGE_1, "xyz"),
+                mService.getUserShortcutsLocked(USER_0).getLastKnownLauncher());
+        assertEquals(cn(CALLING_PACKAGE_1, "xyz"),
+                mService.getUserShortcutsLocked(USER_0).getCachedLauncher());
+
+        // However, now the "real" default launcher is the system one.  So if the system
+        // launcher asks for shortcuts, we'll allow it.
+        assertTrue(mService.hasShortcutHostPermissionInner(PACKAGE_SYSTEM_LAUNCHER, USER_0));
+
+        // Since the cache is updated, CALLING_PACKAGE_1 no longer has the permission.
+        assertFalse(mService.hasShortcutHostPermissionInner(CALLING_PACKAGE_1, USER_0));
+
+        // Cached ones haven't changed.
+        assertEquals(cn(PACKAGE_SYSTEM_LAUNCHER, PACKAGE_SYSTEM_LAUNCHER_NAME),
+                mService.getUserShortcutsLocked(USER_0).getLastKnownLauncher());
+        assertEquals(cn(PACKAGE_SYSTEM_LAUNCHER, PACKAGE_SYSTEM_LAUNCHER_NAME),
+                mService.getUserShortcutsLocked(USER_0).getCachedLauncher());
+    }
+
+    public void testHasShortcutHostPermissionInner_multiUser() {
+        prepareGetHomeActivitiesAsUser(
+                /* preferred */ null,
+                list(getSystemLauncher(), getFallbackLauncher()),
+                USER_0);
+
+        prepareGetHomeActivitiesAsUser(
+                /* preferred */ cn(CALLING_PACKAGE_2, "name"),
+                list(getSystemLauncher(), getFallbackLauncher(),
+                        ri(CALLING_PACKAGE_1, "name", false, 0),
+                        ri(CALLING_PACKAGE_2, "name", false, 0)
+                ),
+                USER_10);
+
+        assertTrue(mService.hasShortcutHostPermissionInner(PACKAGE_SYSTEM_LAUNCHER, USER_0));
+        assertFalse(mService.hasShortcutHostPermissionInner(PACKAGE_FALLBACK_LAUNCHER, USER_0));
+        assertFalse(mService.hasShortcutHostPermissionInner(CALLING_PACKAGE_1, USER_0));
+        assertFalse(mService.hasShortcutHostPermissionInner(CALLING_PACKAGE_2, USER_0));
+
+        // Check the cache.
+        assertEquals(cn(PACKAGE_SYSTEM_LAUNCHER, PACKAGE_SYSTEM_LAUNCHER_NAME),
+                mService.getUserShortcutsLocked(USER_0).getLastKnownLauncher());
+        assertEquals(cn(PACKAGE_SYSTEM_LAUNCHER, PACKAGE_SYSTEM_LAUNCHER_NAME),
+                mService.getUserShortcutsLocked(USER_0).getCachedLauncher());
+
+        assertFalse(mService.hasShortcutHostPermissionInner(PACKAGE_SYSTEM_LAUNCHER, USER_10));
+        assertFalse(mService.hasShortcutHostPermissionInner(PACKAGE_FALLBACK_LAUNCHER, USER_10));
+        assertFalse(mService.hasShortcutHostPermissionInner(CALLING_PACKAGE_1, USER_10));
+        assertTrue(mService.hasShortcutHostPermissionInner(CALLING_PACKAGE_2, USER_10));
+
+        // Check the cache.
+        assertEquals(cn(CALLING_PACKAGE_2, "name"),
+                mService.getUserShortcutsLocked(USER_10).getLastKnownLauncher());
+        assertEquals(cn(CALLING_PACKAGE_2, "name"),
+                mService.getUserShortcutsLocked(USER_10).getCachedLauncher());
+    }
+
+    public void testHasShortcutHostPermissionInner_clearCache() {
+        prepareGetHomeActivitiesAsUser(
+                /* preferred */ null,
+                list(getSystemLauncher(), getFallbackLauncher()),
+                USER_0);
+
+        prepareGetHomeActivitiesAsUser(
+                /* preferred */ cn(CALLING_PACKAGE_2, "name"),
+                list(getSystemLauncher(), getFallbackLauncher(),
+                        ri(CALLING_PACKAGE_1, "name", false, 0),
+                        ri(CALLING_PACKAGE_2, "name", false, 0)
+                ),
+                USER_10);
+
+        assertTrue(mService.hasShortcutHostPermissionInner(PACKAGE_SYSTEM_LAUNCHER, USER_0));
+        assertTrue(mService.hasShortcutHostPermissionInner(CALLING_PACKAGE_2, USER_10));
+
+        assertEquals(cn(PACKAGE_SYSTEM_LAUNCHER, PACKAGE_SYSTEM_LAUNCHER_NAME),
+                mService.getUserShortcutsLocked(USER_0).getCachedLauncher());
+
+        assertEquals(cn(CALLING_PACKAGE_2, "name"),
+                mService.getUserShortcutsLocked(USER_10).getCachedLauncher());
+
+        // Send ACTION_PREFERRED_ACTIVITY_CHANGED on user 10.
+        // But the user is not running, so will be ignored.
+        mService.mPackageMonitor.onReceive(mServiceContext,
+                new Intent(Intent.ACTION_PREFERRED_ACTIVITY_CHANGED).putExtra(
+                        Intent.EXTRA_USER_HANDLE, USER_10));
+
+        assertEquals(cn(PACKAGE_SYSTEM_LAUNCHER, PACKAGE_SYSTEM_LAUNCHER_NAME),
+                mService.getUserShortcutsLocked(USER_0).getCachedLauncher());
+
+        assertEquals(cn(CALLING_PACKAGE_2, "name"),
+                mService.getUserShortcutsLocked(USER_10).getCachedLauncher());
+
+         // Send it again after starting the user.
+        mRunningUsers.put(USER_10, true);
+        mService.mPackageMonitor.onReceive(mServiceContext,
+                new Intent(Intent.ACTION_PREFERRED_ACTIVITY_CHANGED).putExtra(
+                        Intent.EXTRA_USER_HANDLE, USER_10));
+
+        assertEquals(cn(PACKAGE_SYSTEM_LAUNCHER, PACKAGE_SYSTEM_LAUNCHER_NAME),
+                mService.getUserShortcutsLocked(USER_0).getCachedLauncher());
+
+        // Only user-10's cache is cleared.
+        assertEquals(null,
+                mService.getUserShortcutsLocked(USER_10).getCachedLauncher());
+
+    }
+}
diff --git a/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java b/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
index f89c4e4..2f64ad7 100644
--- a/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
+++ b/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
@@ -973,6 +973,8 @@
 
         waitOnMainThread();
 
+        launcherApps.unregisterCallback(asserter.getMockCallback());
+
         return asserter;
     }
 }
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index eb3c665..69cf1a2 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -838,6 +838,10 @@
                     && mAppWidgetManager.isBoundWidgetPackage(packageName, userId)) {
                 return false;
             }
+
+            if (isDeviceProvisioningPackage(packageName)) {
+                return false;
+            }
         }
 
         if (!isAppIdleUnfiltered(packageName, userId, elapsedRealtime)) {
@@ -930,6 +934,16 @@
         return dpm.packageHasActiveAdmins(packageName, userId);
     }
 
+    /**
+     * Returns {@code true} if the supplied package is the device provisioning app. Otherwise,
+     * returns {@code false}.
+     */
+    private boolean isDeviceProvisioningPackage(String packageName) {
+        String deviceProvisioningPackage = getContext().getResources().getString(
+                com.android.internal.R.string.config_deviceProvisioningPackage);
+        return deviceProvisioningPackage != null && deviceProvisioningPackage.equals(packageName);
+    }
+
     private boolean isCarrierApp(String packageName) {
         synchronized (mLock) {
             if (!mHaveCarrierPrivilegedApps) {
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 2a95d3e..3052cdb 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -789,6 +789,13 @@
     public static final int CDMA_ROAMING_MODE_ANY = 2;
 
     /**
+     * Report IMEI as device id even if it's a CDMA/LTE phone.
+     *
+     * @hide
+     */
+    public static final String KEY_FORCE_IMEI_BOOL = "force_imei_bool";
+
+    /**
      * The families of Radio Access Technologies that will get clustered and ratcheted,
      * ie, we will report transitions up within the family, but not down until we change
      * cells.  This prevents flapping between base technologies and higher techs that are
@@ -995,6 +1002,7 @@
         sDefaults.putString(KEY_MMS_USER_AGENT_STRING, "");
         sDefaults.putBoolean(KEY_ALLOW_NON_EMERGENCY_CALLS_IN_ECM_BOOL, true);
         sDefaults.putBoolean(KEY_USE_RCS_PRESENCE_BOOL, false);
+        sDefaults.putBoolean(KEY_FORCE_IMEI_BOOL, false);
         sDefaults.putInt(KEY_CDMA_ROAMING_MODE_INT, CDMA_ROAMING_MODE_RADIO_DEFAULT);
 
         // Carrier Signalling Receivers
diff --git a/telephony/java/com/android/ims/ImsCallProfile.java b/telephony/java/com/android/ims/ImsCallProfile.java
index 65254d8..36abfc9 100644
--- a/telephony/java/com/android/ims/ImsCallProfile.java
+++ b/telephony/java/com/android/ims/ImsCallProfile.java
@@ -205,6 +205,14 @@
      */
     public static final String EXTRA_CALL_RAT_TYPE = "CallRadioTech";
 
+    /**
+     * Similar to {@link #EXTRA_CALL_RAT_TYPE}, except with a lowercase 'c'.  Used to ensure
+     * compatibility with modems that are non-compliant with the {@link #EXTRA_CALL_RAT_TYPE}
+     * extra key.  Should be removed when the non-compliant modems are fixed.
+     * @hide
+     */
+    public static final String EXTRA_CALL_RAT_TYPE_ALT = "callRadioTech";
+
     public int mServiceType;
     public int mCallType;
     public int mRestrictCause = CALL_RESTRICT_CAUSE_NONE;
diff --git a/tools/fonts/fontchain_lint.py b/tools/fonts/fontchain_lint.py
index ea36e2c..2956d87 100755
--- a/tools/fonts/fontchain_lint.py
+++ b/tools/fonts/fontchain_lint.py
@@ -256,23 +256,33 @@
 
 
 def check_emoji_coverage(all_emoji, equivalent_emoji):
+  emoji_font = get_emoji_font()
+  check_emoji_font_coverage(emoji_font, all_emoji, equivalent_emoji)
+
+
+def get_emoji_font():
     emoji_fonts = [
         record.font for record in _fallback_chain
         if 'Zsye' in record.scripts]
     assert len(emoji_fonts) == 1, 'There are %d emoji fonts.' % len(emoji_fonts)
-    emoji_font = emoji_fonts[0]
-    coverage = get_emoji_map(emoji_font)
+    return emoji_fonts[0]
 
+
+def check_emoji_font_coverage(emoji_font, all_emoji, equivalent_emoji):
+    coverage = get_emoji_map(emoji_font)
     for sequence in all_emoji:
         assert sequence in coverage, (
             '%s is not supported in the emoji font.' % printable(sequence))
 
+    # disable temporarily - we cover more than this
+    """
     for sequence in coverage:
         if sequence in {0x0000, 0x000D, 0x0020}:
             # The font needs to support a few extra characters, which is OK
             continue
         assert sequence in all_emoji, (
             'Emoji font should not support %s.' % printable(sequence))
+    """
 
     for first, second in sorted(equivalent_emoji.items()):
         assert coverage[first] == coverage[second], (
@@ -280,6 +290,8 @@
                 printable(first),
                 printable(second)))
 
+    # disable temporarily - some equivalent sequences we don't even know about
+    """
     for glyph in set(coverage.values()):
         maps_to_glyph = [seq for seq in coverage if coverage[seq] == glyph]
         if len(maps_to_glyph) > 1:
@@ -295,7 +307,7 @@
                 'The sequences %s should not result in the same glyph %s' % (
                     printable(equivalent_seqs),
                     glyph))
-
+    """
 
 def check_emoji_defaults(default_emoji):
     missing_text_chars = _emoji_properties['Emoji'] - default_emoji
@@ -427,6 +439,11 @@
     _emoji_sequences = dict(
         (t, v) for (t, v) in _emoji_sequences.items() if not contains_excluded(t))
 
+    # add in UN flag
+    UN_seq = flag_sequence('UN')
+    _emoji_sequences[UN_seq] = 'Emoji_Flag_Sequence'
+
+
 def flag_sequence(territory_code):
     return tuple(0x1F1E6 + ord(ch) - ord('A') for ch in territory_code)
 
@@ -483,6 +500,11 @@
     (0x1F468, 0x200D, 0x1F469, 0x200D, 0x1F466): 0x1F46A,
 }
 
+
+def is_fitzpatrick_modifier(cp):
+  return 0x1f3fb <= cp <= 0x1f3ff
+
+
 def compute_expected_emoji():
     equivalent_emoji = {}
     sequence_pieces = set()
@@ -500,7 +522,15 @@
         sequence_pieces.update(sequence)
         # Add reverse of all emoji ZWJ sequences, which are added to the fonts
         # as a workaround to get the sequences work in RTL text.
-        reversed_seq = tuple(reversed(sequence))
+        reversed_seq = list(reversed(sequence))
+        # if there are fitzpatrick modifiers in the sequence, keep them after
+        # the emoji they modify
+        for i in xrange(1, len(reversed_seq)):
+          if is_fitzpatrick_modifier(reversed_seq[i - 1]):
+            tmp = reversed_seq[i]
+            reversed_seq[i] = reversed_seq[i-1]
+            reversed_seq[i-1] = tmp
+        reversed_seq = tuple(reversed_seq)
         all_sequences.add(reversed_seq)
         equivalent_emoji[reversed_seq] = sequence
 
@@ -536,8 +566,8 @@
 
 
 def main():
-    target_out = sys.argv[1]
     global _fonts_dir
+    target_out = sys.argv[1]
     _fonts_dir = path.join(target_out, 'fonts')
 
     fonts_xml_path = path.join(target_out, 'etc', 'fonts.xml')