Merge "Fixed BugreportReceiverTest failures:"
diff --git a/api/test-current.txt b/api/test-current.txt
index ce7c674..e14b921 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -29290,6 +29290,7 @@
     method public static final long getStartElapsedRealtime();
     method public static final long getStartUptimeMillis();
     method public static final int getThreadPriority(int) throws java.lang.IllegalArgumentException;
+    method public static final int getThreadScheduler(int) throws java.lang.IllegalArgumentException;
     method public static final int getUidForName(java.lang.String);
     method public static final boolean is64Bit();
     method public static boolean isApplicationUid(int);
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
index 5419143..9b9cbee 100644
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -250,9 +250,6 @@
                 if (VDBG) Log.d(TAG, "onCharacteristicRead() - Device=" + address
                             + " handle=" + handle + " Status=" + status);
 
-                 Log.w(TAG, "onCharacteristicRead() - Device=" + address
-                            + " handle=" + handle + " Status=" + status);
-
                 if (!address.equals(mDevice.getAddress())) {
                     return;
                 }
diff --git a/core/java/android/bluetooth/BluetoothGattCharacteristic.java b/core/java/android/bluetooth/BluetoothGattCharacteristic.java
index 01f82e6..1cc2270 100644
--- a/core/java/android/bluetooth/BluetoothGattCharacteristic.java
+++ b/core/java/android/bluetooth/BluetoothGattCharacteristic.java
@@ -321,10 +321,10 @@
     }
 
     /**
-     * Returns the deisred key size.
+     * Returns the desired key size.
      * @hide
      */
-    /*package*/ int getKeySize() {
+    public int getKeySize() {
         return mKeySize;
     }
 
@@ -393,6 +393,14 @@
     }
 
     /**
+     * Force the instance ID.
+     * @hide
+     */
+    public void setInstanceId(int instanceId) {
+        mInstance = instanceId;
+    }
+
+    /**
      * Returns the properties of this characteristic.
      *
      * <p>The properties contain a bit mask of property flags indicating
diff --git a/core/java/android/bluetooth/BluetoothGattDescriptor.java b/core/java/android/bluetooth/BluetoothGattDescriptor.java
index 28317c4..1a4fa48 100644
--- a/core/java/android/bluetooth/BluetoothGattDescriptor.java
+++ b/core/java/android/bluetooth/BluetoothGattDescriptor.java
@@ -227,6 +227,14 @@
     }
 
     /**
+     * Force the instance ID.
+     * @hide
+     */
+    public void setInstanceId(int instanceId) {
+        mInstance = instanceId;
+    }
+
+    /**
      * Returns the permissions for this descriptor.
      *
      * @return Permissions of this descriptor
diff --git a/core/java/android/bluetooth/BluetoothGattServer.java b/core/java/android/bluetooth/BluetoothGattServer.java
index f451340..d3c6444 100644
--- a/core/java/android/bluetooth/BluetoothGattServer.java
+++ b/core/java/android/bluetooth/BluetoothGattServer.java
@@ -52,6 +52,7 @@
     private Object mServerIfLock = new Object();
     private int mServerIf;
     private int mTransport;
+    private BluetoothGattService mPendingService;
     private List<BluetoothGattService> mServices;
 
     private static final int CALLBACK_REG_TIMEOUT = 10000;
@@ -109,17 +110,37 @@
              * Service has been added
              * @hide
              */
-            public void onServiceAdded(int status, int srvcType,
-                                       int srvcInstId, ParcelUuid srvcId) {
-                UUID srvcUuid = srvcId.getUuid();
-                if (DBG) Log.d(TAG, "onServiceAdded() - service=" + srvcUuid
-                    + "status=" + status);
+            public void onServiceAdded(int status, BluetoothGattService service) {
+                if (DBG) Log.d(TAG, "onServiceAdded() - handle=" + service.getInstanceId()
+                    + " uuid=" + service.getUuid() + " status=" + status);
 
-                BluetoothGattService service = getService(srvcUuid, srvcInstId, srvcType);
-                if (service == null) return;
+                if (mPendingService == null)
+                    return;
+
+                BluetoothGattService tmp = mPendingService;
+                mPendingService = null;
+
+                // Rewrite newly assigned handles to existing service.
+                tmp.setInstanceId(service.getInstanceId());
+                List<BluetoothGattCharacteristic> temp_chars = tmp.getCharacteristics();
+                List<BluetoothGattCharacteristic> svc_chars = service.getCharacteristics();
+                for (int i=0; i<svc_chars.size(); i++) {
+                    BluetoothGattCharacteristic temp_char = temp_chars.get(i);
+                    BluetoothGattCharacteristic svc_char = svc_chars.get(i);
+
+                    temp_char.setInstanceId(svc_char.getInstanceId());
+
+                    List<BluetoothGattDescriptor> temp_descs = temp_char.getDescriptors();
+                    List<BluetoothGattDescriptor> svc_descs = svc_char.getDescriptors();
+                    for (int j=0; j<svc_descs.size(); j++) {
+                        temp_descs.get(i).setInstanceId(svc_descs.get(i).getInstanceId());
+                    }
+                }
+
+                mServices.add(tmp);
 
                 try {
-                    mCallback.onServiceAdded((int)status, service);
+                    mCallback.onServiceAdded((int)status, tmp);
                 } catch (Exception ex) {
                     Log.w(TAG, "Unhandled exception in callback", ex);
                 }
@@ -130,19 +151,15 @@
              * @hide
              */
             public void onCharacteristicReadRequest(String address, int transId,
-                            int offset, boolean isLong, int srvcType, int srvcInstId,
-                            ParcelUuid srvcId, int charInstId, ParcelUuid charId) {
-                UUID srvcUuid = srvcId.getUuid();
-                UUID charUuid = charId.getUuid();
-                if (VDBG) Log.d(TAG, "onCharacteristicReadRequest() - "
-                    + "service=" + srvcUuid + ", characteristic=" + charUuid);
+                            int offset, boolean isLong, int handle) {
+                if (VDBG) Log.d(TAG, "onCharacteristicReadRequest() - handle=" + handle);
 
                 BluetoothDevice device = mAdapter.getRemoteDevice(address);
-                BluetoothGattService service = getService(srvcUuid, srvcInstId, srvcType);
-                if (service == null) return;
-
-                BluetoothGattCharacteristic characteristic = service.getCharacteristic(charUuid);
-                if (characteristic == null) return;
+                BluetoothGattCharacteristic characteristic = getCharacteristicByHandle(handle);
+                if (characteristic == null) {
+                    Log.w(TAG, "onCharacteristicReadRequest() no char for handle " + handle);
+                    return;
+                }
 
                 try {
                     mCallback.onCharacteristicReadRequest(device, transId, offset, characteristic);
@@ -156,25 +173,15 @@
              * @hide
              */
             public void onDescriptorReadRequest(String address, int transId,
-                            int offset, boolean isLong, int srvcType, int srvcInstId,
-                            ParcelUuid srvcId, int charInstId, ParcelUuid charId,
-                            ParcelUuid descrId) {
-                UUID srvcUuid = srvcId.getUuid();
-                UUID charUuid = charId.getUuid();
-                UUID descrUuid = descrId.getUuid();
-                if (VDBG) Log.d(TAG, "onCharacteristicReadRequest() - "
-                    + "service=" + srvcUuid + ", characteristic=" + charUuid
-                    + "descriptor=" + descrUuid);
+                            int offset, boolean isLong, int handle) {
+                if (VDBG) Log.d(TAG, "onCharacteristicReadRequest() - handle=" + handle);
 
                 BluetoothDevice device = mAdapter.getRemoteDevice(address);
-                BluetoothGattService service = getService(srvcUuid, srvcInstId, srvcType);
-                if (service == null) return;
-
-                BluetoothGattCharacteristic characteristic = service.getCharacteristic(charUuid);
-                if (characteristic == null) return;
-
-                BluetoothGattDescriptor descriptor = characteristic.getDescriptor(descrUuid);
-                if (descriptor == null) return;
+                BluetoothGattDescriptor descriptor = getDescriptorByHandle(handle);
+                if (descriptor == null) {
+                    Log.w(TAG, "onDescriptorReadRequest() no desc for handle " + handle);
+                    return;
+                }
 
                 try {
                     mCallback.onDescriptorReadRequest(device, transId, offset, descriptor);
@@ -189,19 +196,15 @@
              */
             public void onCharacteristicWriteRequest(String address, int transId,
                             int offset, int length, boolean isPrep, boolean needRsp,
-                            int srvcType, int srvcInstId, ParcelUuid srvcId,
-                            int charInstId, ParcelUuid charId, byte[] value) {
-                UUID srvcUuid = srvcId.getUuid();
-                UUID charUuid = charId.getUuid();
-                if (VDBG) Log.d(TAG, "onCharacteristicWriteRequest() - "
-                    + "service=" + srvcUuid + ", characteristic=" + charUuid);
+                            int handle, byte[] value) {
+                if (VDBG) Log.d(TAG, "onCharacteristicWriteRequest() - handle=" + handle);
 
                 BluetoothDevice device = mAdapter.getRemoteDevice(address);
-                BluetoothGattService service = getService(srvcUuid, srvcInstId, srvcType);
-                if (service == null) return;
-
-                BluetoothGattCharacteristic characteristic = service.getCharacteristic(charUuid);
-                if (characteristic == null) return;
+                BluetoothGattCharacteristic characteristic = getCharacteristicByHandle(handle);
+                if (characteristic == null) {
+                    Log.w(TAG, "onCharacteristicWriteRequest() no char for handle " + handle);
+                    return;
+                }
 
                 try {
                     mCallback.onCharacteristicWriteRequest(device, transId, characteristic,
@@ -216,28 +219,16 @@
              * Remote client descriptor write request.
              * @hide
              */
-            public void onDescriptorWriteRequest(String address, int transId,
-                            int offset, int length, boolean isPrep, boolean needRsp,
-                            int srvcType, int srvcInstId, ParcelUuid srvcId,
-                            int charInstId, ParcelUuid charId, ParcelUuid descrId,
-                            byte[] value) {
-                UUID srvcUuid = srvcId.getUuid();
-                UUID charUuid = charId.getUuid();
-                UUID descrUuid = descrId.getUuid();
-                if (VDBG) Log.d(TAG, "onDescriptorWriteRequest() - "
-                    + "service=" + srvcUuid + ", characteristic=" + charUuid
-                    + "descriptor=" + descrUuid);
+            public void onDescriptorWriteRequest(String address, int transId, int offset,
+                            int length, boolean isPrep, boolean needRsp, int handle, byte[] value) {
+                if (VDBG) Log.d(TAG, "onDescriptorWriteRequest() - handle=" + handle);
 
                 BluetoothDevice device = mAdapter.getRemoteDevice(address);
-
-                BluetoothGattService service = getService(srvcUuid, srvcInstId, srvcType);
-                if (service == null) return;
-
-                BluetoothGattCharacteristic characteristic = service.getCharacteristic(charUuid);
-                if (characteristic == null) return;
-
-                BluetoothGattDescriptor descriptor = characteristic.getDescriptor(descrUuid);
-                if (descriptor == null) return;
+                BluetoothGattDescriptor descriptor = getDescriptorByHandle(handle);
+                if (descriptor == null) {
+                    Log.w(TAG, "onDescriptorWriteRequest() no desc for handle " + handle);
+                    return;
+                }
 
                 try {
                     mCallback.onDescriptorWriteRequest(device, transId, descriptor,
@@ -318,6 +309,36 @@
     }
 
     /**
+     * Returns a characteristic with given handle.
+     * @hide
+     */
+    /*package*/ BluetoothGattCharacteristic getCharacteristicByHandle(int handle) {
+        for(BluetoothGattService svc : mServices) {
+            for(BluetoothGattCharacteristic charac : svc.getCharacteristics()) {
+                if (charac.getInstanceId() == handle)
+                    return charac;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns a descriptor with given handle.
+     * @hide
+     */
+    /*package*/ BluetoothGattDescriptor getDescriptorByHandle(int handle) {
+        for(BluetoothGattService svc : mServices) {
+            for(BluetoothGattCharacteristic charac : svc.getCharacteristics()) {
+                for(BluetoothGattDescriptor desc : charac.getDescriptors()) {
+                    if (desc.getInstanceId() == handle)
+                        return desc;
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
      * Close this GATT server instance.
      *
      * Application should call this method as early as possible after it is done with
@@ -537,9 +558,7 @@
 
         try {
             mService.sendNotification(mServerIf, device.getAddress(),
-                    service.getType(), service.getInstanceId(),
-                    new ParcelUuid(service.getUuid()), characteristic.getInstanceId(),
-                    new ParcelUuid(characteristic.getUuid()), confirm,
+                    characteristic.getInstanceId(), confirm,
                     characteristic.getValue());
         } catch (RemoteException e) {
             Log.e(TAG,"",e);
@@ -568,39 +587,10 @@
         if (DBG) Log.d(TAG, "addService() - service: " + service.getUuid());
         if (mService == null || mServerIf == 0) return false;
 
-        mServices.add(service);
+        mPendingService = service;
 
         try {
-            mService.beginServiceDeclaration(mServerIf, service.getType(),
-                service.getInstanceId(), service.getHandles(),
-                new ParcelUuid(service.getUuid()), service.isAdvertisePreferred());
-
-            List<BluetoothGattService> includedServices = service.getIncludedServices();
-            for (BluetoothGattService includedService : includedServices) {
-                mService.addIncludedService(mServerIf,
-                    includedService.getType(),
-                    includedService.getInstanceId(),
-                    new ParcelUuid(includedService.getUuid()));
-            }
-
-            List<BluetoothGattCharacteristic> characteristics = service.getCharacteristics();
-            for (BluetoothGattCharacteristic characteristic : characteristics) {
-                int permission = ((characteristic.getKeySize() - 7) << 12)
-                                    + characteristic.getPermissions();
-                mService.addCharacteristic(mServerIf,
-                    new ParcelUuid(characteristic.getUuid()),
-                    characteristic.getProperties(), permission);
-
-                List<BluetoothGattDescriptor> descriptors = characteristic.getDescriptors();
-                for (BluetoothGattDescriptor descriptor: descriptors) {
-                    permission = ((characteristic.getKeySize() - 7) << 12)
-                                        + descriptor.getPermissions();
-                    mService.addDescriptor(mServerIf,
-                        new ParcelUuid(descriptor.getUuid()), permission);
-                }
-            }
-
-            mService.endServiceDeclaration(mServerIf);
+            mService.addService(mServerIf, service);
         } catch (RemoteException e) {
             Log.e(TAG,"",e);
             return false;
@@ -626,8 +616,7 @@
         if (intService == null) return false;
 
         try {
-            mService.removeService(mServerIf, service.getType(),
-                service.getInstanceId(), new ParcelUuid(service.getUuid()));
+            mService.removeService(mServerIf, service.getInstanceId());
             mServices.remove(intService);
         } catch (RemoteException e) {
             Log.e(TAG,"",e);
diff --git a/core/java/android/bluetooth/BluetoothGattService.java b/core/java/android/bluetooth/BluetoothGattService.java
index a4e1dc0..c888a45 100644
--- a/core/java/android/bluetooth/BluetoothGattService.java
+++ b/core/java/android/bluetooth/BluetoothGattService.java
@@ -250,7 +250,6 @@
 
     /**
      * Force the instance ID.
-     * This is needed for conformance testing only.
      * @hide
      */
     public void setInstanceId(int instanceId) {
diff --git a/core/java/android/bluetooth/IBluetoothGatt.aidl b/core/java/android/bluetooth/IBluetoothGatt.aidl
index adb07df..d6ea5c8 100644
--- a/core/java/android/bluetooth/IBluetoothGatt.aidl
+++ b/core/java/android/bluetooth/IBluetoothGatt.aidl
@@ -17,6 +17,7 @@
 package android.bluetooth;
 
 import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothGattService;
 import android.bluetooth.le.AdvertiseSettings;
 import android.bluetooth.le.AdvertiseData;
 import android.bluetooth.le.ScanFilter;
@@ -66,26 +67,14 @@
 
     void registerServer(in ParcelUuid appId, in IBluetoothGattServerCallback callback);
     void unregisterServer(in int serverIf);
-    void serverConnect(in int servertIf, in String address, in boolean isDirect, in int transport);
+    void serverConnect(in int serverIf, in String address, in boolean isDirect, in int transport);
     void serverDisconnect(in int serverIf, in String address);
-    void beginServiceDeclaration(in int serverIf, in int srvcType,
-                            in int srvcInstanceId, in int minHandles,
-                            in ParcelUuid srvcId, boolean advertisePreferred);
-    void addIncludedService(in int serverIf, in int srvcType,
-                            in int srvcInstanceId, in ParcelUuid srvcId);
-    void addCharacteristic(in int serverIf, in ParcelUuid charId,
-                            in int properties, in int permissions);
-    void addDescriptor(in int serverIf, in ParcelUuid descId,
-                            in int permissions);
-    void endServiceDeclaration(in int serverIf);
-    void removeService(in int serverIf, in int srvcType,
-                            in int srvcInstanceId, in ParcelUuid srvcId);
+    void addService(in int serverIf, in BluetoothGattService service);
+    void removeService(in int serverIf, in int handle);
     void clearServices(in int serverIf);
     void sendResponse(in int serverIf, in String address, in int requestId,
                             in int status, in int offset, in byte[] value);
-    void sendNotification(in int serverIf, in String address, in int srvcType,
-                            in int srvcInstanceId, in ParcelUuid srvcId,
-                            in int charInstanceId, in ParcelUuid charId,
+    void sendNotification(in int serverIf, in String address, in int handle,
                             in boolean confirm, in byte[] value);
     void disconnectAll();
     void unregAll();
diff --git a/core/java/android/bluetooth/IBluetoothGattServerCallback.aidl b/core/java/android/bluetooth/IBluetoothGattServerCallback.aidl
index 8b202b2..0bcb07b 100644
--- a/core/java/android/bluetooth/IBluetoothGattServerCallback.aidl
+++ b/core/java/android/bluetooth/IBluetoothGattServerCallback.aidl
@@ -15,8 +15,7 @@
  */
 package android.bluetooth;
 
-import android.os.ParcelUuid;
-
+import android.bluetooth.BluetoothGattService;
 
 /**
  * Callback definitions for interacting with BLE / GATT
@@ -27,36 +26,18 @@
     void onScanResult(in String address, in int rssi, in byte[] advData);
     void onServerConnectionState(in int status, in int serverIf,
                                  in boolean connected, in String address);
-    void onServiceAdded(in int status, in int srvcType,
-                        in int srvcInstId, in ParcelUuid srvcId);
-    void onCharacteristicReadRequest(in String address, in int transId,
-                                     in int offset, in boolean isLong,
-                                     in int srvcType,
-                                     in int srvcInstId, in ParcelUuid srvcId,
-                                     in int charInstId, in ParcelUuid charId);
+    void onServiceAdded(in int status, in BluetoothGattService service);
+    void onCharacteristicReadRequest(in String address, in int transId, in int offset,
+                                     in boolean isLong, in int handle);
     void onDescriptorReadRequest(in String address, in int transId,
                                      in int offset, in boolean isLong,
-                                     in int srvcType,
-                                     in int srvcInstId, in ParcelUuid srvcId,
-                                     in int charInstId, in ParcelUuid charId,
-                                     in ParcelUuid descrId);
-    void onCharacteristicWriteRequest(in String address, in int transId,
-                                     in int offset, in int length,
-                                     in boolean isPrep,
-                                     in boolean needRsp,
-                                     in int srvcType,
-                                     in int srvcInstId, in ParcelUuid srvcId,
-                                     in int charInstId, in ParcelUuid charId,
-                                     in byte[] value);
-    void onDescriptorWriteRequest(in String address, in int transId,
-                                     in int offset, in int length,
-                                     in boolean isPrep,
-                                     in boolean needRsp,
-                                     in int srvcType,
-                                     in int srvcInstId, in ParcelUuid srvcId,
-                                     in int charInstId, in ParcelUuid charId,
-                                     in ParcelUuid descrId,
-                                     in byte[] value);
+                                     in int handle);
+    void onCharacteristicWriteRequest(in String address, in int transId, in int offset,
+                                     in int length, in boolean isPrep, in boolean needRsp,
+                                     in int handle, in byte[] value);
+    void onDescriptorWriteRequest(in String address, in int transId, in int offset,
+                                     in int length, in boolean isPrep, in boolean needRsp,
+                                     in int handle, in byte[] value);
     void onExecuteWrite(in String address, in int transId, in boolean execWrite);
     void onNotificationSent(in String address, in int status);
     void onMtuChanged(in String address, in int mtu);
diff --git a/core/java/android/os/Looper.java b/core/java/android/os/Looper.java
index b58ff1f..d299672 100644
--- a/core/java/android/os/Looper.java
+++ b/core/java/android/os/Looper.java
@@ -147,7 +147,7 @@
             }
 
             final long traceTag = me.mTraceTag;
-            if (traceTag != 0) {
+            if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {
                 Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
             }
             try {
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index edd8a39..e9ebe2d 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -16,6 +16,9 @@
 
 package android.os;
 
+import android.annotation.TestApi;
+import android.net.LocalSocket;
+import android.net.LocalSocketAddress;
 import android.system.Os;
 import android.system.OsConstants;
 import android.util.Log;
@@ -717,6 +720,24 @@
             throws IllegalArgumentException;
     
     /**
+     * Return the current scheduling policy of a thread, based on Linux.
+     *
+     * @param tid The identifier of the thread/process to get the scheduling policy.
+     *
+     * @throws IllegalArgumentException Throws IllegalArgumentException if
+     * <var>tid</var> does not exist, or if <var>priority</var> is out of range for the policy.
+     * @throws SecurityException Throws SecurityException if your process does
+     * not have permission to modify the given thread, or to use the given
+     * scheduling policy or priority.
+     *
+     * {@hide}
+     */
+    
+    @TestApi
+    public static final native int getThreadScheduler(int tid)
+            throws IllegalArgumentException;
+
+    /**
      * Set the scheduling policy and priority of a thread, based on Linux.
      *
      * @param tid The identifier of the thread/process to change.
@@ -731,6 +752,7 @@
      *
      * {@hide}
      */
+
     public static final native void setThreadScheduler(int tid, int policy, int priority)
             throws IllegalArgumentException;
 
diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java
index b34dfe0..3180175 100644
--- a/core/java/android/view/TextureView.java
+++ b/core/java/android/view/TextureView.java
@@ -218,35 +218,47 @@
     /** @hide */
     @Override
     protected void onDetachedFromWindowInternal() {
-        destroySurface();
+        destroyHardwareLayer();
+        releaseSurfaceTexture();
         super.onDetachedFromWindowInternal();
     }
 
-    private void destroySurface() {
+    /**
+     * @hide
+     */
+    @Override
+    protected void destroyHardwareResources() {
+        destroyHardwareLayer();
+        mUpdateSurface = mSurface != null;
+    }
+
+    private void destroyHardwareLayer() {
         if (mLayer != null) {
             mLayer.detachSurfaceTexture();
-
-            boolean shouldRelease = true;
-            if (mListener != null) {
-                shouldRelease = mListener.onSurfaceTextureDestroyed(mSurface);
-            }
-
-            synchronized (mNativeWindowLock) {
-                nDestroyNativeWindow();
-            }
-
             mLayer.destroy();
-            if (shouldRelease) mSurface.release();
-            mSurface = null;
             mLayer = null;
-
-            // Make sure if/when new layer gets re-created, transform matrix will
-            // be re-applied.
             mMatrixChanged = true;
-            mHadSurface = true;
         }
     }
 
+    private void releaseSurfaceTexture() {
+        boolean shouldRelease = true;
+
+        if (mListener != null) {
+            shouldRelease = mListener.onSurfaceTextureDestroyed(mSurface);
+        }
+
+        synchronized (mNativeWindowLock) {
+            nDestroyNativeWindow();
+        }
+
+        if (shouldRelease) {
+            mSurface.release();
+        }
+        mSurface = null;
+        mHadSurface = true;
+    }
+
     /**
      * The layer type of a TextureView is ignored since a TextureView is always
      * considered to act as a hardware layer. The optional paint supplied to this
@@ -366,9 +378,9 @@
                 // Create a new SurfaceTexture for the layer.
                 mSurface = new SurfaceTexture(false);
                 mLayer.setSurfaceTexture(mSurface);
+                nCreateNativeWindow(mSurface);
             }
             mSurface.setDefaultBufferSize(getWidth(), getHeight());
-            nCreateNativeWindow(mSurface);
 
             mSurface.setOnFrameAvailableListener(mUpdateListener, mAttachInfo.mHandler);
 
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index cdd7098..30de74ae 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -821,6 +821,17 @@
     static boolean sTextureViewIgnoresDrawableSetters = false;
 
     /**
+     * Prior to N, some ViewGroups would not convert LayoutParams properly even though both extend
+     * MarginLayoutParams. For instance, converting LinearLayout.LayoutParams to
+     * RelativeLayout.LayoutParams would lose margin information. This is fixed on N but target API
+     * check is implemented for backwards compatibility.
+     *
+     * {@hide}
+     */
+    protected static boolean sPreserveMarginParamsInLayoutParamConversion;
+
+
+    /**
      * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when
      * calling setFlags.
      */
@@ -4054,6 +4065,10 @@
             // On N+, we throw, but that breaks compatibility with apps that use these methods.
             sTextureViewIgnoresDrawableSetters = targetSdkVersion <= M;
 
+            // Prior to N, we would drop margins in LayoutParam conversions. The fix triggers bugs
+            // in apps so we target check it to avoid breaking existing apps.
+            sPreserveMarginParamsInLayoutParamConversion = targetSdkVersion >= N;
+
             sCompatibilityDone = true;
         }
     }
diff --git a/core/java/android/widget/FrameLayout.java b/core/java/android/widget/FrameLayout.java
index 029313c..b8c74d8 100644
--- a/core/java/android/widget/FrameLayout.java
+++ b/core/java/android/widget/FrameLayout.java
@@ -382,13 +382,14 @@
 
     @Override
     protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams lp) {
-        if (lp instanceof LayoutParams) {
-            return new LayoutParams((LayoutParams) lp);
-        } else if (lp instanceof MarginLayoutParams) {
-            return new LayoutParams((MarginLayoutParams) lp);
-        } else {
-            return new LayoutParams(lp);
+        if (sPreserveMarginParamsInLayoutParamConversion) {
+            if (lp instanceof LayoutParams) {
+                return new LayoutParams((LayoutParams) lp);
+            } else if (lp instanceof MarginLayoutParams) {
+                return new LayoutParams((MarginLayoutParams) lp);
+            }
         }
+        return new LayoutParams(lp);
     }
 
     @Override
diff --git a/core/java/android/widget/GridLayout.java b/core/java/android/widget/GridLayout.java
index 726586e..af2852c 100644
--- a/core/java/android/widget/GridLayout.java
+++ b/core/java/android/widget/GridLayout.java
@@ -868,13 +868,14 @@
 
     @Override
     protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams lp) {
-        if (lp instanceof LayoutParams) {
-            return new LayoutParams((LayoutParams) lp);
-        } else if (lp instanceof MarginLayoutParams) {
-            return new LayoutParams((MarginLayoutParams) lp);
-        } else {
-            return new LayoutParams(lp);
+        if (sPreserveMarginParamsInLayoutParamConversion) {
+            if (lp instanceof LayoutParams) {
+                return new LayoutParams((LayoutParams) lp);
+            } else if (lp instanceof MarginLayoutParams) {
+                return new LayoutParams((MarginLayoutParams) lp);
+            }
         }
+        return new LayoutParams(lp);
     }
 
     // Draw grid
diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java
index 33d335a..e2c535c 100644
--- a/core/java/android/widget/LinearLayout.java
+++ b/core/java/android/widget/LinearLayout.java
@@ -1871,13 +1871,14 @@
 
     @Override
     protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams lp) {
-        if (lp instanceof LayoutParams) {
-            return new LayoutParams((LayoutParams) lp);
-        } else if (lp instanceof MarginLayoutParams) {
-            return new LayoutParams((MarginLayoutParams) lp);
-        } else {
-            return new LayoutParams(lp);
+        if (sPreserveMarginParamsInLayoutParamConversion) {
+            if (lp instanceof LayoutParams) {
+                return new LayoutParams((LayoutParams) lp);
+            } else if (lp instanceof MarginLayoutParams) {
+                return new LayoutParams((MarginLayoutParams) lp);
+            }
         }
+        return new LayoutParams(lp);
     }
 
 
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index 0136542..a189d3c 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -1104,13 +1104,14 @@
 
     @Override
     protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams lp) {
-        if (lp instanceof LayoutParams) {
-            return new LayoutParams((LayoutParams) lp);
-        } else if (lp instanceof MarginLayoutParams) {
-            return new LayoutParams((MarginLayoutParams) lp);
-        } else {
-            return new LayoutParams(lp);
+        if (sPreserveMarginParamsInLayoutParamConversion) {
+            if (lp instanceof LayoutParams) {
+                return new LayoutParams((LayoutParams) lp);
+            } else if (lp instanceof MarginLayoutParams) {
+                return new LayoutParams((MarginLayoutParams) lp);
+            }
         }
+        return new LayoutParams(lp);
     }
 
     /** @hide */
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 77cc54ff..7a4f74f 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -538,7 +538,8 @@
             OsConstants.CAP_SYS_NICE,
             OsConstants.CAP_SYS_RESOURCE,
             OsConstants.CAP_SYS_TIME,
-            OsConstants.CAP_SYS_TTY_CONFIG
+            OsConstants.CAP_SYS_TTY_CONFIG,
+            OsConstants.CAP_WAKE_ALARM
         );
         /* Containers run without this capability, so avoid setting it in that case */
         if (!SystemProperties.getBoolean(PROPERTY_RUNNING_IN_CONTAINER, false)) {
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index 7487619..23e291f 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -440,6 +440,23 @@
 #endif
 }
 
+jint android_os_Process_getThreadScheduler(JNIEnv* env, jclass clazz,
+                                              jint tid)
+{
+    int policy = 0;
+// linux has sched_getscheduler(), others don't.
+#if defined(__linux__)
+    errno = 0;
+    policy = sched_getscheduler(tid);
+    if (errno != 0) {
+        signalExceptionForPriorityError(env, errno);
+    }
+#else
+    signalExceptionForPriorityError(env, ENOSYS);
+#endif
+    return policy;
+}
+
 void android_os_Process_setThreadScheduler(JNIEnv* env, jclass clazz,
                                               jint tid, jint policy, jint pri)
 {
@@ -1189,6 +1206,7 @@
     {"setCanSelfBackground", "(Z)V", (void*)android_os_Process_setCanSelfBackground},
     {"setThreadPriority",   "(I)V", (void*)android_os_Process_setCallingThreadPriority},
     {"getThreadPriority",   "(I)I", (void*)android_os_Process_getThreadPriority},
+    {"getThreadScheduler",   "(I)I", (void*)android_os_Process_getThreadScheduler},
     {"setThreadGroup",      "(II)V", (void*)android_os_Process_setThreadGroup},
     {"setProcessGroup",     "(II)V", (void*)android_os_Process_setProcessGroup},
     {"getProcessGroup",     "(I)I", (void*)android_os_Process_getProcessGroup},
diff --git a/core/res/res/layout-watch/date_picker_dialog.xml b/core/res/res/layout-watch/date_picker_dialog.xml
new file mode 100644
index 0000000..b8772bc
--- /dev/null
+++ b/core/res/res/layout-watch/date_picker_dialog.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2007 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.
+-->
+
+<DatePicker xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/datePicker"
+    android:layout_gravity="center_horizontal"
+    android:gravity="center_horizontal"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:spinnersShown="true"
+    android:calendarViewShown="false"
+    android:datePickerMode="@integer/date_picker_mode" />
diff --git a/core/res/res/layout-watch/number_picker_material.xml b/core/res/res/layout-watch/number_picker_material.xml
deleted file mode 100644
index a1c0921..0000000
--- a/core/res/res/layout-watch/number_picker_material.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-**
-** Copyright 2012, 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.
-*/
--->
-
-<merge xmlns:android="http://schemas.android.com/apk/res/android">
-
-    <view class="android.widget.NumberPicker$CustomEditText"
-        android:textAppearance="?android:attr/textAppearanceLarge"
-        android:id="@+id/numberpicker_input"
-        android:layout_width="fill_parent"
-        android:layout_height="wrap_content"
-        android:gravity="center"
-        android:singleLine="true"
-        android:background="@null" />
-
-</merge>
diff --git a/core/res/res/layout-watch/time_picker_dialog.xml b/core/res/res/layout-watch/time_picker_dialog.xml
new file mode 100644
index 0000000..788602b
--- /dev/null
+++ b/core/res/res/layout-watch/time_picker_dialog.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2007, 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.
+*/
+-->
+
+<TimePicker xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/timePicker"
+    android:layout_gravity="center_horizontal"
+    android:gravity="center_horizontal"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:timePickerMode="@integer/time_picker_mode" />
diff --git a/core/res/res/layout/date_picker_legacy_holo.xml b/core/res/res/layout/date_picker_legacy_holo.xml
index b465d97..a6e93c9 100644
--- a/core/res/res/layout/date_picker_legacy_holo.xml
+++ b/core/res/res/layout/date_picker_legacy_holo.xml
@@ -41,8 +41,8 @@
             android:id="@+id/month"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginTop="16dip"
-            android:layout_marginBottom="16dip"
+            android:layout_marginTop="@dimen/picker_top_margin"
+            android:layout_marginBottom="@dimen/picker_bottom_margin"
             android:layout_marginStart="8dip"
             android:layout_marginEnd="8dip"
             android:focusable="true"
@@ -54,8 +54,8 @@
             android:id="@+id/day"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginTop="16dip"
-            android:layout_marginBottom="16dip"
+            android:layout_marginTop="@dimen/picker_top_margin"
+            android:layout_marginBottom="@dimen/picker_bottom_margin"
             android:layout_marginStart="8dip"
             android:layout_marginEnd="8dip"
             android:focusable="true"
@@ -67,8 +67,8 @@
             android:id="@+id/year"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginTop="16dip"
-            android:layout_marginBottom="16dip"
+            android:layout_marginTop="@dimen/picker_top_margin"
+            android:layout_marginBottom="@dimen/picker_bottom_margin"
             android:layout_marginStart="8dip"
             android:layout_marginEnd="16dip"
             android:focusable="true"
diff --git a/core/res/res/layout/number_picker_material.xml b/core/res/res/layout/number_picker_material.xml
index b045585..6fbd2b2 100644
--- a/core/res/res/layout/number_picker_material.xml
+++ b/core/res/res/layout/number_picker_material.xml
@@ -22,4 +22,4 @@
       android:gravity="center"
       android:singleLine="true"
       android:background="@null"
-      android:textAppearance="@style/TextAppearance.Material.Body1" />
+      android:textAppearance="@style/TextAppearance.Material.NumberPicker" />
diff --git a/core/res/res/layout/time_picker_legacy_material.xml b/core/res/res/layout/time_picker_legacy_material.xml
index c6b7d3a..ee56266 100644
--- a/core/res/res/layout/time_picker_legacy_material.xml
+++ b/core/res/res/layout/time_picker_legacy_material.xml
@@ -40,8 +40,8 @@
             android:id="@+id/hour"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginTop="16dip"
-            android:layout_marginBottom="16dip"
+            android:layout_marginTop="@dimen/picker_top_margin"
+            android:layout_marginBottom="@dimen/picker_bottom_margin"
             android:focusable="true"
             android:focusableInTouchMode="true"
             />
@@ -62,8 +62,8 @@
             android:id="@+id/minute"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginTop="16dip"
-            android:layout_marginBottom="16dip"
+            android:layout_marginTop="@dimen/picker_top_margin"
+            android:layout_marginBottom="@dimen/picker_bottom_margin"
             android:focusable="true"
             android:focusableInTouchMode="true"
             />
@@ -75,8 +75,8 @@
         android:id="@+id/amPm"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_marginTop="16dip"
-        android:layout_marginBottom="16dip"
+        android:layout_marginTop="@dimen/picker_top_margin"
+        android:layout_marginBottom="@dimen/picker_bottom_margin"
         android:layout_marginStart="8dip"
         android:layout_marginEnd="8dip"
         android:focusable="true"
diff --git a/core/res/res/values-watch/dimens_material.xml b/core/res/res/values-watch/dimens_material.xml
index 96e91a5..b48cde6 100644
--- a/core/res/res/values-watch/dimens_material.xml
+++ b/core/res/res/values-watch/dimens_material.xml
@@ -35,4 +35,8 @@
     <dimen name="text_size_small_material">12sp</dimen>
 
     <item name="text_line_spacing_multiplier_material" format="float" type="dimen">1.2</item>
+
+    <!-- Date and time picker legacy dimens -->
+    <dimen name="picker_top_margin">1dip</dimen>
+    <dimen name="picker_bottom_margin">1dip</dimen>
 </resources>
diff --git a/core/res/res/values-watch/strings.xml b/core/res/res/values-watch/strings.xml
index dde8b2e..75a6f24 100644
--- a/core/res/res/values-watch/strings.xml
+++ b/core/res/res/values-watch/strings.xml
@@ -26,4 +26,10 @@
 
     <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. Override from base which says "Body Sensors". [CHAR_LIMIT=25] -->
     <string name="permgrouplab_sensors">Sensors</string>
+
+    <!-- Do not translate.  timepicker mode, overridden for watch -->
+    <string name="time_picker_mode" translatable="false">"spinner"</string>
+
+    <!-- Do not translate.  datepicker mode, overridden for watch -->
+    <string name="date_picker_mode" translatable="false">"spinner"</string>
 </resources>
diff --git a/core/res/res/values-watch/styles_material.xml b/core/res/res/values-watch/styles_material.xml
index e8d3d74..d09119f 100644
--- a/core/res/res/values-watch/styles_material.xml
+++ b/core/res/res/values-watch/styles_material.xml
@@ -70,6 +70,10 @@
 
     <style name="Widget.Material.ButtonBar" parent="Widget.Material.BaseButtonBar" />
 
+    <style name="TextAppearance.Material.NumberPicker" parent="TextAppearance.Material.Body1">
+        <item name="textSize">@dimen/text_size_medium_material</item>
+    </style>
+
     <!-- Alert dialog button bar button -->
     <style name="Widget.Material.Button.ButtonBar.AlertDialog" parent="Widget.Material.Button.Borderless.Small">
         <item name="paddingStart">@dimen/list_item_padding_start_material</item>
@@ -85,9 +89,9 @@
         <item name="solidColor">@color/transparent</item>
         <item name="selectionDivider">@drawable/numberpicker_selection_divider</item>
         <item name="selectionDividerHeight">2dp</item>
-        <item name="selectionDividersDistance">48dp</item>
-        <item name="internalMinWidth">64dp</item>
-        <item name="internalMaxHeight">180dp</item>
+        <item name="selectionDividersDistance">24dp</item>
+        <item name="internalMinWidth">32dp</item>
+        <item name="internalMaxHeight">90dp</item>
         <item name="virtualButtonPressedDrawable">?selectableItemBackground</item>
         <item name="descendantFocusability">blocksDescendants</item>
     </style>
diff --git a/core/res/res/values/dimens_material.xml b/core/res/res/values/dimens_material.xml
index f96cef9..ae31165 100644
--- a/core/res/res/values/dimens_material.xml
+++ b/core/res/res/values/dimens_material.xml
@@ -189,4 +189,8 @@
     <dimen name="day_picker_button_margin_top">0dp</dimen>
 
     <dimen name="datepicker_view_animator_height">226dp</dimen>
+
+    <!-- Date and time picker legacy dimens -->
+    <dimen name="picker_top_margin">16dip</dimen>
+    <dimen name="picker_bottom_margin">16dip</dimen>
 </resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 77de0af..5a9099b 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1955,7 +1955,7 @@
     <string name="lockscreen_access_pattern_cleared">Pattern cleared</string>
     <!-- Accessibility description sent when user adds a dot to the pattern. [CHAR LIMIT=NONE]  -->
     <string name="lockscreen_access_pattern_cell_added">Cell added</string>
-    <!-- Accessibility description sent when user adds a dot to the pattern. Announces the 
+    <!-- Accessibility description sent when user adds a dot to the pattern. Announces the
     actual cell when headphones are connected [CHAR LIMIT=NONE]  -->
     <string name="lockscreen_access_pattern_cell_added_verbose">
             Cell <xliff:g id="cell_index" example="3">%1$s</xliff:g> added</string>
@@ -2035,6 +2035,12 @@
     <!-- Button to restart the device after the factory test. -->
     <string name="factorytest_reboot">Reboot</string>
 
+    <!-- Do not translate.  timepicker mode, overridden for watch -->
+    <string name="time_picker_mode" translatable="false">"clock"</string>
+
+    <!-- Do not translate.  datepicker mode, overridden for watch -->
+    <string name="date_picker_mode" translatable="false">"calendar"</string>
+
     <!-- Do not translate.  WebView User Agent string -->
     <string name="web_user_agent" translatable="false">Mozilla/5.0 (Linux; U; <xliff:g id="x">Android %s</xliff:g>)
         AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 <xliff:g id="mobile">%s</xliff:g>Safari/534.30</string>
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index c66bc10..132402b 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -255,6 +255,8 @@
         <item name="textColor">?attr/textColorPrimary</item>
     </style>
 
+    <style name="TextAppearance.Material.NumberPicker" parent="TextAppearance.Material.Body1"/>
+
     <!-- Deprecated text styles -->
 
     <style name="TextAppearance.Material.Inverse">
@@ -687,7 +689,7 @@
     </style>
 
     <style name="Widget.Material.TimePicker">
-        <item name="timePickerMode">clock</item>
+        <item name="timePickerMode">@string/time_picker_mode</item>
         <item name="legacyLayout">@layout/time_picker_legacy_material</item>
         <!-- Attributes for new-style TimePicker. -->
         <item name="internalLayout">@layout/time_picker_material</item>
@@ -701,7 +703,7 @@
     </style>
 
     <style name="Widget.Material.DatePicker">
-        <item name="datePickerMode">calendar</item>
+        <item name="datePickerMode">@string/date_picker_mode</item>
         <item name="legacyLayout">@layout/date_picker_legacy_holo</item>
         <item name="calendarViewShown">true</item>
         <!-- Attributes for new-style DatePicker. -->
diff --git a/docs/html/_redirects.yaml b/docs/html/_redirects.yaml
index 00a7edd..fd54b7d 100644
--- a/docs/html/_redirects.yaml
+++ b/docs/html/_redirects.yaml
@@ -819,8 +819,8 @@
   to: /about/versions/marshmallow/android-6.0-changes.html#behavior-apache-http-client
 - from: /shareables/...
   to: https://commondatastorage.googleapis.com/androiddevelopers/shareables/...
-- from: /downloads/
-  to: https://commondatastorage.googleapis.com/androiddevelopers/
+- from: /downloads/...
+  to: https://commondatastorage.googleapis.com/androiddevelopers/...
 - from: /training/performance/battery/network/action-any-traffic.html
   to: /topic/performance/power/network/action-any-traffic.html
 - from: /training/performance/battery/network/action-app-traffic.html
diff --git a/docs/html/guide/topics/manifest/manifest-intro.jd b/docs/html/guide/topics/manifest/manifest-intro.jd
index c843567..851674c 100644
--- a/docs/html/guide/topics/manifest/manifest-intro.jd
+++ b/docs/html/guide/topics/manifest/manifest-intro.jd
@@ -6,50 +6,53 @@
 
 <h2>In this document</h2>
 <ol>
-<li><a href="#filestruct">Structure of the Manifest File</a></li>
-<li><a href="#filec">File Conventions</a>
-<li><a href="#filef">File Features</a>
-	<ol>
-	<li><a href="#ifs">Intent Filters</a></li>
-	<li><a href="#iconlabel">Icons and Labels</a></li>
-	<li><a href="#perms">Permissions</a></li>
-	<li><a href="#libs">Libraries</a></li>
-	</ol></li>
+<li><a href="#filestruct">Manifest file structure</a></li>
+<li><a href="#filec">File conventions</a>
+<li><a href="#filef">File features</a>
+    <ol>
+    <li><a href="#ifs">Intent filters</a></li>
+    <li><a href="#iconlabel">Icons and labels</a></li>
+    <li><a href="#perms">Permissions</a></li>
+    <li><a href="#libs">Libraries</a></li>
+    </ol></li>
 </ol>
 </div>
 </div>
 
 <p>
-  Every application must have an AndroidManifest.xml file (with precisely that
+  Every application must have an {@code AndroidManifest.xml} file (with precisely that
   name) in its root directory. <span itemprop="description">The manifest file
-  presents essential information about your app to the Android system,
-  information the system must have before it can run any of the app's
-  code.</span> Among other things, the manifest does the following:
+  provides essential information about your app to the Android system, which
+  the system must have before it can run any of the app's
+  code.</span>
+</p>
+
+<p>
+Among other things, the manifest file does the following:
 </p>
 
 <ul>
 <li>It names the Java package for the application.
 The package name serves as a unique identifier for the application.</li>
 
-<li>It describes the components of the application &mdash; the activities,
-services, broadcast receivers, and content providers that the application is
-composed of.  It names the classes that implement each of the components and
-publishes their capabilities (for example, which {@link android.content.Intent
-Intent} messages they can handle).  These declarations let the Android system
-know what the components are and under what conditions they can be launched.</li>
+<li>It describes the components of the application, which include the activities,
+services, broadcast receivers, and content providers that compose the application.
+It also names the classes that implement each of the components and
+publishes their capabilities, such as the {@link android.content.Intent
+Intent} messages that they can handle. These declarations inform the Android system
+of the components and the conditions in which they can be launched.</li>
 
-<li>It determines which processes will host application components.</li>
+<li>It determines the processes that host the application components.</li>
 
-<li>It declares which permissions the application must have in order to
-access protected parts of the API and interact with other applications.</li>
-
-<li>It also declares the permissions that others are required to have in
+<li>It declares the permissions that the application must have in order to
+access protected parts of the API and interact with other applications. It also declares
+the permissions that others are required to have in
 order to interact with the application's components.</li>
 
 <li>It lists the {@link android.app.Instrumentation} classes that provide
-profiling and other information as the application is running.  These declarations
+profiling and other information as the application runs. These declarations
 are present in the manifest only while the application is being developed and
-tested; they're removed before the application is published.</li>
+are removed before the application is published.</li>
 
 <li>It declares the minimum level of the Android API that the application
 requires.</li>
@@ -57,16 +60,27 @@
 <li>It lists the libraries that the application must be linked against.</li>
 </ul>
 
+<p class="note"><strong>Note</strong>: As you prepare your Android app to run on Chromebooks,
+there are some important hardware and software feature limitations that you should consider. See
+the <a href="{@docRoot}topic/arc/manifest.html">
+App Manifest Compatibility for Chromebooks</a> document for more information.
+</p>
 
-<h2 id="filestruct">Structure of the Manifest File</h2>
+<h2 id="filestruct">Manifest file structure</h2>
 
 <p>
-The diagram below shows the general structure of the manifest file and
-every element that it can contain.  Each element, along with all of its
-attributes, is documented in full in a separate file.  To view detailed
-information about any element, click on the element name in the diagram,
-in the alphabetical list of elements that follows the diagram, or on any
-other mention of the element name.
+The code snippet below shows the general structure of the manifest file and
+every element that it can contain. Each element, along with all of its
+attributes, is fully documented in a separate file.
+</p>
+
+<p class="note"><strong>Tip</strong>: To view detailed
+information about any of the elements that are mentioned within the text of this document,
+simply click the element name.
+</p>
+
+<p>
+Here is an example of the manifest file:
 </p>
 
 <pre>
@@ -126,45 +140,45 @@
 </pre>
 
 <p>
-All the elements that can appear in the manifest file are listed below
-in alphabetical order.  These are the only legal elements; you cannot
+The following list contains all of the elements that can appear in the manifest file,
+in alphabetical order:
+</p>
+
+<ul>
+ <li><code><a href="{@docRoot}guide/topics/manifest/action-element.html">&lt;action&gt;</a></code></li>
+ <li><code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code></li>
+ <li><code><a href="{@docRoot}guide/topics/manifest/activity-alias-element.html">&lt;activity-alias&gt;</a></code></li>
+ <li><code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code></li>
+ <li><code><a href="{@docRoot}guide/topics/manifest/category-element.html">&lt;category&gt;</a></code></li>
+ <li><code><a href="{@docRoot}guide/topics/manifest/data-element.html">&lt;data&gt;</a></code></li>
+ <li><code><a href="{@docRoot}guide/topics/manifest/grant-uri-permission-element.html">&lt;grant-uri-permission&gt;</a></code></li>
+ <li><code><a href="{@docRoot}guide/topics/manifest/instrumentation-element.html">&lt;instrumentation&gt;</a></code></li>
+ <li><code><a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;intent-filter&gt;</a></code></li>
+ <li><code><a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></code></li>
+ <li><code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html">&lt;meta-data&gt;</a></code></li>
+ <li><code><a href="{@docRoot}guide/topics/manifest/permission-element.html">&lt;permission&gt;</a></code></li>
+ <li><code><a href="{@docRoot}guide/topics/manifest/permission-group-element.html">&lt;permission-group&gt;</a></code></li>
+ <li><code><a href="{@docRoot}guide/topics/manifest/permission-tree-element.html">&lt;permission-tree&gt;</a></code></li>
+ <li><code><a href="{@docRoot}guide/topics/manifest/provider-element.html">&lt;provider&gt;</a></code></li>
+ <li><code><a href="{@docRoot}guide/topics/manifest/receiver-element.html">&lt;receiver&gt;</a></code></li>
+ <li><code><a href="{@docRoot}guide/topics/manifest/service-element.html">&lt;service&gt;</a></code></li>
+ <li><code><a href="{@docRoot}guide/topics/manifest/supports-screens-element.html">&lt;supports-screens&gt;</a></code>  <!-- ##api level 4## --></li>
+ <li><code><a href="{@docRoot}guide/topics/manifest/uses-configuration-element.html">&lt;uses-configuration&gt;</a></code>  <!-- ##api level 3## --></li>
+ <li><code><a href="{@docRoot}guide/topics/manifest/uses-feature-element.html">&lt;uses-feature&gt;</a></code>  <!-- ##api level 4## --></li>
+ <li><code><a href="{@docRoot}guide/topics/manifest/uses-library-element.html">&lt;uses-library&gt;</a></code></li>
+ <li><code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">&lt;uses-permission&gt;</a></code></li>
+ <li><code><a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">&lt;uses-sdk&gt;</a></code></li>
+</ul>
+
+<p class="note"><strong>Note</strong>: These are the only legal elements &ndash; you cannot
 add your own elements or attributes.
 </p>
 
-<p style="margin-left: 2em">
-<code><a href="{@docRoot}guide/topics/manifest/action-element.html">&lt;action&gt;</a></code>
-<br/><code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
-<br/><code><a href="{@docRoot}guide/topics/manifest/activity-alias-element.html">&lt;activity-alias&gt;</a></code>
-<br/><code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code>
-<br/><code><a href="{@docRoot}guide/topics/manifest/category-element.html">&lt;category&gt;</a></code>
-<br/><code><a href="{@docRoot}guide/topics/manifest/data-element.html">&lt;data&gt;</a></code>
-<br/><code><a href="{@docRoot}guide/topics/manifest/grant-uri-permission-element.html">&lt;grant-uri-permission&gt;</a></code>
-<br/><code><a href="{@docRoot}guide/topics/manifest/instrumentation-element.html">&lt;instrumentation&gt;</a></code>
-<br/><code><a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;intent-filter&gt;</a></code>
-<br/><code><a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></code>
-<br/><code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html">&lt;meta-data&gt;</a></code>
-<br/><code><a href="{@docRoot}guide/topics/manifest/permission-element.html">&lt;permission&gt;</a></code>
-<br/><code><a href="{@docRoot}guide/topics/manifest/permission-group-element.html">&lt;permission-group&gt;</a></code>
-<br/><code><a href="{@docRoot}guide/topics/manifest/permission-tree-element.html">&lt;permission-tree&gt;</a></code>
-<br/><code><a href="{@docRoot}guide/topics/manifest/provider-element.html">&lt;provider&gt;</a></code>
-<br/><code><a href="{@docRoot}guide/topics/manifest/receiver-element.html">&lt;receiver&gt;</a></code>
-<br/><code><a href="{@docRoot}guide/topics/manifest/service-element.html">&lt;service&gt;</a></code>
-<br/><code><a href="{@docRoot}guide/topics/manifest/supports-screens-element.html">&lt;supports-screens&gt;</a></code>  <!-- ##api level 4## -->
-<br/><code><a href="{@docRoot}guide/topics/manifest/uses-configuration-element.html">&lt;uses-configuration&gt;</a></code>  <!-- ##api level 3## -->
-<br/><code><a href="{@docRoot}guide/topics/manifest/uses-feature-element.html">&lt;uses-feature&gt;</a></code>  <!-- ##api level 4## -->
-<br/><code><a href="{@docRoot}guide/topics/manifest/uses-library-element.html">&lt;uses-library&gt;</a></code>
-<br/><code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">&lt;uses-permission&gt;</a></code>
-<br/><code><a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">&lt;uses-sdk&gt;</a></code>
-</p>
-
-
-
-
-<h2 id="filec">File Conventions</h2>
+<h2 id="filec">File conventions</h2>
 
 <p>
-Some conventions and rules apply generally to all elements and attributes
-in the manifest:
+This section describes the conventions and rules that apply generally to all of the elements and
+attributes in the manifest file.
 </p>
 
 <dl>
@@ -172,29 +186,28 @@
 <dd>Only the
 <code><a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></code> and
 <code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code>
-elements are required, they each must be present and can occur only once.
-Most of the others can occur many times or not at all &mdash; although at
-least some of them must be present for the manifest to accomplish anything
-meaningful.
+elements are required. They each must be present and can occur only once.
+Most of the other elements can occur many times or not at all. However, at
+least some of them must be present before the manifest file becomes useful.
 
 <p>
 If an element contains anything at all, it contains other elements.
-All values are set through attributes, not as character data within an element.
+All of the values are set through attributes, not as character data within an element.
 </p>
 
 <p>
-Elements at the same level are generally not ordered.  For example,
+Elements at the same level are generally not ordered. For example, the
 <code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>,
 <code><a href="{@docRoot}guide/topics/manifest/provider-element.html">&lt;provider&gt;</a></code>, and
 <code><a href="{@docRoot}guide/topics/manifest/service-element.html">&lt;service&gt;</a></code>
 elements can be intermixed in any sequence. There are two key exceptions to this
-rule, however:
+rule:
 <ul>
   <li>
     An <code><a href="{@docRoot}guide/topics/manifest/activity-alias-element.html">&lt;activity-alias&gt;</a></code>
     element must follow the
     <code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
-    it is an alias for.
+    for which it is an alias.
   </li>
   <li>
     The <code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code>
@@ -207,15 +220,15 @@
 </p></dd>
 
 <dt><b>Attributes</b></dt>
-<dd>In a formal sense, all attributes are optional.  However, there are some
-that must be specified for an element to accomplish its purpose.  Use the
-documentation as a guide.  For truly optional attributes, it mentions a default
+<dd>In a formal sense, all attributes are optional. However, there are some attributes
+that must be specified so that an element can accomplish its purpose. Use the
+documentation as a guide. For truly optional attributes, it mentions a default
 value or states what happens in the absence of a specification.
 
 <p>Except for some attributes of the root
 <code><a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></code>
-element, all attribute names begin with an {@code android:} prefix &mdash;
-for example, {@code android:alwaysRetainTaskState}.  Because the prefix is
+element, all attribute names begin with an {@code android:} prefix.
+For example, {@code android:alwaysRetainTaskState}. Because the prefix is
 universal, the documentation generally omits it when referring to attributes
 by name.</p></dd>
 
@@ -223,7 +236,7 @@
 <dd>Many elements correspond to Java objects, including elements for the
 application itself (the
 <code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code>
-element) and its principal components &mdash; activities
+element) and its principal components: activities
 (<code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>),
 services
 (<code><a href="{@docRoot}guide/topics/manifest/service-element.html">&lt;service&gt;</a></code>),
@@ -238,7 +251,7 @@
 {@link android.content.BroadcastReceiver}, and {@link android.content.ContentProvider}),
 the subclass is declared through a {@code name} attribute.  The name must include
 the full package designation.
-For example, an {@link android.app.Service} subclass might be declared as follows:
+For example, a {@link android.app.Service} subclass might be declared as follows:
 </p>
 
 <pre>&lt;manifest . . . &gt;
@@ -251,12 +264,12 @@
 &lt;/manifest&gt;</pre>
 
 <p>
-However, as a shorthand, if the first character of the string is a period, the
-string is appended to the application's package name (as specified by the
+However, if the first character of the string is a period, the
+application's package name (as specified by the
 <code><a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a></code>
 element's
 <code><a href="{@docRoot}guide/topics/manifest/manifest-element.html#package">package</a></code>
-attribute).  The following assignment is the same as the one above:
+attribute) is appended to the string. The following assignment is the same as that shown above:
 </p>
 
 <pre>&lt;manifest package="com.example.project" . . . &gt;
@@ -269,13 +282,13 @@
 &lt;/manifest&gt;</pre>
 
 <p>
-When starting a component, Android creates an instance of the named subclass.
+When starting a component, the Android system creates an instance of the named subclass.
 If a subclass isn't specified, it creates an instance of the base class.
 </p></dd>
 
 <dt><b>Multiple values</b></dt>
 <dd>If more than one value can be specified, the element is almost always
-repeated, rather than listing multiple values within a single element.
+repeated, rather than multiple values being listed within a single element.
 For example, an intent filter can list several actions:
 
 <pre>&lt;intent-filter . . . &gt;
@@ -286,108 +299,105 @@
 &lt;/intent-filter&gt;</pre></dd>
 
 <dt><b>Resource values</b></dt>
-<dd>Some attributes have values that can be displayed to users &mdash; for
-example, a label and an icon for an activity.  The values of these attributes
-should be localized and therefore set from a resource or theme.  Resource
-values are expressed in the following format,</p>
+<dd>Some attributes have values that can be displayed to users, such as
+a label and an icon for an activity. The values of these attributes
+should be localized and set from a resource or theme. Resource
+values are expressed in the following format:</p>
 
 <p style="margin-left: 2em">{@code @[<i>package</i>:]<i>type</i>/<i>name</i>}</p>
 
 <p>
-where the <i>package</i> name can be omitted if the resource is in the same package
-as the application, <i>type</i> is a type of resource &mdash; such as "string" or
-"drawable" &mdash; and <i>name</i> is the name that identifies the specific resource.
-For example:
+You can ommit the <i>package</i> name if the resource is in the same package
+as the application. The <i>type</i> is a type of resource, such as <em>string</em> or
+<em>drawable</em>, and the <i>name</i> is the name that identifies the specific resource.
+Here is an example:
 </p>
 
 <pre>&lt;activity android:icon="@drawable/smallPic" . . . &gt</pre>
 
 <p>
-Values from a theme are expressed in a similar manner, but with an initial '{@code ?}'
-rather than '{@code @}':
+The values from a theme are expressed similarly, but with an initial {@code ?}
+instead of {@code @}:
 </p>
 
 <p style="margin-left: 2em">{@code ?[<i>package</i>:]<i>type</i>/<i>name</i>}
 </p></dd>
 
 <dt><b>String values</b></dt>
-<dd>Where an attribute value is a string, double backslashes ('{@code \\}')
-must be used to escape characters &mdash; for example, '{@code \\n}' for
-a newline or '{@code \\uxxxx}' for a Unicode character.</dd>
+<dd>Where an attribute value is a string, you must use double backslashes ({@code \\})
+to escape characters, such as {@code \\n} for
+a newline or {@code \\uxxxx} for a Unicode character.</dd>
 </dl>
 
-
-<h2 id="filef">File Features</h2>
+<h2 id="filef">File features</h2>
 
 <p>
-The following sections describe how some Android features are reflected
+The following sections describe the way that some Android features are reflected
 in the manifest file.
 </p>
 
 
-<h3 id="ifs">Intent Filters</h3>
+<h3 id="ifs">Intent filters</h3>
 
 <p>
-The core components of an application (its activities, services, and broadcast
-receivers) are activated by <i>intents</i>.  An intent is a
+The core components of an application, such as its activities, services, and broadcast
+receivers, are activated by <i>intents</i>. An intent is a
 bundle of information (an {@link android.content.Intent} object) describing a
-desired action &mdash; including the data to be acted upon, the category of
+desired action, including the data to be acted upon, the category of
 component that should perform the action, and other pertinent instructions.
-Android locates an appropriate component to respond to the intent, launches
+The Android system locates an appropriate component that can respond to the intent, launches
 a new instance of the component if one is needed, and passes it the
-Intent object.
+{@link android.content.Intent} object.
 </p>
 
 <p>
-Components advertise their capabilities &mdash; the kinds of intents they can
-respond to &mdash; through <i>intent filters</i>.  Since the Android system
-must learn which intents a component can handle before it launches the component,
+The components advertise the types of intents that they can
+respond to through <i>intent filters</i>. Since the Android system
+must learn the intents that a component can handle before it launches the component,
 intent filters are specified in the manifest as
 <code><a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;intent-filter&gt;</a></code>
-elements.  A component may have any number of filters, each one describing
+elements. A component can have any number of filters, each one describing
 a different capability.
 </p>
 
 <p>
-An intent that explicitly names a target component will activate that component;
-the filter doesn't play a role.  But an intent that doesn't specify a target by
+An intent that explicitly names a target component activates that component, so
+the filter doesn't play a role. An intent that doesn't specify a target by
 name can activate a component only if it can pass through one of the component's
 filters.
 </p>
 
 <p>
-For information on how Intent objects are tested against intent filters,
-see a separate document,
-<a href="{@docRoot}guide/components/intents-filters.html">Intents
-and Intent Filters</a>.
+For information about how {@link android.content.Intent} objects are tested against intent filters,
+see the <a href="{@docRoot}guide/components/intents-filters.html">Intents
+and Intent Filters</a> document.
 </p>
 
-
-<h3 id="iconlabel">Icons and Labels</h3>
+<h3 id="iconlabel">Icons and labels</h3>
 
 <p>
 A number of elements have {@code icon} and {@code label} attributes for a
-small icon and a text label that can be displayed to users.  Some also have a
-{@code description} attribute for longer explanatory text that can also be
-shown on-screen.  For example, the
+small icon and a text label that can be displayed to users. Some also have a
+{@code description} attribute for longer, explanatory text that can also be
+shown on-screen. For example, the
 <code><a href="{@docRoot}guide/topics/manifest/permission-element.html">&lt;permission&gt;</a></code>
-element has all three of these attributes, so that when the user is asked whether
+element has all three of these attributes so that when the user is asked whether
 to grant the permission to an application that has requested it, an icon representing
 the permission, the name of the permission, and a description of what it
-entails can all be presented to the user.
+entails are all presented to the user.
 </p>
 
 <p>
-In every case, the icon and label set in a containing element become the default
+In every case, the icon and label that are set in a containing element become the default
 {@code icon} and {@code label} settings for all of the container's subelements.
-Thus, the icon and label set in the
+Thus, the icon and label that are set in the
 <code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code>
 element are the default icon and label for each of the application's components.
-Similarly, the icon and label set for a component &mdash; for example, an
+Similarly, the icon and label that are set for a component, such as an
 <code><a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a></code>
-element &mdash; are the default settings for each of the component's
+element, are the default settings for each of the component's
 <code><a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">&lt;intent-filter&gt;</a></code>
-elements.  If an
+elements. If an
 <code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code>
 element sets a label, but an activity and its intent filter do not,
 the application label is treated as the label for both the activity and
@@ -395,62 +405,62 @@
 </p>
 
 <p>
-The icon and label set for an intent filter are used to represent a component
-whenever the component is presented to the user as fulfilling the function
-advertised by the filter.  For example, a filter with
-"{@code android.intent.action.MAIN}" and
-"{@code android.intent.category.LAUNCHER}" settings advertises an activity
-as one that initiates an application &mdash; that is, as
-one that should be displayed in the application launcher.  The icon and label
-set in the filter are therefore the ones displayed in the launcher.
+The icon and label that are set for an intent filter represent a component
+whenever the component is presented to the user and fulfills the function
+that is advertised by the filter. For example, a filter with
+{@code android.intent.action.MAIN} and
+{@code android.intent.category.LAUNCHER} settings advertises an activity
+as one that initiates an application. That is, as
+one that should be displayed in the application launcher. The icon and label
+that are set in the filter are displayed in the launcher.
 </p>
 
-
 <h3 id="perms">Permissions</h3>
 
 <p>
-A <i>permission</i> is a restriction limiting access to a part of the code
-or to data on the device.   The limitation is imposed to protect critical
+A <i>permission</i> is a restriction that limits access to a part of the code
+or to data on the device. The limitation is imposed to protect critical
 data and code that could be misused to distort or damage the user experience.
 </p>
 
 <p>
-Each permission is identified by a unique label.  Often the label indicates
-the action that's restricted.  For example, here are some permissions defined
+Each permission is identified by a unique label. Often the label indicates
+the action that's restricted. Here are some permissions that are defined
 by Android:
 </p>
 
-<p style="margin-left: 2em">{@code android.permission.CALL_EMERGENCY_NUMBERS}
-<br/>{@code android.permission.READ_OWNER_DATA}
-<br/>{@code android.permission.SET_WALLPAPER}
-<br/>{@code android.permission.DEVICE_POWER}</p>
+<ul>
+  <li>{@code android.permission.CALL_EMERGENCY_NUMBERS}</li>
+  <li>{@code android.permission.READ_OWNER_DATA}</li>
+  <li>{@code android.permission.SET_WALLPAPER}</li>
+  <li>{@code android.permission.DEVICE_POWER}</li>
+</ul>
 
 <p>
-A feature can be protected by at most one permission.
+A feature can be protected by only one permission.
 </p>
 
 <p>
-If an application needs access to a feature protected by a permission,
-it must declare that it requires that permission with a
+If an application needs access to a feature that is protected by a permission,
+it must declare that it requires the permission with a
 <code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">&lt;uses-permission&gt;</a></code>
-element in the manifest.  Then, when the application is installed on
-the device, the installer determines whether or not to grant the requested
+element in the manifest. When the application is installed on
+the device, the installer determines whether to grant the requested
 permission by checking the authorities that signed the application's
 certificates and, in some cases, asking the user.
 If the permission is granted, the application is able to use the protected
-features.  If not, its attempts to access those features will simply fail
+features. If not, its attempts to access those features fail
 without any notification to the user.
 </p>
 
 <p>
-An application can also protect its own components (activities, services,
-broadcast receivers, and content providers) with permissions.  It can employ
-any of the permissions defined by Android (listed in
-{@link android.Manifest.permission android.Manifest.permission}) or declared
-by other applications.  Or it can define its own.  A new permission is declared
+An application can also protect its own components with permissions. It can employ
+any of the permissions that are defined by Android, as listed in
+{@link android.Manifest.permission android.Manifest.permission}, or declared
+by other applications. It can also define its own. A new permission is declared
 with the
 <code><a href="{@docRoot}guide/topics/manifest/permission-element.html">&lt;permission&gt;</a></code>
-element.  For example, an activity could be protected as follows:
+element. For example, an activity could be protected as follows:
 </p>
 
 <pre>
@@ -474,34 +484,34 @@
 <code><a href="{@docRoot}guide/topics/manifest/permission-element.html">&lt;permission&gt;</a></code>
 element, its use is also requested with the
 <code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">&lt;uses-permission&gt;</a></code>
-element.  Its use must be requested in order for other components of the
+element. You must request its use in order for other components of the
 application to launch the protected activity, even though the protection
 is imposed by the application itself.
 </p>
 
 <p>
-If, in the same example, the {@code permission} attribute was set to a
-permission declared elsewhere
-(such as {@code android.permission.CALL_EMERGENCY_NUMBERS}, it would not
-have been necessary to declare it again with a
+If, in the same example shown above, the {@code permission} attribute was set to a
+permission that is declared elsewhere,
+such as {@code android.permission.CALL_EMERGENCY_NUMBERS}, it would not
+be necessary to declare it again with a
 <code><a href="{@docRoot}guide/topics/manifest/permission-element.html">&lt;permission&gt;</a></code>
-element.  However, it would still have been necessary to request its use with
+element. However, it would still be necessary to request its use with
 <code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">&lt;uses-permission&gt;</a></code>.
 </p>
 
 <p>
 The
 <code><a href="{@docRoot}guide/topics/manifest/permission-tree-element.html">&lt;permission-tree&gt;</a></code>
-element declares a namespace for a group of permissions that will be defined in
-code.  And
+element declares a namespace for a group of permissions that are defined in
+code, and the
 <code><a href="{@docRoot}guide/topics/manifest/permission-group-element.html">&lt;permission-group&gt;</a></code>
-defines a label for a set of permissions (both those declared in the manifest with
+defines a label for a set of permissions, both those declared in the manifest with
 <code><a href="{@docRoot}guide/topics/manifest/permission-element.html">&lt;permission&gt;</a></code>
-elements and those declared elsewhere).  It affects only how the permissions are
-grouped when presented to the user.  The
+elements and those declared elsewhere. This affects only how the permissions are
+grouped when presented to the user. The
 <code><a href="{@docRoot}guide/topics/manifest/permission-group-element.html">&lt;permission-group&gt;</a></code>
-element does not specify which permissions belong to the group;
-it just gives the group a name.  A permission is placed in the group
+element does not specify the permissions that belong to the group, but
+it gives the group a name. You can place a permission in the group
 by assigning the group name to the
 <code><a href="{@docRoot}guide/topics/manifest/permission-element.html">&lt;permission&gt;</a></code>
 element's
@@ -515,15 +525,14 @@
 <p>
 Every application is linked against the default Android library, which
 includes the basic packages for building applications (with common classes
-such as Activity, Service, Intent, View, Button, Application, ContentProvider,
-and so on).
+such as Activity, Service, Intent, View, Button, Application, and ContentProvider).
 </p>
 
 <p>
-However, some packages reside in their own libraries.  If your application
-uses code from any of these packages, it must explicitly asked to be linked
-against them.  The manifest must contain a separate
+However, some packages reside in their own libraries. If your application
+uses code from any of these packages, it must explicitly ask to be linked
+against them. The manifest must contain a separate
 <code><a href="{@docRoot}guide/topics/manifest/uses-library-element.html">&lt;uses-library&gt;</a></code>
-element to name each of the libraries.  (The library name can be found in the
-documentation for the package.)
+element to name each of the libraries. You can find the library name in the
+documentation for the package.
 </p>
diff --git a/docs/html/images/topic/arc/sideload_figure_1.jpg b/docs/html/images/topic/arc/sideload_figure_1.jpg
new file mode 100644
index 0000000..8eb5085
--- /dev/null
+++ b/docs/html/images/topic/arc/sideload_figure_1.jpg
Binary files differ
diff --git a/docs/html/topic/arc/_book.yaml b/docs/html/topic/arc/_book.yaml
index ad83ba9..236375b 100644
--- a/docs/html/topic/arc/_book.yaml
+++ b/docs/html/topic/arc/_book.yaml
@@ -1,9 +1,9 @@
 toc:
-- title: Optimize Apps for Chromebooks
+- title: Optimizing Apps for Chromebooks
   path: /topic/arc/index.html
+- title: App Manifest Compatibility for Chromebooks
+  path: /topic/arc/manifest.html
 - title: Loading Apps on Chromebooks
   path: /topic/arc/sideload.html
 - title: Chrome OS Device Support for Apps
-  path: /topic/arc/device-support.html
-- title: App Manifest Compatibility for Chromebooks
-  path: /topic/arc/manifest.html
\ No newline at end of file
+  path: /topic/arc/device-support.html
\ No newline at end of file
diff --git a/docs/html/topic/arc/device-support.jd b/docs/html/topic/arc/device-support.jd
new file mode 100644
index 0000000..89cb02f
--- /dev/null
+++ b/docs/html/topic/arc/device-support.jd
@@ -0,0 +1,153 @@
+page.title=Chrome OS Device Support for Apps
+@jd:body
+
+<div id="qv-wrapper">
+    <div id="qv">
+      <h2>On this page</h2>
+
+      <ol>
+        <li><a href="#overview">Overview</a></li>
+        <li><a href="#support">Supported Platforms</a></li>
+      </ol>
+    </div>
+  </div>
+
+<p>
+You can use the Google Play Store to install Android apps on several Google
+Chromebooks. This document describes the Chromebooks, Chromeboxes, and
+Chromebases that can install Android apps, both currently and in upcoming
+releases of Chrome OS.
+</p>
+
+<h2 id="overview">Overview</h2>
+
+<p>
+The same Android apps that run on phones and tablets can run on Chromebooks
+without compromising their speed, simplicity, or security. To develop the best
+experience for Android apps across Chromebooks, you should test your app on a
+suite of devices that consists of the following categories:
+</p>
+
+<ul>
+  <li>
+    ARM architecture.
+  </li>
+  <li>
+    Intel x86 architecture.
+  </li>
+  <li>
+    Touch.
+  </li>
+  <li>
+    Non-touch (uses fake-touch).
+  </li>
+  <li>
+    Convertible.
+  </li>
+</ul>
+
+<p>To learn more about Google Play Store support on Chromebooks, see the
+following <a class="external-link"
+href="https://chrome.googleblog.com/2016/05/the-google-play-store-coming-to.html">
+Google Chrome blog post</a>.
+</p>
+
+<p class="note"><strong>Note: </strong>You may elect to exclude your app from
+being available to Chromebooks. For more information, visit <a
+class="external-link"
+href="https://support.google.com/googleplay/android-developer/answer/1286017?hl=en">
+View &amp; restrict your app's compatible devices</a>.
+</p>
+
+<p>
+The following section lists the Chromebooks that work with Android apps and the
+categories that each device satisfies.
+</p>
+
+<h2 id="support">Supported Platforms</h2>
+
+<p>
+Android apps are not available on every Chromebook, but Google continues to
+evaluate more devices based on a range of factors, such as processor type, GPU,
+and drivers. The following table shows the platforms that currently support
+Android apps:
+</p>
+
+<p class="table-caption" id="Objects-and-interfaces">
+  <strong>Table 1.</strong> Chromebooks that currently support Android apps.</p>
+<table>
+  <tr>
+    <th scope="col">Manufacturer</th>
+    <th scope="col">Model</th>
+    <th scope="col">Architecture</th>
+    <th scope="col">Touchscreen support</th>
+    <th scope="col">Convertible</th>
+  </tr>
+  <tr>
+    <td>Acer</td>
+    <td>Chromebook R11 / C738T</td>
+    <td>Intel x86</td>
+    <td>Yes</td>
+    <td>Yes</td>
+  </tr>
+  <tr>
+    <td>Asus</td>
+    <td>Chromebook Flip</td>
+    <td>ARM</td>
+    <td>Yes</td>
+    <td>Yes</td>
+  </tr>
+  <tr>
+    <td>Google</td>
+    <td>Chromebook Pixel (2015)</td>
+    <td>Intel x86</td>
+    <td>Yes</td>
+    <td>No</td>
+  </tr>
+</table>
+
+<p>
+The following list shows the platforms that will support Android apps in an
+upcoming release of Chrome OS:
+</p>
+
+<ul>
+  <li><strong>Acer: </strong>Chromebook 11 C740, Chromebook 11 CB3-111 / C730 /
+  C730E / CB3-131, Chromebook 14 CB3-431, Chromebook 14 for Work, Chromebook
+  15 CB5-571 / C910, Chromebook 15 CB3-531, Chromebox CXI2, Chromebase 24
+  </li>
+  <li><strong>Asus: </strong>Chromebook C200, Chromebook C201,
+  Chromebook C202SA, Chromebook C300SA, Chromebook C300, Chromebox CN62,
+  Chromebit CS10</li>
+  <li><strong>AOpen: </strong>Chromebox Commercial,
+  Chromebase Commercial 22"</li>
+  <li><strong>Bobicus: </strong>Chromebook 11</li>
+  <li><strong>CDI: </strong>eduGear Chromebook K Series,
+  eduGear Chromebook M Series, eduGear Chromebook R Series</li>
+  <li><strong>CTL: </strong>Chromebook J2 / J4, N6 Education Chromebook,
+  J5 Convertible Chromebook</li>
+  <li><strong>Dell: </strong>Chromebook 11 3120, Chromebook 13 7310</li>
+  <li><strong>Edxis: </strong>Chromebook, Education Chromebook</li>
+  <li><strong>Haier: </strong>Chromebook 11, Chromebook 11e, Chromebook 11 G2
+  </li>
+  <li><strong>Hexa: </strong>Chromebook Pi</li>
+  <li><strong>HiSense: </strong>Chromebook 11</li>
+  <li><strong>Lava: </strong>Xolo Chromebook</li>
+  <li><strong>HP: </strong>Chromebook 11 G3 / G4 / G4 EE, Chromebook 14 G4,
+  Chromebook 13</li>
+  <li><strong>Lenovo: </strong>100S Chromebook, N20 / N20P Chromebook,
+  N21 Chromebook, ThinkCentre Chromebox, ThinkPad 11e Chromebook,
+  N22 Chromebook, Thinkpad 13 Chromebook, Thinkpad 11e Chromebook Gen 3</li>
+  <li><strong>Medion: </strong>Akoya S2013, Chromebook S2015</li>
+  <li><strong>M&amp;A: </strong>Chromebook</li>
+  <li><strong>NComputing: </strong>Chromebook CX100</li>
+  <li><strong>Nexian: </strong>Chromebook 11.6"</li>
+  <li><strong>PCMerge: </strong>Chromebook PCM-116E</li>
+  <li><strong>Poin2: </strong>Chromebook 11</li>
+  <li><strong>Samsung: </strong>Chromebook 2 11" - XE500C12, Chromebook 3</li>
+  <li><strong>Sector 5: </strong>E1 Rugged Chromebook</li>
+  <li><strong>Senkatel: </strong>C1101 Chromebook</li>
+  <li><strong>Toshiba: </strong>Chromebook 2, Chromebook 2 (2015)</li>
+  <li><strong>True IDC: </strong>Chromebook 11</li>
+  <li><strong>Viglen: </strong>Chromebook 11</li>
+</ul>
diff --git a/docs/html/topic/arc/index.jd b/docs/html/topic/arc/index.jd
new file mode 100644
index 0000000..d46fbc8
--- /dev/null
+++ b/docs/html/topic/arc/index.jd
@@ -0,0 +1,398 @@
+page.title=Optimizing Apps for Chromebooks
+@jd:body
+
+<div id="qv-wrapper">
+    <div id="qv">
+      <h2>On this page</h2>
+
+      <ol>
+        <li><a href="#update-manifest">Update Your App's Manifest File</a></li>
+        <li><a href="#leverage">Leverage Support for Multi-Window Mode</li>
+        <li><a href="#keyboard">Support the Keyboard, Trackpad, and Mouse</a></li>
+        <li><a href="#backup">Use Backup and Restore Effectively</a></li>
+        <li><a href="#update-ndk">Update the NDK Libraries</a></li>
+        <li><a href="#support-new-features">Plan Support for New Android Features</a></li>
+        <li><a href="#testing">Test Your App</a></li>
+        <li><a href="#setup">Set Up ADB</a></li>
+        <li><a href="#learning-materials">Additional Learning Materials</a></li>
+      </ol>
+    </div>
+  </div>
+
+<p>
+Google Chromebooks now support the Google Play Store and Android apps. This
+document describes some ways that you can optimize your Android apps for
+Chromebooks.
+</p>
+
+<h2 id="update-manifest">Update Your App's Manifest File</h2>
+
+<p>
+To begin optimizing your Android app for Chromebooks, update your manifest file
+(<code>AndroidManifest.xml</code>) to account for some key hardware and software
+differences between Chromebooks and other devices running Android.
+</p>
+
+<p>
+As of Chrome OS version M53, all Android apps that don't explicitly require the
+<a
+href="{@docRoot}guide/topics/manifest/uses-feature-element.html#touchscreen-hw-features"><code>android.hardware.touchscreen</code></a>
+feature will also work on Chrome OS devices that support the
+<code>android.hardware.faketouch</code> feature. However, if you want your app
+to work on all Chromebooks in the best possible way, go to your manifest file
+and adjust the settings so that the <code>android.hardware.touchscreen</code>
+feature is not required, as shown in the following example. You should also
+review your mouse and keyboard interactions.
+</p>
+
+<pre>
+&lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          ... &gt;
+    &lt;!-- Some Chromebooks don't support touch. Although not essential,
+         it's a good idea to explicitly include this declaration. --&gt;
+    &lt;uses-feature android:name="android.hardware.touchscreen"
+                  required="false" /&gt;
+&lt;/manifest&gt;
+</pre>
+
+<p>
+Different devices often have different sensors available in them. See the <a
+href="https://developer.android.com/guide/topics/sensors/sensors_overview.html">Sensors
+Overview</a> document for an overview of all sensors that the Android platform
+supports. Although Android handheld devices may have GPS and accelerometers,
+sensors are not guaranteed to be available in every Chromebook. However, there
+are cases where the functionality of a sensor is provided in another way. For
+example, Chromebooks may not have GPS sensors, but they still provide location
+data based on Wi-Fi connections. If you want your app to run on Chromebooks,
+regardless of sensor support, you should update your manifest file so that none
+of the sensors are required.
+</p>
+
+<p class="note"><strong>Note</strong>: If you don't require a particular sensor
+for your app but still use measurements from the sensor when it's available,
+make sure you dynamically check for the sensor's availability before trying to
+gather information from it in your app.
+</p>
+
+<p>
+Some software features are unsupported on Chromebooks. For example, apps that
+provide custom IMEs, app widgets, live wallpapers, and app launchers aren't
+supported and won't be available for installation on Chromebooks. For a complete
+list of software features that aren't currently supported on Chromebooks, see <a
+href="{@docRoot}topic/arc/manifest.html#incompat-software-features">incompatible
+software features</a>.
+</p>
+
+<h2 id="leverage">Leverage Support for Multi-Window Mode</h2>
+
+<p>
+The implementation of Android apps on Chrome OS includes basic multi-window
+support. Instead of automatically drawing over the full screen, Android renders
+apps on Chrome OS into layouts that are appropriate for this form factor. Google
+provides support for the most common window layouts:
+
+<ul>
+  <li>
+    <strong>Portrait</strong> &ndash; Similar to Nexus 5.
+  </li>
+  <li>
+    <strong>Landscape</strong> &ndash; Similar to Nexus 7.
+  </li>
+  <li>
+    <strong>Maximized</strong> &ndash; Uses all available screen pixels.
+  </li>
+</ul>
+
+<p>
+In addition, end users are presented with window controls to toggle among all
+available layouts. By choosing the correct orientation option, you can ensure
+that the user has the correct layout upon launching the app. If an app is
+available in portrait and landscape, it defaults to landscape if possible. After
+this option is set, it is remembered on a per-app basis. Google recommends that
+you test your app to ensure that it handles changes in window size
+appropriately.
+</p>
+
+<h2 id="keyboard">Support the Keyboard, Trackpad, and Mouse</h2>
+
+<p>
+All Chromebooks have a physical keyboard and a trackpad, and some Chromebooks
+have a touchscreen as well. Some devices can even convert from a laptop to a
+tablet.
+</p>
+
+<p>
+Many existing apps already support mouse and trackpad interactions with no extra
+work required. However, it's always best to adjust your app's behavior
+appropriately when users interact with it using a trackpad instead of a
+touchscreen, and you should support and distinguish between both interfaces
+properly. Given the support for physical keyboards, you can now provide hotkeys
+to enable your app's users to be more productive. For example, if your app
+supports printing, you can use <strong>Ctrl+P</strong> to open a print dialog.
+</p>
+
+<h2 id="backup">Use Backup and Restore Effectively</h2>
+
+<p>
+One of the strongest features of Chromebooks is that users can easily migrate
+from one device to another. That is, if someone stops using one Chromebook and
+starts using another, they simply have to sign in, and all of their apps appear.
+</p>
+
+<p class="note"><strong>Tip: </strong> Although it's not mandatory, backing up
+your app's data to the cloud is a good idea.
+</p>
+
+<p>
+Chromebooks can also be shared among a large number of people, such as in
+schools. Since local storage is not infinite, entire accounts&mdash;together
+with their storage&mdash;can be removed from the device at any point. For
+educational settings, it's a good idea to keep this scenario in mind.
+</p>
+
+<h2 id="update-ndk">Update the NDK Libraries</h2>
+
+<p>
+If your app uses the Android NDK libraries, and its target SDK version is 23 or
+higher, ensure that text relocations are removed from both the ARM and x86
+versions of your NDK libraries, as they're not compatible in Android 6.0 (API
+level 23) and higher. By leaving text relocations in your NDK libraries, you may
+also cause incompatibility errors with Chromebooks, especially when running on
+a device that uses an x86 architecture.
+</p>
+
+<p class="note"><strong>Note: </strong>To view more details on updating NDK
+libraries properly, see the <a
+href="https://developer.android.com/about/versions/marshmallow/android-6.0-changes.html#behavior-runtime">
+Runtime</a> section of the Android 6.0 Changes document.
+</p>
+
+<h2 id="support-new-features">Plan Support for New Android Features</h2>
+
+<p>
+Android apps on Chromebooks initially ship with APIs for Android 6.0 (API level
+23). By following the best practices outlined above, your app is likely to be
+compatible with the multi-window improvements introduced in Android 7.0 (API
+level 24). It's good to plan support for the APIs and behaviors available as of
+Android 7.0, which feature several improvements. For example, multi-window
+support is better integrated, and you're able to resize activities arbitrarily,
+making them feel more natural. You can also access APIs for drag-and-drop
+operations across apps and mouse cursor control.
+</p>
+
+<h2 id="testing">Test Your App</h2>
+
+<p>
+To <a href="{@docRoot}topic/arc/sideload.html">load</a> your app onto your
+Chromebook for testing, you must enter <em>Developer</em> mode on your Chrome OS
+device and enable <em>unknown sources</em>. See the <a class="external-link"
+href="https://www.chromium.org/chromium-os/poking-around-your-chrome-os-device#TOC-Putting-your-Chrome-OS-Device-into-Developer-Mode">
+Putting your Chrome OS Device into Developer Mode</a> document for detailed
+instructions about moving your device into Developer mode. After your device is
+in Developer mode, you can go to your Chrome settings and select <strong>Enable
+Unknown Sources</strong> under the <em>security in app</em> settings.
+</p>
+
+<p>
+After enabling Developer mode, you can load an Android app onto your Chrome OS
+device using one of several methods. For more details, see the <a
+href="{@docRoot}topic/arc/sideload.html#load-app">Load Your App</a> section of
+the Loading Apps on Chromebooks page.
+</p>
+
+<p class="note"><strong>Note: </strong>To ensure that your Android app works
+well on a variety of Chromebook devices and available form factors, Google
+recommends that you test your app on an ARM-based Chromebook, an x86-based
+Chromebook, a device with a touchscreen and one without one, and on a
+convertible device (one that can change between a laptop and a tablet). To view
+the full list of supported devices, see the <a
+href="{@docRoot}topic/arc/device-support.html">Chrome OS Device Support for
+Apps</a> page.</p>
+
+<h2 id="setup">Set Up ADB</h2>
+
+<p>
+Before attempting to set up an ADB connection, you must start your Chrome OS in
+<a class="external-link"
+href="https://www.chromium.org/chromium-os/poking-around-your-chrome-os-device">
+Developer Mode</a> so that you have the ability to install Android apps on the
+Chromebook.
+</p>
+
+<p class="caution"><strong>Caution: </strong>After switching your Chrome OS
+device to Developer mode, it restarts and clears all existing data on the
+device.
+</p>
+
+<p>
+To set up ADB, complete the following steps:
+</p>
+
+<ol>
+  <li>
+    Press <strong>Ctrl+D</strong> to start your device.
+  </li>
+  <li>
+    Finish the setup process.
+  </li>
+  <li>
+    Log into your test account.
+  </li>
+  <li>
+    Accept the Google Play Store terms and service conditions.
+  </li>
+</ol>
+
+<h3>Configure the firewall</h3>
+
+<p>
+To configure the Chrome OS firewall to allow incoming ADB connections, complete
+the following steps:
+</p>
+
+<ol>
+  <li>
+    Press <strong>Ctrl+Alt+T</strong> to start the Chrome OS terminal.
+  </li>
+  <li>
+    Type <strong>shell</strong> to get to the bash command shell:
+<pre class="no-pretty-print">
+crosh> shell
+chronos@localhost / $
+</pre>
+  </li>
+  <li>
+    Type the following commands to set up developer features and enable
+    disk-write access for the firewall settings changes:
+<pre class="no-pretty-print">
+chronos@localhost / $ sudo /usr/libexec/debugd/helpers/dev_features_rootfs_verification
+chronos@localhost / $ sudo reboot
+</pre>
+    The <em>sudo reboot</em> command restarts your Chromebook.
+<p class="note"><strong>Note</strong>: You can press the <strong>Tab</strong>
+key to enable autocompletion of file names.</p>
+  </li>
+  <li>
+    After your device restarts, log in to your test account and type the
+    following command to enable the <em>secure shell</em> and configure the
+    firewall properly:
+<pre class="no-pretty-print">
+chronos@localhost / $ sudo /usr/libexec/debugd/helpers/dev_features_ssh
+</pre>
+    You can now exit out of the shell.
+  </li>
+</ol>
+
+<p class="note"><strong>Note</strong>: You must complete this procedure only
+once on your Chromebook.</p>
+
+<h3>Check the IP address of your Chromebook</h3>
+
+<p>
+To verify the IP address of your Chromebook, complete the following steps:
+</p>
+
+<ol>
+  <li>
+    Click the clock icon in the bottom-right area of the screen.
+  </li>
+  <li>
+    Click <strong>Settings</strong>.
+  </li>
+  <li>
+    The <em>Internet Connection</em> section in the Settings area lists all of
+    the available networks. Select the one that you want to use for ADB.
+  </li>
+  <li>
+    Take note of the IP address that appears.
+  </li>
+</ol>
+
+<h3>Enable ADB debugging</h3>
+
+<p>
+To enable ADB debugging, complete the following steps:
+</p>
+
+<ol>
+  <li>
+    Click the clock icon in the bottom-right area of the screen.
+  </li>
+  <li>
+    Click <strong>Settings</strong>.
+  </li>
+  <li>
+    In the <em>Android Apps</em> section, click the <strong>Settings</strong>
+    link in the line that reads <em>Manage your Android apps in Settings</em>.
+    This brings up the Android apps settings.
+  </li>
+  <li>
+    Click <strong>About device</strong>.
+  </li>
+  <li>
+    Click <strong>Build number</strong> seven times to move into Developer mode.
+  </li>
+  <li>
+    Click the arrow in the top-left area of the window to go back to the main
+    Settings screen.
+  </li>
+  <li>
+    Click the new <strong>Developer options</strong> item, activate <strong>ADB
+    debugging</strong>, and then click <strong>OK</strong> to allow ADB
+    debugging.
+  </li>
+  <li>
+    Return to your development machine and use ADB to connect to your
+    Chromebook's using its IP address and port 22.
+  </li>
+  <li>
+    On your Chromebook, click <strong>Allow</strong> when prompted whether you
+    want to allow the debugger. Your ADB session is established.
+  </li>
+</ol>
+
+<h4>Troubleshooting ADB debugging</h4>
+
+<p>
+Sometimes the ADB device shows that it's offline when everything is connected
+properly. In this case, complete the following steps to troubleshoot the issue:
+</p>
+
+<ol>
+  <li>
+    Deactivate <strong>ADB debugging</strong> in <em>Developer options</em>.
+  </li>
+  <li>
+    In a terminal window, run <code>adb kill-server</code>.
+  </li>
+  <li>
+    Re-activate the <strong>ADB debugging</strong> option.
+  </li>
+  <li>
+    In a terminal window, attempt to run <code>adb connect</code>.
+  </li>
+  <li>
+    Click <strong>Allow</strong> when prompted whether you want to allow
+    debugging. Your ADB session is established.
+  </li>
+</ol>
+
+<h2 id="learning-materials">Additional Learning Materials</h2>
+
+<p>
+To learn more about optimizing your Android apps for Chromebooks, consult the
+following resources:
+</p>
+
+<ul>
+  <li>
+    Review the
+    <a class="external-link" href="http://android-developers.blogspot.com/2016/05/bring-your-android-app-to-chromebooks.html">
+    Bring your Android App to Chromebooks</a> I/O session.
+  </li>
+  <li>
+    Post a question on the <a class="external-link"
+    href="https://plus.sandbox.google.com/+AndroidDevelopers">Android developer
+    community</a> with hashtag <em>#AndroidAppsOnChromeOS</em>.
+  </li>
+</ul>
diff --git a/docs/html/topic/arc/manifest.jd b/docs/html/topic/arc/manifest.jd
new file mode 100644
index 0000000..7d18665
--- /dev/null
+++ b/docs/html/topic/arc/manifest.jd
@@ -0,0 +1,341 @@
+page.title=App Manifest Compatibility for Chromebooks
+@jd:body
+
+<div id="qv-wrapper">
+    <div id="qv">
+      <h2>On this page</h2>
+
+      <ol>
+        <li><a href="#incompat-entries">Incompatible Manifest Entries</a></li>
+        <li>
+          <a href="#implied-features">Permissions That Imply Feature
+          Requirements</a>
+        </li>
+      </ol>
+    </div>
+  </div>
+
+<p>
+As you prepare your Android app to run on Chromebooks, you should consider the
+device features that your app uses. Chromebooks don't support all of the
+hardware and software features that are available on other devices running
+Android. If your app requires specific features that aren't supported on
+Chromebooks, it won't be available for installation on Chromebooks.
+</p>
+
+<p>
+You declare your app's requirements for hardware features and certain software
+features in the <a
+href="{@docRoot}guide/topics/manifest/manifest-intro.html">manifest file</a>.
+This document describes the app manifest feature declarations that aren't
+compatible with Chromebooks.
+</p>
+
+<h2 id="incompat-entries">Incompatible Manifest Entries</h2>
+
+<p>
+The manifest entries listed in this section aren't currently compatible with
+Chromebooks. If your app uses any of these entries, consider removing them or
+including the <code>required="false"</code> attribute value with them so that
+your app can be installed on Chromebooks. For more information about declaring
+feature use without requiring that the feature be available on the device, see
+the guide for the <a
+href="{@docRoot}guide/topics/manifest/uses-feature-element.html#market-feature-filtering">
+<code>&lt;uses-feature&gt;</code></a> manifest element.
+</p>
+
+<p class="note"><strong>Note</strong>: See the <a
+href="{@docRoot}guide/topics/manifest/uses-feature-element.html#features-reference">
+Features Reference</a> for a complete list of app manifest features and
+descriptions.
+</p>
+
+<h3 id="incompat-hardware-features">Hardware features</h3>
+
+<p>
+Support for hardware features varies on Chromebooks. Some features aren't
+supported on any Chromebooks while others are supported on some Chromebooks.
+</p>
+
+<h4>Unsupported hardware features</h4>
+
+<p>
+The following list includes the hardware features that aren't currently
+supported on Chromebooks:
+</p>
+
+<ul>
+  <li>
+    <code>android.hardware.camera</code> &ndash; Back-facing camera
+  </li>
+  <li>
+    <code>android.hardware.camera.autofocus</code> &ndash; Camera that uses
+    autofocus
+  </li>
+  <li>
+    <code>android.hardware.camera.capability.manual_post_processing</code>&nbsp;
+    &ndash; Camera that uses the <code>MANUAL_POST_PROCESSING</code> feature,
+    including functionality for overriding auto white balance
+  </li>
+  <li>
+    <code>android.hardware.camera.capability.manual_sensor</code> &ndash; Camera
+    that uses the <code>MANUAL_SENSOR</code> feature, including auto-exposure
+    locking support
+  </li>
+  <li>
+    <code>android.hardware.camera.capability.raw</code> &ndash; Camera that uses
+    the <code>RAW</code> feature, including the ability to save DNG (raw) files
+    and provide DNG-related metadata
+  </li>
+  <li>
+    <code>android.hardware.camera.flash</code> &ndash; Camera that uses flash
+  </li>
+  <li>
+    <code>android.hardware.camera.level.full</code> &ndash; Camera that uses
+    <code>FULL</code>-level image-capturing support
+  </li>
+  <li>
+    <code>android.hardware.consumerir</code> &ndash; Infrared (IR)
+  </li>
+  <li>
+    <code>android.hardware.location.gps</code> &ndash; GPS
+  </li>
+  <li>
+    <code>android.hardware.nfc</code> &ndash; Near-Field Communication (NFC)
+  </li>
+  <li>
+    <code>android.hardware.nfc.hce</code> &ndash; NFC card emulation
+    (<em>deprecated</em>)
+  </li>
+  <li>
+    <code>android.hardware.sensor.barometer</code> &ndash; Barometer (air
+    pressure)
+  </li>
+  <li>
+    <code>android.hardware.telephony</code> &ndash; Telephony, including radio
+    with data communication services
+  </li>
+  <li>
+    <code>android.hardware.telephony.cdma</code> &ndash; Telephony Code Division
+    Multiple Access (CDMA) network support
+  </li>
+  <li>
+    <code>android.hardware.telephony.gsm</code> &ndash; Telephony Global System
+    for Mobile Communications (GSM) network support
+  </li>
+  <li>
+    <code>android.hardware.type.automotive</code> &ndash; Android Auto user
+    interface
+  </li>
+  <li>
+    <code>android.hardware.type.television</code> &ndash; Television
+    (<em>deprecated</em>)
+  <li>
+    <code>android.hardware.usb.accessory</code> &ndash; USB accessory mode
+  </li>
+  <li>
+    <code>android.hardware.usb.host</code> &ndash; USB host mode
+  </li>
+</ul>
+
+<h4>Partially-supported hardware features</h4>
+
+<p>
+The following list includes the hardware features that may be available on some
+Chromebooks:
+</p>
+
+<ul>
+  <li>
+    <code>android.hardware.sensor.accelerometer</code> &ndash; Accelerometer
+    (device orientation)
+  </li>
+  <li>
+    <code>android.hardware.sensor.compass</code> &ndash; Compass
+  </li>
+  <li>
+    <code>android.hardware.sensor.gyroscope</code> &ndash; Gyroscope (device
+    rotation and twist)
+  </li>
+  <li>
+    <code>android.hardware.sensor.light</code> &ndash; Light
+  </li>
+  <li>
+    <code>android.hardware.sensor.proximity</code> &ndash; Proximity (to user)
+  </li>
+  <li>
+    <code>android.hardware.sensor.stepcounter</code> &ndash; Step counter
+  </li>
+  <li>
+    <code>android.hardware.sensor.stepdetector</code> &ndash; Step detector
+  </li>
+</ul>
+
+<h4>Touchscreen hardware support</h4>
+
+<p>
+As of Chrome OS version M53, all Android apps that don't explicitly require the
+<a href="{@docRoot}guide/topics/manifest/uses-feature-element.html#touchscreen-hw-features">
+<code>android.hardware.touchscreen</code></a> feature will also work on Chrome
+OS devices that support the <a
+href="{@docRoot}guide/topics/manifest/uses-feature-element.html#touchscreen-hw-features">
+<code>android.hardware.faketouch</code></a> feature. Devices that have fake
+touch interfaces provide a user input system that emulates basic touch events.
+For example, the user could interact with a mouse or remote control to move an
+on-screen cursor, scroll through a list, and drag elements from one part of the
+screen to another.
+</p>
+
+<p>
+If you don't want your app to be installed on devices that have fake touch
+interfaces but not touchscreens, you can complete one of the following actions:
+</p>
+
+<ul>
+  <li>Exclude specific devices in the <a class="external-link"
+  href="https://play.google.com/apps/publish">Google Play Developer Console.</a>
+  </li>
+  <li>Filter devices with no touchscreen hardware by explicitly declaring <a
+  href="{@docRoot}guide/topics/manifest/uses-feature-element.html#touchscreen-hw-features">
+  <code>android.hardware.touchscreen</code></a> as being required in order to
+  install your app.</li>
+</ul>
+
+<h3 id="incompat-software-features">Software features</h3>
+
+<p>
+The following list includes the software features that aren't currently
+supported on Chromebooks:
+</p>
+
+<ul>
+  <li>
+    <code>android.software.app_widgets</code> &ndash; App Widgets on the Home
+    screen
+  </li>
+  <li>
+    <code>android.software.device_admin</code> &ndash; Device policy
+    administration
+  </li>
+  <li>
+    <code>android.software.home_screen</code> &ndash; Replaces device's Home
+    screen
+  </li>
+  <li>
+    <code>android.software.input_methods</code> &ndash; Custom input methods
+    (instances of <a href="{@docRoot}reference/android/inputmethodservice/InputMethodService.html">
+    <code>InputMethodService</code></a>)
+  </li>
+  <li>
+    <code>android.software.leanback</code> &ndash; UI designed for large-screen
+    viewing
+  </li>
+  <li>
+    <code>android.software.live_wallpaper</code> &ndash; Animated wallpapers
+  </li>
+  <li>
+    <code>android.software.live_tv</code> &ndash; Streaming live TV programs
+  </li>
+  <li>
+    <code>android.software.managed_users</code> &ndash; Secondary users and
+    managed profiles
+  </li>
+  <li>
+    <code>android.software.midi</code> &ndash; Musical Instrument Digital
+    Interface (MIDI) protocol, which supports connecting to musical instruments
+    and providing sound
+  </li>
+  <li>
+    <code>android.software.sip</code> &ndash; Session Initiation Protocol (SIP)
+    service, which supports video conferencing and instant messaging
+  </li>
+  <li>
+    <code>android.software.sip.voip</code> &ndash; Voice Over Internet Protocol
+    (VoIP) service based on SIP, which supports two-way video conferencing
+  </li>
+</ul>
+
+<h2 id="implied-features">Permissions That Imply Feature Requirements</h2>
+
+<p>
+Some permissions that you request in your manifest files can create implied
+requests for hardware and software features. By requesting these permissions,
+you'll prevent your app from being installed on Chromebooks.
+</p>
+
+<p>
+For details about how to prevent permission requests from making your app
+unavailable on Chromebooks, see the <a href="#incompat-entries">Incompatible
+Manifest Entries</a> section of this page.
+</p>
+
+<p>
+The following table shows the permissions that imply certain feature
+requirements which make an app incompatible with Chromebooks:
+</p>
+
+<p class="table-caption">
+<strong>Table 1. </strong>Device permissions that imply hardware features which
+are incompatible with Chromebooks.
+</p>
+
+<table>
+  <tr>
+    <th scope="col">Category</th>
+    <th scope="col">This Permission...</th>
+    <th scope="col">...Implies This Feature Requirement</th>
+  </tr>
+  <tr>
+    <td>Camera</td>
+    <td><code>CAMERA</code></td>
+    <td>
+      <code>android.hardware.camera</code> and<br>
+      <code>android.hardware.camera.autofocus</code>
+    </td>
+  </tr>
+  <tr>
+    <td rowspan="11">Telephony</td>
+    <td><code>CALL_PHONE</code></td>
+    <td><code>android.hardware.telephony</code></td>
+  </tr>
+  <tr>
+    <td><code>CALL_PRIVILEGED</code></td>
+    <td><code>android.hardware.telephony</code></td>
+  </tr>
+  <tr>
+    <td><code>MODIFY_PHONE_STATE</code></td>
+    <td><code>android.hardware.telephony</code></td>
+  </tr>
+  <tr>
+    <td><code>PROCESS_OUTGOING_CALLS</code></td>
+    <td><code>android.hardware.telephony</code></td>
+  </tr>
+  <tr>
+    <td><code>READ_SMSREAD_SMS</code></td>
+    <td><code>android.hardware.telephony</code></td>
+  </tr>
+  <tr>
+    <td><code>RECEIVE_SMS</code></td>
+    <td><code>android.hardware.telephony</code></td>
+  </tr>
+  <tr>
+    <td><code>RECEIVE_MMS</code></td>
+    <td><code>android.hardware.telephony</code></td>
+  </tr>
+  <tr>
+    <td><code>RECEIVE_WAP_PUSH</code></td>
+    <td><code>android.hardware.telephony</code></td>
+  </tr>
+  <tr>
+    <td><code>SEND_SMS</code></td>
+    <td><code>android.hardware.telephony</code></td>
+  </tr>
+  <tr>
+    <td><code>WRITE_APN_SETTINGS</code></td>
+    <td><code>android.hardware.telephony</code></td>
+  </tr>
+  <tr>
+    <td><code>WRITE_SMS</code></td>
+    <td><code>android.hardware.telephony</code></td>
+  </tr>
+</table>
diff --git a/docs/html/topic/arc/sideload.jd b/docs/html/topic/arc/sideload.jd
new file mode 100644
index 0000000..dca84ff
--- /dev/null
+++ b/docs/html/topic/arc/sideload.jd
@@ -0,0 +1,125 @@
+page.title=Loading Apps on Chromebooks
+@jd:body
+
+<div id="qv-wrapper">
+    <div id="qv">
+      <h2>On this page</h2>
+
+      <ol>
+        <li><a href="#enter-dev">Enter Developer Mode</a></li>
+        <li><a href="#enable-unknown">Enable Unknown Sources</a></li>
+        <li><a href="#load-app">Load Your App</a></li>
+      </ol>
+    </div>
+  </div>
+
+<p>
+This document describes how to enter <em>Developer</em> mode and enable
+<em>unknown resources</em> so that you can load Android apps on your Google
+Chromebook.
+</p>
+
+<h2 id="enter-dev">Enter Developer Mode</h2>
+
+<p>
+To load Android apps, you must enable unknown sources. Enabling unknown sources
+is available only when your device is in Developer mode.
+</p>
+
+<p class="caution"><strong>Caution: </strong>Modifications that you make to the
+system are not supported by Google and may void your warranty. Additionally,
+modifications may cause hardware, software, or security issues.
+</p>
+
+<p class="note"><strong>Note: </strong>On most devices, both the
+<em>recovery</em> button and the <em>dev-switch</em> button are virtualized. If
+these instructions don't work for you, see the <a class="external-link"
+href="https://www.chromium.org/chromium-os/developer-information-for-chrome-os-devices">
+specific instructions for your device</a>.
+</p>
+
+<p>
+To enter Developer mode, complete these steps:
+</p>
+
+<ol>
+  <li>
+    Invoke <em>Recovery</em> mode by pressing and holding the
+    <strong>Esc</strong> and <strong>Refresh (F3)</strong> keys, then pressing
+    the <strong>Power</strong> button.
+  </li>
+  <li>
+    When the <em>Recovery</em> screen appears, press <strong>Ctrl+D</strong>.
+    There's no prompt for this action, so you must simply complete it.
+    Afterwards, you are prompted to confirm and reboot into Developer mode.
+  </li>
+</ol>
+
+<p>
+If you see one of the following screens when you turn on your device, you've
+successfully entered Developer mode:
+</p>
+
+<img src="{@docRoot}images/topic/arc/sideload_figure_1.jpg" />
+
+<p class="img-caption"><strong>Figure 1. </strong>Developer mode confirmation
+screens.</p>
+
+<p class="note"><strong>Note</strong>: To skip the OS loading screen, either
+wait 30 seconds or press <strong>Ctrl+D</strong>, and your Chromebook continues
+starting.
+</p>
+
+<h2 id="enable-unknown">Enable Unknown Sources</h2>
+
+<p>
+To enable unknown sources, navigate to <strong>Chrome Settings > App Settings >
+Security</strong>, then enable <strong>Unknown sources</strong> by moving the
+slider to the right.
+</p>
+
+<p class="note"><strong>Note:</strong>You can enable unknown sources only when
+your device is in <a
+href="{@docRoot}topic/arc/sideload.html#enter-dev">Developer mode</a>.
+</p>
+
+<h2 id="load-app">Load Your App</h2>
+
+<p>
+After enabling unknown sources, you can load apps by copying an app's APK file
+to the <em>Downloads</em> folder and opening it with Android's File Manager app.
+
+</p>
+
+<p>
+You can copy the APK file to your Chromebook using one of the following methods:
+</p>
+
+<ul>
+  <li>
+    <strong>Using a cloud app</strong> &ndash; Upload your APK file to Google
+    Drive or send it to yourself via email. Open it with the Android app
+    equivalent (Drive and Gmail, respectively).
+  </li>
+  <li>
+    <strong>Using an external storage device</strong> &ndash; Transfer the APK
+    file to the Downloads folder of your Chromebook using a thumb drive, SD
+    card, or an external hard drive. Afterwards, open the Android File Manager
+    app by navigating to  <strong>Chrome Settings > App Settings > Device &amp;
+    USB > Explore</strong>.
+  </li>
+  <li>
+    <strong>Using ADB</strong> &ndash; After <a
+    href="{@docRoot}topic/arc/index.html#setup"> setting up ADB</a> on your
+    Chromebook, enter the following command into a terminal window on your
+    development workstation:
+<pre class="no-pretty-print">
+adb install <var>app-name</var>.apk
+</pre>
+    <p>This command pushes the app to your connected Chromebook and installs the
+    app. For more information about copying and installing apps from a
+    development computer, see <a
+    href="{@docRoot}studio/command-line/adb.html#move">Installing an
+    Application</a>.</p>
+  </li>
+</ul>
diff --git a/libs/hwui/AnimatorManager.cpp b/libs/hwui/AnimatorManager.cpp
index 9d5860c..7e3ff40 100644
--- a/libs/hwui/AnimatorManager.cpp
+++ b/libs/hwui/AnimatorManager.cpp
@@ -83,8 +83,11 @@
         }
         mNewAnimators.clear();
     }
-    for (auto& animator : mAnimators) {
-        animator->pushStaging(mAnimationHandle->context());
+    if (mAnimators.size()) {
+        for (auto& animator : mAnimators) {
+            animator->pushStaging(mAnimationHandle->context());
+        }
+        mParent.mProperties.updateMatrix();
     }
 }
 
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 38c0e08..c90abad 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -342,7 +342,6 @@
         pushStagingDisplayListChanges(info);
     }
     prepareSubTree(info, childFunctorsNeedLayer, mDisplayList);
-    pushLayerUpdate(info);
 
     if (mDisplayList) {
         for (auto& vectorDrawable : mDisplayList->getVectorDrawables()) {
@@ -353,6 +352,7 @@
             vectorDrawable->setPropertyChangeWillBeConsumed(true);
         }
     }
+    pushLayerUpdate(info);
 
     info.damageAccumulator->popTransform();
 }
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java
index 8d6e07e..108b466 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java
@@ -20,13 +20,14 @@
 import android.graphics.Rect;
 import android.util.AttributeSet;
 import android.view.KeyEvent;
+import android.view.MotionEvent;
 import android.view.View;
 
 /**
  * A Pin based Keyguard input view
  */
 public abstract class KeyguardPinBasedInputView extends KeyguardAbsKeyInputView
-        implements View.OnKeyListener {
+        implements View.OnKeyListener, View.OnTouchListener {
 
     protected PasswordTextView mPasswordEntry;
     private View mOkButton;
@@ -185,10 +186,10 @@
 
         mOkButton = findViewById(R.id.key_enter);
         if (mOkButton != null) {
+            mOkButton.setOnTouchListener(this);
             mOkButton.setOnClickListener(new View.OnClickListener() {
                 @Override
                 public void onClick(View v) {
-                    doHapticKeyClick();
                     if (mPasswordEntry.isEnabled()) {
                         verifyPasswordAndUnlock();
                     }
@@ -199,6 +200,7 @@
 
         mDeleteButton = findViewById(R.id.delete_button);
         mDeleteButton.setVisibility(View.VISIBLE);
+        mDeleteButton.setOnTouchListener(this);
         mDeleteButton.setOnClickListener(new OnClickListener() {
             @Override
             public void onClick(View v) {
@@ -206,7 +208,6 @@
                 if (mPasswordEntry.isEnabled()) {
                     mPasswordEntry.deleteLastChar();
                 }
-                doHapticKeyClick();
             }
         });
         mDeleteButton.setOnLongClickListener(new View.OnLongClickListener() {
@@ -237,6 +238,14 @@
     }
 
     @Override
+    public boolean onTouch(View v, MotionEvent event) {
+        if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
+            doHapticKeyClick();
+        }
+        return false;
+    }
+
+    @Override
     public boolean onKey(View v, int keyCode, KeyEvent event) {
         if (event.getAction() == KeyEvent.ACTION_DOWN) {
             return onKeyDown(keyCode, event);
diff --git a/packages/Shell/src/com/android/shell/Screenshooter.java b/packages/Shell/src/com/android/shell/Screenshooter.java
index 3f4895b..92c5fcc 100644
--- a/packages/Shell/src/com/android/shell/Screenshooter.java
+++ b/packages/Shell/src/com/android/shell/Screenshooter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015 The Android Open Source Project
+ * Copyright (C) 2016 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -20,8 +20,6 @@
 import android.graphics.Canvas;
 import android.graphics.Point;
 import android.hardware.display.DisplayManagerGlobal;
-import android.os.Binder;
-import android.os.RemoteException;
 import android.util.Log;
 import android.view.Display;
 import android.view.Surface;
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 8ad4d9b..d9beeca 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -788,6 +788,10 @@
     <!-- Recents: MultiStack add stack split custom radio button. [CHAR LIMIT=NONE] -->
     <string name="recents_multistack_add_stack_dialog_split_custom">Split Custom</string>
 
+    <!-- Fully qualified activity class names to be blacklisted in Recents, add package names into overlay as needed -->
+    <string-array name="recents_blacklist_array">
+    </string-array>
+
     <!-- Expanded Status Bar Header: Battery Charged [CHAR LIMIT=40] -->
     <string name="expanded_header_battery_charged">Charged</string>
 
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
index 9eb768c..7c8d0f6 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
@@ -57,8 +57,9 @@
     private static SummaryStats sEmergencyCallStats;
     private static SummaryStats[][] sProxStats; // [reason][near/far]
 
-    public static void tracePickupPulse(boolean withinVibrationThreshold) {
+    public static void tracePickupPulse(Context context, boolean withinVibrationThreshold) {
         if (!ENABLED) return;
+        init(context);
         log("pickupPulse withinVibrationThreshold=" + withinVibrationThreshold);
         (withinVibrationThreshold ? sPickupPulseNearVibrationStats
                 : sPickupPulseNotNearVibrationStats).append();
@@ -76,8 +77,9 @@
         log("pulseFinish");
     }
 
-    public static void traceNotificationPulse(long instance) {
+    public static void traceNotificationPulse(Context context, long instance) {
         if (!ENABLED) return;
+        init(context);
         log("notificationPulse instance=" + instance);
         sNotificationPulseStats.append();
     }
@@ -153,9 +155,9 @@
     public static void traceProximityResult(Context context, boolean near, long millis,
             int pulseReason) {
         if (!ENABLED) return;
+        init(context);
         log("proximityResult reason=" + pulseReasonToString(pulseReason) + " near=" + near
                 + " millis=" + millis);
-        init(context);
         sProxStats[pulseReason][near ? 0 : 1].append();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
index 661b347..fc0d8bb 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
@@ -373,7 +373,7 @@
         if (DEBUG) Log.d(mTag, "mScheduleResetsRemaining = " + mScheduleResetsRemaining);
         mNotificationPulseTime = notificationTimeMs;
         if (pulseImmediately) {
-            DozeLog.traceNotificationPulse(0);
+            DozeLog.traceNotificationPulse(mContext, 0);
             requestPulse(DozeLog.PULSE_REASON_NOTIFICATION);
         }
         // schedule the rest of the pulses
@@ -442,7 +442,7 @@
             if (NOTIFICATION_PULSE_ACTION.equals(intent.getAction())) {
                 final long instance = intent.getLongExtra(EXTRA_INSTANCE, -1);
                 if (DEBUG) Log.d(mTag, "Received notification pulse intent instance=" + instance);
-                DozeLog.traceNotificationPulse(instance);
+                DozeLog.traceNotificationPulse(mContext, instance);
                 requestPulse(DozeLog.PULSE_REASON_NOTIFICATION);
                 rescheduleNotificationPulse(mNotificationLightOn);
             }
@@ -576,7 +576,7 @@
                     resetNotificationResets();
                 }
                 if (mSensor.getType() == Sensor.TYPE_PICK_UP_GESTURE) {
-                    DozeLog.tracePickupPulse(withinVibrationThreshold);
+                    DozeLog.tracePickupPulse(mContext, withinVibrationThreshold);
                 }
             } finally {
                 mWakeLock.release();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 7ad5054..b6597a0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -183,6 +183,7 @@
         if (mCustomizePanel != null) {
             mCustomizePanel.setHost(mHost);
         }
+        mBrightnessController.setBackgroundLooper(host.getLooper());
     }
 
     public QSTileHost getHost() {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java
index 7161053..914035b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java
@@ -29,6 +29,7 @@
 
     public boolean launchedWithAltTab;
     public boolean launchedFromApp;
+    public boolean launchedFromBlacklistedApp;
     public boolean launchedFromHome;
     public boolean launchedViaDragGesture;
     public boolean launchedViaDockGesture;
@@ -39,6 +40,7 @@
     public void reset() {
         launchedFromHome = false;
         launchedFromApp = false;
+        launchedFromBlacklistedApp = false;
         launchedToTaskId = -1;
         launchedWithAltTab = false;
         launchedViaDragGesture = false;
@@ -53,8 +55,14 @@
         RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
         if (launchedFromApp) {
             if (!launchState.launchedWithAltTab && debugFlags.isFastToggleRecentsEnabled()) {
-                // If fast toggling, focus the front most task so that the next tap will focus the
-                // N-1 task
+                // If fast toggling, focus the front most task so that the next tap will launch the
+                // task
+                return numTasks - 1;
+            }
+
+            if (launchState.launchedFromBlacklistedApp) {
+                // If we are launching from a blacklisted app, focus the front most task so that the
+                // next tap will launch the task
                 return numTasks - 1;
             }
 
@@ -67,7 +75,7 @@
                 return -1;
             }
 
-            // If coming from home, focus the first task
+            // If coming from home, focus the front most task
             return numTasks - 1;
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index f299c19..20e1665 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -810,15 +810,19 @@
             boolean isHomeStackVisible, boolean animate, int growTarget) {
         RecentsTaskLoader loader = Recents.getTaskLoader();
         RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
+        SystemServicesProxy ssp = Recents.getSystemServices();
+        boolean isBlacklisted = (runningTask != null)
+                ? ssp.isBlackListedActivity(runningTask.baseActivity.getClassName())
+                : false;
 
-        int runningTaskId = !mLaunchedWhileDocking && (runningTask != null)
+        int runningTaskId = !mLaunchedWhileDocking && !isBlacklisted && (runningTask != null)
                 ? runningTask.id
                 : -1;
 
         // In the case where alt-tab is triggered, we never get a preloadRecents() call, so we
         // should always preload the tasks now. If we are dragging in recents, reload them as
         // the stacks might have changed.
-        if (mLaunchedWhileDocking || mTriggeredFromAltTab ||sInstanceLoadPlan == null) {
+        if (mLaunchedWhileDocking || mTriggeredFromAltTab || sInstanceLoadPlan == null) {
             // Create a new load plan if preloadRecents() was never triggered
             sInstanceLoadPlan = loader.createLoadPlan(mContext);
         }
@@ -828,11 +832,13 @@
 
         TaskStack stack = sInstanceLoadPlan.getTaskStack();
         boolean hasRecentTasks = stack.getTaskCount() > 0;
-        boolean useThumbnailTransition = (runningTask != null) && !isHomeStackVisible && hasRecentTasks;
+        boolean useThumbnailTransition = (runningTask != null) && !isHomeStackVisible &&
+                hasRecentTasks;
 
         // Update the launch state that we need in updateHeaderBarLayout()
         launchState.launchedFromHome = !useThumbnailTransition && !mLaunchedWhileDocking;
         launchState.launchedFromApp = useThumbnailTransition || mLaunchedWhileDocking;
+        launchState.launchedFromBlacklistedApp = launchState.launchedFromApp && isBlacklisted;
         launchState.launchedViaDockGesture = mLaunchedWhileDocking;
         launchState.launchedViaDragGesture = mDraggingInRecents;
         launchState.launchedToTaskId = runningTaskId;
@@ -860,7 +866,9 @@
         }
 
         ActivityOptions opts;
-        if (useThumbnailTransition) {
+        if (isBlacklisted) {
+            opts = getUnknownTransitionActivityOptions();
+        } else if (useThumbnailTransition) {
             // Try starting with a thumbnail transition
             opts = getThumbnailTransitionActivityOptions(runningTask, mDummyStackView,
                     windowOverrideRect);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index a93b283..9d9e27389 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -244,6 +244,9 @@
         if (uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION) {
             Collections.addAll(sRecentsBlacklist,
                     res.getStringArray(R.array.recents_tv_blacklist_array));
+        } else {
+            Collections.addAll(sRecentsBlacklist,
+                    res.getStringArray(R.array.recents_blacklist_array));
         }
     }
 
@@ -262,6 +265,13 @@
     }
 
     /**
+     * @return whether the provided {@param className} is blacklisted
+     */
+    public boolean isBlackListedActivity(String className) {
+        return sRecentsBlacklist.contains(className);
+    }
+
+    /**
      * Returns a list of the recents tasks.
      *
      * @param includeFrontMostExcludedTask if set, will ensure that the front most excluded task
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
index 89789bce..702b076 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
@@ -556,7 +556,9 @@
                     Math.max(0, mUnfocusedRange.getAbsoluteX(maxBottomNormX)));
             boolean scrollToFront = launchState.launchedFromHome ||
                     launchState.launchedViaDockGesture;
-            if (launchState.launchedWithAltTab) {
+            if (launchState.launchedFromBlacklistedApp) {
+                mInitialScrollP = mMaxScrollP;
+            } else if (launchState.launchedWithAltTab) {
                 mInitialScrollP = Utilities.clamp(launchTaskIndex, mMinScrollP, mMaxScrollP);
             } else if (scrollToFront) {
                 mInitialScrollP = Utilities.clamp(launchTaskIndex, mMinScrollP, mMaxScrollP);
@@ -579,6 +581,7 @@
         mTaskIndexOverrideMap.clear();
 
         boolean scrollToFront = launchState.launchedFromHome ||
+                launchState.launchedFromBlacklistedApp ||
                 launchState.launchedViaDockGesture;
         if (getInitialFocusState() == STATE_UNFOCUSED && mNumStackTasks > 1) {
             if (ignoreScrollToFront || (!launchState.launchedWithAltTab && !scrollToFront)) {
diff --git a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
index a89fdbd..74dce1c 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
@@ -23,6 +23,8 @@
 import android.os.AsyncTask;
 import android.os.Handler;
 import android.os.IPowerManager;
+import android.os.Looper;
+import android.os.Message;
 import android.os.PowerManager;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -45,6 +47,12 @@
      */
     private static final float BRIGHTNESS_ADJ_RESOLUTION = 2048;
 
+    private static final int MSG_UPDATE_ICON = 0;
+    private static final int MSG_UPDATE_SLIDER = 1;
+    private static final int MSG_SET_CHECKED = 2;
+    private static final int MSG_ATTACH_LISTENER = 3;
+    private static final int MSG_DETACH_LISTENER = 4;
+
     private final int mMinimumBacklight;
     private final int mMaximumBacklight;
 
@@ -54,13 +62,14 @@
     private final boolean mAutomaticAvailable;
     private final IPowerManager mPower;
     private final CurrentUserTracker mUserTracker;
-    private final Handler mHandler;
+
+    private Handler mBackgroundHandler;
     private final BrightnessObserver mBrightnessObserver;
 
     private ArrayList<BrightnessStateChangeCallback> mChangeCallbacks =
             new ArrayList<BrightnessStateChangeCallback>();
 
-    private boolean mAutomatic;
+    private volatile boolean mAutomatic;
     private boolean mListening;
     private boolean mExternalChange;
 
@@ -90,24 +99,20 @@
         @Override
         public void onChange(boolean selfChange, Uri uri) {
             if (selfChange) return;
-            try {
-                mExternalChange = true;
-                if (BRIGHTNESS_MODE_URI.equals(uri)) {
-                    updateMode();
-                    updateSlider();
-                } else if (BRIGHTNESS_URI.equals(uri) && !mAutomatic) {
-                    updateSlider();
-                } else if (BRIGHTNESS_ADJ_URI.equals(uri) && mAutomatic) {
-                    updateSlider();
-                } else {
-                    updateMode();
-                    updateSlider();
-                }
-                for (BrightnessStateChangeCallback cb : mChangeCallbacks) {
-                    cb.onBrightnessLevelChanged();
-                }
-            } finally {
-                mExternalChange = false;
+
+            if (BRIGHTNESS_MODE_URI.equals(uri)) {
+                mBackgroundHandler.post(mUpdateModeRunnable);
+                mBackgroundHandler.post(mUpdateSliderRunnable);
+            } else if (BRIGHTNESS_URI.equals(uri) && !mAutomatic) {
+                mBackgroundHandler.post(mUpdateSliderRunnable);
+            } else if (BRIGHTNESS_ADJ_URI.equals(uri) && mAutomatic) {
+                mBackgroundHandler.post(mUpdateSliderRunnable);
+            } else {
+                mBackgroundHandler.post(mUpdateModeRunnable);
+                mBackgroundHandler.post(mUpdateSliderRunnable);
+            }
+            for (BrightnessStateChangeCallback cb : mChangeCallbacks) {
+                cb.onBrightnessLevelChanged();
             }
         }
 
@@ -132,16 +137,117 @@
 
     }
 
+    private final Runnable mStartListeningRunnable = new Runnable() {
+        @Override
+        public void run() {
+            mBrightnessObserver.startObserving();
+            mUserTracker.startTracking();
+
+            // Update the slider and mode before attaching the listener so we don't
+            // receive the onChanged notifications for the initial values.
+            mUpdateModeRunnable.run();
+            mUpdateSliderRunnable.run();
+
+            mHandler.sendEmptyMessage(MSG_ATTACH_LISTENER);
+        }
+    };
+
+    private final Runnable mStopListeningRunnable = new Runnable() {
+        @Override
+        public void run() {
+            mBrightnessObserver.stopObserving();
+            mUserTracker.stopTracking();
+
+            mHandler.sendEmptyMessage(MSG_DETACH_LISTENER);
+        }
+    };
+
+    /**
+     * Fetch the brightness mode from the system settings and update the icon. Should be called from
+     * background thread.
+     */
+    private final Runnable mUpdateModeRunnable = new Runnable() {
+        @Override
+        public void run() {
+            if (mAutomaticAvailable) {
+                int automatic;
+                automatic = Settings.System.getIntForUser(mContext.getContentResolver(),
+                        Settings.System.SCREEN_BRIGHTNESS_MODE,
+                        Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
+                        UserHandle.USER_CURRENT);
+                mAutomatic = automatic != Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL;
+                mHandler.obtainMessage(MSG_UPDATE_ICON, mAutomatic ? 1 : 0).sendToTarget();
+            } else {
+                mHandler.obtainMessage(MSG_SET_CHECKED, 0).sendToTarget();
+                mHandler.obtainMessage(MSG_UPDATE_ICON, 0 /* automatic */).sendToTarget();
+            }
+        }
+    };
+
+    /**
+     * Fetch the brightness from the system settings and update the slider. Should be called from
+     * background thread.
+     */
+    private final Runnable mUpdateSliderRunnable = new Runnable() {
+        @Override
+        public void run() {
+            if (mAutomatic) {
+                float value = Settings.System.getFloatForUser(mContext.getContentResolver(),
+                        Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, 0,
+                        UserHandle.USER_CURRENT);
+                mHandler.obtainMessage(MSG_UPDATE_SLIDER, (int) BRIGHTNESS_ADJ_RESOLUTION,
+                        (int) ((value + 1) * BRIGHTNESS_ADJ_RESOLUTION / 2f)).sendToTarget();
+            } else {
+                int value;
+                value = Settings.System.getIntForUser(mContext.getContentResolver(),
+                        Settings.System.SCREEN_BRIGHTNESS, mMaximumBacklight,
+                        UserHandle.USER_CURRENT);
+                mHandler.obtainMessage(MSG_UPDATE_SLIDER, mMaximumBacklight - mMinimumBacklight,
+                        value - mMinimumBacklight).sendToTarget();
+            }
+        }
+    };
+
+    private final Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            mExternalChange = true;
+            try {
+                switch (msg.what) {
+                    case MSG_UPDATE_ICON:
+                        updateIcon(msg.arg1 != 0);
+                        break;
+                    case MSG_UPDATE_SLIDER:
+                        mControl.setMax(msg.arg1);
+                        mControl.setValue(msg.arg2);
+                        break;
+                    case MSG_SET_CHECKED:
+                        mControl.setChecked(msg.arg1 != 0);
+                        break;
+                    case MSG_ATTACH_LISTENER:
+                        mControl.setOnChangedListener(BrightnessController.this);
+                        break;
+                    case MSG_DETACH_LISTENER:
+                        mControl.setOnChangedListener(null);
+                    default:
+                        super.handleMessage(msg);
+                }
+            } finally {
+                mExternalChange = false;
+            }
+        }
+    };
+
     public BrightnessController(Context context, ImageView icon, ToggleSlider control) {
         mContext = context;
         mIcon = icon;
         mControl = control;
-        mHandler = new Handler();
+        mBackgroundHandler = new Handler(Looper.getMainLooper());
         mUserTracker = new CurrentUserTracker(mContext) {
             @Override
             public void onUserSwitched(int newUserId) {
-                updateMode();
-                updateSlider();
+                mBackgroundHandler.post(mUpdateModeRunnable);
+                mBackgroundHandler.post(mUpdateSliderRunnable);
             }
         };
         mBrightnessObserver = new BrightnessObserver(mHandler);
@@ -155,6 +261,10 @@
         mPower = IPowerManager.Stub.asInterface(ServiceManager.getService("power"));
     }
 
+    public void setBackgroundLooper(Looper backgroundLooper) {
+        mBackgroundHandler = new Handler(backgroundLooper);
+    }
+
     public void addStateChangedCallback(BrightnessStateChangeCallback cb) {
         mChangeCallbacks.add(cb);
     }
@@ -173,15 +283,7 @@
             return;
         }
 
-        mBrightnessObserver.startObserving();
-        mUserTracker.startTracking();
-
-        // Update the slider and mode before attaching the listener so we don't
-        // receive the onChanged notifications for the initial values.
-        updateMode();
-        updateSlider();
-
-        mControl.setOnChangedListener(this);
+        mBackgroundHandler.post(mStartListeningRunnable);
         mListening = true;
     }
 
@@ -191,9 +293,7 @@
             return;
         }
 
-        mBrightnessObserver.stopObserving();
-        mUserTracker.stopTracking();
-        mControl.setOnChangedListener(null);
+        mBackgroundHandler.post(mStopListeningRunnable);
         mListening = false;
     }
 
@@ -267,39 +367,4 @@
                     com.android.systemui.R.drawable.ic_qs_brightness_auto_off);
         }
     }
-
-    /** Fetch the brightness mode from the system settings and update the icon */
-    private void updateMode() {
-        if (mAutomaticAvailable) {
-            int automatic;
-            automatic = Settings.System.getIntForUser(mContext.getContentResolver(),
-                    Settings.System.SCREEN_BRIGHTNESS_MODE,
-                    Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
-                    UserHandle.USER_CURRENT);
-            mAutomatic = automatic != Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL;
-            updateIcon(mAutomatic);
-        } else {
-            mControl.setChecked(false);
-            updateIcon(false /*automatic*/);
-        }
-    }
-
-    /** Fetch the brightness from the system settings and update the slider */
-    private void updateSlider() {
-        if (mAutomatic) {
-            float value = Settings.System.getFloatForUser(mContext.getContentResolver(),
-                    Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, 0,
-                    UserHandle.USER_CURRENT);
-            mControl.setMax((int) BRIGHTNESS_ADJ_RESOLUTION);
-            mControl.setValue((int) ((value + 1) * BRIGHTNESS_ADJ_RESOLUTION / 2f));
-        } else {
-            int value;
-            value = Settings.System.getIntForUser(mContext.getContentResolver(),
-                    Settings.System.SCREEN_BRIGHTNESS, mMaximumBacklight,
-                    UserHandle.USER_CURRENT);
-            mControl.setMax(mMaximumBacklight - mMinimumBacklight);
-            mControl.setValue(value - mMinimumBacklight);
-        }
-    }
-
 }
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index 998f50f..cb77d7b 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -31,6 +31,7 @@
 import android.hardware.display.DisplayManager;
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.Message;
 import android.util.AttributeSet;
 import android.view.Display;
 import android.view.DisplayInfo;
@@ -106,6 +107,11 @@
     private static final Interpolator IME_ADJUST_INTERPOLATOR =
             new PathInterpolator(0.2f, 0f, 0.1f, 1f);
 
+    private static final long ONE_MS_IN_NS = 1000000;
+    private static final long ONE_S_IN_NS = ONE_MS_IN_NS * 1000;
+
+    private static final int MSG_RESIZE_STACK = 0;
+
     private DividerHandleView mHandle;
     private View mBackground;
     private MinimizedDockShadow mMinimizedShadow;
@@ -150,7 +156,25 @@
     private boolean mDockedStackMinimized;
     private boolean mAdjustedForIme;
     private DividerState mState;
-    private final Handler mHandler = new Handler();
+
+    /**
+     * The offset between vsync-app and vsync-surfaceflinger. See
+     * {@link #calculateAppSurfaceFlingerVsyncOffsetMs} why this is necessary.
+     */
+    private long mSurfaceFlingerOffsetMs;
+
+    private final Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_RESIZE_STACK:
+                    resizeStack(msg.arg1, msg.arg2, (SnapTarget) msg.obj);
+                    break;
+                default:
+                    super.handleMessage(msg);
+            }
+        }
+    };
 
     private final AccessibilityDelegate mHandleDelegate = new AccessibilityDelegate() {
         @Override
@@ -290,6 +314,7 @@
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
         EventBus.getDefault().register(this);
+        mSurfaceFlingerOffsetMs = calculateAppSurfaceFlingerVsyncOffsetMs();
     }
 
     @Override
@@ -298,6 +323,25 @@
         EventBus.getDefault().unregister(this);
     }
 
+    /**
+     * This method calculates the offset between vsync-surfaceflinger and vsync-app. If vsync-app
+     * is a couple of milliseconds before vsync-sf, a touch or animation event that causes the
+     * stacks to be resized are sometimes processed before the vsync-sf tick, and sometimes after,
+     * which leads to jank. Figure out this difference here and then post all the touch/animation
+     * events to start being processed at vsync-sf.
+     *
+     * @return The offset between vsync-app and vsync-sf, or 0 if vsync app happens after vsync-sf.
+     */
+    private long calculateAppSurfaceFlingerVsyncOffsetMs() {
+        Display display = getDisplay();
+
+        // Calculate vsync offset from SurfaceFlinger.
+        // See frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp:getDisplayConfigs
+        long vsyncPeriod = (long) (ONE_S_IN_NS / display.getRefreshRate());
+        long sfVsyncOffset = vsyncPeriod - (display.getPresentationDeadlineNanos() - ONE_MS_IN_NS);
+        return Math.max(0, (sfVsyncOffset - display.getAppVsyncOffsetNanos()) / ONE_MS_IN_NS);
+    }
+
     @Override
     public WindowInsets onApplyWindowInsets(WindowInsets insets) {
         if (mStableInsets.left != insets.getStableInsetLeft()
@@ -453,7 +497,7 @@
                 if (mMoving && mDockSide != WindowManager.DOCKED_INVALID) {
                     SnapTarget snapTarget = mSnapAlgorithm.calculateSnapTarget(
                             mStartPosition, 0 /* velocity */, false /* hardDismiss */);
-                    resizeStack(calculatePosition(x, y), mStartPosition, snapTarget);
+                    resizeStackDelayed(calculatePosition(x, y), mStartPosition, snapTarget);
                 }
                 break;
             case MotionEvent.ACTION_UP:
@@ -532,10 +576,11 @@
             final long endDelay) {
         final boolean taskPositionSameAtEnd = snapTarget.flag == SnapTarget.FLAG_NONE;
         ValueAnimator anim = ValueAnimator.ofInt(position, snapTarget.position);
-        anim.addUpdateListener(animation -> resizeStack((Integer) animation.getAnimatedValue(),
+        anim.addUpdateListener(animation -> resizeStackDelayed((int) animation.getAnimatedValue(),
                 taskPositionSameAtEnd && animation.getAnimatedFraction() == 1f
                         ? TASK_POSITION_SAME
-                        : snapTarget.taskPosition, snapTarget));
+                        : snapTarget.taskPosition,
+                snapTarget));
         Runnable endAction = () -> {
             commitSnapFlags(snapTarget);
             mWindowManagerProxy.setResizing(false);
@@ -551,15 +596,24 @@
 
             @Override
             public void onAnimationCancel(Animator animation) {
+                mHandler.removeMessages(MSG_RESIZE_STACK);
                 mCancelled = true;
             }
 
             @Override
             public void onAnimationEnd(Animator animation) {
-                if (endDelay == 0 || mCancelled) {
+                long delay = 0;
+                if (endDelay != 0) {
+                    delay = endDelay;
+                } else if (mCancelled) {
+                    delay = 0;
+                } else if (mSurfaceFlingerOffsetMs != 0) {
+                    delay = mSurfaceFlingerOffsetMs;
+                }
+                if (delay == 0) {
                     endAction.run();
                 } else {
-                    mHandler.postDelayed(endAction, endDelay);
+                    mHandler.postDelayed(endAction, delay);
                 }
             }
         });
@@ -793,6 +847,17 @@
                 mDisplayHeight, mDividerSize);
     }
 
+    public void resizeStackDelayed(int position, int taskPosition, SnapTarget taskSnapTarget) {
+        if (mSurfaceFlingerOffsetMs != 0) {
+            Message message = mHandler.obtainMessage(MSG_RESIZE_STACK, position, taskPosition,
+                    taskSnapTarget);
+            message.setAsynchronous(true);
+            mHandler.sendMessageDelayed(message, mSurfaceFlingerOffsetMs);
+        } else {
+            resizeStack(position, taskPosition, taskSnapTarget);
+        }
+    }
+
     public void resizeStack(int position, int taskPosition, SnapTarget taskSnapTarget) {
         calculateBoundsForPosition(position, mDockSide, mDockedRect);
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index d93889c..2673ee8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -965,7 +965,6 @@
                 mNotificationGutsExposed = entry.row.getGuts();
                 bindGuts(entry.row);
             }
-            entry.cacheContentViews(mContext, null /* updatedNotification */);
             inflateViews(entry, mStackScroller);
         }
     }
@@ -1589,7 +1588,12 @@
                 entry.notification.getUser().getIdentifier());
 
         final StatusBarNotification sbn = entry.notification;
-        entry.cacheContentViews(mContext, null);
+        try {
+            entry.cacheContentViews(mContext, null);
+        } catch (RuntimeException e) {
+            Log.e(TAG, "Unable to get notification remote views", e);
+            return false;
+        }
 
         final RemoteViews contentView = entry.cachedContentView;
         final RemoteViews bigContentView = entry.cachedBigContentView;
@@ -2358,7 +2362,13 @@
         Notification n = notification.getNotification();
         mNotificationData.updateRanking(ranking);
 
-        boolean applyInPlace = entry.cacheContentViews(mContext, notification.getNotification());
+        boolean applyInPlace;
+        try {
+            applyInPlace = entry.cacheContentViews(mContext, notification.getNotification());
+        } catch (RuntimeException e) {
+            Log.e(TAG, "Unable to get notification remote views", e);
+            applyInPlace = false;
+        }
         boolean shouldPeek = shouldPeek(entry, notification);
         boolean alertAgain = alertAgain(entry, n);
         if (DEBUG) {
@@ -2410,7 +2420,10 @@
                     StatusBarIconView.contentDescForNotification(mContext, n));
             entry.icon.setNotification(n);
             entry.icon.set(ic);
-            inflateViews(entry, mStackScroller);
+            if (!inflateViews(entry, mStackScroller)) {
+                handleNotificationError(notification, "Couldn't update remote views for: "
+                        + notification);
+            }
         }
         updateHeadsUp(key, entry, shouldPeek, alertAgain);
         updateNotifications();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
index c8f8d18..b6e54af 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
@@ -34,7 +34,6 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
-import java.util.Map;
 import java.util.Objects;
 
 /**
@@ -343,7 +342,6 @@
                         entry.notification.setOverrideGroupKey(overrideGroupKey);
                         mGroupManager.onEntryUpdated(entry, oldSbn);
                     }
-                    //mGroupManager.onEntryBundlingUpdated(entry, getOverrideGroupKey(entry.key));
                 }
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index a98601a..048c4bd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -16,6 +16,9 @@
 
 package com.android.systemui.statusbar.phone;
 
+import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK;
+import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
+
 import android.app.ActivityManager;
 import android.app.ActivityManagerNative;
 import android.app.ActivityOptions;
@@ -65,9 +68,6 @@
 import com.android.systemui.statusbar.policy.FlashlightController;
 import com.android.systemui.statusbar.policy.PreviewInflater;
 
-import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK;
-import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
-
 /**
  * Implementation for the bottom area of the Keyguard, including camera/phone affordance and status
  * text.
@@ -403,7 +403,7 @@
     public void bindCameraPrewarmService() {
         Intent intent = getCameraIntent();
         ActivityInfo targetInfo = PreviewInflater.getTargetActivityInfo(mContext, intent,
-                KeyguardUpdateMonitor.getCurrentUser());
+                KeyguardUpdateMonitor.getCurrentUser(), true /* onlyDirectBootAware */);
         if (targetInfo != null && targetInfo.metaData != null) {
             String clazz = targetInfo.metaData.getString(
                     MediaStore.META_DATA_STILL_IMAGE_CAMERA_PREWARM_SERVICE);
@@ -590,10 +590,16 @@
     }
 
     private void inflateCameraPreview() {
+        View previewBefore = mCameraPreview;
+        boolean visibleBefore = false;
+        if (previewBefore != null) {
+            mPreviewContainer.removeView(previewBefore);
+            visibleBefore = previewBefore.getVisibility() == View.VISIBLE;
+        }
         mCameraPreview = mPreviewInflater.inflatePreview(getCameraIntent());
         if (mCameraPreview != null) {
             mPreviewContainer.addView(mCameraPreview);
-            mCameraPreview.setVisibility(View.INVISIBLE);
+            mCameraPreview.setVisibility(visibleBefore ? View.VISIBLE : View.INVISIBLE);
         }
     }
 
@@ -712,4 +718,9 @@
         updateLeftAffordanceIcon();
         updateLeftPreview();
     }
+
+    public void onKeyguardShowingChanged() {
+        updateLeftAffordance();
+        inflateCameraPreview();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
index 204ab7e..1755cc6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
@@ -31,7 +31,6 @@
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Map;
-import java.util.Objects;
 
 /**
  * A class to handle notifications and their corresponding groups.
@@ -43,6 +42,7 @@
     private int mBarState = -1;
     private HashMap<String, StatusBarNotification> mIsolatedEntries = new HashMap<>();
     private HeadsUpManager mHeadsUpManager;
+    private boolean mUpdatingSuppressionBlocked;
 
     public void setOnGroupChangeListener(OnGroupChangeListener listener) {
         mListener = listener;
@@ -140,17 +140,8 @@
         }
     }
 
-    public void onEntryBundlingUpdated(final NotificationData.Entry updated,
-            final String overrideGroupKey) {
-        final StatusBarNotification oldSbn = updated.notification.clone();
-        if (!Objects.equals(oldSbn.getOverrideGroupKey(), overrideGroupKey)) {
-            updated.notification.setOverrideGroupKey(overrideGroupKey);
-            onEntryUpdated(updated, oldSbn);
-        }
-    }
-
     private void updateSuppression(NotificationGroup group) {
-        if (group == null) {
+        if (group == null || mUpdatingSuppressionBlocked) {
             return;
         }
         boolean prevSuppressed = group.suppressed;
@@ -192,19 +183,24 @@
 
     public void onEntryUpdated(NotificationData.Entry entry,
             StatusBarNotification oldNotification) {
+        String oldKey = oldNotification.getGroupKey();
+        String newKey = entry.notification.getGroupKey();
+        boolean groupKeysChanged = !oldKey.equals(newKey);
+        boolean wasGroupChild = isGroupChild(oldNotification);
+        boolean isGroupChild = isGroupChild(entry.notification);
+        mUpdatingSuppressionBlocked = !groupKeysChanged && wasGroupChild == isGroupChild;
         if (mGroupMap.get(getGroupKey(oldNotification)) != null) {
             onEntryRemovedInternal(entry, oldNotification);
         }
         onEntryAdded(entry);
+        mUpdatingSuppressionBlocked = false;
         if (isIsolated(entry.notification)) {
             mIsolatedEntries.put(entry.key, entry.notification);
-            String oldKey = oldNotification.getGroupKey();
-            String newKey = entry.notification.getGroupKey();
-            if (!oldKey.equals(newKey)) {
+            if (groupKeysChanged) {
                 updateSuppression(mGroupMap.get(oldKey));
                 updateSuppression(mGroupMap.get(newKey));
             }
-        } else if (!isGroupChild(oldNotification) && isGroupChild(entry.notification)) {
+        } else if (!wasGroupChild && isGroupChild) {
             onEntryBecomingChild(entry);
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 99fbad2..8658111 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -81,8 +81,8 @@
 
     private static final float LOCK_ICON_ACTIVE_SCALE = 1.2f;
 
-    private static final String COUNTER_PANEL_OPEN = "panel_open";
-    private static final String COUNTER_PANEL_OPEN_QS = "panel_open_qs";
+    static final String COUNTER_PANEL_OPEN = "panel_open";
+    static final String COUNTER_PANEL_OPEN_QS = "panel_open_qs";
     private static final String COUNTER_PANEL_OPEN_PEEK = "panel_open_peek";
 
     private static final Rect mDummyDirtyRect = new Rect(0, 0, 1, 1);
@@ -1013,7 +1013,7 @@
             mKeyguardStatusBar.setAlpha(1f);
             mKeyguardStatusBar.setVisibility(keyguardShowing ? View.VISIBLE : View.INVISIBLE);
             if (keyguardShowing && oldState != mStatusBarState) {
-                mKeyguardBottomArea.updateLeftAffordance();
+                mKeyguardBottomArea.onKeyguardShowingChanged();
                 mAfforanceHelper.updatePreviews();
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index a4531ce..815c369 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -2621,7 +2621,8 @@
     @Override
     public void handleSystemNavigationKey(int key) {
         if (SPEW) Log.d(TAG, "handleSystemNavigationKey: " + key);
-        if (!panelsEnabled() || !mKeyguardMonitor.isDeviceInteractive()) {
+        if (!panelsEnabled() || !mKeyguardMonitor.isDeviceInteractive()
+                || mKeyguardMonitor.isShowing()) {
             return;
         }
 
@@ -2629,12 +2630,16 @@
         if (!mUserSetup) return;
 
         if (KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP == key) {
+            MetricsLogger.action(mContext, MetricsEvent.ACTION_SYSTEM_NAVIGATION_KEY_UP);
             mNotificationPanel.collapse(false /* delayed */, 1.0f /* speedUpFactor */);
         } else if (KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN == key) {
+            MetricsLogger.action(mContext, MetricsEvent.ACTION_SYSTEM_NAVIGATION_KEY_DOWN);
             if (mNotificationPanel.isFullyCollapsed()) {
                 mNotificationPanel.expand(true /* animate */);
+                MetricsLogger.count(mContext, NotificationPanelView.COUNTER_PANEL_OPEN, 1);
             } else if (!mNotificationPanel.isInSettings() && !mNotificationPanel.isExpanding()){
                 mNotificationPanel.flingSettings(0 /* velocity */, true /* expand */);
+                MetricsLogger.count(mContext, NotificationPanelView.COUNTER_PANEL_OPEN_QS, 1);
             }
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
index 58eaf99..3ad09d1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
@@ -197,6 +197,7 @@
 
     @Override
     public void setExpanded(boolean expanded) {
+        if (mExpanded == expanded) return;
         mExpanded = expanded;
         mHeaderQsPanel.setExpanded(expanded);
         updateEverything();
@@ -255,8 +256,10 @@
 
     @Override
     public void updateEverything() {
-        updateVisibilities();
-        setClickable(false);
+        post(() -> {
+            updateVisibilities();
+            setClickable(false);
+        });
     }
 
     protected void updateVisibilities() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java
index 93d0ec3..687b83a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java
@@ -119,13 +119,16 @@
 
     private WidgetInfo getWidgetInfo(Intent intent) {
         PackageManager packageManager = mContext.getPackageManager();
+        int flags = PackageManager.MATCH_DEFAULT_ONLY
+                | PackageManager.MATCH_DIRECT_BOOT_AWARE
+                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
         final List<ResolveInfo> appList = packageManager.queryIntentActivitiesAsUser(
-                intent, PackageManager.MATCH_DEFAULT_ONLY, KeyguardUpdateMonitor.getCurrentUser());
+                intent, flags, KeyguardUpdateMonitor.getCurrentUser());
         if (appList.size() == 0) {
             return null;
         }
         ResolveInfo resolved = packageManager.resolveActivityAsUser(intent,
-                PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA,
+                flags | PackageManager.GET_META_DATA,
                 KeyguardUpdateMonitor.getCurrentUser());
         if (wouldLaunchResolverActivity(resolved, appList)) {
             return null;
@@ -139,23 +142,32 @@
 
     public static boolean wouldLaunchResolverActivity(Context ctx, Intent intent,
             int currentUserId) {
-        return getTargetActivityInfo(ctx, intent, currentUserId) == null;
+        return getTargetActivityInfo(ctx, intent, currentUserId, false /* onlyDirectBootAware */)
+                == null;
     }
 
     /**
+     * @param onlyDirectBootAware a boolean indicating whether the matched activity packages must
+     *                            be direct boot aware when in direct boot mode if false, all
+     *                            packages are considered a match even if they are not aware.
      * @return the target activity info of the intent it resolves to a specific package or
      *         {@code null} if it resolved to the resolver activity
      */
     public static ActivityInfo getTargetActivityInfo(Context ctx, Intent intent,
-            int currentUserId) {
+            int currentUserId, boolean onlyDirectBootAware) {
         PackageManager packageManager = ctx.getPackageManager();
+        int flags = PackageManager.MATCH_DEFAULT_ONLY;
+        if (!onlyDirectBootAware) {
+            flags |=  PackageManager.MATCH_DIRECT_BOOT_AWARE
+                    | PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
+        }
         final List<ResolveInfo> appList = packageManager.queryIntentActivitiesAsUser(
-                intent, PackageManager.MATCH_DEFAULT_ONLY, currentUserId);
+                intent, flags, currentUserId);
         if (appList.size() == 0) {
             return null;
         }
         ResolveInfo resolved = packageManager.resolveActivityAsUser(intent,
-                PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA, currentUserId);
+                flags | PackageManager.GET_META_DATA, currentUserId);
         if (resolved == null || wouldLaunchResolverActivity(resolved, appList)) {
             return null;
         } else {
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index fc19fb5..f5dfa69 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -2197,6 +2197,12 @@
     // Night Light on
     SETTINGS_CONDITION_NIGHT_DISPLAY = 492;
 
+    // System navigation key up.
+    ACTION_SYSTEM_NAVIGATION_KEY_UP = 493;
+
+    // System navigation key down.
+    ACTION_SYSTEM_NAVIGATION_KEY_DOWN = 494;
+
     // ---- End N-MR1 Constants, all N-MR1 constants go above this line ----
 
     // ------- Begin N Keyboard Shortcuts Helper -----
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 4dd88b2..57c25a2 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -1732,9 +1732,10 @@
                 Alarm a = alarms.get(j);
                 if (a.alarmClock != null) {
                     final int userId = UserHandle.getUserId(a.uid);
+                    AlarmManager.AlarmClockInfo current = mNextAlarmClockForUser.get(userId);
 
                     if (DEBUG_ALARM_CLOCK) {
-                        Log.v(TAG, "Found AlarmClockInfo at " +
+                        Log.v(TAG, "Found AlarmClockInfo " + a.alarmClock + " at " +
                                 formatNextAlarm(getContext(), a.alarmClock, userId) +
                                 " for user " + userId);
                     }
@@ -1742,6 +1743,10 @@
                     // Alarms and batches are sorted by time, no need to compare times here.
                     if (nextForUser.get(userId) == null) {
                         nextForUser.put(userId, a.alarmClock);
+                    } else if (a.alarmClock.equals(current)
+                            && current.getTriggerTime() <= nextForUser.get(userId).getTriggerTime()) {
+                        // same/earlier time and it's the one we cited before, so stick with it
+                        nextForUser.put(userId, current);
                     }
                 }
             }
diff --git a/services/core/java/com/android/server/DropBoxManagerService.java b/services/core/java/com/android/server/DropBoxManagerService.java
index 421a8a5..129fbaa 100644
--- a/services/core/java/com/android/server/DropBoxManagerService.java
+++ b/services/core/java/com/android/server/DropBoxManagerService.java
@@ -736,7 +736,7 @@
      * Trims the files on disk to make sure they aren't using too much space.
      * @return the overall quota for storage (in bytes)
      */
-    private synchronized long trimToFit() {
+    private synchronized long trimToFit() throws IOException {
         // Expunge aged items (including tombstones marking deleted data).
 
         int ageSeconds = Settings.Global.getInt(mContentResolver,
@@ -768,7 +768,12 @@
             int quotaKb = Settings.Global.getInt(mContentResolver,
                     Settings.Global.DROPBOX_QUOTA_KB, DEFAULT_QUOTA_KB);
 
-            mStatFs.restat(mDropBoxDir.getPath());
+            String dirPath = mDropBoxDir.getPath();
+            try {
+                mStatFs.restat(dirPath);
+            } catch (IllegalArgumentException e) {  // restat throws this on error
+                throw new IOException("Can't restat: " + mDropBoxDir);
+            }
             int available = mStatFs.getAvailableBlocks();
             int nonreserved = available - mStatFs.getBlockCount() * reservePercent / 100;
             int maximum = quotaKb * 1024 / mBlockSize;
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 228c4fd..acab1af 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -523,15 +523,21 @@
      *
      */
     private boolean isAccountVisible(Account a, int uid, UserAccounts ua) {
+        if(isAccountManagedByCaller(a.type, uid, UserHandle.getUserId(uid))) {
+            return true;
+        }
         int accountMapping = getMockAccountNumber(a, ua);
         if(accountMapping < 0) {
             return true;
         }
         synchronized(ua.cacheLock) {
+            SparseArray<Account> userAcctIdToAcctMap = ua.mMockAccountIdToAccount;
             SparseArray<ArrayList<Integer>> userWlUidToMockAccountNums =
                     ua.mVisibleListUidToMockAccountNumbers;
             ArrayList<Integer> linkedAccountsToUid = userWlUidToMockAccountNums.get(uid);
-            return linkedAccountsToUid != null && linkedAccountsToUid.contains(accountMapping);
+            int indexOfAccountMapping = userAcctIdToAcctMap.indexOfValueByValue(a);
+            return indexOfAccountMapping == -1 || (linkedAccountsToUid != null
+                    && linkedAccountsToUid.contains(accountMapping));
         }
     }
 
@@ -563,7 +569,6 @@
         if(accountMapping < 0) {
             accountMapping = makeAccountNumber(a, ua);
         }
-
         synchronized(ua.cacheLock) {
             SparseArray<ArrayList<Integer>> userWlUidToMockAccountNums =
                     ua.mVisibleListUidToMockAccountNumbers;
@@ -4062,11 +4067,23 @@
         long identityToken = clearCallingIdentity();
         try {
             UserAccounts accounts = getUserAccounts(userId);
-            return getAccountsInternal(
+            Account[] accountsToReturn = getAccountsInternal(
                     accounts,
                     callingUid,
                     callingPackage,
                     visibleAccountTypes);
+            ArrayList<Account> accountsToReturnList = new
+                    ArrayList<Account>(Arrays.asList(accountsToReturn));
+            for(int i = accountsToReturnList.size() - 1; i >= 0 ; i--) {
+                // if account not visible to caller or managed by caller, remove from
+                // accounts to return. Note that all accounts visible by default unless
+                // visible list functionality implemented
+                if(!(isAccountVisible(accountsToReturnList.get(i), callingUid,
+                        getUserAccounts(userId)))) {
+                    accountsToReturnList.remove(i);
+                }
+            }
+            return accountsToReturnList.toArray(new Account[accountsToReturnList.size()]);
         } finally {
             restoreCallingIdentity(identityToken);
         }
@@ -4197,23 +4214,7 @@
     @Override
     @NonNull
     public Account[] getAccounts(String type, String opPackageName) {
-        Account[] accessibleAccounts =
-                getAccountsAsUser(type, UserHandle.getCallingUserId(), opPackageName);
-        /* Up until now, access to accounts is User Specific. With Push API, these accounts
-        can be filtered by application as well. Therefore, in this method specifically,
-        we will additionally add the visible listed accounts tied to the Application
-        specifically through visible listing, as approved by the AccountAuthenticator
-        for a specific application on a device. */
-        ArrayList<Account> allAccounts = new ArrayList<>(Arrays.asList(accessibleAccounts));
-        Account[] visibleListedAccounts = getVisibleListedAccounts(Binder.getCallingUid(),
-                getUserAccounts(UserHandle.getCallingUserId()));
-        for(Account visibleAccount : visibleListedAccounts) {
-            if(!allAccounts.contains(visibleAccount)) {
-                allAccounts.add(visibleAccount);
-            }
-        }
-        Account[] allAccountsArr = new Account[allAccounts.size()];
-        return allAccounts.toArray(allAccountsArr);
+        return getAccountsAsUser(type, UserHandle.getCallingUserId(), opPackageName);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
old mode 100755
new mode 100644
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 1d13d48..f946b38 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -17698,6 +17698,70 @@
         return INTENT_REMOTE_BUGREPORT_FINISHED.equals(intent.getAction());
     }
 
+    private void checkBroadcastFromSystem(Intent intent, ProcessRecord callerApp,
+            String callerPackage, int callingUid, boolean isProtectedBroadcast, List receivers) {
+        final String action = intent.getAction();
+        if (isProtectedBroadcast
+                || Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)
+                || Intent.ACTION_DISMISS_KEYBOARD_SHORTCUTS.equals(action)
+                || Intent.ACTION_MEDIA_BUTTON.equals(action)
+                || Intent.ACTION_MEDIA_SCANNER_SCAN_FILE.equals(action)
+                || Intent.ACTION_SHOW_KEYBOARD_SHORTCUTS.equals(action)
+                || AppWidgetManager.ACTION_APPWIDGET_CONFIGURE.equals(action)
+                || AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)
+                || LocationManager.HIGH_POWER_REQUEST_CHANGE_ACTION.equals(action)
+                || TelephonyIntents.ACTION_REQUEST_OMADM_CONFIGURATION_UPDATE.equals(action)
+                || SuggestionSpan.ACTION_SUGGESTION_PICKED.equals(action)) {
+            // Broadcast is either protected, or it's a public action that
+            // we've relaxed, so it's fine for system internals to send.
+            return;
+        }
+
+        // This broadcast may be a problem...  but there are often system components that
+        // want to send an internal broadcast to themselves, which is annoying to have to
+        // explicitly list each action as a protected broadcast, so we will check for that
+        // one safe case and allow it: an explicit broadcast, only being received by something
+        // that has protected itself.
+        if (receivers != null && receivers.size() > 0
+                && (intent.getPackage() != null || intent.getComponent() != null)) {
+            boolean allProtected = true;
+            for (int i = receivers.size()-1; i >= 0; i--) {
+                Object target = receivers.get(i);
+                if (target instanceof ResolveInfo) {
+                    ResolveInfo ri = (ResolveInfo)target;
+                    if (ri.activityInfo.exported && ri.activityInfo.permission == null) {
+                        allProtected = false;
+                        break;
+                    }
+                } else {
+                    BroadcastFilter bf = (BroadcastFilter)target;
+                    if (bf.requiredPermission == null) {
+                        allProtected = false;
+                        break;
+                    }
+                }
+            }
+            if (allProtected) {
+                // All safe!
+                return;
+            }
+        }
+
+        // The vast majority of broadcasts sent from system internals
+        // should be protected to avoid security holes, so yell loudly
+        // to ensure we examine these cases.
+        if (callerApp != null) {
+            Log.wtf(TAG, "Sending non-protected broadcast " + action
+                            + " from system " + callerApp.toShortString() + " pkg " + callerPackage,
+                    new Throwable());
+        } else {
+            Log.wtf(TAG, "Sending non-protected broadcast " + action
+                            + " from system uid " + UserHandle.formatUid(callingUid)
+                            + " pkg " + callerPackage,
+                    new Throwable());
+        }
+    }
+
     final int broadcastIntentLocked(ProcessRecord callerApp,
             String callerPackage, Intent intent, String resolvedType,
             IIntentReceiver resultTo, int resultCode, String resultData,
@@ -17784,37 +17848,9 @@
                 break;
         }
 
-        if (isCallerSystem) {
-            if (isProtectedBroadcast
-                    || Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)
-                    || Intent.ACTION_DISMISS_KEYBOARD_SHORTCUTS.equals(action)
-                    || Intent.ACTION_MEDIA_BUTTON.equals(action)
-                    || Intent.ACTION_MEDIA_SCANNER_SCAN_FILE.equals(action)
-                    || Intent.ACTION_SHOW_KEYBOARD_SHORTCUTS.equals(action)
-                    || AppWidgetManager.ACTION_APPWIDGET_CONFIGURE.equals(action)
-                    || AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)
-                    || LocationManager.HIGH_POWER_REQUEST_CHANGE_ACTION.equals(action)
-                    || TelephonyIntents.ACTION_REQUEST_OMADM_CONFIGURATION_UPDATE.equals(action)
-                    || SuggestionSpan.ACTION_SUGGESTION_PICKED.equals(action)) {
-                // Broadcast is either protected, or it's a public action that
-                // we've relaxed, so it's fine for system internals to send.
-            } else {
-                // The vast majority of broadcasts sent from system internals
-                // should be protected to avoid security holes, so yell loudly
-                // to ensure we examine these cases.
-                if (callerApp != null) {
-                    Log.wtf(TAG, "Sending non-protected broadcast " + action
-                            + " from system " + callerApp.toShortString() + " pkg " + callerPackage,
-                            new Throwable());
-                } else {
-                    Log.wtf(TAG, "Sending non-protected broadcast " + action
-                            + " from system uid " + UserHandle.formatUid(callingUid)
-                            + " pkg " + callerPackage,
-                            new Throwable());
-                }
-            }
-
-        } else {
+        // First line security check before anything else: stop non-system apps from
+        // sending protected broadcasts.
+        if (!isCallerSystem) {
             if (isProtectedBroadcast) {
                 String msg = "Permission Denial: not allowed to send broadcast "
                         + action + " from pid="
@@ -18200,6 +18236,10 @@
             // If we are not serializing this broadcast, then send the
             // registered receivers separately so they don't wait for the
             // components to be launched.
+            if (isCallerSystem) {
+                checkBroadcastFromSystem(intent, callerApp, callerPackage, callingUid,
+                        isProtectedBroadcast, registeredReceivers);
+            }
             final BroadcastQueue queue = broadcastQueueForIntent(intent);
             BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
                     callerPackage, callingPid, callingUid, resolvedType, requiredPermissions,
@@ -18287,6 +18327,11 @@
             ir++;
         }
 
+        if (isCallerSystem) {
+            checkBroadcastFromSystem(intent, callerApp, callerPackage, callingUid,
+                    isProtectedBroadcast, receivers);
+        }
+
         if ((receivers != null && receivers.size() > 0)
                 || resultTo != null) {
             BroadcastQueue queue = broadcastQueueForIntent(intent);
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
old mode 100755
new mode 100644
diff --git a/services/core/java/com/android/server/am/BaseErrorDialog.java b/services/core/java/com/android/server/am/BaseErrorDialog.java
old mode 100755
new mode 100644
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index 4399e36..d02fbbf 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -226,11 +226,12 @@
     }
 
     public final boolean replaceParallelBroadcastLocked(BroadcastRecord r) {
+        final Intent intent = r.intent;
         for (int i = mParallelBroadcasts.size() - 1; i >= 0; i--) {
-            if (r.intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
+            if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
                 if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
                         "***** DROPPING PARALLEL ["
-                + mQueueName + "]: " + r.intent);
+                + mQueueName + "]: " + intent);
                 mParallelBroadcasts.set(i, r);
                 return true;
             }
@@ -239,11 +240,12 @@
     }
 
     public final boolean replaceOrderedBroadcastLocked(BroadcastRecord r) {
+        final Intent intent = r.intent;
         for (int i = mOrderedBroadcasts.size() - 1; i > 0; i--) {
-            if (r.intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
+            if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
                 if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
                         "***** DROPPING ORDERED ["
-                        + mQueueName + "]: " + r.intent);
+                        + mQueueName + "]: " + intent);
                 mOrderedBroadcasts.set(i, r);
                 return true;
             }
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 0d1727f..a5245a2 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -292,6 +292,7 @@
      */
     private void finishUserUnlocking(final UserState uss) {
         final int userId = uss.mHandle.getIdentifier();
+        boolean proceedWithUnlock = false;
         synchronized (mLock) {
             // Bail if we ended up with a stale user
             if (mStartedUsers.get(uss.mHandle.getIdentifier()) != uss) return;
@@ -301,20 +302,24 @@
 
             if (uss.setState(STATE_RUNNING_LOCKED, STATE_RUNNING_UNLOCKING)) {
                 mInjector.getUserManagerInternal().setUserState(userId, uss.state);
-                uss.mUnlockProgress.start();
-
-                // Prepare app storage before we go any further
-                uss.mUnlockProgress.setProgress(5,
-                        mInjector.getContext().getString(R.string.android_start_title));
-                mInjector.getUserManager().onBeforeUnlockUser(userId);
-                uss.mUnlockProgress.setProgress(20);
-
-                // Dispatch unlocked to system services; when fully dispatched,
-                // that calls through to the next "unlocked" phase
-                mHandler.obtainMessage(SYSTEM_USER_UNLOCK_MSG, userId, 0, uss)
-                        .sendToTarget();
+                proceedWithUnlock = true;
             }
         }
+
+        if (proceedWithUnlock) {
+            uss.mUnlockProgress.start();
+
+            // Prepare app storage before we go any further
+            uss.mUnlockProgress.setProgress(5,
+                        mInjector.getContext().getString(R.string.android_start_title));
+            mInjector.getUserManager().onBeforeUnlockUser(userId);
+            uss.mUnlockProgress.setProgress(20);
+
+            // Dispatch unlocked to system services; when fully dispatched,
+            // that calls through to the next "unlocked" phase
+            mHandler.obtainMessage(SYSTEM_USER_UNLOCK_MSG, userId, 0, uss)
+                    .sendToTarget();
+        }
     }
 
     /**
@@ -961,6 +966,7 @@
 
     boolean unlockUserCleared(final int userId, byte[] token, byte[] secret,
             IProgressListener listener) {
+        UserState uss;
         synchronized (mLock) {
             // TODO Move this block outside of synchronized if it causes lock contention
             if (!StorageManager.isUserKeyUnlocked(userId)) {
@@ -975,7 +981,7 @@
             }
             // Bail if user isn't actually running, otherwise register the given
             // listener to watch for unlock progress
-            final UserState uss = mStartedUsers.get(userId);
+            uss = mStartedUsers.get(userId);
             if (uss == null) {
                 notifyFinished(userId, listener);
                 return false;
@@ -983,8 +989,12 @@
                 uss.mUnlockProgress.addListener(listener);
                 uss.tokenProvided = (token != null);
             }
+        }
 
-            finishUserUnlocking(uss);
+        finishUserUnlocking(uss);
+
+        final ArraySet<Integer> childProfilesToUnlock = new ArraySet<>();
+        synchronized (mLock) {
 
             // We just unlocked a user, so let's now attempt to unlock any
             // managed profiles under that user.
@@ -994,11 +1004,16 @@
                 if (parent != null && parent.id == userId && testUserId != userId) {
                     Slog.d(TAG, "User " + testUserId + " (parent " + parent.id
                             + "): attempting unlock because parent was just unlocked");
-                    maybeUnlockUser(testUserId);
+                    childProfilesToUnlock.add(testUserId);
                 }
             }
         }
 
+        final int size = childProfilesToUnlock.size();
+        for (int i = 0; i < size; i++) {
+            maybeUnlockUser(childProfilesToUnlock.valueAt(i));
+        }
+
         return true;
     }
 
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index f433af8..d8e5f63 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -2824,7 +2824,6 @@
             for (int j = mPowerSaveTempWhitelistAppIds.size() - 1; j >= 0; j--) {
                 int appId = mPowerSaveTempWhitelistAppIds.keyAt(j);
                 int uid = UserHandle.getUid(user.id, appId);
-                updateRulesForRestrictPowerUL();
                 // Update external firewall rules.
                 updateRuleForAppIdleUL(uid);
                 updateRuleForDeviceIdleUL(uid);
diff --git a/services/core/java/com/android/server/pm/ShortcutUser.java b/services/core/java/com/android/server/pm/ShortcutUser.java
index 21e4165..ce3ed9c 100644
--- a/services/core/java/com/android/server/pm/ShortcutUser.java
+++ b/services/core/java/com/android/server/pm/ShortcutUser.java
@@ -57,7 +57,9 @@
 
     private static final String ATTR_VALUE = "value";
     private static final String ATTR_KNOWN_LOCALES = "locales";
-    private static final String ATTR_LAST_APP_SCAN_TIME = "last-app-scan-time";
+
+    // Suffix "2" was added to force rescan all packages after the next OTA.
+    private static final String ATTR_LAST_APP_SCAN_TIME = "last-app-scan-time2";
     private static final String KEY_USER_ID = "userId";
     private static final String KEY_LAUNCHERS = "launchers";
     private static final String KEY_PACKAGES = "packages";
diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java
index 7d20931..fdadc8d 100644
--- a/services/core/java/com/android/server/vr/VrManagerService.java
+++ b/services/core/java/com/android/server/vr/VrManagerService.java
@@ -46,6 +46,7 @@
 import android.service.vr.IVrManager;
 import android.service.vr.IVrStateCallbacks;
 import android.service.vr.VrListenerService;
+import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.Slog;
@@ -218,6 +219,7 @@
                     String packageName = mNotificationAccessPackageToUserId.keyAt(i);
                     revokeNotificationListenerAccess(packageName, grantUserId);
                     revokeNotificationPolicyAccess(packageName);
+                    revokeCoarseLocationPermissionIfNeeded(packageName, grantUserId);
                     mNotificationAccessPackageToUserId.removeAt(i);
                 }
             }
@@ -226,6 +228,7 @@
                 if (!packageNames.contains(pkg)) {
                     revokeNotificationListenerAccess(pkg, currentUserId);
                     revokeNotificationPolicyAccess(pkg);
+                    revokeCoarseLocationPermissionIfNeeded(pkg, currentUserId);
                     mNotificationAccessPackageToUserId.remove(pkg);
                 }
             }
@@ -233,6 +236,7 @@
                 if (!allowed.contains(pkg)) {
                     grantNotificationPolicyAccess(pkg);
                     grantNotificationListenerAccess(pkg, currentUserId);
+                    grantCoarseLocationPermissionIfNeeded(pkg, currentUserId);
                     mNotificationAccessPackageToUserId.put(pkg, currentUserId);
                 }
             }
@@ -643,7 +647,7 @@
 
         for (String c : current) {
             ComponentName component = ComponentName.unflattenFromString(c);
-            if (component.getPackageName().equals(pkg)) {
+            if (component != null && component.getPackageName().equals(pkg)) {
                 toRemove.add(c);
             }
         }
@@ -656,6 +660,22 @@
                 flatSettings, userId);
     }
 
+    private void grantCoarseLocationPermissionIfNeeded(String pkg, int userId) {
+        // Don't clobber the user if permission set in current state explicitly
+        if (!isPermissionUserUpdated(Manifest.permission.ACCESS_COARSE_LOCATION, pkg, userId)) {
+            mContext.getPackageManager().grantRuntimePermission(pkg,
+                    Manifest.permission.ACCESS_COARSE_LOCATION, new UserHandle(userId));
+        }
+    }
+
+    private void revokeCoarseLocationPermissionIfNeeded(String pkg, int userId) {
+        // Don't clobber the user if permission set in current state explicitly
+        if (!isPermissionUserUpdated(Manifest.permission.ACCESS_COARSE_LOCATION, pkg, userId)) {
+            mContext.getPackageManager().revokeRuntimePermission(pkg,
+                    Manifest.permission.ACCESS_COARSE_LOCATION, new UserHandle(userId));
+        }
+    }
+
     private boolean isPermissionUserUpdated(String permission, String pkg, int userId) {
         final int flags = mContext.getPackageManager().getPermissionFlags(
                 permission, pkg, new UserHandle(userId));
@@ -671,7 +691,9 @@
         if (flat != null) {
             String[] allowed = flat.split(":");
             for (String s : allowed) {
-                current.add(s);
+                if (!TextUtils.isEmpty(s)) {
+                    current.add(s);
+                }
             }
         }
         return current;
diff --git a/tools/aapt2/flatten/XmlFlattener.cpp b/tools/aapt2/flatten/XmlFlattener.cpp
index 3c1750c..ed5b60f 100644
--- a/tools/aapt2/flatten/XmlFlattener.cpp
+++ b/tools/aapt2/flatten/XmlFlattener.cpp
@@ -88,9 +88,14 @@
     }
 
     void visit(xml::Namespace* node) override {
-        writeNamespace(node, android::RES_XML_START_NAMESPACE_TYPE);
-        xml::Visitor::visit(node);
-        writeNamespace(node, android::RES_XML_END_NAMESPACE_TYPE);
+        if (node->namespaceUri == xml::kSchemaTools) {
+            // Skip dedicated tools namespace.
+            xml::Visitor::visit(node);
+        } else {
+            writeNamespace(node, android::RES_XML_START_NAMESPACE_TYPE);
+            xml::Visitor::visit(node);
+            writeNamespace(node, android::RES_XML_END_NAMESPACE_TYPE);
+        }
     }
 
     void visit(xml::Text* node) override {
@@ -183,6 +188,9 @@
                     continue;
                 }
             }
+            if (attr.namespaceUri == xml::kSchemaTools) {
+                continue;
+            }
             mFilteredAttrs.push_back(&attr);
         }
 
diff --git a/tools/aapt2/flatten/XmlFlattener_test.cpp b/tools/aapt2/flatten/XmlFlattener_test.cpp
index 8b3378f..d26f2e4 100644
--- a/tools/aapt2/flatten/XmlFlattener_test.cpp
+++ b/tools/aapt2/flatten/XmlFlattener_test.cpp
@@ -167,6 +167,33 @@
     EXPECT_EQ(uint32_t(0x010103b3), tree.getAttributeNameResID(0));
 }
 
+TEST_F(XmlFlattenerTest, FlattenCompiledXmlAndStripOnlyTools) {
+    std::unique_ptr<xml::XmlResource> doc = test::buildXmlDom(R"EOF(
+            <View xmlns:tools="http://schemas.android.com/tools"
+                xmlns:foo="http://schemas.android.com/foo"
+                foo:bar="Foo"
+                tools:ignore="MissingTranslation"/>)EOF");
+
+    android::ResXMLTree tree;
+    ASSERT_TRUE(flatten(doc.get(), &tree));
+
+    ASSERT_EQ(tree.next(), android::ResXMLTree::START_NAMESPACE);
+
+    size_t len;
+    const char16_t* namespacePrefix = tree.getNamespacePrefix(&len);
+    EXPECT_EQ(StringPiece16(namespacePrefix, len), u"foo");
+
+    const char16_t* namespaceUri = tree.getNamespaceUri(&len);
+    ASSERT_EQ(StringPiece16(namespaceUri, len), u"http://schemas.android.com/foo");
+
+    ASSERT_EQ(tree.next(), android::ResXMLTree::START_TAG);
+
+    EXPECT_EQ(
+            tree.indexOfAttribute("http://schemas.android.com/tools", "ignore"),
+            android::NAME_NOT_FOUND);
+    EXPECT_GE(tree.indexOfAttribute("http://schemas.android.com/foo", "bar"), 0);
+}
+
 TEST_F(XmlFlattenerTest, AssignSpecialAttributeIndices) {
     std::unique_ptr<xml::XmlResource> doc = test::buildXmlDom(R"EOF(
             <View xmlns:android="http://schemas.android.com/apk/res/android"
diff --git a/tools/aapt2/xml/XmlUtil.h b/tools/aapt2/xml/XmlUtil.h
index f0d59b7..b75d8ac 100644
--- a/tools/aapt2/xml/XmlUtil.h
+++ b/tools/aapt2/xml/XmlUtil.h
@@ -29,6 +29,7 @@
 constexpr const char* kSchemaPublicPrefix = "http://schemas.android.com/apk/res/";
 constexpr const char* kSchemaPrivatePrefix = "http://schemas.android.com/apk/prv/res/";
 constexpr const char* kSchemaAndroid = "http://schemas.android.com/apk/res/android";
+constexpr const char* kSchemaTools = "http://schemas.android.com/tools";
 
 /**
  * Result of extracting a package name from a namespace URI declaration.