Merge "More lint checks." into nyc-dev
diff --git a/api/current.txt b/api/current.txt
index f7a316d..f1647d0 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -26859,7 +26859,8 @@
     method public static void glGetSynciv(long, int, int, int[], int, int[], int);
     method public static void glGetSynciv(long, int, int, java.nio.IntBuffer, java.nio.IntBuffer);
     method public static void glGetTransformFeedbackVarying(int, int, int, int[], int, int[], int, int[], int, byte[], int);
-    method public static void glGetTransformFeedbackVarying(int, int, int, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.IntBuffer, byte);
+    method public static deprecated void glGetTransformFeedbackVarying(int, int, int, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.IntBuffer, byte);
+    method public static void glGetTransformFeedbackVarying(int, int, int, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.ByteBuffer);
     method public static java.lang.String glGetTransformFeedbackVarying(int, int, int[], int, int[], int);
     method public static java.lang.String glGetTransformFeedbackVarying(int, int, java.nio.IntBuffer, java.nio.IntBuffer);
     method public static int glGetUniformBlockIndex(int, java.lang.String);
@@ -36419,6 +36420,7 @@
   public class TelecomManager {
     method public void addNewIncomingCall(android.telecom.PhoneAccountHandle, android.os.Bundle);
     method public void cancelMissedCallsNotification();
+    method public android.content.Intent createManageBlockedNumbersIntent();
     method public android.net.Uri getAdnUriForPhoneAccount(android.telecom.PhoneAccountHandle);
     method public java.util.List<android.telecom.PhoneAccountHandle> getCallCapablePhoneAccounts();
     method public java.lang.String getDefaultDialerPackage();
diff --git a/api/system-current.txt b/api/system-current.txt
index b2b5982..61a8953 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -29161,7 +29161,8 @@
     method public static void glGetSynciv(long, int, int, int[], int, int[], int);
     method public static void glGetSynciv(long, int, int, java.nio.IntBuffer, java.nio.IntBuffer);
     method public static void glGetTransformFeedbackVarying(int, int, int, int[], int, int[], int, int[], int, byte[], int);
-    method public static void glGetTransformFeedbackVarying(int, int, int, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.IntBuffer, byte);
+    method public static deprecated void glGetTransformFeedbackVarying(int, int, int, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.IntBuffer, byte);
+    method public static void glGetTransformFeedbackVarying(int, int, int, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.ByteBuffer);
     method public static java.lang.String glGetTransformFeedbackVarying(int, int, int[], int, int[], int);
     method public static java.lang.String glGetTransformFeedbackVarying(int, int, java.nio.IntBuffer, java.nio.IntBuffer);
     method public static int glGetUniformBlockIndex(int, java.lang.String);
@@ -39118,6 +39119,7 @@
     method public void cancelMissedCallsNotification();
     method public deprecated void clearAccounts();
     method public void clearPhoneAccounts();
+    method public android.content.Intent createManageBlockedNumbersIntent();
     method public java.util.List<android.telecom.ParcelableCallAnalytics> dumpAnalytics();
     method public void enablePhoneAccount(android.telecom.PhoneAccountHandle, boolean);
     method public boolean endCall();
diff --git a/api/test-current.txt b/api/test-current.txt
index 472daf6..d2d470b 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -26868,7 +26868,8 @@
     method public static void glGetSynciv(long, int, int, int[], int, int[], int);
     method public static void glGetSynciv(long, int, int, java.nio.IntBuffer, java.nio.IntBuffer);
     method public static void glGetTransformFeedbackVarying(int, int, int, int[], int, int[], int, int[], int, byte[], int);
-    method public static void glGetTransformFeedbackVarying(int, int, int, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.IntBuffer, byte);
+    method public static deprecated void glGetTransformFeedbackVarying(int, int, int, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.IntBuffer, byte);
+    method public static void glGetTransformFeedbackVarying(int, int, int, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.ByteBuffer);
     method public static java.lang.String glGetTransformFeedbackVarying(int, int, int[], int, int[], int);
     method public static java.lang.String glGetTransformFeedbackVarying(int, int, java.nio.IntBuffer, java.nio.IntBuffer);
     method public static int glGetUniformBlockIndex(int, java.lang.String);
@@ -36434,6 +36435,7 @@
   public class TelecomManager {
     method public void addNewIncomingCall(android.telecom.PhoneAccountHandle, android.os.Bundle);
     method public void cancelMissedCallsNotification();
+    method public android.content.Intent createManageBlockedNumbersIntent();
     method public android.net.Uri getAdnUriForPhoneAccount(android.telecom.PhoneAccountHandle);
     method public java.util.List<android.telecom.PhoneAccountHandle> getCallCapablePhoneAccounts();
     method public java.lang.String getDefaultDialerPackage();
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 0d852e5..f2a8ea5 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -978,18 +978,19 @@
 
         @Override
         public void dumpMemInfo(FileDescriptor fd, Debug.MemoryInfo mem, boolean checkin,
-                boolean dumpFullInfo, boolean dumpDalvik, boolean dumpSummaryOnly, String[] args) {
+                boolean dumpFullInfo, boolean dumpDalvik, boolean dumpSummaryOnly,
+                boolean dumpUnreachable, String[] args) {
             FileOutputStream fout = new FileOutputStream(fd);
             PrintWriter pw = new FastPrintWriter(fout);
             try {
-                dumpMemInfo(pw, mem, checkin, dumpFullInfo, dumpDalvik, dumpSummaryOnly);
+                dumpMemInfo(pw, mem, checkin, dumpFullInfo, dumpDalvik, dumpSummaryOnly, dumpUnreachable);
             } finally {
                 pw.flush();
             }
         }
 
         private void dumpMemInfo(PrintWriter pw, Debug.MemoryInfo memInfo, boolean checkin,
-                boolean dumpFullInfo, boolean dumpDalvik, boolean dumpSummaryOnly) {
+                boolean dumpFullInfo, boolean dumpDalvik, boolean dumpSummaryOnly, boolean dumpUnreachable) {
             long nativeMax = Debug.getNativeHeapSize() / 1024;
             long nativeAllocated = Debug.getNativeHeapAllocatedSize() / 1024;
             long nativeFree = Debug.getNativeHeapFreeSize() / 1024;
@@ -1103,6 +1104,16 @@
                 pw.println(" Asset Allocations");
                 pw.print(assetAlloc);
             }
+
+            // Unreachable native memory
+            if (dumpUnreachable) {
+                boolean showContents = ((mBoundApplication != null)
+                    && ((mBoundApplication.appInfo.flags&ApplicationInfo.FLAG_DEBUGGABLE) != 0))
+                    || android.os.Build.IS_DEBUGGABLE;
+                pw.println(" ");
+                pw.println(" Unreachable memory");
+                pw.print(Debug.getUnreachableMemory(100, showContents));
+            }
         }
 
         @Override
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index 59ecc03..744ddf7 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -548,11 +548,12 @@
             boolean dumpInfo = data.readInt() != 0;
             boolean dumpDalvik = data.readInt() != 0;
             boolean dumpSummaryOnly = data.readInt() != 0;
+            boolean dumpUnreachable = data.readInt() != 0;
             String[] args = data.readStringArray();
             if (fd != null) {
                 try {
                     dumpMemInfo(fd.getFileDescriptor(), mi, checkin, dumpInfo,
-                            dumpDalvik, dumpSummaryOnly, args);
+                            dumpDalvik, dumpSummaryOnly, dumpUnreachable, args);
                 } finally {
                     try {
                         fd.close();
@@ -1328,7 +1329,8 @@
     }
 
     public void dumpMemInfo(FileDescriptor fd, Debug.MemoryInfo mem, boolean checkin,
-            boolean dumpInfo, boolean dumpDalvik, boolean dumpSummaryOnly, String[] args) throws RemoteException {
+            boolean dumpInfo, boolean dumpDalvik, boolean dumpSummaryOnly,
+            boolean dumpUnreachable, String[] args) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IApplicationThread.descriptor);
@@ -1338,6 +1340,7 @@
         data.writeInt(dumpInfo ? 1 : 0);
         data.writeInt(dumpDalvik ? 1 : 0);
         data.writeInt(dumpSummaryOnly ? 1 : 0);
+        data.writeInt(dumpUnreachable ? 1 : 0);
         data.writeStringArray(args);
         mRemote.transact(DUMP_MEM_INFO_TRANSACTION, data, reply, 0);
         reply.readException();
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index b55da88..a3c9591 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -133,7 +133,8 @@
     void updatePackageCompatibilityInfo(String pkg, CompatibilityInfo info) throws RemoteException;
     void scheduleTrimMemory(int level) throws RemoteException;
     void dumpMemInfo(FileDescriptor fd, Debug.MemoryInfo mem, boolean checkin, boolean dumpInfo,
-            boolean dumpDalvik, boolean dumpSummaryOnly, String[] args) throws RemoteException;
+            boolean dumpDalvik, boolean dumpSummaryOnly, boolean dumpUnreachable,
+            String[] args) throws RemoteException;
     void dumpGfxInfo(FileDescriptor fd, String[] args) throws RemoteException;
     void dumpDbInfo(FileDescriptor fd, String[] args) throws RemoteException;
     void unstableProviderDied(IBinder provider) throws RemoteException;
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index a9150e8..a54f40f 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -68,6 +68,7 @@
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.Arrays;
 import java.util.Locale;
 
 /**
@@ -119,6 +120,9 @@
     private static final LongSparseArray<android.content.res.ConstantState<ComplexColor>>
             sPreloadedComplexColors = new LongSparseArray<>();
 
+    /** Size of the cyclical cache used to map XML files to blocks. */
+    private static final int XML_BLOCK_CACHE_SIZE = 4;
+
     // Pool of TypedArrays targeted to this Resources object.
     final SynchronizedPool<TypedArray> mTypedArrayPool = new SynchronizedPool<>(5);
 
@@ -154,8 +158,9 @@
 
     // Cyclical cache used for recently-accessed XML files.
     private int mLastCachedXmlBlockIndex = -1;
-    private final String[] mCachedXmlBlockFiles = new String[4];
-    private final XmlBlock[] mCachedXmlBlocks = new XmlBlock[4];
+    private final int[] mCachedXmlBlockCookies = new int[XML_BLOCK_CACHE_SIZE];
+    private final String[] mCachedXmlBlockFiles = new String[XML_BLOCK_CACHE_SIZE];
+    private final XmlBlock[] mCachedXmlBlocks = new XmlBlock[XML_BLOCK_CACHE_SIZE];
 
     final AssetManager mAssets;
     final ClassLoader mClassLoader;
@@ -2339,18 +2344,18 @@
      * tools.
      */
     public final void flushLayoutCache() {
-        final String[] cachedXmlBlockFiles = mCachedXmlBlockFiles;
-        final XmlBlock[] cachedXmlBlocks = mCachedXmlBlocks;
-        synchronized (cachedXmlBlockFiles) {
-            final int num = cachedXmlBlockFiles.length;
-            for (int i = 0; i < num; i++) {
+        synchronized (mCachedXmlBlocks) {
+            Arrays.fill(mCachedXmlBlockCookies, 0);
+            Arrays.fill(mCachedXmlBlockFiles, null);
+
+            final XmlBlock[] cachedXmlBlocks = mCachedXmlBlocks;
+            for (int i = 0; i < XML_BLOCK_CACHE_SIZE; i++) {
                 final XmlBlock oldBlock = cachedXmlBlocks[i];
                 if (oldBlock != null) {
                     oldBlock.close();
                 }
-                cachedXmlBlockFiles[i] = null;
-                cachedXmlBlocks[i] = null;
             }
+            Arrays.fill(cachedXmlBlocks, null);
         }
     }
 
@@ -2852,13 +2857,14 @@
             int assetCookie, @NonNull String type) throws NotFoundException {
         if (id != 0) {
             try {
-                final String[] cachedXmlBlockFiles = mCachedXmlBlockFiles;
-                final XmlBlock[] cachedXmlBlocks = mCachedXmlBlocks;
-                synchronized (cachedXmlBlockFiles) {
+                synchronized (mCachedXmlBlocks) {
+                    final int[] cachedXmlBlockCookies = mCachedXmlBlockCookies;
+                    final String[] cachedXmlBlockFiles = mCachedXmlBlockFiles;
+                    final XmlBlock[] cachedXmlBlocks = mCachedXmlBlocks;
                     // First see if this block is in our cache.
                     final int num = cachedXmlBlockFiles.length;
                     for (int i = 0; i < num; i++) {
-                        if (cachedXmlBlockFiles[i] != null
+                        if (cachedXmlBlockCookies[i] == assetCookie && cachedXmlBlockFiles[i] != null
                                 && cachedXmlBlockFiles[i].equals(file)) {
                             return cachedXmlBlocks[i].newParser();
                         }
@@ -2874,6 +2880,7 @@
                         if (oldBlock != null) {
                             oldBlock.close();
                         }
+                        cachedXmlBlockCookies[pos] = assetCookie;
                         cachedXmlBlockFiles[pos] = file;
                         cachedXmlBlocks[pos] = block;
                         return block.newParser();
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index fb16150..f382241 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -2160,6 +2160,14 @@
     public static native void dumpNativeBacktraceToFile(int pid, String file);
 
     /**
+     * Get description of unreachable native memory.
+     * @param limit the number of leaks to provide info on, 0 to only get a summary.
+     * @param contents true to include a hex dump of the contents of unreachable memory.
+     * @return the String containing a description of unreachable memory.
+     * @hide */
+    public static native String getUnreachableMemory(int limit, boolean contents);
+
+    /**
      * Return a String describing the calling method and location at a particular stack depth.
      * @param callStack the Thread stack
      * @param depth the depth of stack to return information for.
diff --git a/core/java/android/os/HardwarePropertiesManager.java b/core/java/android/os/HardwarePropertiesManager.java
index c72a6481..f48306a 100644
--- a/core/java/android/os/HardwarePropertiesManager.java
+++ b/core/java/android/os/HardwarePropertiesManager.java
@@ -69,7 +69,6 @@
      * @return an array of requested float device temperatures.
      *         Empty if platform doesn't provide the queried temperature.
      *
-     * @throws IllegalArgumentException if an incorrect temperature type is queried.
      * @throws SecurityException if a non profile or device owner tries to call this method.
     */
     public @NonNull float[] getDeviceTemperatures(@DeviceTemperatureType int type) {
@@ -84,7 +83,8 @@
                 return new float[0];
             }
         default:
-            throw new IllegalArgumentException();
+            Log.w(TAG, "Unknown device temperature type.");
+            return new float[0];
         }
     }
 
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index c5b1653..afe2f10 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -4398,8 +4398,14 @@
     private boolean updatePointerIcon(MotionEvent event) {
         final float x = event.getX();
         final float y = event.getY();
+        if (mView == null) {
+            // E.g. click outside a popup to dismiss it
+            Slog.d(mTag, "updatePointerIcon called after view was removed");
+            return false;
+        }
         if (x < 0 || x >= mView.getWidth() || y < 0 || y >= mView.getHeight()) {
-            Slog.e(mTag, "updatePointerIcon called with position out of bounds");
+            // E.g. when moving window divider with mouse
+            Slog.d(mTag, "updatePointerIcon called with position out of bounds");
             return false;
         }
         final PointerIcon pointerIcon = mView.getPointerIcon(event, x, y);
diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java
index 3796df7..9a4d69f 100644
--- a/core/java/android/widget/SearchView.java
+++ b/core/java/android/widget/SearchView.java
@@ -1358,6 +1358,17 @@
                     + Integer.toHexString(System.identityHashCode(this))
                     + " isIconified=" + isIconified + "}";
         }
+
+        public static final Parcelable.Creator<SavedState> CREATOR =
+                new Parcelable.Creator<SavedState>() {
+                    public SavedState createFromParcel(Parcel in) {
+                        return new SavedState(in);
+                    }
+
+                    public SavedState[] newArray(int size) {
+                        return new SavedState[size];
+                    }
+                };
     }
 
     @Override
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index a8d684d..d5f080a 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -260,7 +260,8 @@
     libprocessgroup \
     libnativebridge \
     libradio_metadata \
-    libnativeloader
+    libnativeloader \
+    libmemunreachable \
 
 LOCAL_SHARED_LIBRARIES += \
     libhwui \
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 8b248b0..29c1075 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -555,6 +555,12 @@
     std::unique_ptr<SkFILEStream> fileStream(new SkFILEStream(file,
             SkFILEStream::kCallerPasses_Ownership));
 
+    // If there is no offset for the file descriptor, we use SkFILEStream directly.
+    if (::lseek(descriptor, 0, SEEK_CUR) == 0) {
+        assert(isSeekable(dupDescriptor));
+        return doDecode(env, fileStream.release(), padding, bitmapFactoryOptions);
+    }
+
     // Use a buffered stream. Although an SkFILEStream can be rewound, this
     // ensures that SkImageDecoder::Factory never rewinds beyond the
     // current position of the file descriptor.
@@ -584,7 +590,7 @@
 
 static jboolean nativeIsSeekable(JNIEnv* env, jobject, jobject fileDescriptor) {
     jint descriptor = jniGetFDFromFileDescriptor(env, fileDescriptor);
-    return ::lseek64(descriptor, 0, SEEK_CUR) != -1 ? JNI_TRUE : JNI_FALSE;
+    return isSeekable(descriptor) ? JNI_TRUE : JNI_FALSE;
 }
 
 jobject decodeBitmap(JNIEnv* env, void* data, size_t size) {
diff --git a/core/jni/android/graphics/Utils.cpp b/core/jni/android/graphics/Utils.cpp
index 4f9ce8b..5fa445e 100644
--- a/core/jni/android/graphics/Utils.cpp
+++ b/core/jni/android/graphics/Utils.cpp
@@ -116,3 +116,7 @@
     }
     return NULL;
 }
+
+bool android::isSeekable(int descriptor) {
+    return ::lseek64(descriptor, 0, SEEK_CUR) != -1;
+}
diff --git a/core/jni/android/graphics/Utils.h b/core/jni/android/graphics/Utils.h
index c0b9410..d1a74a0 100644
--- a/core/jni/android/graphics/Utils.h
+++ b/core/jni/android/graphics/Utils.h
@@ -68,6 +68,10 @@
 
 jobject nullObjectReturn(const char msg[]);
 
+/** Check if the file descriptor is seekable.
+ */
+bool isSeekable(int descriptor);
+
 }; // namespace android
 
 #endif  // _ANDROID_GRAPHICS_UTILS_H_
diff --git a/core/jni/android_opengl_GLES30.cpp b/core/jni/android_opengl_GLES30.cpp
index 2d69eaa..59b8911 100644
--- a/core/jni/android_opengl_GLES30.cpp
+++ b/core/jni/android_opengl_GLES30.cpp
@@ -2012,22 +2012,35 @@
 static void
 android_glGetTransformFeedbackVarying__IIILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2B
   (JNIEnv *_env, jobject _this, jint program, jint index, jint bufsize, jobject length_buf, jobject size_buf, jobject type_buf, jbyte name) {
+    jniThrowException(_env, "java/lang/UnsupportedOperationException", "deprecated");
+}
+
+/* void glGetTransformFeedbackVarying ( GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name ) */
+static void
+android_glGetTransformFeedbackVarying__IIILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_ByteBuffer_2
+  (JNIEnv *_env, jobject _this, jint program, jint index, jint bufsize, jobject length_buf, jobject size_buf, jobject type_buf, jobject name_buf) {
     jintArray _lengthArray = (jintArray) 0;
     jint _lengthBufferOffset = (jint) 0;
     jintArray _sizeArray = (jintArray) 0;
     jint _sizeBufferOffset = (jint) 0;
     jintArray _typeArray = (jintArray) 0;
     jint _typeBufferOffset = (jint) 0;
+    jbyteArray _nameArray = (jbyteArray)0;
+    jint _nameBufferOffset = (jint)0;
     jint _lengthRemaining;
     GLsizei *length = (GLsizei *) 0;
     jint _sizeRemaining;
     GLint *size = (GLint *) 0;
     jint _typeRemaining;
     GLenum *type = (GLenum *) 0;
+    jint _nameRemaining;
+    GLchar* name = (GLchar*)0;
+
 
     length = (GLsizei *)getPointer(_env, length_buf, (jarray*)&_lengthArray, &_lengthRemaining, &_lengthBufferOffset);
     size = (GLint *)getPointer(_env, size_buf, (jarray*)&_sizeArray, &_sizeRemaining, &_sizeBufferOffset);
     type = (GLenum *)getPointer(_env, type_buf, (jarray*)&_typeArray, &_typeRemaining, &_typeBufferOffset);
+    name = (GLchar*)getPointer(_env, name_buf, (jarray*)&_nameArray, &_nameRemaining, &_nameBufferOffset);
     if (length == NULL) {
         char * _lengthBase = (char *)_env->GetIntArrayElements(_lengthArray, (jboolean *) 0);
         length = (GLsizei *) (_lengthBase + _lengthBufferOffset);
@@ -2040,6 +2053,10 @@
         char * _typeBase = (char *)_env->GetIntArrayElements(_typeArray, (jboolean *) 0);
         type = (GLenum *) (_typeBase + _typeBufferOffset);
     }
+    if (name == NULL) {
+        char* _nameBase = (char *)_env->GetByteArrayElements(_nameArray, (jboolean*)0);
+        name = (GLchar *) (_nameBase + _nameBufferOffset);
+    }
     glGetTransformFeedbackVarying(
         (GLuint)program,
         (GLuint)index,
@@ -2047,11 +2064,7 @@
         (GLsizei *)length,
         (GLint *)size,
         (GLenum *)type,
-        // The cast below is incorrect. The driver will end up writing to the
-        // address specified by name, which will always crash the process since
-        // it is guaranteed to be in low memory. The additional static_cast
-        // suppresses the warning for now. http://b/19478262
-        (char *)static_cast<uintptr_t>(name)
+        (GLchar*)name
     );
     if (_typeArray) {
         releaseArrayPointer<jintArray, jint*, IntArrayReleaser>(_env, _typeArray, (jint*)type, JNI_TRUE);
@@ -2062,6 +2075,9 @@
     if (_lengthArray) {
         releaseArrayPointer<jintArray, jint*, IntArrayReleaser>(_env, _lengthArray, (jint*)length, JNI_TRUE);
     }
+    if (_nameArray) {
+        releaseArrayPointer<jbyteArray, jbyte*, ByteArrayReleaser>(_env, _nameArray, (jbyte*)name, JNI_TRUE);
+    }
 }
 
 /* void glGetTransformFeedbackVarying ( GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name ) */
@@ -5233,6 +5249,7 @@
 {"glTransformFeedbackVaryings", "(I[Ljava/lang/String;I)V", (void *) android_glTransformFeedbackVaryings },
 {"glGetTransformFeedbackVarying", "(III[II[II[II[BI)V", (void *) android_glGetTransformFeedbackVarying__III_3II_3II_3II_3BI },
 {"glGetTransformFeedbackVarying", "(IIILjava/nio/IntBuffer;Ljava/nio/IntBuffer;Ljava/nio/IntBuffer;B)V", (void *) android_glGetTransformFeedbackVarying__IIILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2B },
+{"glGetTransformFeedbackVarying", "(IIILjava/nio/IntBuffer;Ljava/nio/IntBuffer;Ljava/nio/IntBuffer;Ljava/nio/ByteBuffer;)V", (void *) android_glGetTransformFeedbackVarying__IIILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_ByteBuffer_2 },
 {"glGetTransformFeedbackVarying", "(II[II[II)Ljava/lang/String;", (void *) android_glGetTransformFeedbackVarying1 },
 {"glGetTransformFeedbackVarying", "(IILjava/nio/IntBuffer;Ljava/nio/IntBuffer;)Ljava/lang/String;", (void *) android_glGetTransformFeedbackVarying2 },
 {"glVertexAttribIPointerBounds", "(IIIILjava/nio/Buffer;I)V", (void *) android_glVertexAttribIPointerBounds__IIIILjava_nio_Buffer_2I },
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index 03a1e71..3df0876 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -21,6 +21,7 @@
 #include "utils/misc.h"
 #include "cutils/debugger.h"
 #include <memtrack/memtrack.h>
+#include <memunreachable/memunreachable.h>
 
 #include <cutils/log.h>
 #include <fcntl.h>
@@ -36,6 +37,9 @@
 #include <ctype.h>
 #include <malloc.h>
 
+#include <iomanip>
+#include <string>
+
 namespace android
 {
 
@@ -1023,6 +1027,13 @@
     close(fd);
 }
 
+static jstring android_os_Debug_getUnreachableMemory(JNIEnv* env, jobject clazz,
+    jint limit, jboolean contents)
+{
+    std::string s = GetUnreachableMemoryString(contents, limit);
+    return env->NewStringUTF(s.c_str());
+}
+
 /*
  * JNI registration.
  */
@@ -1058,6 +1069,8 @@
             (void*)android_os_Debug_getDeathObjectCount },
     { "dumpNativeBacktraceToFile", "(ILjava/lang/String;)V",
             (void*)android_os_Debug_dumpNativeBacktraceToFile },
+    { "getUnreachableMemory", "(IZ)Ljava/lang/String;",
+            (void*)android_os_Debug_getUnreachableMemory },
 };
 
 int register_android_os_Debug(JNIEnv *env)
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index ae109c6..abc6c4b 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -556,7 +556,7 @@
     }
 
     // For the rest of the function we will hold this lock, to serialize
-    // looking/creation of Java proxies for native Binder proxies.
+    // looking/creation/destruction of Java proxies for native Binder proxies.
     AutoMutex _l(mProxyLock);
 
     // Someone else's...  do we know about it?
@@ -1225,16 +1225,21 @@
 
 static void android_os_BinderProxy_destroy(JNIEnv* env, jobject obj)
 {
+    // Don't race with construction/initialization
+    AutoMutex _l(mProxyLock);
+
     IBinder* b = (IBinder*)
             env->GetLongField(obj, gBinderProxyOffsets.mObject);
     DeathRecipientList* drl = (DeathRecipientList*)
             env->GetLongField(obj, gBinderProxyOffsets.mOrgue);
 
     LOGDEATH("Destroying BinderProxy %p: binder=%p drl=%p\n", obj, b, drl);
-    env->SetLongField(obj, gBinderProxyOffsets.mObject, 0);
-    env->SetLongField(obj, gBinderProxyOffsets.mOrgue, 0);
-    drl->decStrong((void*)javaObjectForIBinder);
-    b->decStrong((void*)javaObjectForIBinder);
+    if (b != nullptr) {
+        env->SetLongField(obj, gBinderProxyOffsets.mObject, 0);
+        env->SetLongField(obj, gBinderProxyOffsets.mOrgue, 0);
+        drl->decStrong((void*)javaObjectForIBinder);
+        b->decStrong((void*)javaObjectForIBinder);
+    }
 
     IPCThreadState::self()->flushCommands();
 }
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index d4f745d..af99f79 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -91,8 +91,11 @@
     // a Canvas object.
     private static final long NATIVE_ALLOCATION_SIZE = 525;
 
-    private static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
-        getNativeFinalizer(), NATIVE_ALLOCATION_SIZE);
+    // Use a Holder to allow static initialization of Canvas in the boot image.
+    private static class NoImagePreloadHolder {
+        public static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
+                getNativeFinalizer(), NATIVE_ALLOCATION_SIZE);
+    }
 
     // This field is used to finalize the native Canvas properly
     private Runnable mFinalizer;
@@ -107,7 +110,8 @@
         if (!isHardwareAccelerated()) {
             // 0 means no native bitmap
             mNativeCanvasWrapper = initRaster(null);
-            mFinalizer = sRegistry.registerNativeAllocation(this, mNativeCanvasWrapper);
+            mFinalizer = NoImagePreloadHolder.sRegistry.registerNativeAllocation(
+                    this, mNativeCanvasWrapper);
         } else {
             mFinalizer = null;
         }
@@ -128,7 +132,8 @@
         }
         throwIfCannotDraw(bitmap);
         mNativeCanvasWrapper = initRaster(bitmap);
-        mFinalizer = sRegistry.registerNativeAllocation(this, mNativeCanvasWrapper);
+        mFinalizer = NoImagePreloadHolder.sRegistry.registerNativeAllocation(
+                this, mNativeCanvasWrapper);
         mBitmap = bitmap;
         mDensity = bitmap.mDensity;
     }
@@ -139,7 +144,8 @@
             throw new IllegalStateException();
         }
         mNativeCanvasWrapper = nativeCanvas;
-        mFinalizer = sRegistry.registerNativeAllocation(this, mNativeCanvasWrapper);
+        mFinalizer = NoImagePreloadHolder.sRegistry.registerNativeAllocation(
+                this, mNativeCanvasWrapper);
         mDensity = Bitmap.getDefaultDensity();
     }
 
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 534121a..291fdc4 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -44,8 +44,11 @@
     // The approximate size of a native paint object.
     private static final long NATIVE_PAINT_SIZE = 98;
 
-    private static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
-        nGetNativeFinalizer(), NATIVE_PAINT_SIZE);
+    // Use a Holder to allow static initialization of Paint in the boot image.
+    private static class NoImagePreloadHolder {
+        public static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
+                nGetNativeFinalizer(), NATIVE_PAINT_SIZE);
+    }
 
     /**
      * @hide
@@ -452,7 +455,7 @@
      */
     public Paint(int flags) {
         mNativePaint = nInit();
-        sRegistry.registerNativeAllocation(this, mNativePaint);
+        NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, mNativePaint);
         setFlags(flags | HIDDEN_DEFAULT_PAINT_FLAGS);
         // TODO: Turning off hinting has undesirable side effects, we need to
         //       revisit hinting once we add support for subpixel positioning
@@ -471,7 +474,7 @@
      */
     public Paint(Paint paint) {
         mNativePaint = nInitWithPaint(paint.getNativeInstance());
-        sRegistry.registerNativeAllocation(this, mNativePaint);
+        NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, mNativePaint);
         setClassVariablesFrom(paint);
     }
 
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 8831baf..54b453d 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -242,6 +242,7 @@
     tests/unit/GpuMemoryTrackerTests.cpp \
     tests/unit/LayerUpdateQueueTests.cpp \
     tests/unit/LinearAllocatorTests.cpp \
+    tests/unit/MatrixTests.cpp \
     tests/unit/OffscreenBufferPoolTests.cpp \
     tests/unit/SkiaBehaviorTests.cpp \
     tests/unit/StringUtilsTests.cpp \
diff --git a/libs/hwui/AnimatorManager.cpp b/libs/hwui/AnimatorManager.cpp
index 2198fcc..f170e9c 100644
--- a/libs/hwui/AnimatorManager.cpp
+++ b/libs/hwui/AnimatorManager.cpp
@@ -95,11 +95,11 @@
 
 class AnimateFunctor {
 public:
-    AnimateFunctor(TreeInfo& info, AnimationContext& context)
-            : dirtyMask(0), mInfo(info), mContext(context) {}
+    AnimateFunctor(TreeInfo& info, AnimationContext& context, uint32_t* outDirtyMask)
+            : mInfo(info), mContext(context), mDirtyMask(outDirtyMask) {}
 
     bool operator() (sp<BaseRenderNodeAnimator>& animator) {
-        dirtyMask |= animator->dirtyMask();
+        *mDirtyMask |= animator->dirtyMask();
         bool remove = animator->animate(mContext);
         if (remove) {
             animator->detach();
@@ -114,11 +114,10 @@
         return remove;
     }
 
-    uint32_t dirtyMask;
-
 private:
     TreeInfo& mInfo;
     AnimationContext& mContext;
+    uint32_t* mDirtyMask;
 };
 
 uint32_t AnimatorManager::animate(TreeInfo& info) {
@@ -143,12 +142,13 @@
 }
 
 uint32_t AnimatorManager::animateCommon(TreeInfo& info) {
-    AnimateFunctor functor(info, mAnimationHandle->context());
+    uint32_t dirtyMask;
+    AnimateFunctor functor(info, mAnimationHandle->context(), &dirtyMask);
     auto newEnd = std::remove_if(mAnimators.begin(), mAnimators.end(), functor);
     mAnimators.erase(newEnd, mAnimators.end());
     mAnimationHandle->notifyAnimationsRan();
     mParent.mProperties.updateMatrix();
-    return functor.dirtyMask;
+    return dirtyMask;
 }
 
 static void endStagingAnimator(sp<BaseRenderNodeAnimator>& animator) {
diff --git a/libs/hwui/BakedOpDispatcher.cpp b/libs/hwui/BakedOpDispatcher.cpp
index 78764b5..1aab3c7 100644
--- a/libs/hwui/BakedOpDispatcher.cpp
+++ b/libs/hwui/BakedOpDispatcher.cpp
@@ -368,7 +368,7 @@
                 op.startAngle, op.sweepAngle, op.useCenter, op.paint);
         const AutoTexture holder(texture);
         if (CC_LIKELY(holder.texture)) {
-            renderPathTexture(renderer, state, op.unmappedBounds.left, op.unmappedBounds.right,
+            renderPathTexture(renderer, state, op.unmappedBounds.left, op.unmappedBounds.top,
                     *texture, *(op.paint));
         }
     } else {
diff --git a/libs/hwui/ClipArea.cpp b/libs/hwui/ClipArea.cpp
index e368537..501cbe5 100644
--- a/libs/hwui/ClipArea.cpp
+++ b/libs/hwui/ClipArea.cpp
@@ -404,11 +404,17 @@
     return currentRectCount + recordedRectCount > RectangleList::kMaxTransformedRectangles;
 }
 
+static const ClipRect sEmptyClipRect(Rect(0, 0));
+
 const ClipBase* ClipArea::serializeIntersectedClip(LinearAllocator& allocator,
         const ClipBase* recordedClip, const Matrix4& recordedClipTransform) {
+
     // if no recordedClip passed, just serialize current state
     if (!recordedClip) return serializeClip(allocator);
 
+    // if either is empty, clip is empty
+    if (CC_UNLIKELY(recordedClip->rect.isEmpty())|| mClipRect.isEmpty()) return &sEmptyClipRect;
+
     if (!mLastResolutionResult
             || recordedClip != mLastResolutionClip
             || recordedClipTransform != mLastResolutionTransform) {
diff --git a/libs/hwui/Matrix.cpp b/libs/hwui/Matrix.cpp
index 73ebd1304..deab956 100644
--- a/libs/hwui/Matrix.cpp
+++ b/libs/hwui/Matrix.cpp
@@ -438,7 +438,7 @@
 }
 
 void Matrix4::mapRect(Rect& r) const {
-    if (isIdentity()) return;
+    if (isIdentity() || r.isEmpty()) return;
 
     if (isSimple()) {
         MUL_ADD_STORE(r.left, data[kScaleX], data[kTranslateX]);
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index 31de305..9ae2212 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -594,7 +594,14 @@
 }
 
 size_t RecordingCanvas::addOp(RecordedOp* op) {
-    // TODO: validate if "addDrawOp" quickrejection logic is useful before adding
+    // skip op with empty clip
+    if (op->localClip && op->localClip->rect.isEmpty()) {
+        // NOTE: this rejection happens after op construction/content ref-ing, so content ref'd
+        // and held by renderthread isn't affected by clip rejection.
+        // Could rewind alloc here if desired, but callers would have to not touch op afterwards.
+        return -1;
+    }
+
     int insertIndex = mDisplayList->ops.size();
     mDisplayList->ops.push_back(op);
     if (mDeferredBarrierType != DeferredBarrierType::None) {
diff --git a/libs/hwui/tests/unit/ClipAreaTests.cpp b/libs/hwui/tests/unit/ClipAreaTests.cpp
index 679569e..dc2ea07 100644
--- a/libs/hwui/tests/unit/ClipAreaTests.cpp
+++ b/libs/hwui/tests/unit/ClipAreaTests.cpp
@@ -228,6 +228,7 @@
 
         ClipRegion recordedClip;
         recordedClip.region.setPath(ovalPath, SkRegion(SkIRect::MakeWH(200, 200)));
+        recordedClip.rect = Rect(200, 200);
 
         Matrix4 translate10x20;
         translate10x20.loadTranslate(10, 20, 0);
diff --git a/libs/hwui/tests/unit/MatrixTests.cpp b/libs/hwui/tests/unit/MatrixTests.cpp
new file mode 100644
index 0000000..da22637
--- /dev/null
+++ b/libs/hwui/tests/unit/MatrixTests.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include "Matrix.h"
+#include "Rect.h"
+
+using namespace android::uirenderer;
+
+TEST(Matrix, mapRect) {
+    // Skew, so we don't hit identity/translate/simple fast paths
+    Matrix4 matrix;
+    matrix.skew(0.1f, 0.1f);
+
+    // non-zero empty rect, so sorting x/y would make rect non-empty
+    Rect empty(100, 100, -100, -100);
+    ASSERT_TRUE(empty.isEmpty());
+    matrix.mapRect(empty);
+    EXPECT_TRUE(empty.isEmpty())
+        << "Empty rect should always remain empty, regardless of mapping.";
+}
diff --git a/libs/hwui/tests/unit/RecordingCanvasTests.cpp b/libs/hwui/tests/unit/RecordingCanvasTests.cpp
index f988da3..c39047c 100644
--- a/libs/hwui/tests/unit/RecordingCanvasTests.cpp
+++ b/libs/hwui/tests/unit/RecordingCanvasTests.cpp
@@ -58,6 +58,17 @@
             << "Clip should be serialized once";
 }
 
+TEST(RecordingCanvas, emptyClipRect) {
+    auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
+        canvas.save(SaveFlags::MatrixClip);
+        canvas.clipRect(0, 0, 100, 100, SkRegion::kIntersect_Op);
+        canvas.clipRect(100, 100, 200, 200, SkRegion::kIntersect_Op);
+        canvas.drawRect(0, 0, 50, 50, SkPaint()); // rejected at record time
+        canvas.restore();
+    });
+    ASSERT_EQ(0u, dl->getOps().size()) << "Must be zero ops. Rect should be rejected.";
+}
+
 TEST(RecordingCanvas, drawArc) {
     auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
         canvas.drawArc(0, 0, 200, 200, 0, 180, true, SkPaint());
diff --git a/opengl/java/android/opengl/GLES30.java b/opengl/java/android/opengl/GLES30.java
index 9c3b505..74181c5 100644
--- a/opengl/java/android/opengl/GLES30.java
+++ b/opengl/java/android/opengl/GLES30.java
@@ -889,7 +889,10 @@
     );
 
     // C function void glGetTransformFeedbackVarying ( GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name )
-
+    /**
+     * @deprecated
+     * Use the version that takes a ByteBuffer as the last argument, or the versions that return a String.
+     * */
     public static native void glGetTransformFeedbackVarying(
         int program,
         int index,
@@ -902,6 +905,18 @@
 
     // C function void glGetTransformFeedbackVarying ( GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name )
 
+    public static native void glGetTransformFeedbackVarying(
+        int program,
+        int index,
+        int bufsize,
+        java.nio.IntBuffer length,
+        java.nio.IntBuffer size,
+        java.nio.IntBuffer type,
+        java.nio.ByteBuffer name
+    );
+
+    // C function void glGetTransformFeedbackVarying ( GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name )
+
     public static native String glGetTransformFeedbackVarying(
         int program,
         int index,
diff --git a/packages/DocumentsUI/Android.mk b/packages/DocumentsUI/Android.mk
index e1650e1..6dfc3bb 100644
--- a/packages/DocumentsUI/Android.mk
+++ b/packages/DocumentsUI/Android.mk
@@ -30,6 +30,10 @@
   --extra-packages android.support.design \
   --extra-packages android.support.v7.recyclerview
 
+LOCAL_JACK_FLAGS := \
+  -D jack.assert.policy=enable \
+  -D jack.optimization.inner-class.accessors=true
+
 LOCAL_PACKAGE_NAME := DocumentsUI
 LOCAL_CERTIFICATE := platform
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
index 95c49ff..46cbbdf 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
@@ -22,8 +22,6 @@
 import static com.android.documentsui.dirlist.DirectoryFragment.ANIM_LEAVE;
 import static com.android.documentsui.dirlist.DirectoryFragment.ANIM_NONE;
 import static com.android.documentsui.dirlist.DirectoryFragment.ANIM_SIDE;
-import static com.android.internal.util.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkState;
 
 import android.app.Activity;
 import android.app.Fragment;
@@ -54,7 +52,6 @@
 import com.android.documentsui.model.DocumentInfo;
 import com.android.documentsui.model.DocumentStack;
 import com.android.documentsui.model.RootInfo;
-import com.android.internal.util.Preconditions;
 
 import java.io.FileNotFoundException;
 import java.util.ArrayList;
@@ -330,7 +327,8 @@
     }
 
     void openContainerDocument(DocumentInfo doc) {
-        checkArgument(doc.isContainer());
+        assert(doc.isContainer());
+
         mState.pushDocument(doc);
         // Show an opening animation only if pressing "back" would get us back to the
         // previous directory. Especially after opening a root document, pressing
@@ -373,7 +371,8 @@
     @Override
     public void onSearchChanged(@Nullable String query) {
         // We should not get here if root is not searchable
-        checkState(canSearchRoot());
+        assert(canSearchRoot());
+
         reloadSearch(query);
     }
 
@@ -673,7 +672,8 @@
 
         @Override
         protected RootInfo run(RootInfo... roots) {
-            checkArgument(roots.length == 1);
+            assert(roots.length == 1);
+
             final RootInfo currentRoot = roots[0];
             final Collection<RootInfo> cachedRoots = mOwner.mRoots.getRootsBlocking();
             RootInfo homeRoot = null;
@@ -686,7 +686,7 @@
                     return null;
                 }
             }
-            Preconditions.checkNotNull(homeRoot);
+            assert(homeRoot != null);
             mHome = mOwner.getRootDocumentBlocking(homeRoot);
             return homeRoot;
         }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentClipper.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentClipper.java
index b3c2846..15bfc3b 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentClipper.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentClipper.java
@@ -28,7 +28,6 @@
 import android.util.Log;
 
 import com.android.documentsui.model.DocumentInfo;
-import com.android.internal.util.Preconditions;
 
 import libcore.io.IoUtils;
 
@@ -85,7 +84,7 @@
      * This should be run from inside an AsyncTask.
      */
     public List<DocumentInfo> getDocumentsFromClipData(ClipData clipData) {
-        Preconditions.checkNotNull(clipData);
+        assert(clipData != null);
         final List<DocumentInfo> srcDocs = new ArrayList<>();
 
         int count = clipData.getItemCount();
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
index ed531a8..12a4186 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
@@ -23,7 +23,6 @@
 import static com.android.documentsui.State.ACTION_OPEN_TREE;
 import static com.android.documentsui.State.ACTION_PICK_COPY_DESTINATION;
 import static com.android.documentsui.dirlist.DirectoryFragment.ANIM_NONE;
-import static com.android.internal.util.Preconditions.checkArgument;
 
 import android.app.Activity;
 import android.app.Fragment;
@@ -333,7 +332,7 @@
 
     @Override
     void onDirectoryCreated(DocumentInfo doc) {
-        checkArgument(doc.isDirectory());
+        assert(doc.isDirectory());
         openContainerDocument(doc);
     }
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DownloadsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DownloadsActivity.java
index 536feeb..b5d3ea0 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DownloadsActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DownloadsActivity.java
@@ -16,10 +16,8 @@
 
 package com.android.documentsui;
 
-import static com.android.documentsui.Shared.DEBUG;
 import static com.android.documentsui.State.ACTION_MANAGE;
 import static com.android.documentsui.dirlist.DirectoryFragment.ANIM_NONE;
-import static com.android.internal.util.Preconditions.checkState;
 
 import android.app.Activity;
 import android.app.Fragment;
@@ -41,7 +39,6 @@
 import com.android.documentsui.dirlist.Model;
 import com.android.documentsui.model.DocumentInfo;
 import com.android.documentsui.model.RootInfo;
-import com.android.internal.util.Preconditions;
 
 import java.util.Arrays;
 import java.util.List;
@@ -121,11 +118,11 @@
         final RootInfo root = getCurrentRoot();
         final DocumentInfo cwd = getCurrentDirectory();
 
-        if (DEBUG) checkState(!mSearchManager.isSearching());
+        assert(!mSearchManager.isSearching());
 
         // If started in manage roots mode, there has to be a cwd (i.e. the root dir of the managed
         // root).
-        Preconditions.checkNotNull(cwd);
+        assert(cwd != null);
 
         // Normal boring directory
         DirectoryFragment.showDirectory(fm, root, cwd, anim);
@@ -133,7 +130,8 @@
 
     @Override
     public void onDocumentPicked(DocumentInfo doc, Model model) {
-        Preconditions.checkArgument(!doc.isDirectory());
+        assert(!doc.isDirectory());
+
         // First try managing the document; we expect manager to filter
         // based on authority, so we don't grant.
         final Intent manage = new Intent(DocumentsContract.ACTION_MANAGE_DOCUMENT);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DrawerController.java b/packages/DocumentsUI/src/com/android/documentsui/DrawerController.java
index bcf69c4..9fceff5 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DrawerController.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DrawerController.java
@@ -16,8 +16,6 @@
 
 package com.android.documentsui;
 
-import static com.android.internal.util.Preconditions.checkArgument;
-
 import android.app.Activity;
 import android.support.v4.app.ActionBarDrawerToggle;
 import android.support.v4.widget.DrawerLayout;
@@ -83,7 +81,7 @@
                 DrawerLayout layout, View drawer, ActionBarDrawerToggle toggle,
                 Toolbar drawerToolbar) {
             mToolbar = drawerToolbar;
-            checkArgument(layout != null);
+            assert(layout != null);
 
             mLayout = layout;
             mDrawer = drawer;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
index a3378ad..c17be06 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
@@ -19,8 +19,6 @@
 import static com.android.documentsui.OperationDialogFragment.DIALOG_TYPE_UNKNOWN;
 import static com.android.documentsui.Shared.DEBUG;
 import static com.android.documentsui.dirlist.DirectoryFragment.ANIM_NONE;
-import static com.android.internal.util.Preconditions.checkArgument;
-import static com.android.internal.util.Preconditions.checkState;
 
 import android.app.Activity;
 import android.app.FragmentManager;
@@ -97,11 +95,11 @@
             // Launch URIs support sensible activity management, but don't specify a real
             // content target.
             if (DEBUG) Log.d(TAG, "Launching with non-empty stack.");
-            checkState(uri == null || uri.getAuthority() == null ||
+            assert(uri == null || uri.getAuthority() == null ||
                     LauncherActivity.isLaunchUri(uri));
             refreshCurrentRootAndDirectory(ANIM_NONE);
         } else if (intent.getAction() == Intent.ACTION_VIEW) {
-            checkArgument(uri != null);
+            assert(uri != null);
             new OpenUriForViewTask(this).executeOnExecutor(
                     ProviderExecutor.forAuthority(uri.getAuthority()), uri);
         } else if (DocumentsContract.isRootUri(this, uri)) {
@@ -143,7 +141,7 @@
         state.allowMultiple = true;
 
         // Options specific to the DocumentsActivity.
-        checkArgument(!intent.hasExtra(Intent.EXTRA_LOCAL_ONLY));
+        assert(!intent.hasExtra(Intent.EXTRA_LOCAL_ONLY));
 
         final DocumentStack stack = intent.getParcelableExtra(Shared.EXTRA_STACK);
         if (stack != null) {
@@ -212,7 +210,7 @@
     public boolean onOptionsItemSelected(MenuItem item) {
         switch (item.getItemId()) {
             case R.id.menu_create_dir:
-                checkState(canCreateDirectory());
+                assert(canCreateDirectory());
                 showCreateDirectoryDialog();
                 return true;
             case R.id.menu_new_window:
@@ -250,7 +248,7 @@
         final RootInfo root = getCurrentRoot();
         final DocumentInfo cwd = getCurrentDirectory();
 
-        if (DEBUG) checkState(!mSearchManager.isSearching());
+        assert(!mSearchManager.isSearching());
 
         if (cwd == null) {
             DirectoryFragment.showRecentsOpen(fm, anim);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/LocalPreferences.java b/packages/DocumentsUI/src/com/android/documentsui/LocalPreferences.java
index 4bffc49..170fb89 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/LocalPreferences.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/LocalPreferences.java
@@ -17,7 +17,6 @@
 package com.android.documentsui;
 
 import static com.android.documentsui.State.MODE_UNKNOWN;
-import static com.android.internal.util.Preconditions.checkArgument;
 
 import android.content.Context;
 import android.preference.PreferenceManager;
@@ -59,7 +58,8 @@
     }
 
     public static void setViewMode(Context context, RootInfo root, @ViewMode int viewMode) {
-        checkArgument(viewMode != MODE_UNKNOWN);
+        assert(viewMode != MODE_UNKNOWN);
+
         PreferenceManager.getDefaultSharedPreferences(context).edit()
                 .putInt(createKey(root), viewMode).apply();
     }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/Metrics.java b/packages/DocumentsUI/src/com/android/documentsui/Metrics.java
index 699605f..bff65d5 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/Metrics.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/Metrics.java
@@ -17,7 +17,6 @@
 package com.android.documentsui;
 
 import static com.android.documentsui.Shared.DEBUG;
-import static com.android.internal.util.Preconditions.checkArgument;
 
 import android.annotation.IntDef;
 import android.annotation.Nullable;
@@ -363,7 +362,7 @@
         if (operationType == FileOperationService.OPERATION_DELETE) {
             logHistogram(context, histogram, FILEOP_DELETE);
         } else {
-            checkArgument(dst != null);
+            assert(dst != null);
             @Provider int providerType =
                     isSystemProvider(dst.authority) ? PROVIDER_SYSTEM : PROVIDER_EXTERNAL;
             logHistogram(context, histogram, getOpCode(operationType, providerType));
diff --git a/packages/DocumentsUI/src/com/android/documentsui/PickFragment.java b/packages/DocumentsUI/src/com/android/documentsui/PickFragment.java
index 32543c8..933506c 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/PickFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/PickFragment.java
@@ -19,7 +19,6 @@
 import static com.android.documentsui.services.FileOperationService.OPERATION_DELETE;
 import static com.android.documentsui.services.FileOperationService.OPERATION_MOVE;
 import static com.android.documentsui.services.FileOperationService.OPERATION_UNKNOWN;
-import static com.android.internal.util.Preconditions.checkArgument;
 
 import android.app.Activity;
 import android.app.Fragment;
@@ -101,7 +100,8 @@
      */
     public void setPickTarget(
             int action, @OpType int copyOperationSubType, DocumentInfo pickTarget) {
-        checkArgument(copyOperationSubType != OPERATION_DELETE);
+        assert(copyOperationSubType != OPERATION_DELETE);
+
         mAction = action;
         mCopyOperationSubType = copyOperationSubType;
         mPickTarget = pickTarget;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/ProviderExecutor.java b/packages/DocumentsUI/src/com/android/documentsui/ProviderExecutor.java
index b0e332f..8145edc 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/ProviderExecutor.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/ProviderExecutor.java
@@ -19,7 +19,6 @@
 import android.os.AsyncTask;
 
 import com.android.internal.annotations.GuardedBy;
-import com.android.internal.util.Preconditions;
 
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
@@ -85,7 +84,7 @@
     private Executor mNonPreemptingExecutor = new Executor() {
         @Override
         public void execute(Runnable command) {
-            Preconditions.checkNotNull(command);
+            assert(command != null);
             mQueue.add(command);
         }
     };
@@ -93,7 +92,7 @@
     @Override
     public void execute(Runnable command) {
         preempt();
-        Preconditions.checkNotNull(command);
+        assert(command != null);
         mQueue.add(command);
     }
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
index c4c5124..ab67a51 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
@@ -18,7 +18,6 @@
 
 import static com.android.documentsui.Shared.DEBUG;
 import static com.android.documentsui.Shared.TAG;
-import static com.android.internal.util.Preconditions.checkState;
 
 import android.content.ContentProviderClient;
 import android.content.ContentResolver;
@@ -41,7 +40,6 @@
 
 import com.android.documentsui.model.RootInfo;
 import com.android.internal.annotations.GuardedBy;
-import com.android.internal.util.Preconditions;
 
 import com.google.common.collect.ArrayListMultimap;
 import com.google.common.collect.Multimap;
@@ -118,17 +116,16 @@
      */
     public void updateAsync() {
         // Verifying an assumption about the recents root being immutable.
-        if (DEBUG) {
-            checkState(mRecentsRoot.authority == null);
-            checkState(mRecentsRoot.rootId == null);
-            checkState(mRecentsRoot.derivedIcon == R.drawable.ic_root_recent);
-            checkState(mRecentsRoot.derivedType == RootInfo.TYPE_RECENTS);
-            checkState(mRecentsRoot.flags == (Root.FLAG_LOCAL_ONLY
-                    | Root.FLAG_SUPPORTS_IS_CHILD
-                    | Root.FLAG_SUPPORTS_CREATE));
-            checkState(mRecentsRoot.title == mContext.getString(R.string.root_recent));
-            checkState(mRecentsRoot.availableBytes == -1);
-        }
+        assert(mRecentsRoot.authority == null);
+        assert(mRecentsRoot.rootId == null);
+        assert(mRecentsRoot.derivedIcon == R.drawable.ic_root_recent);
+        assert(mRecentsRoot.derivedType == RootInfo.TYPE_RECENTS);
+        assert(mRecentsRoot.flags == (Root.FLAG_LOCAL_ONLY
+                | Root.FLAG_SUPPORTS_IS_CHILD
+                | Root.FLAG_SUPPORTS_CREATE));
+        assert(mRecentsRoot.title == mContext.getString(R.string.root_recent));
+        assert(mRecentsRoot.availableBytes == -1);
+
         new UpdateTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
     }
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/SearchViewManager.java b/packages/DocumentsUI/src/com/android/documentsui/SearchViewManager.java
index 8beb245..63dc2ee 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/SearchViewManager.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/SearchViewManager.java
@@ -61,7 +61,8 @@
     }
 
     public void install(DocumentsToolbar actionBar) {
-        assert (mActionBar == null);
+        // assert(mActionBar == null);
+
         mActionBar = actionBar;
         mMenu = actionBar.getSearchMenu();
         mView = (SearchView) mMenu.getActionView();
diff --git a/packages/DocumentsUI/src/com/android/documentsui/Shared.java b/packages/DocumentsUI/src/com/android/documentsui/Shared.java
index a288fe8..99c2d80 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/Shared.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/Shared.java
@@ -28,6 +28,10 @@
 /** @hide */
 public final class Shared {
 
+    public static final String TAG = "Documents";
+
+    public static final boolean DEBUG = true;
+
     /** Intent action name to pick a copy destination. */
     public static final String ACTION_PICK_COPY_DESTINATION =
             "com.android.documentsui.PICK_COPY_DESTINATION";
@@ -79,9 +83,6 @@
      */
     public static final String EXTRA_IGNORE_STATE = "ignoreState";
 
-    public static final boolean DEBUG = true;
-    public static final String TAG = "Documents";
-
 
     /**
      * String prefix used to indicate the document is a directory.
diff --git a/packages/DocumentsUI/src/com/android/documentsui/Snackbars.java b/packages/DocumentsUI/src/com/android/documentsui/Snackbars.java
index 48c1a73..b4d7971 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/Snackbars.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/Snackbars.java
@@ -16,8 +16,6 @@
 
 package com.android.documentsui;
 
-import static com.android.internal.util.Preconditions.checkNotNull;
-
 import android.app.Activity;
 import android.support.design.widget.Snackbar;
 import android.view.View;
@@ -26,12 +24,13 @@
     private Snackbars() {}
 
     public static final Snackbar makeSnackbar(Activity activity, int messageId, int duration) {
-        return Snackbars.makeSnackbar(activity, activity.getResources().getText(messageId), duration);
+        return Snackbars.makeSnackbar(
+                activity, activity.getResources().getText(messageId), duration);
     }
 
-    public static final Snackbar makeSnackbar(Activity activity, CharSequence message, int duration)
-    {
-        final View view = checkNotNull(activity.findViewById(R.id.coordinator_layout));
+    public static final Snackbar makeSnackbar(
+            Activity activity, CharSequence message, int duration) {
+        final View view = activity.findViewById(R.id.coordinator_layout);
         return Snackbar.make(view, message, duration);
     }
 }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
index d1b2264..dfceff8 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
@@ -23,9 +23,6 @@
 import static com.android.documentsui.State.SORT_ORDER_UNKNOWN;
 import static com.android.documentsui.model.DocumentInfo.getCursorInt;
 import static com.android.documentsui.model.DocumentInfo.getCursorString;
-import static com.android.internal.util.Preconditions.checkNotNull;
-import static com.android.internal.util.Preconditions.checkState;
-import static com.google.common.base.Preconditions.checkArgument;
 
 import android.annotation.IntDef;
 import android.annotation.StringRes;
@@ -102,6 +99,7 @@
 import com.android.documentsui.services.FileOperationService;
 import com.android.documentsui.services.FileOperationService.OpType;
 import com.android.documentsui.services.FileOperations;
+
 import com.google.common.collect.Lists;
 
 import java.lang.annotation.Retention;
@@ -359,7 +357,9 @@
 
     private boolean handleViewItem(String id) {
         final Cursor cursor = mModel.getItem(id);
-        checkNotNull(cursor, "Cursor cannot be null.");
+
+        assert(cursor != null);
+
         final String docMimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE);
         final int docFlags = getCursorInt(cursor, Document.COLUMN_FLAGS);
         if (mTuner.isDocumentEnabled(docMimeType, docFlags)) {
@@ -430,7 +430,8 @@
         int cellMargin = 2 * getResources().getDimensionPixelSize(R.dimen.grid_item_margin);
         int viewPadding = mRecView.getPaddingLeft() + mRecView.getPaddingRight();
 
-        checkState(mRecView.getWidth() > 0);
+        assert(mRecView.getWidth() > 0);
+
         int columnCount = Math.max(1,
                 (mRecView.getWidth() - viewPadding) / (cellWidth + cellMargin));
 
@@ -471,7 +472,9 @@
         public boolean onBeforeItemStateChange(String modelId, boolean selected) {
             if (selected) {
                 final Cursor cursor = mModel.getItem(modelId);
-                checkNotNull(cursor, "Cursor cannot be null.");
+
+                assert(cursor != null);
+
                 final String docMimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE);
                 final int docFlags = getCursorInt(cursor, Document.COLUMN_FLAGS);
                 return mTuner.canSelectType(docMimeType, docFlags);
@@ -564,7 +567,7 @@
         }
 
         private void updateActionMenu() {
-            checkNotNull(mMenu);
+            assert(mMenu != null);
 
             // Delegate update logic to our owning action, since specialized logic is desired.
             mTuner.updateActionMenu(mMenu, mType, canDeleteSelection(), canRenameSelection());
@@ -699,8 +702,8 @@
     }
 
     private void deleteDocuments(final Selection selected) {
+        assert(!selected.isEmpty());
 
-        checkArgument(!selected.isEmpty());
         final DocumentInfo srcParent = getDisplayState().stack.peek();
         new GetDocumentsTask() {
             @Override
@@ -777,7 +780,7 @@
     private void renameDocuments(Selection selected) {
         // Batch renaming not supported
         // Rename option is only available in menu when 1 document selected
-        checkArgument(selected.size() == 1);
+        assert(selected.size() == 1);
 
         new GetDocumentsTask() {
             @Override
@@ -890,7 +893,8 @@
     }
 
     private void copyFromClipData(final ClipData clipData, final DocumentInfo destination) {
-        checkNotNull(clipData);
+        assert(clipData != null);
+
         new AsyncTask<Void, Void, List<DocumentInfo>>() {
 
             @Override
@@ -941,7 +945,7 @@
     }
 
     void copySelectionToClipboard(Selection selection) {
-        checkArgument(!selection.isEmpty());
+        assert(!selection.isEmpty());
         new GetDocumentsTask() {
             @Override
             void onDocumentsReady(List<DocumentInfo> docs) {
@@ -1059,7 +1063,7 @@
             String id = getModelId(v);
             if (id != null) {
                 Cursor dstCursor = mModel.getItem(id);
-                checkNotNull(dstCursor, "Cursor cannot be null.");
+                assert(dstCursor != null);
                 return DocumentInfo.fromDirectoryCursor(dstCursor);
             }
 
@@ -1132,10 +1136,11 @@
         }
 
         final Cursor cursor = mModel.getItem(modelId);
-        checkNotNull(cursor, "Cursor cannot be null.");
-        final DocumentInfo doc = DocumentInfo.fromDirectoryCursor(cursor);
 
-        return Lists.newArrayList(doc);
+        assert(cursor != null);
+
+        return Lists.newArrayList(
+                DocumentInfo.fromDirectoryCursor(cursor));
     }
 
     private Drawable getDragShadowIcon(List<DocumentInfo> docs) {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DocumentHolder.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DocumentHolder.java
index 2967a90..3b5ce87 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DocumentHolder.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DocumentHolder.java
@@ -16,9 +16,6 @@
 
 package com.android.documentsui.dirlist;
 
-import static com.android.internal.util.Preconditions.checkNotNull;
-import static com.android.internal.util.Preconditions.checkState;
-
 import android.content.Context;
 import android.database.Cursor;
 import android.graphics.Rect;
@@ -97,19 +94,20 @@
     @Override
     public boolean onKey(View v, int keyCode, KeyEvent event) {
         // Event listener should always be set.
-        checkNotNull(mEventListener);
+        assert(mEventListener != null);
+
         return mEventListener.onKey(this,  keyCode,  event);
     }
 
     public void addEventListener(DocumentHolder.EventListener listener) {
         // Just handle one for now; switch to a list if necessary.
-        checkState(mEventListener == null);
+        assert(mEventListener == null);
         mEventListener = listener;
     }
 
     public void addOnKeyListener(View.OnKeyListener listener) {
         // Just handle one for now; switch to a list if necessary.
-        checkState(mKeyListener == null);
+        assert(mKeyListener == null);
         mKeyListener = listener;
     }
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java
index 8ef89103..f99ec85c 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java
@@ -22,7 +22,6 @@
 import static com.android.documentsui.State.ACTION_MANAGE;
 import static com.android.documentsui.State.ACTION_OPEN;
 import static com.android.documentsui.State.ACTION_OPEN_TREE;
-import static com.android.internal.util.Preconditions.checkArgument;
 
 import android.content.Context;
 import android.provider.DocumentsContract.Document;
@@ -172,7 +171,7 @@
         @Override
         public void updateActionMenu(
                 Menu menu, @ResultType int resultType, boolean canDelete, boolean canRename) {
-            checkArgument(resultType != DirectoryFragment.TYPE_RECENT_OPEN);
+            assert(resultType != DirectoryFragment.TYPE_RECENT_OPEN);
 
             MenuItem open = menu.findItem(R.id.menu_open);
             MenuItem delete = menu.findItem(R.id.menu_delete);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/GridDirectoryHolder.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/GridDirectoryHolder.java
index a0ff1b5..90b2341 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/GridDirectoryHolder.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/GridDirectoryHolder.java
@@ -17,7 +17,6 @@
 package com.android.documentsui.dirlist;
 
 import static com.android.documentsui.model.DocumentInfo.getCursorString;
-import static com.android.internal.util.Preconditions.checkNotNull;
 
 import android.content.Context;
 import android.database.Cursor;
@@ -58,7 +57,7 @@
      * @param state Current display state.
      */
     public void bind(Cursor cursor, String modelId, State state) {
-        checkNotNull(cursor, "Cursor cannot be null.");
+        assert(cursor != null);
 
         this.modelId = modelId;
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/GridDocumentHolder.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/GridDocumentHolder.java
index 8eaed17e..a4bce16 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/GridDocumentHolder.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/GridDocumentHolder.java
@@ -19,7 +19,6 @@
 import static com.android.documentsui.model.DocumentInfo.getCursorInt;
 import static com.android.documentsui.model.DocumentInfo.getCursorLong;
 import static com.android.documentsui.model.DocumentInfo.getCursorString;
-import static com.android.internal.util.Preconditions.checkNotNull;
 
 import android.content.Context;
 import android.database.Cursor;
@@ -79,9 +78,9 @@
      * @param state Current display state.
      */
     public void bind(Cursor cursor, String modelId, State state) {
-        this.modelId = modelId;
+        assert(cursor != null);
 
-        checkNotNull(cursor, "Cursor cannot be null.");
+        this.modelId = modelId;
 
         final String docAuthority = getCursorString(cursor, RootCursorWrapper.COLUMN_AUTHORITY);
         final String docId = getCursorString(cursor, Document.COLUMN_DOCUMENT_ID);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/ListDocumentHolder.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/ListDocumentHolder.java
index be6413b..b940ffb 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/ListDocumentHolder.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/ListDocumentHolder.java
@@ -19,7 +19,6 @@
 import static com.android.documentsui.model.DocumentInfo.getCursorInt;
 import static com.android.documentsui.model.DocumentInfo.getCursorLong;
 import static com.android.documentsui.model.DocumentInfo.getCursorString;
-import static com.android.internal.util.Preconditions.checkNotNull;
 
 import android.content.Context;
 import android.database.Cursor;
@@ -79,9 +78,9 @@
      */
     @Override
     public void bind(Cursor cursor, String modelId, State state) {
-        this.modelId = modelId;
+        assert(cursor != null);
 
-        checkNotNull(cursor, "Cursor cannot be null.");
+        this.modelId = modelId;
 
         final String docAuthority = getCursorString(cursor, RootCursorWrapper.COLUMN_AUTHORITY);
         final String docId = getCursorString(cursor, Document.COLUMN_DOCUMENT_ID);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java
index 9684a5a..5e55e1a 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java
@@ -22,11 +22,9 @@
 import static com.android.documentsui.State.SORT_ORDER_SIZE;
 import static com.android.documentsui.model.DocumentInfo.getCursorLong;
 import static com.android.documentsui.model.DocumentInfo.getCursorString;
-import static com.android.internal.util.Preconditions.checkNotNull;
 
 import android.database.Cursor;
 import android.os.Bundle;
-import android.os.Looper;
 import android.provider.DocumentsContract;
 import android.provider.DocumentsContract.Document;
 import android.support.annotation.Nullable;
@@ -381,9 +379,9 @@
         final List<DocumentInfo> docs =  new ArrayList<>(size);
         for (String modelId: items.getAll()) {
             final Cursor cursor = getItem(modelId);
-            checkNotNull(cursor, "Cursor cannot be null.");
-            final DocumentInfo doc = DocumentInfo.fromDirectoryCursor(cursor);
-            docs.add(doc);
+            assert(cursor != null);
+
+            docs.add(DocumentInfo.fromDirectoryCursor(cursor));
         }
         return docs;
     }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java
index 4cf1048..b0cc09a 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java
@@ -19,9 +19,6 @@
 import static com.android.documentsui.Shared.DEBUG;
 import static com.android.documentsui.dirlist.ModelBackedDocumentsAdapter.ITEM_TYPE_DIRECTORY;
 import static com.android.documentsui.dirlist.ModelBackedDocumentsAdapter.ITEM_TYPE_DOCUMENT;
-import static com.android.internal.util.Preconditions.checkArgument;
-import static com.android.internal.util.Preconditions.checkNotNull;
-import static com.android.internal.util.Preconditions.checkState;
 
 import android.annotation.IntDef;
 import android.graphics.Point;
@@ -134,8 +131,12 @@
             @SelectionMode int mode,
             @Nullable Selection initialSelection) {
 
-        mEnvironment = checkNotNull(environment, "'environment' cannot be null.");
-        mAdapter = checkNotNull(adapter, "'adapter' cannot be null.");
+        assert(environment != null);
+        assert(adapter != null);
+
+        mEnvironment = environment;
+        mAdapter = adapter;
+
         mSingleSelect = mode == MODE_SINGLE;
         if (initialSelection != null) {
             mSelection.copyFrom(initialSelection);
@@ -168,8 +169,8 @@
 
                     @Override
                     public void onItemRangeRemoved(int startPosition, int itemCount) {
-                        checkState(startPosition >= 0);
-                        checkState(itemCount > 0);
+                        assert(startPosition >= 0);
+                        assert(itemCount > 0);
 
                         mSelection.cancelProvisionalSelection();
                         // Remove any disappeared IDs from the selection.
@@ -356,7 +357,8 @@
      * @param modelId
      */
     public void toggleSelection(String modelId) {
-        checkNotNull(modelId);
+        assert(modelId != null);
+
         boolean changed = false;
         if (mSelection.contains(modelId)) {
             changed = attemptDeselect(modelId);
@@ -389,7 +391,8 @@
      * @param pos The new end position for the selection range.
      */
     void snapRangeSelection(int pos) {
-        checkNotNull(mRanger);
+        assert(mRanger != null);
+
         mRanger.snapSelection(pos);
         notifySelectionChanged();
     }
@@ -436,7 +439,7 @@
      * @param selected New selection state.
      */
     private void updateRange(int begin, int end, boolean selected) {
-        checkState(end >= begin);
+        assert(end >= begin);
         for (int i = begin; i <= end; i++) {
             String id = mAdapter.getModelId(i);
             if (id == null) {
@@ -474,7 +477,7 @@
      * @return True if the update was applied.
      */
     private boolean attemptDeselect(String id) {
-        checkArgument(id != null);
+        assert(id != null);
         if (notifyBeforeItemStateChange(id, false)) {
             mSelection.remove(id);
             notifyItemStateChanged(id, false);
@@ -491,7 +494,7 @@
      * @return True if the update was applied.
      */
     private boolean attemptSelect(String id) {
-        checkArgument(id != null);
+        assert(id != null);
         boolean canSelect = notifyBeforeItemStateChange(id, true);
         if (!canSelect) {
             return false;
@@ -519,7 +522,7 @@
      * (identified by {@code position}) changes.
      */
     private void notifyItemStateChanged(String id, boolean selected) {
-        checkArgument(id != null);
+        assert(id != null);
         int lastListener = mCallbacks.size() - 1;
         for (int i = lastListener; i > -1; i--) {
             mCallbacks.get(i).onItemStateChanged(id, selected);
@@ -555,8 +558,8 @@
         }
 
         private void snapSelection(int position) {
-            checkState(mRanger != null);
-            checkArgument(position != RecyclerView.NO_POSITION);
+            assert(mRanger != null);
+            assert(position != RecyclerView.NO_POSITION);
 
             if (mEnd == UNDEFINED || mEnd == mBegin) {
                 // Reset mEnd so it can be established in establishRange.
@@ -568,7 +571,7 @@
         }
 
         private void establishRange(int position) {
-            checkState(mRanger.mEnd == UNDEFINED);
+            assert(mRanger.mEnd == UNDEFINED);
 
             if (position == mBegin) {
                 mEnd = position;
@@ -584,8 +587,8 @@
         }
 
         private void reviseRange(int position) {
-            checkState(mEnd != UNDEFINED);
-            checkState(mBegin != mEnd);
+            assert(mEnd != UNDEFINED);
+            assert(mBegin != mEnd);
 
             if (position == mEnd) {
                 if (DEBUG) Log.i(TAG, "Skipping no-op revision click on mEndRange.");
@@ -1185,7 +1188,7 @@
          * @param input
          */
         private void processInputEvent(InputEvent input) {
-            checkArgument(input.isMouseEvent());
+            assert(input.isMouseEvent());
 
             if (shouldStop(input)) {
                 endBandSelect();
@@ -1199,7 +1202,6 @@
             }
 
             mCurrentPosition = input.getOrigin();
-            mModel.resizeSelection(input.getOrigin());
             scrollViewIfNecessary();
             resizeBandSelectRectangle();
         }
@@ -1488,6 +1490,7 @@
          *     top-left of the viewport would have a relative origin of (0, 0), even though its
          *     absolute point has a higher y-value.
          */
+        @VisibleForTesting
         void resizeSelection(Point relativePointer) {
             mPointer = mHelper.createAbsolutePoint(relativePointer);
             updateModel();
@@ -1615,7 +1618,7 @@
         private void updateSelection(Rect rect) {
             int columnStart =
                     Collections.binarySearch(mColumnBounds, new Limits(rect.left, rect.left));
-            checkState(columnStart >= 0);
+            assert(columnStart >= 0);
             int columnEnd = columnStart;
 
             for (int i = columnStart; i < mColumnBounds.size()
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/RenameDocumentFragment.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/RenameDocumentFragment.java
index 38a71ec..0018d01 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/RenameDocumentFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/RenameDocumentFragment.java
@@ -17,7 +17,6 @@
 package com.android.documentsui.dirlist;
 
 import static com.android.documentsui.Shared.TAG;
-import static com.android.internal.util.Preconditions.checkArgument;
 
 import android.app.AlertDialog;
 import android.app.Dialog;
@@ -36,9 +35,9 @@
 import android.support.design.widget.Snackbar;
 import android.util.Log;
 import android.view.KeyEvent;
-import android.view.inputmethod.EditorInfo;
 import android.view.LayoutInflater;
 import android.view.View;
+import android.view.inputmethod.EditorInfo;
 import android.widget.EditText;
 import android.widget.TextView;
 import android.widget.TextView.OnEditorActionListener;
@@ -205,7 +204,7 @@
 
         @Override
         protected DocumentInfo doInBackground(DocumentInfo... document) {
-            checkArgument(document.length == 1);
+            assert(document.length == 1);
             final ContentResolver resolver = mActivity.getContentResolver();
             ContentProviderClient client = null;
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/SectionBreakDocumentsAdapterWrapper.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/SectionBreakDocumentsAdapterWrapper.java
index 2485ad9..3ee5cfc 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/SectionBreakDocumentsAdapterWrapper.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/SectionBreakDocumentsAdapterWrapper.java
@@ -16,8 +16,6 @@
 
 package com.android.documentsui.dirlist;
 
-import static com.android.internal.util.Preconditions.checkArgument;
-
 import android.content.Context;
 import android.database.Cursor;
 import android.support.v7.widget.GridLayoutManager;
@@ -204,12 +202,12 @@
         }
 
         public void onItemRangeChanged(int positionStart, int itemCount, Object payload) {
-            checkArgument(itemCount == 1);
+            assert(itemCount == 1);
             notifyItemRangeChanged(toViewPosition(positionStart), itemCount, payload);
         }
 
         public void onItemRangeInserted(int positionStart, int itemCount) {
-            checkArgument(itemCount == 1);
+            assert(itemCount == 1);
             if (positionStart < mBreakPosition) {
                 mBreakPosition++;
             }
@@ -217,7 +215,7 @@
         }
 
         public void onItemRangeRemoved(int positionStart, int itemCount) {
-            checkArgument(itemCount == 1);
+            assert(itemCount == 1);
             if (positionStart < mBreakPosition) {
                 mBreakPosition--;
             }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/services/CopyJob.java b/packages/DocumentsUI/src/com/android/documentsui/services/CopyJob.java
index faedd5e..ad48a70 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/services/CopyJob.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/services/CopyJob.java
@@ -29,7 +29,6 @@
 import static com.android.documentsui.services.FileOperationService.EXTRA_OPERATION;
 import static com.android.documentsui.services.FileOperationService.EXTRA_SRC_LIST;
 import static com.android.documentsui.services.FileOperationService.OPERATION_COPY;
-import static com.google.common.base.Preconditions.checkArgument;
 
 import android.annotation.StringRes;
 import android.app.Notification;
@@ -95,7 +94,7 @@
             String id, DocumentStack stack, List<DocumentInfo> srcs) {
         super(service, appContext, listener, OPERATION_COPY, id, stack);
 
-        checkArgument(!srcs.isEmpty());
+        assert(!srcs.isEmpty());
         this.mSrcs = srcs;
     }
 
@@ -108,7 +107,7 @@
             @OpType int opType, String id, DocumentStack destination, List<DocumentInfo> srcs) {
         super(service, appContext, listener, opType, id, destination);
 
-        checkArgument(!srcs.isEmpty());
+        assert(!srcs.isEmpty());
         this.mSrcs = srcs;
     }
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/services/FileOperationService.java b/packages/DocumentsUI/src/com/android/documentsui/services/FileOperationService.java
index 05a3f11..580fa38 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/services/FileOperationService.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/services/FileOperationService.java
@@ -17,9 +17,6 @@
 package com.android.documentsui.services;
 
 import static com.android.documentsui.Shared.DEBUG;
-import static com.android.internal.util.Preconditions.checkArgument;
-import static com.android.internal.util.Preconditions.checkNotNull;
-import static com.android.internal.util.Preconditions.checkState;
 
 import android.annotation.IntDef;
 import android.app.NotificationManager;
@@ -136,12 +133,12 @@
 
         String jobId = intent.getStringExtra(EXTRA_JOB_ID);
         @OpType int operationType = intent.getIntExtra(EXTRA_OPERATION, OPERATION_UNKNOWN);
-        checkArgument(jobId != null);
+        assert(jobId != null);
 
         if (intent.hasExtra(EXTRA_CANCEL)) {
             handleCancel(intent);
         } else {
-            checkArgument(operationType != OPERATION_UNKNOWN);
+            assert(operationType != OPERATION_UNKNOWN);
             handleOperation(intent, serviceId, jobId, operationType);
         }
 
@@ -173,9 +170,9 @@
             mWakeLock.acquire();
         }
 
-        checkState(job != null);
+        assert(job != null);
         int delay = intent.getIntExtra(EXTRA_DELAY, DEFAULT_DELAY);
-        checkArgument(delay <= MAX_DELAY);
+        assert(delay <= MAX_DELAY);
         if (DEBUG) Log.d(
                 TAG, "Scheduling job " + job.id + " to run in " + delay + " milliseconds.");
         ScheduledFuture<?> future = executor.schedule(job, delay, TimeUnit.MILLISECONDS);
@@ -188,8 +185,10 @@
      * @param intent The cancellation intent.
      */
     private void handleCancel(Intent intent) {
-        checkArgument(intent.hasExtra(EXTRA_CANCEL));
-        String jobId = checkNotNull(intent.getStringExtra(EXTRA_JOB_ID));
+        assert(intent.hasExtra(EXTRA_CANCEL));
+        assert(intent.getStringExtra(EXTRA_JOB_ID) != null);
+
+        String jobId = intent.getStringExtra(EXTRA_JOB_ID);
 
         if (DEBUG) Log.d(TAG, "handleCancel: " + jobId);
 
@@ -253,7 +252,8 @@
                 throw new UnsupportedOperationException();
         }
 
-        return checkNotNull(job);
+        assert(job != null);
+        return job;
     }
 
     @GuardedBy("mRunning")
@@ -261,7 +261,7 @@
         if (DEBUG) Log.d(TAG, "deleteJob: " + job.id);
 
         JobRecord record = mRunning.remove(job.id);
-        checkArgument(record != null);
+        assert(record != null);
         record.job.cleanup();
 
         if (mRunning.isEmpty()) {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/services/Job.java b/packages/DocumentsUI/src/com/android/documentsui/services/Job.java
index a158654..c723ac6 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/services/Job.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/services/Job.java
@@ -23,8 +23,6 @@
 import static com.android.documentsui.services.FileOperationService.EXTRA_OPERATION;
 import static com.android.documentsui.services.FileOperationService.EXTRA_SRC_LIST;
 import static com.android.documentsui.services.FileOperationService.OPERATION_UNKNOWN;
-import static com.android.internal.util.Preconditions.checkArgument;
-import static com.android.internal.util.Preconditions.checkNotNull;
 
 import android.annotation.DrawableRes;
 import android.annotation.PluralsRes;
@@ -98,7 +96,7 @@
     Job(Context service, Context appContext, Listener listener,
             @OpType int operationType, String id, DocumentStack stack) {
 
-        checkArgument(operationType != OPERATION_UNKNOWN);
+        assert(operationType != OPERATION_UNKNOWN);
 
         this.service = service;
         this.appContext = appContext;
@@ -150,7 +148,8 @@
             mClients.put(doc.authority, client);
         }
 
-        return checkNotNull(client);
+        assert(client != null);
+        return client;
     }
 
     final void cleanup() {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/services/MoveJob.java b/packages/DocumentsUI/src/com/android/documentsui/services/MoveJob.java
index b5826a4..dc39235 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/services/MoveJob.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/services/MoveJob.java
@@ -21,11 +21,9 @@
 import android.app.Notification;
 import android.app.Notification.Builder;
 import android.content.Context;
-import android.net.Uri;
 import android.os.RemoteException;
 import android.provider.DocumentsContract;
 import android.provider.DocumentsContract.Document;
-import android.util.Log;
 
 import com.android.documentsui.R;
 import com.android.documentsui.model.DocumentInfo;
@@ -36,7 +34,6 @@
 // TODO: Stop extending CopyJob.
 final class MoveJob extends CopyJob {
 
-    private static final String TAG = "MoveJob";
     final DocumentInfo mSrcParent;
 
     /**
diff --git a/packages/SystemUI/res/drawable/tv_pip_play_button.xml b/packages/SystemUI/res/drawable/tv_pip_play_button.xml
new file mode 100644
index 0000000..fecdc09
--- /dev/null
+++ b/packages/SystemUI/res/drawable/tv_pip_play_button.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:constantSize="true">
+    <item android:state_focused="true">
+        <layer-list>
+            <item android:drawable="@drawable/tv_pip_button_focused" />
+            <item android:drawable="@drawable/ic_play_arrow_white_24dp" />
+        </layer-list>
+    </item>
+    <item android:drawable="@drawable/ic_play_arrow_white_24dp" />
+</selector>
diff --git a/packages/SystemUI/res/layout/tv_pip_menu.xml b/packages/SystemUI/res/layout/tv_pip_menu.xml
index 0b98d0e..1fec49e 100644
--- a/packages/SystemUI/res/layout/tv_pip_menu.xml
+++ b/packages/SystemUI/res/layout/tv_pip_menu.xml
@@ -34,7 +34,7 @@
         android:gravity="center"
         android:clipChildren="false">
 
-        <ImageView android:id="@+id/full"
+        <ImageView android:id="@+id/full_button"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:focusable="true"
@@ -53,17 +53,16 @@
             android:clipChildren="false" />
     </LinearLayout>
 
-    <LinearLayout
+    <LinearLayout android:id="@+id/play_pause"
         android:layout_width="34dp"
         android:layout_height="wrap_content"
         android:layout_marginStart="3dp"
         android:layout_marginEnd="3dp"
         android:orientation="vertical"
         android:gravity="center"
-        android:visibility="gone"
         android:clipChildren="false">
 
-        <ImageView android:id="@+id/play_pause"
+        <ImageView android:id="@+id/play_pause_button"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:focusable="true"
@@ -90,7 +89,7 @@
         android:gravity="center"
         android:clipChildren="false">
 
-        <ImageView android:id="@+id/close"
+        <ImageView android:id="@+id/close_button"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:focusable="true"
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
index c31bb33..c643d67 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
@@ -54,8 +54,7 @@
         mQsContainer = container;
         mQuickQsPanel = quickPanel;
         mQsPanel = panel;
-        mQuickQsPanel.addOnLayoutChangeListener(this);
-        mQsPanel.addOnLayoutChangeListener(this);
+        container.addOnLayoutChangeListener(this);
         QSTileLayout tileLayout = mQsPanel.getTileLayout();
         if (tileLayout instanceof PagedTileLayout) {
             ((PagedTileLayout) tileLayout).setPageListener(this);
@@ -161,6 +160,7 @@
 
     @Override
     public void onAnimationAtStart() {
+        mQuickQsPanel.setVisibility(View.VISIBLE);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/TouchAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/TouchAnimator.java
index 026dd0e..35ade58 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/TouchAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/TouchAnimator.java
@@ -38,7 +38,7 @@
     private final float mSpan;
     private final Interpolator mInterpolator;
     private final Listener mListener;
-    private float mLastT;
+    private float mLastT = -1;
 
     private TouchAnimator(Object[] targets, KeyframeSet[] keyframeSets,
             float startDelay, float endDelay, Interpolator interpolator, Listener listener) {
@@ -56,15 +56,16 @@
         if (mInterpolator != null) {
             t = mInterpolator.getInterpolation(t);
         }
+        if (t == mLastT) {
+            return;
+        }
         if (mListener != null) {
-            if (mLastT == 0 || mLastT == 1) {
-                if (t != mLastT) {
-                    mListener.onAnimationStarted();
-                }
-            } else if (t == 1) {
+            if (t == 1) {
                 mListener.onAnimationAtEnd();
             } else if (t == 0) {
                 mListener.onAnimationAtStart();
+            } else if (mLastT <= 0 || mLastT == 1) {
+                mListener.onAnimationStarted();
             }
             mLastT = t;
         }
@@ -114,12 +115,12 @@
         private Listener mListener;
 
         public Builder addFloat(Object target, String property, float... values) {
-            add(target, KeyframeSet.ofFloat(getProperty(target, property), values));
+            add(target, KeyframeSet.ofFloat(getProperty(target, property, float.class), values));
             return this;
         }
 
         public Builder addInt(Object target, String property, int... values) {
-            add(target, KeyframeSet.ofInt(getProperty(target, property), values));
+            add(target, KeyframeSet.ofInt(getProperty(target, property, int.class), values));
             return this;
         }
 
@@ -128,7 +129,7 @@
             mValues.add(keyframeSet);
         }
 
-        private static Property getProperty(Object target, String property) {
+        private static Property getProperty(Object target, String property, Class<?> cls) {
             if (target instanceof View) {
                 switch (property) {
                     case "translationX":
@@ -151,7 +152,7 @@
                         return View.SCALE_Y;
                 }
             }
-            return Property.of(target.getClass(), float.class, property);
+            return Property.of(target.getClass(), cls, property);
         }
 
         public Builder setStartDelay(float startDelay) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
index 67fe8e5e..225c10f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -77,11 +77,10 @@
         TypedValue value = new TypedValue();
         mContext.getTheme().resolveAttribute(android.R.attr.homeAsUpIndicator, value, true);
         mToolbar.setNavigationIcon(
-                getResources().getDrawable(R.drawable.ic_close_white, mContext.getTheme()));
+                getResources().getDrawable(value.resourceId, mContext.getTheme()));
         mToolbar.setNavigationOnClickListener(new OnClickListener() {
             @Override
             public void onClick(View v) {
-                save();
                 hide((int) v.getX() + v.getWidth() / 2, (int) v.getY() + v.getHeight() / 2);
             }
         });
@@ -115,6 +114,7 @@
     public void hide(int x, int y) {
         if (isShown) {
             isShown = false;
+            save();
             mClipper.animateCircularClip(x, y, false, mCollapseAnimationListener);
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
index c6c497f..d1953b1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
@@ -27,7 +27,6 @@
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
-import android.view.View.OnTouchListener;
 import android.view.ViewGroup;
 import android.widget.FrameLayout;
 import com.android.systemui.R;
@@ -159,13 +158,6 @@
 
         TileInfo info = mTiles.get(position);
         holder.mTileView.onStateChanged(info.state);
-        holder.mTileView.setOnTouchListener(new OnTouchListener() {
-            @Override
-            public boolean onTouch(View v, MotionEvent event) {
-                mItemTouchHelper.startDrag(holder);
-                return true;
-            }
-        });
     }
 
     public SpanSizeLookup getSizeLookup() {
@@ -179,6 +171,7 @@
             super(itemView);
             if (itemView instanceof FrameLayout) {
                 mTileView = (QSTileView) ((FrameLayout) itemView).getChildAt(0);
+                mTileView.setBackground(null);
             }
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
index e4e3790..12c8c44 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
@@ -69,6 +69,11 @@
     }
 
     @Override
+    public boolean isAvailable() {
+        return mFlashlightController.hasFlashlight();
+    }
+
+    @Override
     protected void handleClick() {
         if (ActivityManager.isUserAMonkey()) {
             return;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java b/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java
index 9450287..0c48cf7 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java
@@ -97,6 +97,9 @@
 
         @Override
         public void onPipResizeAboutToStart() { }
+
+        @Override
+        public void onMediaControllerChanged() { }
     };
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 9bd645d..d0358f4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -959,7 +959,7 @@
         }, false /* afterKeyguardGone */);
     }
 
-    private void bindGuts(ExpandableNotificationRow row) {
+    private void bindGuts(final ExpandableNotificationRow row) {
         row.inflateGuts();
         final StatusBarNotification sbn = row.getStatusBarNotification();
         PackageManager pmUser = getPackageManagerForUser(mContext, sbn.getUser().getIdentifier());
@@ -1003,7 +1003,17 @@
             @Override
             public void onClick(View v) {
                 guts.saveImportance(sbn);
-                dismissPopups();
+
+                int[] rowLocation = new int[2];
+                int[] doneLocation = new int[2];
+                row.getLocationOnScreen(rowLocation);
+                v.getLocationOnScreen(doneLocation);
+
+                final int centerX = v.getWidth() / 2;
+                final int centerY = v.getHeight() / 2;
+                final int x = doneLocation[0] - rowLocation[0] + centerX;
+                final int y = doneLocation[1] - rowLocation[1] + centerY;
+                dismissPopups(x, y);
             }
         });
 
@@ -1049,7 +1059,7 @@
                 // Post to ensure the the guts are properly laid out.
                 guts.post(new Runnable() {
                     public void run() {
-                        dismissPopups();
+                        dismissPopups(-1 /* x */, -1 /* y */, false /* resetGear */);
                         guts.setVisibility(View.VISIBLE);
                         final double horz = Math.max(guts.getWidth() - x, x);
                         final double vert = Math.max(guts.getHeight() - y, y);
@@ -1083,10 +1093,14 @@
     }
 
     public void dismissPopups() {
-        dismissPopups(-1, -1);
+        dismissPopups(-1 /* x */, -1 /* y */, true /* resetGear */);
     }
 
     private void dismissPopups(int x, int y) {
+        dismissPopups(x, y, true /* resetGear */);
+    }
+
+    public void dismissPopups(int x, int y, boolean resetGear) {
         if (mNotificationGutsExposed != null) {
             final NotificationGuts v = mNotificationGutsExposed;
             mNotificationGutsExposed = null;
@@ -1114,8 +1128,7 @@
             v.setExposed(false);
             mStackScroller.onHeightChanged(null, true /* needsAnimation */);
         }
-
-        if (mNotificationGearDisplayed != null) {
+        if (resetGear && mNotificationGearDisplayed != null) {
             mNotificationGearDisplayed.resetTranslation();
             mNotificationGearDisplayed = null;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index da125d8..e109b09 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -656,7 +656,6 @@
                 mGuts = (NotificationGuts) inflated;
                 mGuts.setClipTopAmount(getClipTopAmount());
                 mGuts.setActualHeight(getActualHeight());
-                mTranslateableViews.add(mGuts);
                 mGutsStub = null;
             }
         });
@@ -1175,6 +1174,10 @@
     @Override
     public void setActualHeight(int height, boolean notifyListeners) {
         super.setActualHeight(height, notifyListeners);
+        if (mGuts != null && mGuts.areGutsExposed()) {
+            mGuts.setActualHeight(height);
+            return;
+        }
         int contentHeight = Math.max(getMinHeight(), height);
         mPrivateLayout.setContentHeight(contentHeight);
         mPublicLayout.setContentHeight(contentHeight);
@@ -1184,7 +1187,6 @@
         if (mGuts != null) {
             mGuts.setActualHeight(height);
         }
-        invalidate();
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSettingsIconRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSettingsIconRow.java
index 4491ebd..476e146 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSettingsIconRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSettingsIconRow.java
@@ -33,7 +33,7 @@
         /**
          * Called when the gear behind a notification is touched.
          */
-        public void onGearTouched(ExpandableNotificationRow row);
+        public void onGearTouched(ExpandableNotificationRow row, int x, int y);
     }
 
     private ExpandableNotificationRow mParent;
@@ -45,6 +45,8 @@
     private boolean mSettingsFadedIn = false;
     private boolean mAnimating = false;
     private boolean mOnLeft = true;
+    private int[] mGearLocation = new int[2];
+    private int[] mParentLocation = new int[2];
 
     public NotificationSettingsIconRow(Context context) {
         this(context, null);
@@ -74,6 +76,12 @@
         resetState();
     }
 
+    public void resetState() {
+        setGearAlpha(0f);
+        mAnimating = false;
+        setIconLocation(true /* on left */);
+    }
+
     public void setGearListener(SettingsIconRowListener listener) {
         mListener = listener;
     }
@@ -86,12 +94,6 @@
         return mParent;
     }
 
-    public void resetState() {
-        setGearAlpha(0f);
-        mAnimating = false;
-        setIconLocation(true /* on left */);
-    }
-
     private void setGearAlpha(float alpha) {
         if (alpha == 0) {
             mSettingsFadedIn = false; // Can fade in again once it's gone.
@@ -200,7 +202,16 @@
     public void onClick(View v) {
         if (v.getId() == R.id.gear_icon) {
             if (mListener != null) {
-                mListener.onGearTouched(mParent);
+                mGearIcon.getLocationOnScreen(mGearLocation);
+                mParent.getLocationOnScreen(mParentLocation);
+
+                final int centerX = (int) (mHorizSpaceForGear / 2);
+                // Top / bottom padding are not equal, need to subtract them to get center of gear.
+                final int centerY = (int) (mGearIcon.getHeight() - mGearIcon.getPaddingTop()
+                        - mGearIcon.getPaddingBottom()) / 2 + mGearIcon.getPaddingTop();
+                final int x = mGearLocation[0] - mParentLocation[0] + centerX;
+                final int y = mGearLocation[1] - mParentLocation[1] + centerY;
+                mListener.onGearTouched(mParent, x, y);
             }
         } else {
             // Do nothing when the background is touched.
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 cf5531f..b549d59 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
@@ -38,7 +38,6 @@
 import com.android.systemui.qs.QSTile;
 import com.android.systemui.qs.QuickQSPanel;
 import com.android.systemui.qs.TouchAnimator;
-import com.android.systemui.qs.TouchAnimator.Listener;
 import com.android.systemui.statusbar.policy.BatteryController;
 import com.android.systemui.statusbar.policy.NextAlarmController;
 import com.android.systemui.statusbar.policy.NextAlarmController.NextAlarmChangeCallback;
@@ -46,7 +45,7 @@
 import com.android.systemui.tuner.TunerService;
 
 public class QuickStatusBarHeader extends BaseStatusBarHeader implements
-        NextAlarmChangeCallback, OnClickListener, Listener {
+        NextAlarmChangeCallback, OnClickListener {
 
     private static final String TAG = "QuickStatusBarHeader";
 
@@ -157,7 +156,6 @@
         mAnimator = new TouchAnimator.Builder()
                 .addFloat(mSettingsContainer, "translationY", -mGearTranslation, 0)
                 .addFloat(mMultiUserSwitch, "translationY", -mGearTranslation, 0)
-                .setListener(this)
                 .build();
         mSecondHalfAnimator = new TouchAnimator.Builder()
                 .addFloat(mSettingsButton, "rotation", -180, 0)
@@ -224,20 +222,6 @@
         mExpandIndicator.setExpanded(headerExpansionFraction > EXPAND_INDICATOR_THRESHOLD);
     }
 
-    @Override
-    public void onAnimationAtStart() {
-    }
-
-    @Override
-    public void onAnimationAtEnd() {
-        mHeaderQsPanel.setVisibility(View.INVISIBLE);
-    }
-
-    @Override
-    public void onAnimationStarted() {
-        mHeaderQsPanel.setVisibility(View.VISIBLE);
-    }
-
     private void updateAlarmVisibilities() {
         mAlarmStatus.setVisibility(mAlarmShowing ? View.VISIBLE : View.INVISIBLE);
         mAlarmStatusCollapsed.setVisibility(mAlarmShowing ? View.VISIBLE : View.INVISIBLE);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java
index 29a8f67..9a21a1e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java
@@ -93,6 +93,10 @@
         }
     }
 
+    public boolean hasFlashlight() {
+        return mCameraId != null;
+    }
+
     public synchronized boolean isEnabled() {
         return mFlashlightEnabled;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 340ebb4..85b1426 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -361,9 +361,9 @@
     }
 
     @Override
-    public void onGearTouched(ExpandableNotificationRow row) {
+    public void onGearTouched(ExpandableNotificationRow row, int x, int y) {
         if (mLongPressListener != null) {
-            mLongPressListener.onLongPress(row, 0, 0);
+            mLongPressListener.onLongPress(row, x, y);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java
index 0925638..123165e 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java
@@ -23,11 +23,14 @@
 import android.app.IActivityManager;
 import android.app.ITaskStackListener;
 import android.content.BroadcastReceiver;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.res.Resources;
 import android.graphics.Rect;
+import android.media.session.MediaController;
+import android.media.session.MediaSessionManager;
 import android.os.Debug;
 import android.os.Handler;
 import android.os.RemoteException;
@@ -69,6 +72,7 @@
 
     private Context mContext;
     private IActivityManager mActivityManager;
+    private MediaSessionManager mMediaSessionManager;
     private int mState = STATE_NO_PIP;
     private final Handler mHandler = new Handler();
     private List<Listener> mListeners = new ArrayList<>();
@@ -79,6 +83,8 @@
     private Rect mRecentsFocusedPipBounds;
     private boolean mInitialized;
     private int mPipTaskId = TASK_ID_NO_PIP;
+    private ComponentName mPipComponentName;
+    private MediaController mPipMediaController;
     private boolean mOnboardingShown;
 
     private boolean mIsRecentsShown;
@@ -100,10 +106,15 @@
             }
             if (DEBUG) Log.d(TAG, "PINNED_STACK:" + stackInfo);
             mPipTaskId = stackInfo.taskIds[stackInfo.taskIds.length - 1];
+            mPipComponentName = ComponentName.unflattenFromString(
+                    stackInfo.taskNames[stackInfo.taskNames.length - 1]);
             // Set state to overlay so we show it when the pinned stack animation ends.
             mState = STATE_PIP_OVERLAY;
             mCurrentPipBounds = mPipBounds;
             launchPipOnboardingActivityIfNeeded();
+            mMediaSessionManager.addOnActiveSessionsChangedListener(
+                    mActiveMediaSessionListener, null);
+            updateMediaController(mMediaSessionManager.getActiveSessions(null));
         }
     };
     private final Runnable mOnTaskStackChanged = new Runnable() {
@@ -176,6 +187,13 @@
 
         }
     };
+    private final MediaSessionManager.OnActiveSessionsChangedListener mActiveMediaSessionListener =
+            new MediaSessionManager.OnActiveSessionsChangedListener() {
+                @Override
+                public void onActiveSessionsChanged(List<MediaController> controllers) {
+                    updateMediaController(controllers);
+                }
+            };
 
     private PipManager() { }
 
@@ -215,6 +233,9 @@
         mContext.registerReceiver(mBroadcastReceiver, intentFilter);
         mOnboardingShown = Prefs.getBoolean(
                 mContext, TV_PICTURE_IN_PICTURE_ONBOARDING_SHOWN, false);
+
+        mMediaSessionManager =
+                (MediaSessionManager) mContext.getSystemService(Context.MEDIA_SESSION_SERVICE);
     }
 
     /**
@@ -248,6 +269,8 @@
     private void closePipInternal(boolean removePipStack) {
         mState = STATE_NO_PIP;
         mPipTaskId = TASK_ID_NO_PIP;
+        mPipMediaController = null;
+        mMediaSessionManager.removeOnActiveSessionsChangedListener(mActiveMediaSessionListener);
         if (removePipStack) {
             try {
                 mActivityManager.removeStack(PINNED_STACK_ID);
@@ -502,6 +525,34 @@
         }
     }
 
+    private void updateMediaController(List<MediaController> controllers) {
+        MediaController mediaController = null;
+        if (controllers != null && mState != STATE_NO_PIP && mPipComponentName != null) {
+            for (int i = controllers.size() - 1; i >= 0; i--) {
+                MediaController controller = controllers.get(i);
+                // We assumes that an app with PIPable activity
+                // keeps the single instance of media controller especially when PIP is on.
+                if (controller.getPackageName().equals(mPipComponentName.getPackageName())) {
+                    mediaController = controller;
+                    break;
+                }
+            }
+        }
+        if (mPipMediaController != mediaController) {
+            mPipMediaController = mediaController;
+            for (int i = mListeners.size() - 1; i >= 0; i--) {
+                mListeners.get(i).onMediaControllerChanged();
+            }
+        }
+    }
+
+    /**
+     * Gets the {@link android.media.session.MediaController} for the PIPed activity.
+     */
+    MediaController getMediaController() {
+        return mPipMediaController;
+    }
+
     private class TaskStackListener extends ITaskStackListener.Stub {
         @Override
         public void onTaskStackChanged() throws RemoteException {
@@ -542,6 +593,8 @@
         void onMoveToFullscreen();
         /** Invoked when we are above to start resizing the Pip. */
         void onPipResizeAboutToStart();
+        /** Invoked when the MediaController on PIPed activity is changed. */
+        void onMediaControllerChanged();
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipMenuActivity.java
index a392bec..fb7fa4d 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipMenuActivity.java
@@ -18,34 +18,49 @@
 
 import android.app.Activity;
 import android.media.session.MediaController;
+import android.media.session.PlaybackState;
 import android.os.Bundle;
 import android.view.View;
+import android.widget.ImageView;
+import android.widget.TextView;
 
 import com.android.systemui.R;
 
+import static android.content.pm.PackageManager.FEATURE_LEANBACK;
+import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
+import static android.media.session.PlaybackState.ACTION_PAUSE;
+import static android.media.session.PlaybackState.ACTION_PLAY;
+
 /**
  * Activity to show the PIP menu to control PIP.
  */
 public class PipMenuActivity extends Activity implements PipManager.Listener {
     private static final String TAG = "PipMenuActivity";
-    private static final boolean DEBUG = false;
 
     private final PipManager mPipManager = PipManager.getInstance();
     private MediaController mMediaController;
 
     private View mFullButtonView;
     private View mFullDescriptionView;
-    private View mPlayPauseButtonView;
-    private View mPlayPauseDescriptionView;
+    private View mPlayPauseView;
+    private ImageView mPlayPauseButtonImageView;
+    private TextView mPlayPauseDescriptionTextView;
     private View mCloseButtonView;
     private View mCloseDescriptionView;
 
+    private MediaController.Callback mMediaControllerCallback = new MediaController.Callback() {
+        @Override
+        public void onPlaybackStateChanged(PlaybackState state) {
+            updatePlayPauseView(state);
+        }
+    };
+
     @Override
     protected void onCreate(Bundle bundle) {
         super.onCreate(bundle);
         setContentView(R.layout.tv_pip_menu);
         mPipManager.addListener(this);
-        mFullButtonView = findViewById(R.id.full);
+        mFullButtonView = findViewById(R.id.full_button);
         mFullDescriptionView = findViewById(R.id.full_desc);
         mFullButtonView.setOnClickListener(new View.OnClickListener() {
             @Override
@@ -61,22 +76,33 @@
             }
         });
 
-        mPlayPauseButtonView = findViewById(R.id.play_pause);
-        mPlayPauseDescriptionView = findViewById(R.id.play_pause_desc);
-        mPlayPauseButtonView.setOnClickListener(new View.OnClickListener() {
+        mPlayPauseView = findViewById(R.id.play_pause);
+        mPlayPauseButtonImageView = (ImageView) findViewById(R.id.play_pause_button);
+        mPlayPauseDescriptionTextView = (TextView) findViewById(R.id.play_pause_desc);
+        mPlayPauseButtonImageView.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
-                // TODO: Implement play/pause.
+                if (mMediaController == null || mMediaController.getPlaybackState() == null) {
+                    return;
+                }
+                long actions = mMediaController.getPlaybackState().getActions();
+                int state = mMediaController.getPlaybackState().getState();
+                if (((actions & ACTION_PLAY) != 0) && !isPlaying(state)) {
+                    mMediaController.getTransportControls().play();
+                } else if ((actions & ACTION_PAUSE) != 0 && isPlaying(state)) {
+                    mMediaController.getTransportControls().pause();
+                }
+                // View will be updated later in {@link mMediaControllerCallback}
             }
         });
-        mPlayPauseButtonView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
+        mPlayPauseButtonImageView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
             @Override
             public void onFocusChange(View v, boolean hasFocus) {
-                mPlayPauseDescriptionView.setVisibility(hasFocus ? View.VISIBLE : View.INVISIBLE);
+                mPlayPauseDescriptionTextView.setVisibility(hasFocus ? View.VISIBLE : View.INVISIBLE);
             }
         });
 
-        mCloseButtonView = findViewById(R.id.close);
+        mCloseButtonView = findViewById(R.id.close_button);
         mCloseDescriptionView = findViewById(R.id.close_desc);
         mCloseButtonView.setOnClickListener(new View.OnClickListener() {
             @Override
@@ -91,6 +117,50 @@
                 mCloseDescriptionView.setVisibility(hasFocus ? View.VISIBLE : View.INVISIBLE);
             }
         });
+        updateMediaController();
+    }
+
+    private void updateMediaController() {
+        MediaController newController = mPipManager.getMediaController();
+        if (mMediaController == newController) {
+            return;
+        }
+        if (mMediaController != null) {
+            mMediaController.unregisterCallback(mMediaControllerCallback);
+        }
+        mMediaController = newController;
+        if (mMediaController != null) {
+            mMediaController.registerCallback(mMediaControllerCallback);
+            updatePlayPauseView(mMediaController.getPlaybackState());
+        } else {
+            updatePlayPauseView(null);
+        }
+    }
+
+    private void updatePlayPauseView(PlaybackState playbackState) {
+        if (playbackState != null
+                && (playbackState.getActions() & (ACTION_PLAY | ACTION_PAUSE)) != 0) {
+            mPlayPauseView.setVisibility(View.VISIBLE);
+            if (isPlaying(playbackState.getState())) {
+                mPlayPauseButtonImageView.setImageResource(R.drawable.tv_pip_pause_button);
+                mPlayPauseDescriptionTextView.setText(R.string.pip_pause);
+            } else {
+                mPlayPauseButtonImageView.setImageResource(R.drawable.tv_pip_play_button);
+                mPlayPauseDescriptionTextView.setText(R.string.pip_play);
+            }
+        } else {
+            mPlayPauseView.setVisibility(View.GONE);
+        }
+    }
+
+    private boolean isPlaying(int state) {
+        return state == PlaybackState.STATE_BUFFERING
+                || state == PlaybackState.STATE_CONNECTING
+                || state == PlaybackState.STATE_PLAYING
+                || state == PlaybackState.STATE_FAST_FORWARDING
+                || state == PlaybackState.STATE_REWINDING
+                || state == PlaybackState.STATE_SKIPPING_TO_PREVIOUS
+                || state == PlaybackState.STATE_SKIPPING_TO_NEXT;
     }
 
     private void restorePipAndFinish() {
@@ -107,6 +177,9 @@
     @Override
     protected void onDestroy() {
         super.onDestroy();
+        if (mMediaController != null) {
+            mMediaController.unregisterCallback(mMediaControllerCallback);
+        }
         mPipManager.removeListener(this);
         mPipManager.resumePipResizing(
                 PipManager.SUSPEND_PIP_RESIZE_REASON_WAITING_FOR_MENU_ACTIVITY_FINISH);
@@ -131,6 +204,11 @@
     }
 
     @Override
+    public void onMediaControllerChanged() {
+        updateMediaController();
+    }
+
+    @Override
     public void onPipResizeAboutToStart() {
         finish();
         mPipManager.suspendPipResizing(
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipOnboardingActivity.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipOnboardingActivity.java
index e5c07d2..ad45625b 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipOnboardingActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipOnboardingActivity.java
@@ -82,6 +82,8 @@
     }
 
     @Override
-    public void onPipResizeAboutToStart() {
-    }
+    public void onPipResizeAboutToStart() { }
+
+    @Override
+    public void onMediaControllerChanged() { }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipOverlayActivity.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipOverlayActivity.java
index cfeab6d..95d655c 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipOverlayActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipOverlayActivity.java
@@ -103,4 +103,8 @@
         mPipManager.suspendPipResizing(
                 PipManager.SUSPEND_PIP_RESIZE_REASON_WAITING_FOR_OVERLAY_ACTIVITY_FINISH);
     }
+
+    @Override
+    public void onMediaControllerChanged() {
+    }
 }
diff --git a/packages/SystemUI/tests/AndroidManifest.xml b/packages/SystemUI/tests/AndroidManifest.xml
index 2825601..5389c804 100644
--- a/packages/SystemUI/tests/AndroidManifest.xml
+++ b/packages/SystemUI/tests/AndroidManifest.xml
@@ -20,6 +20,8 @@
     <uses-permission android:name="android.permission.INJECT_EVENTS" />
     <uses-permission android:name="android.permission.READ_PHONE_STATE" />
     <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
+    <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
+    <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
     <uses-permission android:name="android.permission.MANAGE_USERS" />
 
     <application>
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/TouchAnimatorTests.java b/packages/SystemUI/tests/src/com/android/systemui/qs/TouchAnimatorTests.java
new file mode 100644
index 0000000..1d81fd4
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/TouchAnimatorTests.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.qs;
+
+import android.view.View;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.qs.TouchAnimator.Listener;
+import org.mockito.Mockito;
+
+public class TouchAnimatorTests extends SysuiTestCase {
+
+    private Listener mTouchListener;
+    private View mTestView;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mTestView = new View(getContext());
+        mTouchListener = Mockito.mock(Listener.class);
+    }
+
+    public void testSetValueFloat() {
+        TouchAnimator animator = new TouchAnimator.Builder()
+                .addFloat(mTestView, "x", 0, 50)
+                .build();
+
+        animator.setPosition(0);
+        assertEquals(0f, mTestView.getX());
+
+        animator.setPosition(.5f);
+        assertEquals(25f, mTestView.getX());
+
+        animator.setPosition(1);
+        assertEquals(50f, mTestView.getX());
+    }
+
+    public void testSetValueInt() {
+        TouchAnimator animator = new TouchAnimator.Builder()
+                .addInt(mTestView, "top", 0, 50)
+                .build();
+
+        animator.setPosition(0);
+        assertEquals(0, mTestView.getTop());
+
+        animator.setPosition(.5f);
+        assertEquals(25, mTestView.getTop());
+
+        animator.setPosition(1);
+        assertEquals(50, mTestView.getTop());
+    }
+
+    public void testStartDelay() {
+        TouchAnimator animator = new TouchAnimator.Builder()
+                .addFloat(mTestView, "x", 0, 50)
+                .setStartDelay(.5f)
+                .build();
+
+        animator.setPosition(0);
+        assertEquals(0f, mTestView.getX());
+
+        animator.setPosition(.5f);
+        assertEquals(0f, mTestView.getX());
+
+        animator.setPosition(.75f);
+        assertEquals(25f, mTestView.getX());
+
+        animator.setPosition(1);
+        assertEquals(50f, mTestView.getX());
+    }
+
+    public void testEndDelay() {
+        TouchAnimator animator = new TouchAnimator.Builder()
+                .addFloat(mTestView, "x", 0, 50)
+                .setEndDelay(.5f)
+                .build();
+
+        animator.setPosition(0);
+        assertEquals(0f, mTestView.getX());
+
+        animator.setPosition(.25f);
+        assertEquals(25f, mTestView.getX());
+
+        animator.setPosition(.5f);
+        assertEquals(50f, mTestView.getX());
+
+        animator.setPosition(1);
+        assertEquals(50f, mTestView.getX());
+    }
+
+    public void testOnAnimationAtStartCallback() {
+        TouchAnimator animator = new TouchAnimator.Builder()
+                .setListener(mTouchListener)
+                .build();
+
+        // Called on init.
+        animator.setPosition(0);
+        verifyOnAnimationAtStart(1);
+
+        // Not called from same state.
+        animator.setPosition(0);
+        verifyOnAnimationAtStart(1);
+
+        // Called after starting and moving back to start.
+        animator.setPosition(.5f);
+        animator.setPosition(0);
+        verifyOnAnimationAtStart(2);
+
+        // Called when move from end to end.
+        animator.setPosition(1);
+        animator.setPosition(0);
+        verifyOnAnimationAtStart(3);
+    }
+
+    public void testOnAnimationAtEndCallback() {
+        TouchAnimator animator = new TouchAnimator.Builder()
+                .setListener(mTouchListener)
+                .build();
+
+        // Called on init.
+        animator.setPosition(1);
+        verifyOnAnimationAtEnd(1);
+
+        // Not called from same state.
+        animator.setPosition(1);
+        verifyOnAnimationAtEnd(1);
+
+        // Called after starting and moving back to end.
+        animator.setPosition(.5f);
+        animator.setPosition(1);
+        verifyOnAnimationAtEnd(2);
+
+        // Called when move from end to end.
+        animator.setPosition(0);
+        animator.setPosition(1);
+        verifyOnAnimationAtEnd(3);
+    }
+
+    public void testOnAnimationStartedCallback() {
+        TouchAnimator animator = new TouchAnimator.Builder()
+                .setListener(mTouchListener)
+                .build();
+
+        // Called on init.
+        animator.setPosition(.5f);
+        verifyOnAnimationStarted(1);
+
+        // Not called from same state.
+        animator.setPosition(.6f);
+        verifyOnAnimationStarted(1);
+
+        // Called after going to end then moving again.
+        animator.setPosition(1);
+        animator.setPosition(.5f);
+        verifyOnAnimationStarted(2);
+
+        // Called after moving to start then moving again.
+        animator.setPosition(0);
+        animator.setPosition(.5f);
+        verifyOnAnimationStarted(3);
+    }
+
+    // TODO: Add test for interpolator.
+
+    private void verifyOnAnimationAtStart(int times) {
+        Mockito.verify(mTouchListener, Mockito.times(times)).onAnimationAtStart();
+    }
+
+    private void verifyOnAnimationAtEnd(int times) {
+        Mockito.verify(mTouchListener, Mockito.times(times)).onAnimationAtEnd();
+    }
+
+    private void verifyOnAnimationStarted(int times) {
+        Mockito.verify(mTouchListener, Mockito.times(times)).onAnimationStarted();
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTests.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTests.java
index c4ca039..1841251 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTests.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTests.java
@@ -19,6 +19,9 @@
 import android.os.Looper;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.statusbar.phone.QSTileHost;
+import com.android.systemui.statusbar.policy.DataSaverController;
+import com.android.systemui.statusbar.policy.HotspotController;
+import com.android.systemui.statusbar.policy.NetworkController;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mockito;
 
@@ -34,7 +37,12 @@
     protected void setUp() throws Exception {
         super.setUp();
         mManagers = new ArrayList<>();
-        QSTileHost host = new QSTileHost(mContext, null, null, null, null, null, null, null, null,
+        final NetworkController networkController = Mockito.mock(NetworkController.class);
+        Mockito.when(networkController.getDataSaverController()).thenReturn(
+                Mockito.mock(DataSaverController.class));
+        QSTileHost host = new QSTileHost(mContext, null, null, null, null,
+                networkController, null,
+                Mockito.mock(HotspotController.class), null,
                 null, null, null, null, null, null, null);
         mTileService = new TestTileServices(host, Looper.myLooper());
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
index 5cf3767..ebd5384 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
@@ -16,9 +16,6 @@
 
 package com.android.systemui.statusbar.policy;
 
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
 import android.content.Intent;
 import android.net.ConnectivityManager;
 import android.net.NetworkCapabilities;
@@ -31,14 +28,12 @@
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 import android.util.Log;
-
 import com.android.internal.telephony.cdma.EriInfo;
 import com.android.settingslib.net.DataUsageController;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.statusbar.policy.NetworkController.IconState;
 import com.android.systemui.statusbar.policy.NetworkControllerImpl.Config;
 import com.android.systemui.statusbar.policy.NetworkControllerImpl.SubscriptionDefaults;
-
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mockito;
 
@@ -47,6 +42,9 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
 public class NetworkControllerBaseTest extends SysuiTestCase {
     private static final String TAG = "NetworkControllerBaseTest";
     protected static final int DEFAULT_LEVEL = 2;
@@ -109,6 +107,7 @@
     protected void setupNetworkController() {
         // For now just pretend to be the data sim, so we can test that too.
         mSubId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
+        when(mMockTm.getDataEnabled(mSubId)).thenReturn(true);
         setDefaultSubId(mSubId);
         setSubscriptions(mSubId);
         mMobileSignalController = mNetworkController.mMobileSignalControllers.get(mSubId);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 5f40e5c..71a0f49 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -15150,6 +15150,7 @@
         boolean dumpFullDetails = false;
         boolean dumpDalvik = false;
         boolean dumpSummaryOnly = false;
+        boolean dumpUnreachable = false;
         boolean oomOnly = false;
         boolean isCompact = false;
         boolean localOnly = false;
@@ -15178,6 +15179,8 @@
                 dumpSummaryOnly = true;
             } else if ("-S".equals(opt)) {
                 dumpSwapPss = true;
+            } else if ("--unreachable".equals(opt)) {
+                dumpUnreachable = true;
             } else if ("--oom".equals(opt)) {
                 oomOnly = true;
             } else if ("--local".equals(opt)) {
@@ -15339,7 +15342,7 @@
                         try {
                             pw.flush();
                             thread.dumpMemInfo(fd, mi, isCheckinRequest, dumpFullDetails,
-                                    dumpDalvik, dumpSummaryOnly, innerArgs);
+                                    dumpDalvik, dumpSummaryOnly, dumpUnreachable, innerArgs);
                         } catch (RemoteException e) {
                             if (!isCheckinRequest) {
                                 pw.println("Got RemoteException!");
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index 0181640..bcdc800 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -1416,7 +1416,7 @@
                 }
                 intentActivity.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
                         mStartActivity.launchedFromPackage);
-            } else if (!mStartActivity.intent.filterEquals(intentActivity.intent)) {
+            } else if (!intentActivity.task.isSameIntentResolution(mStartActivity)) {
                 // In this case we are launching the root activity of the task, but with a
                 // different intent. We should start a new instance on top.
                 mAddingToTask = true;
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 37a549a..62275a9 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -469,6 +469,19 @@
         setLockTaskAuth();
     }
 
+    /**
+     * Return true if the input activity has the same intent resolution as the intent this task
+     * record is based on (normally the root activity intent).
+     */
+    boolean isSameIntentResolution(ActivityRecord r) {
+        final Intent intent = new Intent(r.intent);
+        // Correct the activity intent for aliasing. The task record intent will always be based on
+        // the real activity that will be launched not the alias, so we need to use an intent with
+        // the component name pointing to the real activity not the alias in the activity record.
+        intent.setComponent(r.realActivity);
+        return this.intent.filterEquals(intent);
+    }
+
     void setTaskToReturnTo(int taskToReturnTo) {
         mTaskToReturnTo = (taskToReturnTo == RECENTS_ACTIVITY_TYPE)
                 ? HOME_ACTIVITY_TYPE : taskToReturnTo;
diff --git a/services/core/java/com/android/server/pm/EphemeralApplicationRegistry.java b/services/core/java/com/android/server/pm/EphemeralApplicationRegistry.java
index 8786350..389e0a1 100644
--- a/services/core/java/com/android/server/pm/EphemeralApplicationRegistry.java
+++ b/services/core/java/com/android/server/pm/EphemeralApplicationRegistry.java
@@ -210,6 +210,9 @@
     }
 
     public void onPackageUninstalledLPw(PackageParser.Package pkg) {
+        if (pkg == null) {
+            return;
+        }
         PackageSetting ps = (PackageSetting) pkg.mExtras;
         if (ps == null) {
             return;
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 6cfa1c9..9988694 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -13303,18 +13303,21 @@
         return null;
     }
 
-    private void removeNativeBinariesLI(PackageParser.Package pkg) {
+    private void removeNativeBinariesLI(PackageSetting ps) {
         // Remove the lib path for the parent package
-        PackageSetting ps = (PackageSetting) pkg.mExtras;
         if (ps != null) {
             NativeLibraryHelper.removeNativeBinariesLI(ps.legacyNativeLibraryPathString);
-        }
-        // Remove the lib path for the child packages
-        final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
-        for (int i = 0; i < childCount; i++) {
-            ps = (PackageSetting) pkg.childPackages.get(i).mExtras;
-            if (ps != null) {
-                NativeLibraryHelper.removeNativeBinariesLI(ps.legacyNativeLibraryPathString);
+            // Remove the lib path for the child packages
+            final int childCount = (ps.childPackageNames != null) ? ps.childPackageNames.size() : 0;
+            for (int i = 0; i < childCount; i++) {
+                PackageSetting childPs = null;
+                synchronized (mPackages) {
+                    childPs = mSettings.peekPackageLPr(ps.childPackageNames.get(i));
+                }
+                if (childPs != null) {
+                    NativeLibraryHelper.removeNativeBinariesLI(childPs
+                            .legacyNativeLibraryPathString);
+                }
             }
         }
     }
@@ -14437,7 +14440,7 @@
     private boolean deleteSystemPackageLI(PackageParser.Package deletedPkg,
             PackageSetting deletedPs, int[] allUserHandles, int flags, PackageRemovedInfo outInfo,
             boolean writeSettings) {
-        if (deletedPkg.parentPackage != null) {
+        if (deletedPs.parentPackageName != null) {
             Slog.w(TAG, "Attempt to delete child system package " + deletedPkg.packageName);
             return false;
         }
@@ -14450,7 +14453,7 @@
         // the system pkg from system partition
         // reader
         synchronized (mPackages) {
-            disabledPs = mSettings.getDisabledSystemPkgLPr(deletedPkg.packageName);
+            disabledPs = mSettings.getDisabledSystemPkgLPr(deletedPs.name);
         }
 
         if (DEBUG_REMOVE) Slog.d(TAG, "deleteSystemPackageLI: newPs=" + deletedPkg.packageName
@@ -14476,10 +14479,10 @@
         // Delete the updated package
         outInfo.isRemovedPackageSystemUpdate = true;
         if (outInfo.removedChildPackages != null) {
-            final int childCount = (deletedPkg.childPackages != null)
-                    ? deletedPkg.childPackages.size() : 0;
+            final int childCount = (deletedPs.childPackageNames != null)
+                    ? deletedPs.childPackageNames.size() : 0;
             for (int i = 0; i < childCount; i++) {
-                String childPackageName = deletedPkg.childPackages.get(i).packageName;
+                String childPackageName = deletedPs.childPackageNames.get(i);
                 if (disabledPs.childPackageNames != null && disabledPs.childPackageNames
                         .contains(childPackageName)) {
                     PackageRemovedInfo childInfo = outInfo.removedChildPackages.get(
@@ -14499,7 +14502,7 @@
             flags |= PackageManager.DELETE_KEEP_DATA;
         }
 
-        boolean ret = deleteInstalledPackageLI(deletedPkg, true, flags, allUserHandles,
+        boolean ret = deleteInstalledPackageLI(deletedPs, true, flags, allUserHandles,
                 outInfo, writeSettings, disabledPs.pkg);
         if (!ret) {
             return false;
@@ -14510,7 +14513,7 @@
             // Reinstate the old system package
             enableSystemPackageLPw(disabledPs.pkg);
             // Remove any native libraries from the upgraded package.
-            removeNativeBinariesLI(deletedPkg);
+            removeNativeBinariesLI(deletedPs);
         }
 
         // Install the system package
@@ -14567,29 +14570,18 @@
         return true;
     }
 
-    private boolean deleteInstalledPackageLI(PackageParser.Package pkg,
+    private boolean deleteInstalledPackageLI(PackageSetting ps,
             boolean deleteCodeAndResources, int flags, int[] allUserHandles,
             PackageRemovedInfo outInfo, boolean writeSettings,
             PackageParser.Package replacingPackage) {
-        PackageSetting ps = null;
-
         synchronized (mPackages) {
-            pkg = mPackages.get(pkg.packageName);
-            if (pkg == null) {
-                return false;
-            }
-
-            ps = mSettings.mPackages.get(pkg.packageName);
-            if (ps == null) {
-                return false;
-            }
-
             if (outInfo != null) {
                 outInfo.uid = ps.appId;
             }
 
             if (outInfo != null && outInfo.removedChildPackages != null) {
-                final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
+                final int childCount = (ps.childPackageNames != null)
+                        ? ps.childPackageNames.size() : 0;
                 for (int i = 0; i < childCount; i++) {
                     String childPackageName = ps.childPackageNames.get(i);
                     PackageSetting childPs = mSettings.mPackages.get(childPackageName);
@@ -14609,11 +14601,11 @@
         removePackageDataLI(ps, allUserHandles, outInfo, flags, writeSettings);
 
         // Delete the child packages data
-        final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
+        final int childCount = (ps.childPackageNames != null) ? ps.childPackageNames.size() : 0;
         for (int i = 0; i < childCount; i++) {
             PackageSetting childPs;
             synchronized (mPackages) {
-                childPs = mSettings.peekPackageLPr(pkg.childPackages.get(i).packageName);
+                childPs = mSettings.peekPackageLPr(ps.childPackageNames.get(i));
             }
             if (childPs != null) {
                 PackageRemovedInfo childOutInfo = (outInfo != null
@@ -14629,7 +14621,7 @@
         }
 
         // Delete application code and resources only for parent packages
-        if (ps.pkg.parentPackage == null) {
+        if (ps.parentPackageName == null) {
             if (deleteCodeAndResources && (outInfo != null)) {
                 outInfo.args = createInstallArgsForExisting(packageFlagsToInstallFlags(ps),
                         ps.codePathString, ps.resourcePathString, getAppDexInstructionSets(ps));
@@ -14720,7 +14712,7 @@
                 return false;
             }
 
-            if (ps.pkg != null && ps.pkg.parentPackage != null && (!isSystemApp(ps)
+            if (ps.parentPackageName != null && (!isSystemApp(ps)
                     || (flags & PackageManager.DELETE_SYSTEM_APP) != 0)) {
                 if (DEBUG_REMOVE) {
                     Slog.d(TAG, "Uninstalled child package:" + packageName + " for user:"
@@ -14808,7 +14800,7 @@
             if (DEBUG_REMOVE) Slog.d(TAG, "Removing non-system package: " + ps.name);
             // Kill application pre-emptively especially for apps on sd.
             killApplication(packageName, ps.appId, "uninstall pkg");
-            ret = deleteInstalledPackageLI(ps.pkg, deleteCodeAndResources, flags, allUserHandles,
+            ret = deleteInstalledPackageLI(ps, deleteCodeAndResources, flags, allUserHandles,
                     outInfo, writeSettings, replacingPackage);
         }
 
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 60c3a35..0252ea4 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -769,7 +769,7 @@
                 out.attribute(null, ATTR_VALUE, Boolean.toString(disableContactsSearch));
                 out.endTag(null, TAG_DISABLE_CONTACTS_SEARCH);
             }
-            if (disableBluetoothContactSharing) {
+            if (!disableBluetoothContactSharing) {
                 out.startTag(null, TAG_DISABLE_BLUETOOTH_CONTACT_SHARING);
                 out.attribute(null, ATTR_VALUE,
                         Boolean.toString(disableBluetoothContactSharing));
diff --git a/telecomm/java/android/telecom/Conference.java b/telecomm/java/android/telecom/Conference.java
index 094b3a9..1b70d65 100644
--- a/telecomm/java/android/telecom/Conference.java
+++ b/telecomm/java/android/telecom/Conference.java
@@ -181,7 +181,10 @@
      * @hide
      */
     public void removeCapability(int capability) {
-        mConnectionCapabilities &= ~capability;
+        int newCapabilities = mConnectionCapabilities;
+        newCapabilities &= ~capability;
+
+        setConnectionCapabilities(newCapabilities);
     }
 
     /**
@@ -191,7 +194,10 @@
      * @hide
      */
     public void addCapability(int capability) {
-        mConnectionCapabilities |= capability;
+        int newCapabilities = mConnectionCapabilities;
+        newCapabilities |= capability;
+
+        setConnectionCapabilities(newCapabilities);
     }
 
     /**
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 9f478df..857d2df 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -1426,6 +1426,7 @@
      * {@link android.provider.BlockedNumberContract#canCurrentUserBlockNumbers(Context)} returns
      * {@code true} for the current user.
      */
+    // TODO: Delete this.
     public void launchManageBlockedNumbersActivity() {
         ITelecomService service = getTelecomService();
         if (service != null) {
@@ -1437,6 +1438,26 @@
         }
     }
 
+    /**
+     * Creates the {@link Intent} which can be used with {@link Context#startActivity(Intent)} to
+     * launch the activity to manage blocked numbers.
+     * <p> This method displays the UI to manage blocked numbers only if
+     * {@link android.provider.BlockedNumberContract#canCurrentUserBlockNumbers(Context)} returns
+     * {@code true} for the current user.
+     */
+    public Intent createManageBlockedNumbersIntent() {
+        ITelecomService service = getTelecomService();
+        Intent result = null;
+        if (service != null) {
+            try {
+                result = service.createManageBlockedNumbersIntent();
+            } catch (RemoteException e) {
+                Log.e(TAG, "Error calling ITelecomService#createManageBlockedNumbersIntent", e);
+            }
+        }
+        return result;
+    }
+
     private ITelecomService getTelecomService() {
         if (mTelecomServiceOverride != null) {
             return mTelecomServiceOverride;
diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
index 95c8db5..3c250f1 100644
--- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
+++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
@@ -17,6 +17,7 @@
 package com.android.internal.telecom;
 
 import android.content.ComponentName;
+import android.content.Intent;
 import android.telecom.ParcelableCallAnalytics;
 import android.telecom.PhoneAccountHandle;
 import android.net.Uri;
@@ -247,5 +248,11 @@
     /**
     * @see TelecomServiceImpl#launchManageBlockedNumbersActivity
     **/
+    // TODO: Delete this.
     void launchManageBlockedNumbersActivity(in String callingPackageName);
+
+    /**
+    * @see TelecomServiceImpl#createManageBlockedNumbersIntent
+    **/
+    Intent createManageBlockedNumbersIntent();
 }
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/RefactorClassAdapter.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/RefactorClassAdapter.java
index 91161f5..024e32f 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/RefactorClassAdapter.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/RefactorClassAdapter.java
@@ -16,9 +16,11 @@
 
 package com.android.tools.layoutlib.create;
 
+import java.util.Arrays;
 import java.util.HashMap;
 
 import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.MethodVisitor;
 
 public class RefactorClassAdapter extends AbstractClassAdapter {
 
@@ -30,6 +32,14 @@
     }
 
     @Override
+    public MethodVisitor visitMethod(int access, String name, String desc, String signature,
+            String[] exceptions) {
+        MethodVisitor mw = super.visitMethod(access, name, desc, signature, exceptions);
+
+        return new RefactorStackMapAdapter(mw);
+    }
+
+    @Override
     protected String renameInternalType(String oldClassName) {
         if (oldClassName != null) {
             String newName = mRefactorClasses.get(oldClassName);
@@ -46,4 +56,49 @@
         }
         return oldClassName;
     }
+
+    /**
+     * A method visitor that renames all references from an old class name to a new class name in
+     * the stackmap of the method.
+     */
+    private class RefactorStackMapAdapter extends MethodVisitor {
+
+        private RefactorStackMapAdapter(MethodVisitor mv) {
+            super(Main.ASM_VERSION, mv);
+        }
+
+
+        private Object[] renameFrame(Object[] elements) {
+            if (elements == null) {
+                return null;
+            }
+
+            // The input array cannot be modified. We only copy the source array on write
+            boolean copied = false;
+            for (int i = 0; i < elements.length; i++) {
+                if (!(elements[i] instanceof String)) {
+                    continue;
+                }
+
+                if (!copied) {
+                    elements = Arrays.copyOf(elements, elements.length);
+                    copied = true;
+                }
+
+                String type = (String)elements[i];
+                if (type.indexOf(';') > 0) {
+                    elements[i] = renameTypeDesc(type);
+                } else {
+                    elements[i] = renameInternalType(type);
+                }
+            }
+
+            return elements;
+        }
+
+        @Override
+        public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) {
+            super.visitFrame(type, nLocal, renameFrame(local), nStack, renameFrame(stack));
+        }
+    }
 }