Merge "Cache the default launcher." 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/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/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 765a3a8..3eb2ac3 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -6380,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/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_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/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/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..90b4e39 100644
--- a/docs/html/preview/api-overview.jd
+++ b/docs/html/preview/api-overview.jd
@@ -755,6 +755,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/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..b1bcd8b 100644
--- a/docs/html/preview/download.jd
+++ b/docs/html/preview/download.jd
@@ -302,72 +302,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/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/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/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/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/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index 39a34121..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/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/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/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/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/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 97b46c4..8716811 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -643,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;
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..46efd98
--- /dev/null
+++ b/services/core/java/com/android/server/pm/CompilerStats.java
@@ -0,0 +1,294 @@
+/*
+ * 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);
+            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 0061171..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.
@@ -18211,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;
 
@@ -18328,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)) {
@@ -18449,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();
@@ -18811,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);
@@ -18875,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();
@@ -21036,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/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/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/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;