Merge "Add importance to notification guts."
diff --git a/api/current.txt b/api/current.txt
index b5def49..622d79b 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -20303,6 +20303,8 @@
     field public static final java.lang.String MIMETYPE_TEXT_CEA_608 = "text/cea-608";
     field public static final java.lang.String MIMETYPE_TEXT_VTT = "text/vtt";
     field public static final java.lang.String MIMETYPE_VIDEO_AVC = "video/avc";
+    field public static final java.lang.String MIMETYPE_VIDEO_DOLBY_AVC = "video/dolby-avc";
+    field public static final java.lang.String MIMETYPE_VIDEO_DOLBY_HEVC = "video/dolby-hevc";
     field public static final java.lang.String MIMETYPE_VIDEO_H263 = "video/3gpp";
     field public static final java.lang.String MIMETYPE_VIDEO_HEVC = "video/hevc";
     field public static final java.lang.String MIMETYPE_VIDEO_MPEG2 = "video/mpeg2";
@@ -28098,11 +28100,13 @@
     method public boolean isSystemUser();
     method public boolean isUserAGoat();
     method public boolean isUserRunning(android.os.UserHandle);
-    method public boolean isUserRunningAndLocked();
-    method public boolean isUserRunningAndLocked(android.os.UserHandle);
-    method public boolean isUserRunningAndUnlocked();
-    method public boolean isUserRunningAndUnlocked(android.os.UserHandle);
+    method public deprecated boolean isUserRunningAndLocked();
+    method public deprecated boolean isUserRunningAndLocked(android.os.UserHandle);
+    method public deprecated boolean isUserRunningAndUnlocked();
+    method public deprecated boolean isUserRunningAndUnlocked(android.os.UserHandle);
     method public boolean isUserRunningOrStopping(android.os.UserHandle);
+    method public boolean isUserUnlocked();
+    method public boolean isUserUnlocked(android.os.UserHandle);
     method public deprecated boolean setRestrictionsChallenge(java.lang.String);
     method public deprecated void setUserRestriction(java.lang.String, boolean);
     method public deprecated void setUserRestrictions(android.os.Bundle);
diff --git a/api/system-current.txt b/api/system-current.txt
index 34377fc..ba3b7e3 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -21594,6 +21594,8 @@
     field public static final java.lang.String MIMETYPE_TEXT_CEA_608 = "text/cea-608";
     field public static final java.lang.String MIMETYPE_TEXT_VTT = "text/vtt";
     field public static final java.lang.String MIMETYPE_VIDEO_AVC = "video/avc";
+    field public static final java.lang.String MIMETYPE_VIDEO_DOLBY_AVC = "video/dolby-avc";
+    field public static final java.lang.String MIMETYPE_VIDEO_DOLBY_HEVC = "video/dolby-hevc";
     field public static final java.lang.String MIMETYPE_VIDEO_H263 = "video/3gpp";
     field public static final java.lang.String MIMETYPE_VIDEO_HEVC = "video/hevc";
     field public static final java.lang.String MIMETYPE_VIDEO_MPEG2 = "video/mpeg2";
@@ -30092,11 +30094,13 @@
     method public boolean isSystemUser();
     method public boolean isUserAGoat();
     method public boolean isUserRunning(android.os.UserHandle);
-    method public boolean isUserRunningAndLocked();
-    method public boolean isUserRunningAndLocked(android.os.UserHandle);
-    method public boolean isUserRunningAndUnlocked();
-    method public boolean isUserRunningAndUnlocked(android.os.UserHandle);
+    method public deprecated boolean isUserRunningAndLocked();
+    method public deprecated boolean isUserRunningAndLocked(android.os.UserHandle);
+    method public deprecated boolean isUserRunningAndUnlocked();
+    method public deprecated boolean isUserRunningAndUnlocked(android.os.UserHandle);
     method public boolean isUserRunningOrStopping(android.os.UserHandle);
+    method public boolean isUserUnlocked();
+    method public boolean isUserUnlocked(android.os.UserHandle);
     method public deprecated boolean setRestrictionsChallenge(java.lang.String);
     method public deprecated void setUserRestriction(java.lang.String, boolean);
     method public deprecated void setUserRestrictions(android.os.Bundle);
diff --git a/api/test-current.txt b/api/test-current.txt
index 5c00957..3b53be4 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -20303,6 +20303,8 @@
     field public static final java.lang.String MIMETYPE_TEXT_CEA_608 = "text/cea-608";
     field public static final java.lang.String MIMETYPE_TEXT_VTT = "text/vtt";
     field public static final java.lang.String MIMETYPE_VIDEO_AVC = "video/avc";
+    field public static final java.lang.String MIMETYPE_VIDEO_DOLBY_AVC = "video/dolby-avc";
+    field public static final java.lang.String MIMETYPE_VIDEO_DOLBY_HEVC = "video/dolby-hevc";
     field public static final java.lang.String MIMETYPE_VIDEO_H263 = "video/3gpp";
     field public static final java.lang.String MIMETYPE_VIDEO_HEVC = "video/hevc";
     field public static final java.lang.String MIMETYPE_VIDEO_MPEG2 = "video/mpeg2";
@@ -28098,11 +28100,13 @@
     method public boolean isSystemUser();
     method public boolean isUserAGoat();
     method public boolean isUserRunning(android.os.UserHandle);
-    method public boolean isUserRunningAndLocked();
-    method public boolean isUserRunningAndLocked(android.os.UserHandle);
-    method public boolean isUserRunningAndUnlocked();
-    method public boolean isUserRunningAndUnlocked(android.os.UserHandle);
+    method public deprecated boolean isUserRunningAndLocked();
+    method public deprecated boolean isUserRunningAndLocked(android.os.UserHandle);
+    method public deprecated boolean isUserRunningAndUnlocked();
+    method public deprecated boolean isUserRunningAndUnlocked(android.os.UserHandle);
     method public boolean isUserRunningOrStopping(android.os.UserHandle);
+    method public boolean isUserUnlocked();
+    method public boolean isUserUnlocked(android.os.UserHandle);
     method public deprecated boolean setRestrictionsChallenge(java.lang.String);
     method public deprecated void setUserRestriction(java.lang.String, boolean);
     method public deprecated void setUserRestrictions(android.os.Bundle);
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index f3242a7..4cb2619 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -2718,10 +2718,10 @@
             reply.writeNoException();
             return true;
         }
-        case REMOVE_STACK_TRANSACTION: {
+        case MOVE_TASKS_TO_FULLSCREEN_STACK_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             final int stackId = data.readInt();
-            removeStack(stackId);
+            moveTasksToFullscreenStack(stackId);
             reply.writeNoException();
             return true;
         }
@@ -6358,12 +6358,12 @@
     }
 
     @Override
-    public void removeStack(int stackId) throws RemoteException {
+    public void moveTasksToFullscreenStack(int fromStackId) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(stackId);
-        mRemote.transact(REMOVE_STACK_TRANSACTION, data, reply, 0);
+        data.writeInt(fromStackId);
+        mRemote.transact(MOVE_TASKS_TO_FULLSCREEN_STACK_TRANSACTION, data, reply, 0);
         reply.readException();
         data.recycle();
         reply.recycle();
diff --git a/core/java/android/app/ApplicationLoaders.java b/core/java/android/app/ApplicationLoaders.java
index 413c369..ddb2d46 100644
--- a/core/java/android/app/ApplicationLoaders.java
+++ b/core/java/android/app/ApplicationLoaders.java
@@ -27,7 +27,8 @@
         return gApplicationLoaders;
     }
 
-    public ClassLoader getClassLoader(String zip, String libPath, ClassLoader parent)
+    public ClassLoader getClassLoader(String zip, String librarySearchPath,
+                                      String libraryPermittedPath, ClassLoader parent)
     {
         /*
          * This is the parent we use if they pass "null" in.  In theory
@@ -55,7 +56,7 @@
     
                 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, zip);
                 PathClassLoader pathClassloader =
-                    new PathClassLoader(zip, libPath, parent);
+                    new PathClassLoader(zip, librarySearchPath, libraryPermittedPath, parent);
                 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
 
                 mLoaders.put(zip, pathClassloader);
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 22a2d64..eb8d6bc 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -541,7 +541,7 @@
 
     public void suppressResizeConfigChanges(boolean suppress) throws RemoteException;
 
-    public void removeStack(int stackId) throws RemoteException;
+    public void moveTasksToFullscreenStack(int fromStackId) throws RemoteException;
 
     public int getAppStartMode(int uid, String packageName) throws RemoteException;
 
@@ -906,7 +906,7 @@
     int REPORT_SIZE_CONFIGURATIONS = IBinder.FIRST_CALL_TRANSACTION + 345;
     int MOVE_TASK_TO_DOCKED_STACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 346;
     int SUPPRESS_RESIZE_CONFIG_CHANGES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 347;
-    int REMOVE_STACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 348;
+    int MOVE_TASKS_TO_FULLSCREEN_STACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 348;
     int MOVE_TOP_ACTIVITY_TO_PINNED_STACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 349;
     int GET_APP_START_MODE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 350;
     int UNLOCK_USER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 351;
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index 891558f..7313fd1 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -366,7 +366,15 @@
                     }
                 }
 
-                final String lib = TextUtils.join(File.pathSeparator, libPaths);
+                if (mApplicationInfo.isSystemApp()) {
+                    // Add path to system libraries to libPaths;
+                    // Access to system libs should be limited
+                    // to bundled applications; this is why updated
+                    // system apps are not included.
+                    libPaths.add(System.getProperty("java.library.path"));
+                }
+
+                final String librarySearchPath = TextUtils.join(File.pathSeparator, libPaths);
 
                 /*
                  * With all the combination done (if necessary, actually
@@ -374,14 +382,17 @@
                  */
 
                 if (ActivityThread.localLOGV)
-                    Slog.v(ActivityThread.TAG, "Class path: " + zip + ", JNI path: " + lib);
+                    Slog.v(ActivityThread.TAG, "Class path: " + zip +
+                            ", JNI path: " + librarySearchPath);
 
                 // Temporarily disable logging of disk reads on the Looper thread
                 // as this is early and necessary.
                 StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
 
-                mClassLoader = ApplicationLoaders.getDefault().getClassLoader(zip, lib,
-                        mBaseClassLoader);
+                String libraryPermittedPath = mAppDir + File.pathSeparator + mDataDir;
+
+                mClassLoader = ApplicationLoaders.getDefault().getClassLoader(zip, librarySearchPath,
+                        libraryPermittedPath, mBaseClassLoader);
 
                 StrictMode.setThreadPolicy(oldPolicy);
             } else {
diff --git a/core/java/android/app/NativeActivity.java b/core/java/android/app/NativeActivity.java
index 1370000..aa14cb5 100644
--- a/core/java/android/app/NativeActivity.java
+++ b/core/java/android/app/NativeActivity.java
@@ -35,6 +35,8 @@
 import android.view.WindowManager;
 import android.view.inputmethod.InputMethodManager;
 
+import dalvik.system.BaseDexClassLoader;
+
 import java.io.File;
 
 /**
@@ -93,7 +95,9 @@
     
     private native long loadNativeCode(String path, String funcname, MessageQueue queue,
             String internalDataPath, String obbPath, String externalDataPath, int sdkVersion,
-            AssetManager assetMgr, byte[] savedState);
+            AssetManager assetMgr, byte[] savedState, ClassLoader classLoader, String libraryPath,
+            String isolationPath);
+    private native String getDlError();
     private native void unloadNativeCode(long handle);
     private native void onStartNative(long handle);
     private native void onResumeNative(long handle);
@@ -157,15 +161,10 @@
         } catch (PackageManager.NameNotFoundException e) {
             throw new RuntimeException("Error getting activity info", e);
         }
-        
-        String path = null;
-        
-        File libraryFile = new File(ai.applicationInfo.nativeLibraryDir,
-                System.mapLibraryName(libname));
-        if (libraryFile.exists()) {
-            path = libraryFile.getPath();
-        }
-        
+
+        BaseDexClassLoader classLoader = (BaseDexClassLoader) getClassLoader();
+        String path = classLoader.findLibrary(libname);
+
         if (path == null) {
             throw new IllegalArgumentException("Unable to find native library: " + libname);
         }
@@ -176,10 +175,13 @@
         mNativeHandle = loadNativeCode(path, funcname, Looper.myQueue(),
                 getAbsolutePath(getFilesDir()), getAbsolutePath(getObbDir()),
                 getAbsolutePath(getExternalFilesDir(null)),
-                Build.VERSION.SDK_INT, getAssets(), nativeSavedState);
+                Build.VERSION.SDK_INT, getAssets(), nativeSavedState,
+                classLoader, classLoader.getLdLibraryPath(),
+                classLoader.getLibraryPermittedPath());
 
         if (mNativeHandle == 0) {
-            throw new IllegalArgumentException("Unable to load native library: " + path);
+            throw new UnsatisfiedLinkError(
+                    "Unable to load native library \"" + path + "\": " + getDlError());
         }
         super.onCreate(savedInstanceState);
     }
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 6b900a8..93f137f 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -89,7 +89,6 @@
     private final Context mContext;
     private final IDevicePolicyManager mService;
 
-    // TODO Use it everywhere.
     private static final String REMOTE_EXCEPTION_MESSAGE =
             "Failed to talk with device policy manager service";
 
@@ -841,7 +840,7 @@
             try {
                 return mService.isAdminActive(admin, userId);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
         return false;
@@ -856,7 +855,7 @@
             try {
                 return mService.isRemovingAdmin(admin, userId);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
         return false;
@@ -881,7 +880,7 @@
             try {
                 return mService.getActiveAdmins(userId);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
         return null;
@@ -897,7 +896,7 @@
             try {
                 return mService.packageHasActiveAdmins(packageName, myUserId());
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
         return false;
@@ -914,7 +913,7 @@
             try {
                 mService.removeActiveAdmin(admin, myUserId());
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
     }
@@ -933,7 +932,7 @@
             try {
                 return mService.hasGrantedPolicy(admin, usesPolicy, myUserId());
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
         return false;
@@ -1034,7 +1033,7 @@
             try {
                 mService.setPasswordQuality(admin, quality);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
     }
@@ -1055,7 +1054,7 @@
             try {
                 return mService.getPasswordQuality(admin, userHandle);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
         return PASSWORD_QUALITY_UNSPECIFIED;
@@ -1087,7 +1086,7 @@
             try {
                 mService.setPasswordMinimumLength(admin, length);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
     }
@@ -1108,7 +1107,7 @@
             try {
                 return mService.getPasswordMinimumLength(admin, userHandle);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
         return 0;
@@ -1141,7 +1140,7 @@
             try {
                 mService.setPasswordMinimumUpperCase(admin, length);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
     }
@@ -1169,7 +1168,7 @@
             try {
                 return mService.getPasswordMinimumUpperCase(admin, userHandle);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
         return 0;
@@ -1202,7 +1201,7 @@
             try {
                 mService.setPasswordMinimumLowerCase(admin, length);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
     }
@@ -1230,7 +1229,7 @@
             try {
                 return mService.getPasswordMinimumLowerCase(admin, userHandle);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
         return 0;
@@ -1262,7 +1261,7 @@
             try {
                 mService.setPasswordMinimumLetters(admin, length);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
     }
@@ -1288,7 +1287,7 @@
             try {
                 return mService.getPasswordMinimumLetters(admin, userHandle);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
         return 0;
@@ -1320,7 +1319,7 @@
             try {
                 mService.setPasswordMinimumNumeric(admin, length);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
     }
@@ -1347,7 +1346,7 @@
             try {
                 return mService.getPasswordMinimumNumeric(admin, userHandle);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
         return 0;
@@ -1379,7 +1378,7 @@
             try {
                 mService.setPasswordMinimumSymbols(admin, length);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
     }
@@ -1405,7 +1404,7 @@
             try {
                 return mService.getPasswordMinimumSymbols(admin, userHandle);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
         return 0;
@@ -1437,7 +1436,7 @@
             try {
                 mService.setPasswordMinimumNonLetter(admin, length);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
     }
@@ -1464,7 +1463,7 @@
             try {
                 return mService.getPasswordMinimumNonLetter(admin, userHandle);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
         return 0;
@@ -1497,7 +1496,7 @@
             try {
                 mService.setPasswordHistoryLength(admin, length);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
     }
@@ -1529,7 +1528,7 @@
             try {
                 mService.setPasswordExpirationTimeout(admin, timeout);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
     }
@@ -1548,7 +1547,7 @@
             try {
                 return mService.getPasswordExpirationTimeout(admin, myUserId());
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
         return 0;
@@ -1569,7 +1568,7 @@
             try {
                 return mService.getPasswordExpiration(admin, myUserId());
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
         return 0;
@@ -1592,7 +1591,7 @@
             try {
                 return mService.getPasswordHistoryLength(admin, userHandle);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
         return 0;
@@ -1625,7 +1624,7 @@
             try {
                 return mService.isActivePasswordSufficient(myUserId());
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
         return false;
@@ -1644,7 +1643,7 @@
             try {
                 return mService.getCurrentFailedPasswordAttempts(myUserId());
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
         return -1;
@@ -1661,7 +1660,7 @@
             try {
                 return mService.getDoNotAskCredentialsOnBoot();
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed to call getDoNotAskCredentialsOnBoot()", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
         return false;
@@ -1691,7 +1690,7 @@
             try {
                 mService.setMaximumFailedPasswordsForWipe(admin, num);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
     }
@@ -1713,7 +1712,7 @@
             try {
                 return mService.getMaximumFailedPasswordsForWipe(admin, userHandle);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
         return 0;
@@ -1731,7 +1730,7 @@
             try {
                 return mService.getProfileWithMinimumFailedPasswordsForWipe(userHandle);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
         return UserHandle.USER_NULL;
@@ -1796,7 +1795,7 @@
             try {
                 return mService.resetPassword(password, flags);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
         return false;
@@ -1820,7 +1819,7 @@
             try {
                 mService.setMaximumTimeToLock(admin, timeMs);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
     }
@@ -1843,7 +1842,7 @@
             try {
                 return mService.getMaximumTimeToLock(admin, userHandle);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
         return 0;
@@ -1862,7 +1861,7 @@
             try {
                 mService.lockNow();
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
     }
@@ -1899,7 +1898,7 @@
             try {
                 mService.wipeData(flags);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
     }
@@ -1969,7 +1968,7 @@
                 }
                 return mService.setGlobalProxy(admin, hostSpec, exclSpec);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
         return null;
@@ -1997,7 +1996,7 @@
             try {
                 mService.setRecommendedGlobalProxy(admin, proxyInfo);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
     }
@@ -2013,7 +2012,7 @@
             try {
                 return mService.getGlobalProxyAdmin(myUserId());
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
         return null;
@@ -2143,7 +2142,7 @@
             try {
                 return mService.setStorageEncryption(admin, encrypt);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
         return ENCRYPTION_STATUS_UNSUPPORTED;
@@ -2163,7 +2162,7 @@
             try {
                 return mService.getStorageEncryption(admin, myUserId());
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
         return false;
@@ -2198,7 +2197,7 @@
             try {
                 return mService.getStorageEncryptionStatus(userHandle);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
         return ENCRYPTION_STATUS_UNSUPPORTED;
@@ -2219,7 +2218,7 @@
             try {
                 return mService.installCaCert(admin, certBuffer);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
         return false;
@@ -2240,7 +2239,7 @@
             } catch (CertificateException e) {
                 Log.w(TAG, "Unable to parse certificate", e);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
     }
@@ -2268,7 +2267,7 @@
                     }
                 }
             } catch (RemoteException re) {
-                Log.w(TAG, "Failed talking with device policy service", re);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
             }
         }
         return certs;
@@ -2287,7 +2286,7 @@
                 mService.uninstallCaCerts(admin, new TrustedCertificateStore().userAliases()
                         .toArray(new String[0]));
             } catch (RemoteException re) {
-                Log.w(TAG, "Failed talking with device policy service", re);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
             }
         }
     }
@@ -2305,7 +2304,7 @@
                 mService.enforceCanManageCaCerts(admin);
                 return getCaCertAlias(certBuffer) != null;
             } catch (RemoteException re) {
-                Log.w(TAG, "Failed talking with device policy service", re);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
             } catch (CertificateException ce) {
                 Log.w(TAG, "Could not parse certificate", ce);
             }
@@ -2333,7 +2332,7 @@
                     .getKeySpec(privKey, PKCS8EncodedKeySpec.class).getEncoded();
             return mService.installKeyPair(admin, pkcs8Key, pemCert, alias);
         } catch (RemoteException e) {
-            Log.w(TAG, "Failed talking with device policy service", e);
+            Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
         } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
             Log.w(TAG, "Failed to obtain private key material", e);
         } catch (CertificateException | IOException e) {
@@ -2391,7 +2390,7 @@
             try {
                 mService.setCertInstallerPackage(admin, installerPackage);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
     }
@@ -2409,7 +2408,7 @@
             try {
                 return mService.getCertInstallerPackage(admin);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
         return null;
@@ -2434,7 +2433,7 @@
             try {
                 mService.setCameraDisabled(admin, disabled);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
     }
@@ -2455,7 +2454,7 @@
             try {
                 return mService.getCameraDisabled(admin, userHandle);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
         return false;
@@ -2492,7 +2491,7 @@
             try {
                 mService.setScreenCaptureDisabled(admin, disabled);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
     }
@@ -2513,7 +2512,7 @@
             try {
                 return mService.getScreenCaptureDisabled(admin, userHandle);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
         return false;
@@ -2536,7 +2535,7 @@
             try {
                 mService.setAutoTimeRequired(admin, required);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
     }
@@ -2549,7 +2548,7 @@
             try {
                 return mService.getAutoTimeRequired();
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
         return false;
@@ -2590,7 +2589,7 @@
             try {
                 mService.setKeyguardDisabledFeatures(admin, which);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
     }
@@ -2613,7 +2612,7 @@
             try {
                 return mService.getKeyguardDisabledFeatures(admin, userHandle);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
         return KEYGUARD_DISABLE_FEATURES_NONE;
@@ -2628,7 +2627,7 @@
             try {
                 mService.setActiveAdmin(policyReceiver, refreshing, userHandle);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
     }
@@ -2659,10 +2658,7 @@
 
         try {
             return new DeviceAdminInfo(mContext, ri);
-        } catch (XmlPullParserException e) {
-            Log.w(TAG, "Unable to parse device policy " + cn, e);
-            return null;
-        } catch (IOException e) {
+        } catch (XmlPullParserException | IOException e) {
             Log.w(TAG, "Unable to parse device policy " + cn, e);
             return null;
         }
@@ -2676,7 +2672,7 @@
             try {
                 mService.getRemoveWarning(admin, result, myUserId());
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
     }
@@ -2691,7 +2687,7 @@
                 mService.setActivePasswordState(quality, length, letters, uppercase, lowercase,
                         numbers, symbols, nonletter, userHandle);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
     }
@@ -2704,7 +2700,7 @@
             try {
                 mService.reportFailedPasswordAttempt(userHandle);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
     }
@@ -2717,7 +2713,7 @@
             try {
                 mService.reportSuccessfulPasswordAttempt(userHandle);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
     }
@@ -2770,7 +2766,7 @@
             try {
                 return mService.setDeviceOwner(who, ownerName, userId);
             } catch (RemoteException re) {
-                Log.w(TAG, "Failed to set device owner");
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
             }
         }
         return false;
@@ -2852,7 +2848,7 @@
             try {
                 return mService.getDeviceOwnerComponent(callingUserOnly);
             } catch (RemoteException re) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
             }
         }
         return null;
@@ -2871,7 +2867,7 @@
             try {
                 return mService.getDeviceOwnerUserId();
             } catch (RemoteException re) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
             }
         }
         return UserHandle.USER_NULL;
@@ -2891,7 +2887,7 @@
             try {
                 mService.clearDeviceOwner(packageName);
             } catch (RemoteException re) {
-                Log.w(TAG, "Failed to clear device owner");
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
             }
         }
     }
@@ -2933,7 +2929,7 @@
             try {
                 return mService.getDeviceOwnerName();
             } catch (RemoteException re) {
-                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
             }
         }
         return null;
@@ -2986,7 +2982,6 @@
                 mService.setActiveAdmin(admin, false, myUserId);
                 return mService.setProfileOwner(admin, ownerName, myUserId);
             } catch (RemoteException re) {
-                Log.w(TAG, "Failed to set profile owner " + re);
                 throw new IllegalArgumentException("Couldn't set profile owner.", re);
             }
         }
@@ -3008,7 +3003,7 @@
             try {
                 mService.clearProfileOwner(admin);
             } catch (RemoteException re) {
-                Log.w(TAG, "Failed to clear profile owner " + admin + re);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
             }
         }
     }
@@ -3022,7 +3017,7 @@
             try {
                 return mService.hasUserSetupCompleted();
             } catch (RemoteException re) {
-                Log.w(TAG, "Failed to check whether user setup has completed");
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
             }
         }
         return true;
@@ -3053,7 +3048,7 @@
                 }
                 return mService.setProfileOwner(admin, ownerName, userHandle);
             } catch (RemoteException re) {
-                Log.w(TAG, "Failed to set profile owner", re);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
                 throw new IllegalArgumentException("Couldn't set profile owner.", re);
             }
         }
@@ -3076,7 +3071,7 @@
             try {
                 return mService.setDeviceOwnerLockScreenInfo(admin, info);
             } catch (RemoteException re) {
-                Log.w(TAG, "Failed talking with device policy service", re);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
             }
         }
         return false;
@@ -3090,7 +3085,7 @@
             try {
                 return mService.getDeviceOwnerLockScreenInfo();
             } catch (RemoteException re) {
-                Log.w(TAG, "Failed talking with device policy service", re);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
             }
         }
         return null;
@@ -3109,7 +3104,7 @@
             try {
                 mService.setProfileEnabled(admin);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
     }
@@ -3130,7 +3125,7 @@
             try {
                 mService.setProfileName(admin, profileName);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
     }
@@ -3151,7 +3146,7 @@
                 return profileOwner != null
                         && profileOwner.getPackageName().equals(packageName);
             } catch (RemoteException re) {
-                Log.w(TAG, "Failed to check profile owner");
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
             }
         }
         return false;
@@ -3177,7 +3172,7 @@
             try {
                 return mService.getProfileOwner(userId);
             } catch (RemoteException re) {
-                Log.w(TAG, "Failed to get profile owner");
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
                 throw new IllegalArgumentException(
                         "Requested profile owner for invalid userId", re);
             }
@@ -3196,7 +3191,7 @@
             try {
                 return mService.getProfileOwnerName(Process.myUserHandle().getIdentifier());
             } catch (RemoteException re) {
-                Log.w(TAG, "Failed to get profile owner");
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
                 throw new IllegalArgumentException(
                         "Requested profile owner for invalid userId", re);
             }
@@ -3217,7 +3212,7 @@
             try {
                 return mService.getProfileOwnerName(userId);
             } catch (RemoteException re) {
-                Log.w(TAG, "Failed to get profile owner");
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
                 throw new IllegalArgumentException(
                         "Requested profile owner for invalid userId", re);
             }
@@ -3248,7 +3243,7 @@
             try {
                 mService.addPersistentPreferredActivity(admin, filter, activity);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
     }
@@ -3269,7 +3264,7 @@
             try {
                 mService.clearPackagePersistentPreferredActivities(admin, packageName);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
     }
@@ -3309,7 +3304,7 @@
             try {
                 mService.setApplicationRestrictions(admin, packageName, settings);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
     }
@@ -3339,7 +3334,7 @@
             try {
                 mService.setTrustAgentConfiguration(admin, target, configuration);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
     }
@@ -3370,7 +3365,7 @@
             try {
                 return mService.getTrustAgentConfiguration(admin, agent, userHandle);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
         return new ArrayList<PersistableBundle>(); // empty list
@@ -3391,7 +3386,7 @@
             try {
                 mService.setCrossProfileCallerIdDisabled(admin, disabled);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
     }
@@ -3410,7 +3405,7 @@
             try {
                 return mService.getCrossProfileCallerIdDisabled(admin);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
         return false;
@@ -3427,7 +3422,7 @@
             try {
                 return mService.getCrossProfileCallerIdDisabledForUser(userHandle.getIdentifier());
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
         return false;
@@ -3444,7 +3439,7 @@
                 mService.startManagedQuickContact(
                         actualLookupKey, actualContactId, directoryId, originalIntent);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
     }
@@ -3478,7 +3473,7 @@
             try {
                 mService.setBluetoothContactSharingDisabled(admin, disabled);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
     }
@@ -3500,7 +3495,7 @@
             try {
                 return mService.getBluetoothContactSharingDisabled(admin);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
         return true;
@@ -3520,7 +3515,7 @@
                 return mService.getBluetoothContactSharingDisabledForUser(userHandle
                         .getIdentifier());
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
         return true;
@@ -3542,7 +3537,7 @@
             try {
                 mService.addCrossProfileIntentFilter(admin, filter, flags);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
     }
@@ -3558,7 +3553,7 @@
             try {
                 mService.clearCrossProfileIntentFilters(admin);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
     }
@@ -3590,7 +3585,7 @@
             try {
                 return mService.setPermittedAccessibilityServices(admin, packageNames);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
         return false;
@@ -3610,7 +3605,7 @@
             try {
                 return mService.getPermittedAccessibilityServices(admin);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
         return null;
@@ -3634,7 +3629,7 @@
             try {
                 return mService.getPermittedAccessibilityServicesForUser(userId);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
         return null;
@@ -3668,7 +3663,7 @@
             try {
                 return mService.setPermittedInputMethods(admin, packageNames);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
         return false;
@@ -3689,7 +3684,7 @@
             try {
                 return mService.getPermittedInputMethods(admin);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
         return null;
@@ -3712,7 +3707,7 @@
             try {
                 return mService.getPermittedInputMethodsForCurrentUser();
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
         return null;
@@ -3732,7 +3727,7 @@
             try {
                 return mService.getKeepUninstalledPackages(admin);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
         return null;
@@ -3755,7 +3750,7 @@
             try {
                 mService.setKeepUninstalledPackages(admin, packageNames);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
     }
@@ -3779,7 +3774,7 @@
         try {
             return mService.createUser(admin, name);
         } catch (RemoteException re) {
-            Log.w(TAG, "Could not create a user", re);
+            Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
         }
         return null;
     }
@@ -3818,7 +3813,7 @@
             return mService.createAndInitializeUser(admin, name, ownerName, profileOwnerComponent,
                     adminExtras);
         } catch (RemoteException re) {
-            Log.w(TAG, "Could not create a user", re);
+            Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
         }
         return null;
     }
@@ -3835,7 +3830,7 @@
         try {
             return mService.removeUser(admin, userHandle);
         } catch (RemoteException re) {
-            Log.w(TAG, "Could not remove user ", re);
+            Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
             return false;
         }
     }
@@ -3853,7 +3848,7 @@
         try {
             return mService.switchUser(admin, userHandle);
         } catch (RemoteException re) {
-            Log.w(TAG, "Could not switch user ", re);
+            Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
             return false;
         }
     }
@@ -3876,7 +3871,7 @@
             try {
                 return mService.getApplicationRestrictions(admin, packageName);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
         return null;
@@ -3898,7 +3893,7 @@
             try {
                 mService.setUserRestriction(admin, key, true);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
     }
@@ -3919,7 +3914,7 @@
             try {
                 mService.setUserRestriction(admin, key, false);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
     }
@@ -3946,7 +3941,7 @@
             try {
                 ret = mService.getUserRestrictions(admin, userHandle);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
         return ret == null ? new Bundle() : ret;
@@ -3968,7 +3963,7 @@
             try {
                 return mService.setApplicationHidden(admin, packageName, hidden);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
         return false;
@@ -3986,7 +3981,7 @@
             try {
                 return mService.isApplicationHidden(admin, packageName);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
         return false;
@@ -4004,7 +3999,7 @@
             try {
                 mService.enableSystemApp(admin, packageName);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed to install package: " + packageName);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
     }
@@ -4023,7 +4018,7 @@
             try {
                 return mService.enableSystemAppWithIntent(admin, intent);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed to install packages matching filter: " + intent);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
         return 0;
@@ -4050,7 +4045,7 @@
             try {
                 mService.setAccountManagementDisabled(admin, accountType, disabled);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
     }
@@ -4078,7 +4073,7 @@
             try {
                 return mService.getAccountTypesWithManagementDisabledAsUser(userId);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
 
@@ -4109,7 +4104,7 @@
             try {
                 mService.setLockTaskPackages(admin, packages);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
     }
@@ -4125,7 +4120,7 @@
             try {
                 return mService.getLockTaskPackages(admin);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
         return null;
@@ -4141,7 +4136,7 @@
             try {
                 return mService.isLockTaskPermitted(pkg);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
         return false;
@@ -4188,7 +4183,7 @@
             try {
                 mService.setGlobalSetting(admin, setting, value);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
     }
@@ -4216,7 +4211,7 @@
             try {
                 mService.setSecureSetting(admin, setting, value);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed talking with device policy service", e);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
             }
         }
     }
@@ -4237,7 +4232,7 @@
             try {
                 mService.setRestrictionsProvider(admin, provider);
             } catch (RemoteException re) {
-                Log.w(TAG, "Failed to set permission provider on device policy service");
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
             }
         }
     }
@@ -4253,7 +4248,7 @@
             try {
                 mService.setMasterVolumeMuted(admin, on);
             } catch (RemoteException re) {
-                Log.w(TAG, "Failed to setMasterMute on device policy service");
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
             }
         }
     }
@@ -4269,7 +4264,7 @@
             try {
                 return mService.isMasterVolumeMuted(admin);
             } catch (RemoteException re) {
-                Log.w(TAG, "Failed to get isMasterMute on device policy service");
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
             }
         }
         return false;
@@ -4289,7 +4284,7 @@
             try {
                 mService.setUninstallBlocked(admin, packageName, uninstallBlocked);
             } catch (RemoteException re) {
-                Log.w(TAG, "Failed to call block uninstall on device policy service");
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
             }
         }
     }
@@ -4313,7 +4308,7 @@
             try {
                 return mService.isUninstallBlocked(admin, packageName);
             } catch (RemoteException re) {
-                Log.w(TAG, "Failed to call block uninstall on device policy service");
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
             }
         }
         return false;
@@ -4341,7 +4336,7 @@
             try {
                 return mService.addCrossProfileWidgetProvider(admin, packageName);
             } catch (RemoteException re) {
-                Log.w(TAG, "Error calling addCrossProfileWidgetProvider", re);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
             }
         }
         return false;
@@ -4368,7 +4363,7 @@
             try {
                 return mService.removeCrossProfileWidgetProvider(admin, packageName);
             } catch (RemoteException re) {
-                Log.w(TAG, "Error calling removeCrossProfileWidgetProvider", re);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
             }
         }
         return false;
@@ -4392,7 +4387,7 @@
                     return providers;
                 }
             } catch (RemoteException re) {
-                Log.w(TAG, "Error calling getCrossProfileWidgetProviders", re);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
             }
         }
         return Collections.emptyList();
@@ -4408,7 +4403,7 @@
         try {
             mService.setUserIcon(admin, icon);
         } catch (RemoteException re) {
-            Log.w(TAG, "Could not set the user icon ", re);
+            Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
         }
     }
 
@@ -4428,7 +4423,7 @@
             try {
                 mService.setSystemUpdatePolicy(admin, policy);
             } catch (RemoteException re) {
-                Log.w(TAG, "Error calling setSystemUpdatePolicy", re);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
             }
         }
     }
@@ -4443,7 +4438,7 @@
             try {
                 return mService.getSystemUpdatePolicy();
             } catch (RemoteException re) {
-                Log.w(TAG, "Error calling getSystemUpdatePolicy", re);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
             }
         }
         return null;
@@ -4467,7 +4462,7 @@
         try {
             return mService.setKeyguardDisabled(admin, disabled);
         } catch (RemoteException re) {
-            Log.w(TAG, "Failed talking with device policy service", re);
+            Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
             return false;
         }
     }
@@ -4487,7 +4482,7 @@
         try {
             return mService.setStatusBarDisabled(admin, disabled);
         } catch (RemoteException re) {
-            Log.w(TAG, "Failed talking with device policy service", re);
+            Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
             return false;
         }
     }
@@ -4507,7 +4502,7 @@
             try {
                 mService.notifyPendingSystemUpdate(updateReceivedTime);
             } catch (RemoteException re) {
-                Log.w(TAG, "Could not notify device owner about pending system update", re);
+                Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
             }
         }
     }
@@ -4533,7 +4528,7 @@
         try {
             mService.setPermissionPolicy(admin, policy);
         } catch (RemoteException re) {
-            Log.w(TAG, "Failed talking with device policy service", re);
+            Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
         }
     }
 
@@ -4584,7 +4579,7 @@
         try {
             return mService.setPermissionGrantState(admin, packageName, permission, grantState);
         } catch (RemoteException re) {
-            Log.w(TAG, "Failed talking with device policy service", re);
+            Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
             return false;
         }
     }
@@ -4611,7 +4606,7 @@
         try {
             return mService.getPermissionGrantState(admin, packageName, permission);
         } catch (RemoteException re) {
-            Log.w(TAG, "Failed talking with device policy service", re);
+            Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
             return PERMISSION_GRANT_STATE_DEFAULT;
         }
     }
@@ -4630,7 +4625,7 @@
         try {
             return mService.isProvisioningAllowed(action);
         } catch (RemoteException re) {
-            Log.w(TAG, "Failed talking with device policy service", re);
+            Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
             return false;
         }
     }
@@ -4647,7 +4642,7 @@
         try {
             return mService.isManagedProfile(admin);
         } catch (RemoteException re) {
-            Log.w(TAG, "Failed talking with device policy service", re);
+            Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
             return false;
         }
     }
@@ -4663,7 +4658,7 @@
         try {
             return mService.isSystemOnlyUser(admin);
         } catch (RemoteException re) {
-            Log.w(TAG, "Failed talking with device policy service", re);
+            Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
             return false;
         }
     }
@@ -4680,7 +4675,7 @@
         try {
             return mService.getWifiMacAddress();
         } catch (RemoteException re) {
-            Log.w(TAG, "Failed talking with device policy service", re);
+            Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
             return null;
         }
     }
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 54bfca3..eca2c3b 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -144,6 +144,12 @@
     public static final int SHARED_RELRO_UID = 1037;
 
     /**
+     * Defines the UID/GID for the audioserver process.
+     * @hide
+     */
+    public static final int AUDIOSERVER_UID = 1041;
+
+    /**
      * Defines the start of a range of UIDs (and GIDs), going from this
      * number to {@link #LAST_APPLICATION_UID} that are reserved for assigning
      * to applications.
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 00a874b..1f16c4a 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -781,6 +781,7 @@
      * pattern or PIN), and credential-encrypted private app data storage is
      * available.
      */
+    @Deprecated
     public boolean isUserRunningAndLocked() {
         return isUserRunningAndLocked(Process.myUserHandle());
     }
@@ -793,6 +794,7 @@
      *
      * @param user to retrieve the unlocked state for.
      */
+    @Deprecated
     public boolean isUserRunningAndLocked(UserHandle user) {
         try {
             return ActivityManagerNative.getDefault().isUserRunning(
@@ -808,6 +810,7 @@
      * pattern or PIN), and credential-encrypted private app data storage is
      * available.
      */
+    @Deprecated
     public boolean isUserRunningAndUnlocked() {
         return isUserRunningAndUnlocked(Process.myUserHandle());
     }
@@ -820,6 +823,7 @@
      *
      * @param user to retrieve the unlocked state for.
      */
+    @Deprecated
     public boolean isUserRunningAndUnlocked(UserHandle user) {
         try {
             return ActivityManagerNative.getDefault().isUserRunning(
@@ -830,6 +834,33 @@
     }
 
     /**
+     * Return whether the calling user is running in an "unlocked" state. A user
+     * is unlocked only after they've entered their credentials (such as a lock
+     * pattern or PIN), and credential-encrypted private app data storage is
+     * available.
+     */
+    public boolean isUserUnlocked() {
+        return isUserUnlocked(Process.myUserHandle());
+    }
+
+    /**
+     * Return whether the given user is running in an "unlocked" state. A user
+     * is unlocked only after they've entered their credentials (such as a lock
+     * pattern or PIN), and credential-encrypted private app data storage is
+     * available.
+     *
+     * @param user to retrieve the unlocked state for.
+     */
+    public boolean isUserUnlocked(UserHandle user) {
+        try {
+            return ActivityManagerNative.getDefault().isUserRunning(
+                    user.getIdentifier(), ActivityManager.FLAG_AND_UNLOCKED);
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+
+    /**
      * Returns the UserInfo object describing a specific user.
      * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
      * @param userHandle the user handle of the user whose information is being requested.
diff --git a/core/java/android/security/net/config/ApplicationConfig.java b/core/java/android/security/net/config/ApplicationConfig.java
index b627641..71d9d5d 100644
--- a/core/java/android/security/net/config/ApplicationConfig.java
+++ b/core/java/android/security/net/config/ApplicationConfig.java
@@ -68,7 +68,7 @@
      */
     public NetworkSecurityConfig getConfigForHostname(String hostname) {
         ensureInitialized();
-        if (hostname.isEmpty() || mConfigs == null) {
+        if (hostname == null || hostname.isEmpty() || mConfigs == null) {
             return mDefaultConfig;
         }
         if (hostname.charAt(0) ==  '.') {
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index 2f10cda..76c63b9 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -863,6 +863,8 @@
         private boolean mMatchesInterruptionFilter;
         private int mVisibilityOverride;
         private int mSuppressedVisualEffects;
+        private int mImportance;
+        private CharSequence mImportanceExplanation;
 
         public Ranking() {}
 
@@ -928,7 +930,7 @@
          * @return the rank of the notification
          */
         public int getImportance() {
-            return IMPORTANCE_DEFAULT;  // TODO implement;
+            return mImportance;
         }
 
         /**
@@ -939,18 +941,21 @@
          * @return the explanation for the importance, or null if it is the natural importance
          */
         public CharSequence getImportanceExplanation() {
-            return null;  // TODO implement
+            return mImportanceExplanation;
         }
 
         private void populate(String key, int rank, boolean isAmbient,
                 boolean matchesInterruptionFilter, int visibilityOverride,
-                int suppressedVisualEffects) {
+                int suppressedVisualEffects, int importance,
+                CharSequence explanation) {
             mKey = key;
             mRank = rank;
             mIsAmbient = isAmbient;
             mMatchesInterruptionFilter = matchesInterruptionFilter;
             mVisibilityOverride = visibilityOverride;
             mSuppressedVisualEffects = suppressedVisualEffects;
+            mImportance = importance;
+            mImportanceExplanation = explanation;
         }
 
         /**
@@ -990,6 +995,8 @@
         private ArraySet<Object> mIntercepted;
         private ArrayMap<String, Integer> mVisibilityOverrides;
         private ArrayMap<String, Integer> mSuppressedVisualEffects;
+        private ArrayMap<String, Integer> mImportance;
+        private ArrayMap<String, String> mImportanceExplanation;
 
         private RankingMap(NotificationRankingUpdate rankingUpdate) {
             mRankingUpdate = rankingUpdate;
@@ -1015,7 +1022,8 @@
         public boolean getRanking(String key, Ranking outRanking) {
             int rank = getRank(key);
             outRanking.populate(key, rank, isAmbient(key), !isIntercepted(key),
-                    getVisibilityOverride(key), getSuppressedVisualEffects(key));
+                    getVisibilityOverride(key), getSuppressedVisualEffects(key),
+                    getImportance(key), getImportanceExplanation(key));
             return rank >= 0;
         }
 
@@ -1073,6 +1081,28 @@
             return suppressed.intValue();
         }
 
+        private int getImportance(String key) {
+            synchronized (this) {
+                if (mImportance == null) {
+                    buildImportanceLocked();
+                }
+            }
+            Integer importance = mImportance.get(key);
+            if (importance == null) {
+                return Ranking.IMPORTANCE_DEFAULT;
+            }
+            return importance.intValue();
+        }
+
+        private String getImportanceExplanation(String key) {
+            synchronized (this) {
+                if (mImportanceExplanation == null) {
+                    buildImportanceExplanationLocked();
+                }
+            }
+            return mImportanceExplanation.get(key);
+        }
+
         // Locked by 'this'
         private void buildRanksLocked() {
             String[] orderedKeys = mRankingUpdate.getOrderedKeys();
@@ -1107,6 +1137,25 @@
                 mSuppressedVisualEffects.put(key, suppressedBundle.getInt(key));
             }
         }
+        // Locked by 'this'
+        private void buildImportanceLocked() {
+            String[] orderedKeys = mRankingUpdate.getOrderedKeys();
+            int[] importance = mRankingUpdate.getImportance();
+            mImportance = new ArrayMap<>(orderedKeys.length);
+            for (int i = 0; i < orderedKeys.length; i++) {
+                String key = orderedKeys[i];
+                mImportance.put(key, importance[i]);
+            }
+        }
+
+        // Locked by 'this'
+        private void buildImportanceExplanationLocked() {
+            Bundle explanationBundle = mRankingUpdate.getImportanceExplanation();
+            mImportanceExplanation = new ArrayMap<>(explanationBundle.size());
+            for (String key: explanationBundle.keySet()) {
+                mImportanceExplanation.put(key, explanationBundle.getString(key));
+            }
+        }
 
         // ----------- Parcelable
 
diff --git a/core/java/android/service/notification/NotificationRankingUpdate.java b/core/java/android/service/notification/NotificationRankingUpdate.java
index 1282fb1..0d42ffb 100644
--- a/core/java/android/service/notification/NotificationRankingUpdate.java
+++ b/core/java/android/service/notification/NotificationRankingUpdate.java
@@ -29,14 +29,19 @@
     private final int mFirstAmbientIndex;
     private final Bundle mVisibilityOverrides;
     private final Bundle mSuppressedVisualEffects;
+    private final int[] mImportance;
+    private final Bundle mImportanceExplanation;
 
     public NotificationRankingUpdate(String[] keys, String[] interceptedKeys,
-            Bundle visibilityOverrides, int firstAmbientIndex, Bundle suppressedVisualEffects) {
+            Bundle visibilityOverrides, int firstAmbientIndex, Bundle suppressedVisualEffects,
+            int[] importance, Bundle explanation) {
         mKeys = keys;
         mFirstAmbientIndex = firstAmbientIndex;
         mInterceptedKeys = interceptedKeys;
         mVisibilityOverrides = visibilityOverrides;
         mSuppressedVisualEffects = suppressedVisualEffects;
+        mImportance = importance;
+        mImportanceExplanation = explanation;
     }
 
     public NotificationRankingUpdate(Parcel in) {
@@ -45,6 +50,9 @@
         mInterceptedKeys = in.readStringArray();
         mVisibilityOverrides = in.readBundle();
         mSuppressedVisualEffects = in.readBundle();
+        mImportance = new int[mKeys.length];
+        in.readIntArray(mImportance);
+        mImportanceExplanation = in.readBundle();
     }
 
     @Override
@@ -59,6 +67,8 @@
         out.writeStringArray(mInterceptedKeys);
         out.writeBundle(mVisibilityOverrides);
         out.writeBundle(mSuppressedVisualEffects);
+        out.writeIntArray(mImportance);
+        out.writeBundle(mImportanceExplanation);
     }
 
     public static final Parcelable.Creator<NotificationRankingUpdate> CREATOR
@@ -91,4 +101,12 @@
     public Bundle getSuppressedVisualEffects() {
         return mSuppressedVisualEffects;
     }
+
+    public int[] getImportance() {
+        return mImportance;
+    }
+
+    public Bundle getImportanceExplanation() {
+        return mImportanceExplanation;
+    }
 }
diff --git a/core/java/android/service/notification/StatusBarNotification.java b/core/java/android/service/notification/StatusBarNotification.java
index 2cab914..198e43d 100644
--- a/core/java/android/service/notification/StatusBarNotification.java
+++ b/core/java/android/service/notification/StatusBarNotification.java
@@ -42,7 +42,6 @@
     private final UserHandle user;
     private final long postTime;
 
-    private final int score;
     private Context mContext; // used for inflation & icon expansion
 
     /** @hide */
@@ -64,7 +63,6 @@
         this.tag = tag;
         this.uid = uid;
         this.initialPid = initialPid;
-        this.score = score;
         this.notification = notification;
         this.user = user;
         this.postTime = postTime;
@@ -83,7 +81,6 @@
         }
         this.uid = in.readInt();
         this.initialPid = in.readInt();
-        this.score = in.readInt();
         this.notification = new Notification(in);
         this.user = UserHandle.readFromParcel(in);
         this.postTime = in.readLong();
@@ -120,7 +117,6 @@
         }
         out.writeInt(this.uid);
         out.writeInt(this.initialPid);
-        out.writeInt(this.score);
         this.notification.writeToParcel(out, flags);
         user.writeToParcel(out, flags);
 
@@ -153,14 +149,14 @@
         this.notification.cloneInto(no, false); // light copy
         return new StatusBarNotification(this.pkg, this.opPkg,
                 this.id, this.tag, this.uid, this.initialPid,
-                this.score, no, this.user, this.postTime);
+                0, no, this.user, this.postTime);
     }
 
     @Override
     public StatusBarNotification clone() {
         return new StatusBarNotification(this.pkg, this.opPkg,
                 this.id, this.tag, this.uid, this.initialPid,
-                this.score, this.notification.clone(), this.user, this.postTime);
+                0, this.notification.clone(), this.user, this.postTime);
     }
 
     @Override
@@ -168,7 +164,7 @@
         return String.format(
                 "StatusBarNotification(pkg=%s user=%s id=%d tag=%s score=%d key=%s: %s)",
                 this.pkg, this.user, this.id, this.tag,
-                this.score, this.key, this.notification);
+                0, this.key, this.notification);
     }
 
     /** Convenience method to check the notification's flags for
@@ -247,11 +243,6 @@
         return postTime;
     }
 
-    /** @hide */
-    public int getScore() {
-        return score;
-    }
-
     /**
      * A unique instance key for this notification record.
      */
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index f1e7afb..bdbd096 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -250,7 +250,8 @@
     libminikin \
     libprocessgroup \
     libnativebridge \
-    libradio_metadata
+    libradio_metadata \
+    libnativeloader
 
 LOCAL_SHARED_LIBRARIES += \
     libhwui \
diff --git a/core/jni/android_app_NativeActivity.cpp b/core/jni/android_app_NativeActivity.cpp
index 95be3f2..6ecb3fb 100644
--- a/core/jni/android_app_NativeActivity.cpp
+++ b/core/jni/android_app_NativeActivity.cpp
@@ -21,6 +21,8 @@
 #include <dlfcn.h>
 #include <fcntl.h>
 
+#include <memory>
+
 #include <android_runtime/android_app_NativeActivity.h>
 #include <android_runtime/android_util_AssetManager.h>
 #include <android_runtime/android_view_Surface.h>
@@ -39,6 +41,7 @@
 #include "android_view_KeyEvent.h"
 
 #include "nativebridge/native_bridge.h"
+#include "nativeloader/native_loader.h"
 
 #include "core_jni_helpers.h"
 
@@ -255,18 +258,19 @@
 static jlong
 loadNativeCode_native(JNIEnv* env, jobject clazz, jstring path, jstring funcName,
         jobject messageQueue, jstring internalDataDir, jstring obbDir,
-        jstring externalDataDir, jint sdkVersion,
-        jobject jAssetMgr, jbyteArray savedState)
-{
+        jstring externalDataDir, jint sdkVersion, jobject jAssetMgr,
+        jbyteArray savedState, jobject classLoader, jstring libraryPath,
+        jstring isolationPath) {
     if (kLogTrace) {
         ALOGD("loadNativeCode_native");
     }
 
     const char* pathStr = env->GetStringUTFChars(path, NULL);
-    NativeCode* code = NULL;
+    std::unique_ptr<NativeCode> code;
     bool needNativeBridge = false;
 
-    void* handle = dlopen(pathStr, RTLD_LAZY);
+    void* handle = OpenNativeLibrary(env, sdkVersion, pathStr, classLoader,
+                                     libraryPath, isolationPath);
     if (handle == NULL) {
         if (NativeBridgeIsSupported(pathStr)) {
             handle = NativeBridgeLoadLibrary(pathStr, RTLD_LAZY);
@@ -284,26 +288,23 @@
             funcPtr = dlsym(handle, funcStr);
         }
 
-        code = new NativeCode(handle, (ANativeActivity_createFunc*)funcPtr);
+        code.reset(new NativeCode(handle, (ANativeActivity_createFunc*)funcPtr));
         env->ReleaseStringUTFChars(funcName, funcStr);
 
         if (code->createActivityFunc == NULL) {
             ALOGW("ANativeActivity_onCreate not found");
-            delete code;
             return 0;
         }
         
         code->messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueue);
         if (code->messageQueue == NULL) {
             ALOGW("Unable to retrieve native MessageQueue");
-            delete code;
             return 0;
         }
         
         int msgpipe[2];
         if (pipe(msgpipe)) {
             ALOGW("could not create pipe: %s", strerror(errno));
-            delete code;
             return 0;
         }
         code->mainWorkRead = msgpipe[0];
@@ -315,12 +316,11 @@
         SLOGW_IF(result != 0, "Could not make main work write pipe "
                 "non-blocking: %s", strerror(errno));
         code->messageQueue->getLooper()->addFd(
-                code->mainWorkRead, 0, ALOOPER_EVENT_INPUT, mainWorkCallback, code);
+                code->mainWorkRead, 0, ALOOPER_EVENT_INPUT, mainWorkCallback, code.get());
         
         code->ANativeActivity::callbacks = &code->callbacks;
         if (env->GetJavaVM(&code->vm) < 0) {
             ALOGW("NativeActivity GetJavaVM failed");
-            delete code;
             return 0;
         }
         code->env = env;
@@ -356,14 +356,18 @@
             rawSavedSize = env->GetArrayLength(savedState);
         }
 
-        code->createActivityFunc(code, rawSavedState, rawSavedSize);
+        code->createActivityFunc(code.get(), rawSavedState, rawSavedSize);
 
         if (rawSavedState != NULL) {
             env->ReleaseByteArrayElements(savedState, rawSavedState, 0);
         }
     }
     
-    return (jlong)code;
+    return (jlong)code.release();
+}
+
+static jstring getDlError_native(JNIEnv* env, jobject clazz) {
+  return env->NewStringUTF(dlerror());
 }
 
 static void
@@ -651,8 +655,10 @@
 }
 
 static const JNINativeMethod g_methods[] = {
-    { "loadNativeCode", "(Ljava/lang/String;Ljava/lang/String;Landroid/os/MessageQueue;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILandroid/content/res/AssetManager;[B)J",
-            (void*)loadNativeCode_native },
+    { "loadNativeCode",
+        "(Ljava/lang/String;Ljava/lang/String;Landroid/os/MessageQueue;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILandroid/content/res/AssetManager;[BLjava/lang/ClassLoader;Ljava/lang/String;Ljava/lang/String;)J",
+        (void*)loadNativeCode_native },
+    { "getDlError", "()Ljava/lang/String;", (void*) getDlError_native },
     { "unloadNativeCode", "(J)V", (void*)unloadNativeCode_native },
     { "onStartNative", "(J)V", (void*)onStart_native },
     { "onResumeNative", "(J)V", (void*)onResume_native },
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index b6a29d3..4d967ff 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4105,4 +4105,7 @@
     </plurals>
 
     <string name="default_notification_topic_label">Miscellaneous</string>
+
+    <string name="importance_from_topic">You set the importance of these notifications.</string>
+    <string name="importance_from_person">This is important because of the people involved.</string>
 </resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 0573ae6..6367d37 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2380,4 +2380,6 @@
   <java-symbol type="dimen" name="notification_content_margin_end" />
   <java-symbol type="dimen" name="notification_content_picture_margin" />
   <java-symbol type="dimen" name="notification_content_margin_top" />
+  <java-symbol type="string" name="importance_from_topic" />
+  <java-symbol type="string" name="importance_from_person" />
 </resources>
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index 51019cc..b4f88c33 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -106,6 +106,7 @@
     </permission>
 
     <permission name="android.permission.ACCESS_FM_RADIO" >
+        <!-- /dev/fm is gid media, not audio -->
         <group gid="media" />
     </permission>
 
@@ -128,6 +129,12 @@
     <assign-permission name="android.permission.UPDATE_APP_OPS_STATS" uid="media" />
     <assign-permission name="android.permission.GET_PROCESS_STATE_AND_OOM_SCORE" uid="media" />
 
+    <assign-permission name="android.permission.MODIFY_AUDIO_SETTINGS" uid="audioserver" />
+    <assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="audioserver" />
+    <assign-permission name="android.permission.WAKE_LOCK" uid="audioserver" />
+    <assign-permission name="android.permission.UPDATE_DEVICE_STATS" uid="audioserver" />
+    <assign-permission name="android.permission.UPDATE_APP_OPS_STATS" uid="audioserver" />
+
     <assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="graphics" />
 
     <!-- This is a list of all the libraries available for application
diff --git a/data/fonts/Android.mk b/data/fonts/Android.mk
index 3181017..d2bd106 100644
--- a/data/fonts/Android.mk
+++ b/data/fonts/Android.mk
@@ -17,11 +17,6 @@
 
 LOCAL_PATH := $(call my-dir)
 
-# Use full Noto Sans Japanese font on non-smaller footprints
-ifneq ($(SMALLER_FONT_FOOTPRINT),true)
-FONT_NOTOSANS_JP_FULL := true
-endif
-
 ##########################################
 # create symlink for given font
 # $(1): new font $(2): link target
@@ -52,24 +47,6 @@
     DroidSans-Bold.ttf
 
 ################################
-# Do not include Motoya on space-constrained devices
-ifneq ($(SMALLER_FONT_FOOTPRINT),true)
-# Do not include Motoya if we are including Noto Sans Japanese
-ifneq ($(FONT_NOTOSANS_JP_FULL),true)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := MTLmr3m.ttf
-LOCAL_SRC_FILES := $(LOCAL_MODULE)
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_PATH := $(TARGET_OUT)/fonts
-include $(BUILD_PREBUILT)
-extra_font_files += MTLmr3m.ttf
-
-endif  # !FONT_NOTOSANS_JP_FULL
-endif  # !SMALLER_FONT_FOOTPRINT
-
-################################
 # Use DroidSansMono to hang extra_font_files on
 include $(CLEAR_VARS)
 LOCAL_MODULE := DroidSansMono.ttf
diff --git a/data/fonts/fonts.xml b/data/fonts/fonts.xml
index 0e66374..679a6a5 100644
--- a/data/fonts/fonts.xml
+++ b/data/fonts/fonts.xml
@@ -330,16 +330,16 @@
         <font weight="400" style="normal">NotoSansSymbols-Regular-Subsetted.ttf</font>
     </family>
     <family lang="zh-Hans">
-        <font weight="400" style="normal">NotoSansSC-Regular.otf</font>
+        <font weight="400" style="normal" ttcIndex="2">NotoSansCJK-Regular.ttc</font>
     </family>
     <family lang="zh-Hant">
-        <font weight="400" style="normal">NotoSansTC-Regular.otf</font>
+        <font weight="400" style="normal" ttcIndex="3">NotoSansCJK-Regular.ttc</font>
     </family>
     <family lang="ja">
-        <font weight="400" style="normal">NotoSansJP-Regular.otf</font>
+        <font weight="400" style="normal" ttcIndex="0">NotoSansCJK-Regular.ttc</font>
     </family>
     <family lang="ko">
-        <font weight="400" style="normal">NotoSansKR-Regular.otf</font>
+        <font weight="400" style="normal" ttcIndex="1">NotoSansCJK-Regular.ttc</font>
     </family>
     <family>
         <font weight="400" style="normal">NanumGothic.ttf</font>
@@ -350,9 +350,6 @@
     <family>
         <font weight="400" style="normal">DroidSansFallback.ttf</font>
     </family>
-    <family lang="ja">
-        <font weight="400" style="normal">MTLmr3m.ttf</font>
-    </family>
     <!--
         Tai Le and Mongolian are intentionally kept last, to make sure they don't override
         the East Asian punctuation for Chinese.
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index 4101935..e6bc8f1 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -1735,7 +1735,8 @@
             CodecProfileLevel[] profileLevels = mParent.profileLevels;
             String mime = mParent.getMimeType();
 
-            if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_AVC)) {
+            if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_AVC) ||
+                    mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_DOLBY_AVC)) {
                 maxBlocks = 99;
                 maxBlocksPerSecond = 1485;
                 maxBps = 64000;
@@ -2089,7 +2090,8 @@
                 applyMacroBlockLimits(Short.MAX_VALUE, Short.MAX_VALUE,
                         maxBlocks, maxBlocksPerSecond, blockSize, blockSize,
                         1 /* widthAlignment */, 1 /* heightAlignment */);
-            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_HEVC)) {
+            } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_HEVC) ||
+                    mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_DOLBY_HEVC)) {
                 maxBlocks = 36864;
                 maxBlocksPerSecond = maxBlocks * 15;
                 maxBps = 128000;
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index b2fa0ac..a102e51 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -92,6 +92,8 @@
     public static final String MIMETYPE_VIDEO_H263 = "video/3gpp";
     public static final String MIMETYPE_VIDEO_MPEG2 = "video/mpeg2";
     public static final String MIMETYPE_VIDEO_RAW = "video/raw";
+    public static final String MIMETYPE_VIDEO_DOLBY_AVC = "video/dolby-avc";
+    public static final String MIMETYPE_VIDEO_DOLBY_HEVC = "video/dolby-hevc";
 
     public static final String MIMETYPE_AUDIO_AMR_NB = "audio/3gpp";
     public static final String MIMETYPE_AUDIO_AMR_WB = "audio/amr-wb";
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index b604768..e902589 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -91,7 +91,7 @@
  * </ol>
  */
 public class BugreportProgressService extends Service {
-    private static final String TAG = "Shell";
+    static final String TAG = "Shell";
     private static final boolean DEBUG = false;
 
     private static final String AUTHORITY = "com.android.shell";
diff --git a/packages/Shell/src/com/android/shell/BugreportReceiver.java b/packages/Shell/src/com/android/shell/BugreportReceiver.java
index 5133162..b818343 100644
--- a/packages/Shell/src/com/android/shell/BugreportReceiver.java
+++ b/packages/Shell/src/com/android/shell/BugreportReceiver.java
@@ -19,6 +19,7 @@
 import static com.android.shell.BugreportProgressService.EXTRA_BUGREPORT;
 import static com.android.shell.BugreportProgressService.EXTRA_ORIGINAL_INTENT;
 import static com.android.shell.BugreportProgressService.INTENT_BUGREPORT_FINISHED;
+import static com.android.shell.BugreportProgressService.TAG;
 import static com.android.shell.BugreportProgressService.getFileExtra;
 
 import java.io.File;
@@ -29,6 +30,7 @@
 import android.os.AsyncTask;
 import android.os.FileUtils;
 import android.text.format.DateUtils;
+import android.util.Log;
 
 /**
  * Receiver that handles finished bugreports, usually by attaching them to an
@@ -63,6 +65,10 @@
             return;
         }
         final File bugreportFile = getFileExtra(intent, EXTRA_BUGREPORT);
+        if (bugreportFile == null || !bugreportFile.exists()) {
+            Log.e(TAG, "Not deleting old files because file " + bugreportFile + " doesn't exist");
+            return;
+        }
         final PendingResult result = goAsync();
         new AsyncTask<Void, Void, Void>() {
             @Override
diff --git a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
index cd0fcfe..6b6b0da 100644
--- a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
+++ b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
@@ -29,6 +29,7 @@
 import java.io.BufferedOutputStream;
 import java.io.BufferedWriter;
 import java.io.ByteArrayOutputStream;
+import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
@@ -45,6 +46,7 @@
 import android.app.Instrumentation;
 import android.app.NotificationManager;
 import android.content.Context;
+import android.content.ContextWrapper;
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Bundle;
@@ -82,16 +84,18 @@
     // Timeout for UI operations, in milliseconds.
     private static final int TIMEOUT = (int) BugreportProgressService.POLLING_FREQUENCY * 4;
 
-    private static final String ROOT_DIR = "/data/data/com.android.shell/files/bugreports";
+    private static final String BUGREPORTS_DIR = "bugreports";
     private static final String BUGREPORT_FILE = "test_bugreport.txt";
     private static final String ZIP_FILE = "test_bugreport.zip";
-    private static final String PLAIN_TEXT_PATH = ROOT_DIR + "/" + BUGREPORT_FILE;
-    private static final String ZIP_PATH = ROOT_DIR + "/" + ZIP_FILE;
-    private static final String SCREENSHOT_PATH = ROOT_DIR + "/test_screenshot.png";
+    private static final String SCREENSHOT_FILE = "test_screenshot.png";
 
     private static final String BUGREPORT_CONTENT = "Dump, might as well dump!\n";
     private static final String SCREENSHOT_CONTENT = "A picture is worth a thousand words!\n";
 
+    private String mPlainTextPath;
+    private String mZipPath;
+    private String mScreenshotPath;
+
     private Context mContext;
     private UiBot mUiBot;
     private CustomActionSendMultipleListener mListener;
@@ -102,6 +106,9 @@
         mContext = instrumentation.getTargetContext();
         mUiBot = new UiBot(UiDevice.getInstance(instrumentation), TIMEOUT);
         mListener = ActionSendMultipleConsumerActivity.getListener(mContext);
+        mPlainTextPath = getPath(BUGREPORT_FILE);
+        mZipPath = getPath(ZIP_FILE);
+        mScreenshotPath = getPath(SCREENSHOT_FILE);
         cancelExistingNotifications();
         BugreportPrefs.setWarningState(mContext, BugreportPrefs.STATE_HIDE);
     }
@@ -129,9 +136,9 @@
         SystemProperties.set("dumpstate.42.max", "2000");
         assertProgressNotification(name, "25.00%");
 
-        createTextFile(PLAIN_TEXT_PATH, BUGREPORT_CONTENT);
-        createTextFile(SCREENSHOT_PATH, SCREENSHOT_CONTENT);
-        Bundle extras = sendBugreportFinishedIntent(42, PLAIN_TEXT_PATH, SCREENSHOT_PATH);
+        createTextFile(mPlainTextPath, BUGREPORT_CONTENT);
+        createTextFile(mScreenshotPath, SCREENSHOT_CONTENT);
+        Bundle extras = sendBugreportFinishedIntent(42, mPlainTextPath, mScreenshotPath);
         assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT);
 
         String service = BugreportProgressService.class.getName();
@@ -143,9 +150,9 @@
         BugreportPrefs.setWarningState(mContext, BugreportPrefs.STATE_SHOW);
 
         // Send notification and click on share.
-        createTextFile(PLAIN_TEXT_PATH, BUGREPORT_CONTENT);
+        createTextFile(mPlainTextPath, BUGREPORT_CONTENT);
         Intent intent = new Intent(INTENT_BUGREPORT_FINISHED);
-        intent.putExtra(EXTRA_BUGREPORT, PLAIN_TEXT_PATH);
+        intent.putExtra(EXTRA_BUGREPORT, mPlainTextPath);
         mContext.sendBroadcast(intent);
         mUiBot.clickOnNotification(mContext.getString(R.string.bugreport_finished_title));
 
@@ -169,28 +176,28 @@
     }
 
     public void testBugreportFinished_plainBugreportAndScreenshot() throws Exception {
-        createTextFile(PLAIN_TEXT_PATH, BUGREPORT_CONTENT);
-        createTextFile(SCREENSHOT_PATH, SCREENSHOT_CONTENT);
-        Bundle extras = sendBugreportFinishedIntent(PLAIN_TEXT_PATH, SCREENSHOT_PATH);
+        createTextFile(mPlainTextPath, BUGREPORT_CONTENT);
+        createTextFile(mScreenshotPath, SCREENSHOT_CONTENT);
+        Bundle extras = sendBugreportFinishedIntent(mPlainTextPath, mScreenshotPath);
         assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT);
     }
 
     public void testBugreportFinished_zippedBugreportAndScreenshot() throws Exception {
-        createZipFile(ZIP_PATH, BUGREPORT_FILE, BUGREPORT_CONTENT);
-        createTextFile(SCREENSHOT_PATH, SCREENSHOT_CONTENT);
-        Bundle extras = sendBugreportFinishedIntent(ZIP_PATH, SCREENSHOT_PATH);
+        createZipFile(mZipPath, BUGREPORT_FILE, BUGREPORT_CONTENT);
+        createTextFile(mScreenshotPath, SCREENSHOT_CONTENT);
+        Bundle extras = sendBugreportFinishedIntent(mZipPath, mScreenshotPath);
         assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT);
     }
 
     public void testBugreportFinished_plainBugreportAndNoScreenshot() throws Exception {
-        createTextFile(PLAIN_TEXT_PATH, BUGREPORT_CONTENT);
-        Bundle extras = sendBugreportFinishedIntent(PLAIN_TEXT_PATH, null);
+        createTextFile(mPlainTextPath, BUGREPORT_CONTENT);
+        Bundle extras = sendBugreportFinishedIntent(mPlainTextPath, null);
         assertActionSendMultiple(extras, BUGREPORT_CONTENT, null);
     }
 
     public void testBugreportFinished_zippedBugreportAndNoScreenshot() throws Exception {
-        createZipFile(ZIP_PATH, BUGREPORT_FILE, BUGREPORT_CONTENT);
-        Bundle extras = sendBugreportFinishedIntent(ZIP_PATH, null);
+        createZipFile(mZipPath, BUGREPORT_FILE, BUGREPORT_CONTENT);
+        Bundle extras = sendBugreportFinishedIntent(mZipPath, null);
         assertActionSendMultiple(extras, BUGREPORT_CONTENT, null);
     }
 
@@ -341,4 +348,12 @@
             zos.closeEntry();
         }
     }
+
+    private String getPath(String file) {
+        File rootDir = new ContextWrapper(mContext).getFilesDir();
+        File dir = new File(rootDir, BUGREPORTS_DIR);
+        String path = new File(dir, file).getAbsolutePath();
+        Log.v(TAG, "Path for '" + file + "': " + path);
+        return path;
+    }
 }
diff --git a/packages/SystemUI/res/drawable/recents_freeform_workspace_bg.xml b/packages/SystemUI/res/drawable/recents_freeform_workspace_bg.xml
new file mode 100644
index 0000000..5f9341c
--- /dev/null
+++ b/packages/SystemUI/res/drawable/recents_freeform_workspace_bg.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+       android:shape="rectangle">
+    <corners android:topLeftRadius="@dimen/recents_task_view_rounded_corners_radius"
+             android:topRightRadius="@dimen/recents_task_view_rounded_corners_radius"/>
+    <solid android:color="#00000000" />
+</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index d703bd6..94350d9 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -68,6 +68,8 @@
     <color name="recents_task_view_lock_to_app_button_background_color">#ffe6e6e6</color>
     <!-- The lock to task button foreground color. -->
     <color name="recents_task_view_lock_to_app_button_color">#ff666666</color>
+    <!-- The background color for the freeform workspace. -->
+    <color name="recents_freeform_workspace_bg_color">#66000000</color>
 
     <color name="keyguard_affordance">#ffffffff</color>
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java b/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java
index 757d2aa..f646a92 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java
@@ -46,19 +46,6 @@
                 }
             };
 
-    public static final Property<AnimateableViewBounds, Integer> CLIP_RIGHT =
-            new IntProperty<AnimateableViewBounds>("clipRight") {
-                @Override
-                public void setValue(AnimateableViewBounds object, int clip) {
-                    object.setClipRight(clip, false /* force */);
-                }
-
-                @Override
-                public Integer get(AnimateableViewBounds object) {
-                    return object.getClipRight();
-                }
-            };
-
     public AnimateableViewBounds(View source, int cornerRadius) {
         mSourceView = source;
         mCornerRadius = cornerRadius;
@@ -102,19 +89,6 @@
         return mClipRect.bottom;
     }
 
-    /** Sets the right clip. */
-    public void setClipRight(int right, boolean force) {
-        if (right != mClipRect.right || force) {
-            mClipRect.right = right;
-            updateClipBounds();
-        }
-    }
-
-    /** Returns the right clip. */
-    public int getClipRight() {
-        return mClipRect.right;
-    }
-
     private void updateClipBounds() {
         mClipBounds.set(mClipRect.left, mClipRect.top,
                 mSourceView.getWidth() - mClipRect.right,
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/FreeformWorkspaceLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/FreeformWorkspaceLayoutAlgorithm.java
index 9b9d58c..2351aa3 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/FreeformWorkspaceLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/FreeformWorkspaceLayoutAlgorithm.java
@@ -19,7 +19,6 @@
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.util.Log;
-import com.android.systemui.recents.misc.Utilities;
 import com.android.systemui.recents.model.Task;
 
 import java.util.Collections;
@@ -80,7 +79,6 @@
                 float width = normalizedTaskWidths[i] * rowScale;
                 if (rowWidth + width > normalizedWorkspaceWidth) {
                     // That is too long for this row, create new row
-                    rowWidth = 0f;
                     if ((rowCount + 1) * rowScale > normalizedWorkspaceHeight) {
                         // The new row is too high, so we need to try fitting again.  Update the
                         // scale to be the smaller of the scale needed to fit the task in the
@@ -88,9 +86,11 @@
                         rowScale = Math.min(normalizedWorkspaceWidth / (rowWidth + width),
                                 normalizedWorkspaceHeight / (rowCount + 1));
                         rowCount = 1;
+                        rowWidth = 0;
                         i = 0;
                     } else {
                         // The new row fits, so continue
+                        rowWidth = width;
                         rowCount++;
                         i++;
                     }
@@ -103,20 +103,20 @@
             }
 
             // Normalize each of the actual rects to that scale
-            int height = (int) (rowScale * workspaceHeight);
-            float rowTop = ((1f - (rowScale * rowCount)) * workspaceHeight) / 2f;
             float defaultRowLeft = ((1f - (maxRowWidth / normalizedWorkspaceWidth)) *
                     workspaceWidth) / 2f;
             float rowLeft = defaultRowLeft;
+            float rowTop = ((1f - (rowScale * rowCount)) * workspaceHeight) / 2f;
+            float rowHeight = rowScale * workspaceHeight;
             for (int i = 0; i < numFreeformTasks; i++) {
                 Task task = freeformTasks.get(i);
-                int width = (int) (height * normalizedTaskWidths[i]);
+                float width = rowHeight * normalizedTaskWidths[i];
                 if (rowLeft + width > workspaceWidth) {
                     // This goes on the next line
-                    rowTop += height;
+                    rowTop += rowHeight;
                     rowLeft = defaultRowLeft;
                 }
-                RectF rect = new RectF(rowLeft, rowTop, rowLeft + width, rowTop + height);
+                RectF rect = new RectF(rowLeft, rowTop, rowLeft + width, rowTop + rowHeight);
                 rowLeft += width;
                 mTaskRectMap.put(task.key, rect);
             }
@@ -140,34 +140,29 @@
     public TaskViewTransform getTransform(Task task, TaskViewTransform transformOut,
             TaskStackLayoutAlgorithm stackLayout) {
         if (mTaskRectMap.containsKey(task.key)) {
-            Rect taskRect = stackLayout.mTaskRect;
-            RectF ffRect = mTaskRectMap.get(task.key);
-            float scale = Math.max(ffRect.width() / taskRect.width(),
-                    ffRect.height() / taskRect.height());
-            int topOffset = (stackLayout.mFreeformRect.top - taskRect.top);
-            int scaleXOffset = (int) (((1f - scale) * taskRect.width()) / 2);
-            int scaleYOffset = (int) (((1f - scale) * taskRect.height()) / 2);
+            final Rect taskRect = stackLayout.mTaskRect;
+            final RectF ffRect = mTaskRectMap.get(task.key);
 
-            transformOut.scale = scale * 0.95f;
-            transformOut.translationX = (int) (ffRect.left - scaleXOffset);
-            transformOut.translationY = (int) (topOffset + ffRect.top - scaleYOffset);
+            transformOut.scale = 1f;
+            transformOut.alpha = 1f;
             transformOut.translationZ = stackLayout.mMaxTranslationZ;
-            transformOut.clipBottom = (int) (taskRect.height() - (ffRect.height() / scale));
-            transformOut.clipRight = (int) (taskRect.width() - (ffRect.width() / scale));
             if (task.thumbnail != null) {
-                transformOut.thumbnailScale = Math.min(
-                        ((float) taskRect.width() - transformOut.clipRight) /
-                                task.thumbnail.getWidth(),
-                        ((float) taskRect.height() - transformOut.clipBottom) /
-                                task.thumbnail.getHeight());
+                if (task.bounds == null) {
+                    // This is a stack task that has no freeform thumbnail, so keep the same bitmap
+                    // scale as it had in the stack
+                    transformOut.thumbnailScale = (float) taskRect.width() /
+                            task.thumbnail.getWidth();
+                } else {
+                    // This is a freeform rect so fit the bitmap to the task bounds
+                    transformOut.thumbnailScale = Math.min(
+                            ffRect.width() / task.thumbnail.getWidth(),
+                            ffRect.height() / task.thumbnail.getHeight());
+                }
             } else {
                 transformOut.thumbnailScale = 1f;
             }
-            transformOut.rect.set(taskRect);
-            transformOut.rect.offset(transformOut.translationX, transformOut.translationY);
-            Utilities.scaleRectAboutCenter(transformOut.rect, transformOut.scale);
-            transformOut.rect.right -= transformOut.clipRight * scale;
-            transformOut.rect.bottom -= transformOut.clipBottom * scale;
+            transformOut.rect.set(ffRect);
+            transformOut.rect.offset(stackLayout.mFreeformRect.left, stackLayout.mFreeformRect.top);
             transformOut.visible = true;
             transformOut.p = 1f;
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index 7ae686e..55a54a2 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -142,7 +142,8 @@
     public void setTaskStack(TaskStack stack) {
         RecentsConfiguration config = Recents.getConfiguration();
         mStack = stack;
-        if (config.getLaunchState().launchedReuseTaskStackViews) {
+        // Disable reusing task stack views until the visibility bug is fixed. b/25998134
+        if (false && config.getLaunchState().launchedReuseTaskStackViews) {
             if (mTaskStackView != null) {
                 // If onRecentsHidden is not triggered, we need to the stack view again here
                 mTaskStackView.reset();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
index 7d5daae..f599f52 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
@@ -507,6 +507,15 @@
     }
 
     /**
+     * Returns the task progress that would put the task just off the back of the stack.
+     */
+    public float getStackBackTaskProgress(float stackScroll) {
+        float min = mUnfocusedRange.relativeMin +
+                mFocusState * (mFocusedRange.relativeMin - mUnfocusedRange.relativeMin);
+        return stackScroll + min;
+    }
+
+    /**
      * Returns the task progress that would put the task just off the front of the stack.
      */
     public float getStackFrontTaskProgress(float stackScroll) {
@@ -647,6 +656,7 @@
             return transformOut;
         }
 
+        int x = (mStackRect.width() - mTaskRect.width()) / 2;
         int y;
         float z;
         float relP;
@@ -671,16 +681,13 @@
 
         // Fill out the transform
         transformOut.scale = 1f;
-        transformOut.translationX = (mStackRect.width() - mTaskRect.width()) / 2;
-        transformOut.translationY = y;
+        transformOut.alpha = 1f;
         transformOut.translationZ = z;
         transformOut.rect.set(mTaskRect);
-        transformOut.rect.offset(transformOut.translationX, transformOut.translationY);
+        transformOut.rect.offset(x, y);
         Utilities.scaleRectAboutCenter(transformOut.rect, transformOut.scale);
         transformOut.visible = (transformOut.rect.top < mStackRect.bottom) &&
                 (frontTransform == null || transformOut.rect.top != frontTransform.rect.top);
-        transformOut.clipBottom = 0;
-        transformOut.clipRight = 0;
         transformOut.thumbnailScale = 1f;
         transformOut.p = relP;
         return transformOut;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index cc5aaae..350bc2b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -20,11 +20,12 @@
 import android.animation.ValueAnimator;
 import android.content.ComponentName;
 import android.content.Context;
+import android.content.res.Resources;
 import android.graphics.Canvas;
 import android.graphics.Rect;
 import android.graphics.RectF;
-import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
+import android.graphics.drawable.GradientDrawable;
 import android.os.Bundle;
 import android.util.IntProperty;
 import android.util.Log;
@@ -94,15 +95,15 @@
     private static final float SHOW_HISTORY_BUTTON_SCROLL_THRESHOLD = 0.3f;
     private static final float HIDE_HISTORY_BUTTON_SCROLL_THRESHOLD = 0.3f;
 
-    public static final Property<ColorDrawable, Integer> COLOR_DRAWABLE_ALPHA =
-            new IntProperty<ColorDrawable>("colorDrawableAlpha") {
+    public static final Property<Drawable, Integer> DRAWABLE_ALPHA =
+            new IntProperty<Drawable>("drawableAlpha") {
                 @Override
-                public void setValue(ColorDrawable object, int alpha) {
+                public void setValue(Drawable object, int alpha) {
                     object.setAlpha(alpha);
                 }
 
                 @Override
-                public Integer get(ColorDrawable object) {
+                public Integer get(Drawable object) {
                     return object.getAlpha();
                 }
             };
@@ -118,7 +119,7 @@
     TaskStackViewScroller mStackScroller;
     TaskStackViewTouchHandler mTouchHandler;
     TaskStackViewCallbacks mCb;
-    ColorDrawable mFreeformWorkspaceBackground;
+    GradientDrawable mFreeformWorkspaceBackground;
     ObjectAnimator mFreeformWorkspaceBackgroundAnimator;
     ViewPool<TaskView, Task> mViewPool;
     ArrayList<TaskViewTransform> mCurrentTaskTransforms = new ArrayList<>();
@@ -126,6 +127,7 @@
     Task mFocusedTask;
     // Optimizations
     int mStackViewsAnimationDuration;
+    int mTaskCornerRadiusPx;
     boolean mStackViewsDirty = true;
     boolean mStackViewsClipDirty = true;
     boolean mAwaitingFirstLayout = true;
@@ -174,6 +176,9 @@
 
     public TaskStackView(Context context, TaskStack stack) {
         super(context);
+        SystemServicesProxy ssp = Recents.getSystemServices();
+        Resources res = context.getResources();
+
         // Set the stack first
         setStack(stack);
         mViewPool = new ViewPool<>(context, this);
@@ -184,6 +189,8 @@
         mTouchHandler = new TaskStackViewTouchHandler(context, this, mStackScroller);
         mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
                 com.android.internal.R.interpolator.fast_out_slow_in);
+        mTaskCornerRadiusPx = res.getDimensionPixelSize(
+                R.dimen.recents_task_view_rounded_corners_radius);
 
         int taskBarDismissDozeDelaySeconds = getResources().getInteger(
                 R.integer.recents_task_bar_dismiss_delay_seconds);
@@ -201,8 +208,12 @@
         });
         setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
 
-        mFreeformWorkspaceBackground = new ColorDrawable(0x33000000);
+        mFreeformWorkspaceBackground = (GradientDrawable) getContext().getDrawable(
+                R.drawable.recents_freeform_workspace_bg);
         mFreeformWorkspaceBackground.setCallback(this);
+        if (ssp.hasFreeformWorkspaceSupport()) {
+            setBackgroundColor(getContext().getColor(R.color.recents_freeform_workspace_bg_color));
+        }
     }
 
     /** Sets the callbacks */
@@ -364,8 +375,7 @@
     private boolean updateStackTransforms(ArrayList<TaskViewTransform> taskTransforms,
                                        ArrayList<Task> tasks,
                                        float stackScroll,
-                                       int[] visibleRangeOut,
-                                       boolean boundTranslationsToRect) {
+                                       int[] visibleRangeOut) {
         int taskTransformCount = taskTransforms.size();
         int taskCount = tasks.size();
         int frontMostVisibleIndex = -1;
@@ -411,11 +421,6 @@
                     break;
                 }
             }
-
-            if (boundTranslationsToRect) {
-                transform.translationY = Math.min(transform.translationY,
-                        mLayoutAlgorithm.mStackRect.bottom);
-            }
             frontTransform = transform;
         }
         if (visibleRangeOut != null) {
@@ -433,7 +438,7 @@
             float stackScroll = mStackScroller.getStackScroll();
             int[] visibleStackRange = mTmpVisibleRange;
             boolean isValidVisibleStackRange = updateStackTransforms(mCurrentTaskTransforms, tasks,
-                    stackScroll, visibleStackRange, false);
+                    stackScroll, visibleStackRange);
             boolean hasStackBackTransform = false;
             boolean hasStackFrontTransform = false;
             if (DEBUG) {
@@ -490,7 +495,7 @@
                 }
 
                 // Animate the task into place
-                tv.updateViewPropertiesToTaskTransform(transform, transform.clipBottom,
+                tv.updateViewPropertiesToTaskTransform(transform, 0,
                         mStackViewsAnimationDuration, mFastOutSlowInInterpolator,
                         mRequestUpdateClippingListener);
 
@@ -513,8 +518,9 @@
                         if (Float.compare(transform.p, 0f) <= 0) {
                             if (!hasStackBackTransform) {
                                 hasStackBackTransform = true;
-                                mLayoutAlgorithm.getStackTransform(0f, 0f, mTmpStackBackTransform,
-                                        null);
+                                mLayoutAlgorithm.getStackTransform(
+                                        mLayoutAlgorithm.getStackBackTaskProgress(0f), 0f,
+                                        mTmpStackBackTransform, null);
                             }
                             tv.updateViewPropertiesToTaskTransform(mTmpStackBackTransform, 0, 0,
                                     mFastOutSlowInInterpolator, mRequestUpdateClippingListener);
@@ -586,17 +592,11 @@
                 // stacked and we can make assumptions about the visibility of the this
                 // task relative to the ones in front of it.
                 if (frontTv != null) {
-                    mTmpTaskRect.set(mLayoutAlgorithm.mTaskRect);
-                    mTmpTaskRect.offset(0, tv.getTranslationY());
-                    Utilities.scaleRectAboutCenter(mTmpTaskRect, tv.getScaleX());
-                    float taskBottom = mTmpTaskRect.bottom;
-                    mTmpTaskRect.set(mLayoutAlgorithm.mTaskRect);
-                    mTmpTaskRect.offset(0, frontTv.getTranslationY());
-                    Utilities.scaleRectAboutCenter(mTmpTaskRect, frontTv.getScaleX());
-                    float frontTaskTop = mTmpTaskRect.top;
+                    float taskBottom = tv.getBottom();
+                    float frontTaskTop = frontTv.getTop();
                     if (frontTaskTop < taskBottom) {
                         // Map the stack view space coordinate (the rects) to view space
-                        clipBottom = (int) ((taskBottom - frontTaskTop) / tv.getScaleX()) - 1;
+                        clipBottom = (int) (taskBottom - frontTaskTop) - mTaskCornerRadiusPx;
                     }
                 }
             }
@@ -980,11 +980,11 @@
             onFirstLayout();
         }
 
+        requestSynchronizeStackViewsWithModel();
         if (changed) {
             if (mStackScroller.isScrollOutOfBounds()) {
                 mStackScroller.boundScroll();
             }
-            requestSynchronizeStackViewsWithModel();
             synchronizeStackViewsWithModel();
             requestUpdateStackViewsClip();
             clipTaskViews(true /* forceUpdate */);
@@ -1147,8 +1147,7 @@
         transformPointToViewLocal(point, tv);
         x = point[0];
         y = point[1];
-        return (0 <= x) && (x < (tv.getMeasuredWidth() - tv.getViewBounds().getClipRight())) &&
-                (0 <= y) && (y < (tv.getMeasuredHeight() - tv.getViewBounds().getClipBottom()));
+        return (0 <= x) && (x < tv.getWidth()) && (0 <= y) && (y < tv.getHeight());
     }
 
     @Override
@@ -1221,14 +1220,13 @@
             } else if (pullStackForward) {
                 // Otherwise, offset the scroll by the movement of the anchor task
                 float anchorTaskScroll = mLayoutAlgorithm.getStackScrollForTask(anchorTask);
-                float newStackScroll = mStackScroller.getStackScroll() +
-                        (anchorTaskScroll - prevAnchorTaskScroll);
+                float stackScrollOffset = (anchorTaskScroll - prevAnchorTaskScroll);
                 if (mLayoutAlgorithm.getFocusState() != TaskStackLayoutAlgorithm.STATE_FOCUSED) {
                     // If we are focused, we don't want the front task to move, but otherwise, we
                     // allow the back task to move up, and the front task to move back
-                    newStackScroll /= 2;
+                    stackScrollOffset /= 2;
                 }
-                mStackScroller.setStackScroll(newStackScroll);
+                mStackScroller.setStackScroll(mStackScroller.getStackScroll() + stackScrollOffset);
                 mStackScroller.boundScroll();
             }
 
@@ -1498,6 +1496,18 @@
         event.taskView.animate()
                 .withEndAction(event.postAnimationTrigger.decrementAsRunnable());
 
+        // We translated the view but we need to animate it back from the current layout-space rect
+        // to its final layout-space rect
+        int x = (int) event.taskView.getTranslationX();
+        int y = (int) event.taskView.getTranslationY();
+        Rect taskViewRect = new Rect(event.taskView.getLeft(), event.taskView.getTop(),
+                event.taskView.getRight(), event.taskView.getBottom());
+        taskViewRect.offset(x, y);
+        event.taskView.setTranslationX(0);
+        event.taskView.setTranslationY(0);
+        event.taskView.setLeftTopRightBottom(taskViewRect.left, taskViewRect.top,
+                taskViewRect.right, taskViewRect.bottom);
+
         // Animate the tack view back into position
         requestSynchronizeStackViewsWithModel(250);
     }
@@ -1582,7 +1592,7 @@
 
         Utilities.cancelAnimationWithoutCallbacks(mFreeformWorkspaceBackgroundAnimator);
         mFreeformWorkspaceBackgroundAnimator = ObjectAnimator.ofInt(mFreeformWorkspaceBackground,
-                COLOR_DRAWABLE_ALPHA, mFreeformWorkspaceBackground.getAlpha(), targetAlpha);
+                DRAWABLE_ALPHA, mFreeformWorkspaceBackground.getAlpha(), targetAlpha);
         mFreeformWorkspaceBackgroundAnimator.setDuration(duration);
         mFreeformWorkspaceBackgroundAnimator.setInterpolator(interpolator);
         mFreeformWorkspaceBackgroundAnimator.start();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index 813a1fc..1e2227e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -179,6 +179,13 @@
     }
 
     @Override
+    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+        super.onSizeChanged(w, h, oldw, oldh);
+        mHeaderView.onTaskViewSizeChanged(w, h);
+        mThumbnailView.onTaskViewSizeChanged(w, h);
+    }
+
+    @Override
     public boolean onInterceptTouchEvent(MotionEvent ev) {
         if (ev.getAction() == MotionEvent.ACTION_DOWN) {
             mDownTouchPos.set((int) (ev.getX() * getScaleX()), (int) (ev.getY() * getScaleY()));
@@ -232,8 +239,14 @@
             mClipAnimation.playTogether(
                     ObjectAnimator.ofInt(mViewBounds, AnimateableViewBounds.CLIP_BOTTOM,
                             mViewBounds.getClipBottom(), clipBottom),
-                    ObjectAnimator.ofInt(mViewBounds, AnimateableViewBounds.CLIP_RIGHT,
-                            mViewBounds.getClipRight(), toTransform.clipRight),
+                    ObjectAnimator.ofInt(this, TaskViewTransform.LEFT, getLeft(),
+                            (int) toTransform.rect.left),
+                    ObjectAnimator.ofInt(this, TaskViewTransform.TOP, getTop(),
+                            (int) toTransform.rect.top),
+                    ObjectAnimator.ofInt(this, TaskViewTransform.RIGHT, getRight(),
+                            (int) toTransform.rect.right),
+                    ObjectAnimator.ofInt(this, TaskViewTransform.BOTTOM, getBottom(),
+                            (int) toTransform.rect.bottom),
                     ObjectAnimator.ofFloat(mThumbnailView, TaskViewThumbnail.BITMAP_SCALE,
                             mThumbnailView.getBitmapScale(), toTransform.thumbnailScale));
             mClipAnimation.setStartDelay(toTransform.startDelay);
@@ -242,8 +255,9 @@
             mClipAnimation.start();
         } else {
             mViewBounds.setClipBottom(clipBottom, false /* forceUpdate */);
-            mViewBounds.setClipRight(toTransform.clipRight, false /* forceUpdate */);
             mThumbnailView.setBitmapScale(toTransform.thumbnailScale);
+            setLeftTopRightBottom((int) toTransform.rect.left, (int) toTransform.rect.top,
+                    (int) toTransform.rect.right, (int) toTransform.rect.bottom);
         }
         if (!config.useHardwareLayers) {
             mThumbnailView.updateThumbnailVisibility(clipBottom - getPaddingBottom());
@@ -336,10 +350,10 @@
             } else {
                 // Animate the task up if it was occluding the launch target
                 if (ctx.currentTaskOccludesLaunchTarget) {
-                    setTranslationY(transform.translationY + taskViewAffiliateGroupEnterOffset);
+                    setTranslationY(taskViewAffiliateGroupEnterOffset);
                     setAlpha(0f);
                     animate().alpha(1f)
-                            .translationY(transform.translationY)
+                            .translationY(0)
                             .setUpdateListener(null)
                             .setListener(new AnimatorListenerAdapter() {
                                 private boolean hasEnded;
@@ -372,7 +386,7 @@
                 animate().translationZ(transform.translationZ);
             }
             animate()
-                    .translationY(transform.translationY)
+                    .translationY(0)
                     .setStartDelay(delay)
                     .setUpdateListener(ctx.updateListener)
                     .setListener(new AnimatorListenerAdapter() {
@@ -644,7 +658,6 @@
         }
 
         SystemServicesProxy ssp = Recents.getSystemServices();
-        mHeaderView.onTaskViewFocusChanged(isFocused, animated);
         if (isFocused) {
             if (requestViewFocus && !isFocused()) {
                 requestFocus();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
index 78a2c7f..d8220fd 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
@@ -31,6 +31,7 @@
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.GradientDrawable;
 import android.graphics.drawable.RippleDrawable;
+import android.graphics.drawable.ShapeDrawable;
 import android.util.AttributeSet;
 import android.view.View;
 import android.view.ViewOutlineProvider;
@@ -55,8 +56,6 @@
 public class TaskViewHeader extends FrameLayout
         implements View.OnClickListener, View.OnLongClickListener {
 
-    private static final float FOCUS_TRANSLATION_Z = 4f;
-
     Task mTask;
 
     // Header views
@@ -66,13 +65,13 @@
     TextView mActivityDescription;
 
     // Header drawables
+    Rect mTaskViewRect = new Rect();
     int mCornerRadius;
     int mHighlightHeight;
     Drawable mLightDismissDrawable;
     Drawable mDarkDismissDrawable;
     RippleDrawable mBackground;
     GradientDrawable mBackgroundColorDrawable;
-    ObjectAnimator mFocusAnimator;
     String mDismissContentDescription;
 
     // Static highlight that we draw at the top of each view
@@ -99,13 +98,6 @@
     public TaskViewHeader(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
         setWillNotDraw(false);
-        setClipToOutline(true);
-        setOutlineProvider(new ViewOutlineProvider() {
-            @Override
-            public void getOutline(View view, Outline outline) {
-                outline.setRect(0, 0, getMeasuredWidth(), getMeasuredHeight());
-            }
-        });
 
         // Load the dismiss resources
         mDimLayerPaint.setColor(Color.argb(0, 0, 0, 0));
@@ -148,8 +140,8 @@
             mApplicationIcon.setBackground(null);
         }
 
-        mBackgroundColorDrawable = (GradientDrawable) getContext().getDrawable(R.drawable
-                .recents_task_view_header_bg_color);
+        mBackgroundColorDrawable = (GradientDrawable) getContext().getDrawable(
+                R.drawable.recents_task_view_header_bg_color);
         // Copy the ripple drawable since we are going to be manipulating it
         mBackground = (RippleDrawable)
                 getContext().getDrawable(R.drawable.recents_task_view_header_bg);
@@ -159,14 +151,37 @@
         setBackground(mBackground);
     }
 
+    /**
+     * Called when the task view frame changes, allowing us to move the contents of the header
+     * to match the frame changes.
+     */
+    public void onTaskViewSizeChanged(int width, int height) {
+        mTaskViewRect.set(0, 0, width, height);
+        if (mDismissButton.getMeasuredWidth() > (width - mApplicationIcon.getMeasuredWidth())) {
+            mDismissButton.setAlpha(0f);
+        } else {
+            mDismissButton.setAlpha(1f);
+            if (mDismissButton != null) {
+                mDismissButton.setTranslationX(width - getMeasuredWidth());
+            }
+        }
+        if (mActivityDescription.getMeasuredWidth() > (width -
+                (mApplicationIcon.getMeasuredWidth() + mDismissButton.getMeasuredWidth()))) {
+            mActivityDescription.setAlpha(0f);
+        } else {
+            mActivityDescription.setAlpha(1f);
+        }
+        invalidate();
+    }
+
     @Override
     protected void onDraw(Canvas canvas) {
         // Draw the highlight at the top edge (but put the bottom edge just out of view)
         float offset = (float) Math.ceil(mHighlightHeight / 2f);
         float radius = mCornerRadius;
         int count = canvas.save(Canvas.CLIP_SAVE_FLAG);
-        canvas.clipRect(0, 0, getMeasuredWidth(), getMeasuredHeight());
-        canvas.drawRoundRect(-offset, 0f, (float) getMeasuredWidth() + offset,
+        canvas.clipRect(0, 0, mTaskViewRect.width(), getMeasuredHeight());
+        canvas.drawRoundRect(-offset, 0f, (float) mTaskViewRect.width() + offset,
                 getMeasuredHeight() + radius, radius, radius, sHighlightPaint);
         canvas.restoreToCount(count);
     }
@@ -180,12 +195,6 @@
         invalidate();
     }
 
-    /** Returns the secondary color for a primary color. */
-    int getSecondaryColor(int primaryColor, boolean useLightOverlayColor) {
-        int overlayColor = useLightOverlayColor ? Color.WHITE : Color.BLACK;
-        return Utilities.getColorWithOverlay(primaryColor, overlayColor, 0.8f);
-    }
-
     /** Binds the bar view to the task */
     public void rebindToTask(Task t) {
         mTask = t;
@@ -236,9 +245,6 @@
         mApplicationIcon.setImageDrawable(null);
         mApplicationIcon.setOnClickListener(null);
         mMoveTaskButton.setOnClickListener(null);
-
-        // Stop any focus animations
-        Utilities.cancelAnimationWithoutCallbacks(mFocusAnimator);
     }
 
     /** Updates the resize task bar button. */
@@ -332,39 +338,9 @@
     protected void dispatchDraw(Canvas canvas) {
         super.dispatchDraw(canvas);
 
-        // Draw the thumbnail with the rounded corners
-        canvas.drawRoundRect(0, 0, getWidth(), getHeight(),
-                mCornerRadius,
-                mCornerRadius, mDimLayerPaint);
-    }
-
-    /** Notifies the associated TaskView has been focused. */
-    void onTaskViewFocusChanged(boolean focused, boolean animateFocusedState) {
-        boolean isRunning = false;
-        if (mFocusAnimator != null) {
-            isRunning = mFocusAnimator.isRunning();
-        }
-        Utilities.cancelAnimationWithoutCallbacks(mFocusAnimator);
-
-        if (focused) {
-            if (animateFocusedState) {
-                // Bump up the translation
-                mFocusAnimator = ObjectAnimator.ofFloat(this, "translationZ", FOCUS_TRANSLATION_Z);
-                mFocusAnimator.setDuration(200);
-                mFocusAnimator.start();
-            } else {
-                setTranslationZ(FOCUS_TRANSLATION_Z);
-            }
-        } else {
-            if (isRunning) {
-                // Restore the translation
-                mFocusAnimator = ObjectAnimator.ofFloat(this, "translationZ", 0f);
-                mFocusAnimator.setDuration(150);
-                mFocusAnimator.start();
-            } else {
-                setTranslationZ(0f);
-            }
-        }
+        // Draw the dim layer with the rounded corners
+        canvas.drawRoundRect(0, 0, mTaskViewRect.width(), getHeight(),
+                mCornerRadius, mCornerRadius, mDimLayerPaint);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
index 7bb2c7b..37d8cd6 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
@@ -56,6 +56,7 @@
             };
 
     // Drawing
+    Rect mTaskViewRect = new Rect();
     int mCornerRadius;
     float mDimAlpha;
     Matrix mScaleMatrix = new Matrix();
@@ -98,13 +99,22 @@
                 com.android.internal.R.interpolator.fast_out_slow_in);
     }
 
+    /**
+     * Called when the task view frame changes, allowing us to move the contents of the header
+     * to match the frame changes.
+     */
+    public void onTaskViewSizeChanged(int width, int height) {
+        mTaskViewRect.set(0, 0, width, height);
+        invalidate();
+    }
+
     @Override
     protected void onDraw(Canvas canvas) {
         if (mInvisible) {
             return;
         }
         // Draw the thumbnail with the rounded corners
-        canvas.drawRoundRect(0, 0, getWidth(), getHeight(),
+        canvas.drawRoundRect(0, 0, mTaskViewRect.width(), mTaskViewRect.height(),
                 mCornerRadius,
                 mCornerRadius, mDrawPaint);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java
index c3e0906..3ee50ac 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java
@@ -18,6 +18,9 @@
 
 import android.animation.ValueAnimator;
 import android.graphics.RectF;
+import android.util.IntProperty;
+import android.util.Property;
+import android.view.View;
 import android.view.ViewPropertyAnimator;
 import android.view.animation.Interpolator;
 
@@ -25,26 +28,70 @@
 /* The transform state for a task view */
 public class TaskViewTransform {
 
+    public static final Property<View, Integer> LEFT =
+            new IntProperty<View>("left") {
+                @Override
+                public void setValue(View object, int v) {
+                    object.setLeft(v);
+                }
+
+                @Override
+                public Integer get(View object) {
+                    return object.getLeft();
+                }
+            };
+
+    public static final Property<View, Integer> TOP =
+            new IntProperty<View>("top") {
+                @Override
+                public void setValue(View object, int v) {
+                    object.setTop(v);
+                }
+
+                @Override
+                public Integer get(View object) {
+                    return object.getTop();
+                }
+            };
+
+    public static final Property<View, Integer> RIGHT =
+            new IntProperty<View>("right") {
+                @Override
+                public void setValue(View object, int v) {
+                    object.setRight(v);
+                }
+
+                @Override
+                public Integer get(View object) {
+                    return object.getRight();
+                }
+            };
+
+    public static final Property<View, Integer> BOTTOM =
+            new IntProperty<View>("bottom") {
+                @Override
+                public void setValue(View object, int v) {
+                    object.setBottom(v);
+                }
+
+                @Override
+                public Integer get(View object) {
+                    return object.getBottom();
+                }
+            };
+
     // TODO: Move this out of the transform
     public int startDelay = 0;
 
-    public int translationX = 0;
-    public int translationY = 0;
     public float translationZ = 0;
     public float scale = 1f;
     public float alpha = 1f;
-
-    // Clip and thumbnail scale are untransformed layout-space properties
-    // The bottom clip is only used for freeform workspace tasks
-    public int clipBottom = 0;
-    public int clipRight = 0;
     public float thumbnailScale = 1f;
 
     public boolean visible = false;
     float p = 0f;
 
-    // This is a window-space rect that is purely used for coordinating the animation of an app
-    // window into Recents.
+    // This is a window-space rect used for positioning the task in the stack and freeform workspace
     public RectF rect = new RectF();
 
     public TaskViewTransform() {
@@ -56,13 +103,9 @@
      */
     public void reset() {
         startDelay = 0;
-        translationX = 0;
-        translationY = 0;
         translationZ = 0;
         scale = 1f;
         alpha = 1f;
-        clipBottom = 0;
-        clipRight = 0;
         thumbnailScale = 1f;
         visible = false;
         rect.setEmpty();
@@ -76,12 +119,6 @@
     public boolean hasScaleChangedFrom(float v) {
         return (Float.compare(scale, v) != 0);
     }
-    public boolean hasTranslationXChangedFrom(float v) {
-        return (Float.compare(translationX, v) != 0);
-    }
-    public boolean hasTranslationYChangedFrom(float v) {
-        return (Float.compare(translationY, v) != 0);
-    }
     public boolean hasTranslationZChangedFrom(float v) {
         return (Float.compare(translationZ, v) != 0);
     }
@@ -95,12 +132,6 @@
             boolean requiresLayers = false;
 
             // Animate to the final state
-            if (hasTranslationXChangedFrom(v.getTranslationX())) {
-                anim.translationX(translationX);
-            }
-            if (hasTranslationYChangedFrom(v.getTranslationY())) {
-                anim.translationY(translationY);
-            }
             if (allowShadows && hasTranslationZChangedFrom(v.getTranslationZ())) {
                 anim.translationZ(translationZ);
             }
@@ -129,12 +160,6 @@
                     .start();
         } else {
             // Set the changed properties
-            if (hasTranslationXChangedFrom(v.getTranslationX())) {
-                v.setTranslationX(translationX);
-            }
-            if (hasTranslationYChangedFrom(v.getTranslationY())) {
-                v.setTranslationY(translationY);
-            }
             if (allowShadows && hasTranslationZChangedFrom(v.getTranslationZ())) {
                 v.setTranslationZ(translationZ);
             }
@@ -150,7 +175,8 @@
 
     /** Reset the transform on a view. */
     public static void reset(TaskView v) {
-        // Cancel any running animations
+        // Cancel any running animations and reset the translation in case something else (like a
+        // dismiss animation) changes it
         v.animate().cancel();
         v.setTranslationX(0f);
         v.setTranslationY(0f);
@@ -158,16 +184,15 @@
         v.setScaleX(1f);
         v.setScaleY(1f);
         v.setAlpha(1f);
-        v.getViewBounds().setClipRight(0, false /* forceUpdate */);
         v.getViewBounds().setClipBottom(0, false /* forceUpdate */);
+        v.setLeftTopRightBottom(0, 0, 0, 0);
         v.mThumbnailView.setBitmapScale(1f);
     }
 
     @Override
     public String toString() {
-        return "TaskViewTransform delay: " + startDelay +
-                " x: " + translationX + " y: " + translationY + " z: " + translationZ +
-                " scale: " + scale + " alpha: " + alpha + " visible: " + visible + " rect: " + rect +
-                " p: " + p;
+        return "TaskViewTransform delay: " + startDelay + " z: " + translationZ +
+                " scale: " + scale + " alpha: " + alpha + " visible: " + visible +
+                " rect: " + rect + " p: " + p;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java b/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java
index 58de5d5..ef47d8d 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java
@@ -62,7 +62,7 @@
         @Override
         public void run() {
             try {
-                ActivityManagerNative.getDefault().removeStack(DOCKED_STACK_ID);
+                ActivityManagerNative.getDefault().moveTasksToFullscreenStack(DOCKED_STACK_ID);
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed to remove stack: " + e);
             }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index ea0a16f..ab1ec72 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.statusbar;
 
+import static  android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_MAX;
+
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.TimeInterpolator;
@@ -2131,11 +2133,11 @@
         mNotificationData.updateRanking(ranking);
 
         boolean applyInPlace = entry.cacheContentViews(mContext, notification.getNotification());
-        boolean shouldInterrupt = shouldInterrupt(entry, notification);
+        boolean shouldPeek = shouldPeek(entry, notification);
         boolean alertAgain = alertAgain(entry, n);
         if (DEBUG) {
             Log.d(TAG, "applyInPlace=" + applyInPlace
-                    + " shouldInterrupt=" + shouldInterrupt
+                    + " shouldPeek=" + shouldPeek
                     + " alertAgain=" + alertAgain);
         }
 
@@ -2182,7 +2184,7 @@
             entry.icon.set(ic);
             inflateViews(entry, mStackScroller);
         }
-        updateHeadsUp(key, entry, shouldInterrupt, alertAgain);
+        updateHeadsUp(key, entry, shouldPeek, alertAgain);
         updateNotifications();
 
         // Update the veto button accordingly (and as a result, whether this row is
@@ -2198,7 +2200,7 @@
         setAreThereNotifications();
     }
 
-    protected abstract void updateHeadsUp(String key, Entry entry, boolean shouldInterrupt,
+    protected abstract void updateHeadsUp(String key, Entry entry, boolean shouldPeek,
             boolean alertAgain);
 
     private void updateNotificationViews(Entry entry, StatusBarNotification sbn) {
@@ -2241,49 +2243,54 @@
                 || (newNotification.flags & Notification.FLAG_ONLY_ALERT_ONCE) == 0;
     }
 
-    protected boolean shouldInterrupt(Entry entry) {
-        return shouldInterrupt(entry, entry.notification);
+    protected boolean shouldPeek(Entry entry) {
+        return shouldPeek(entry, entry.notification);
     }
 
-    protected boolean shouldInterrupt(Entry entry, StatusBarNotification sbn) {
+    protected boolean shouldPeek(Entry entry, StatusBarNotification sbn) {
         if (mNotificationData.shouldFilterOut(sbn)) {
-            if (DEBUG) {
-                Log.d(TAG, "Skipping HUN check for " + sbn.getKey() + " since it's filtered out.");
-            }
+            if (DEBUG) Log.d(TAG, "No peeking: filtered notification: " + sbn.getKey());
             return false;
         }
 
         if (isSnoozedPackage(sbn)) {
+            if (DEBUG) Log.d(TAG, "No peeking: snoozed package: " + sbn.getKey());
             return false;
         }
 
-        Notification notification = sbn.getNotification();
-        // some predicates to make the boolean logic legible
-        boolean isNoisy = (notification.defaults & Notification.DEFAULT_SOUND) != 0
-                || (notification.defaults & Notification.DEFAULT_VIBRATE) != 0
-                || notification.sound != null
-                || notification.vibrate != null;
-        boolean isHighPriority = sbn.getScore() >= INTERRUPTION_THRESHOLD;
-        boolean isFullscreen = notification.fullScreenIntent != null;
-        boolean hasTicker = mHeadsUpTicker && !TextUtils.isEmpty(notification.tickerText);
-        boolean accessibilityForcesLaunch = isFullscreen
-                && mAccessibilityManager.isTouchExplorationEnabled();
-        boolean justLaunchedFullScreenIntent = entry.hasJustLaunchedFullScreenIntent();
-        boolean interrupt = (isFullscreen || (isHighPriority && (isNoisy || hasTicker)))
-                && !accessibilityForcesLaunch
-                && !justLaunchedFullScreenIntent
-                && mPowerManager.isScreenOn()
+        if (entry.hasJustLaunchedFullScreenIntent()) {
+            if (DEBUG) Log.d(TAG, "No peeking: recent fullscreen: " + sbn.getKey());
+            return false;
+        }
+
+        if (sbn.getNotification().fullScreenIntent != null
+                && mAccessibilityManager.isTouchExplorationEnabled()) {
+            if (DEBUG) Log.d(TAG, "No peeking: accessible fullscreen: " + sbn.getKey());
+            return false;
+        }
+
+
+        if (mNotificationData.shouldSuppressPeek(sbn.getKey())) {
+            if (DEBUG) Log.d(TAG, "No peeking: suppressed by manager: " + sbn.getKey());
+            return false;
+        }
+
+        if (mNotificationData.getImportance(sbn.getKey()) < IMPORTANCE_MAX) {
+            if (DEBUG) Log.d(TAG, "No peeking: unimportant notification: " + sbn.getKey());
+            return false;
+        }
+
+        boolean inUse = mPowerManager.isScreenOn()
                 && (!mStatusBarKeyguardViewManager.isShowing()
                         || mStatusBarKeyguardViewManager.isOccluded())
-                && !mStatusBarKeyguardViewManager.isInputRestricted()
-                && !mNotificationData.shouldSuppressPeek(sbn.getKey());
+                && !mStatusBarKeyguardViewManager.isInputRestricted();
         try {
-            interrupt = interrupt && !mDreamManager.isDreaming();
+            inUse = inUse && !mDreamManager.isDreaming();
         } catch (RemoteException e) {
             Log.d(TAG, "failed to query dream manager", e);
         }
-        if (DEBUG) Log.d(TAG, "interrupt: " + interrupt);
-        return interrupt;
+        if (DEBUG) Log.d(TAG, "peek if device in use: " + inUse);
+        return inUse;
     }
 
     protected abstract boolean isSnoozedPackage(StatusBarNotification sbn);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
index d6f2ec8..b2fbe20 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
@@ -188,22 +188,33 @@
         public int compare(Entry a, Entry b) {
             final StatusBarNotification na = a.notification;
             final StatusBarNotification nb = b.notification;
-            final int aPriority = na.getNotification().priority;
-            final int bPriority = nb.getNotification().priority;
+            int aImportance = Ranking.IMPORTANCE_DEFAULT;
+            int bImportance = Ranking.IMPORTANCE_DEFAULT;
+            int aRank = 0;
+            int bRank = 0;
+
+            if (mRankingMap != null) {
+                // RankingMap as received from NoMan
+                mRankingMap.getRanking(a.key, mRankingA);
+                mRankingMap.getRanking(b.key, mRankingB);
+                aImportance = mRankingA.getImportance();
+                bImportance = mRankingB.getImportance();
+                aRank = mRankingA.getRank();
+                bRank = mRankingB.getRank();
+            }
 
             String mediaNotification = mEnvironment.getCurrentMediaNotificationKey();
 
             // PRIORITY_MIN media streams are allowed to drift to the bottom
             final boolean aMedia = a.key.equals(mediaNotification)
-                    && aPriority > Notification.PRIORITY_MIN;
+                    && aImportance > Ranking.IMPORTANCE_LOW;
             final boolean bMedia = b.key.equals(mediaNotification)
-                    && bPriority > Notification.PRIORITY_MIN;
+                    && bImportance > Ranking.IMPORTANCE_LOW;
 
-            boolean aSystemMax = aPriority >= Notification.PRIORITY_MAX &&
+            boolean aSystemMax = aImportance >= Ranking.IMPORTANCE_MAX &&
                     isSystemNotification(na);
-            boolean bSystemMax = bPriority >= Notification.PRIORITY_MAX &&
+            boolean bSystemMax = bImportance >= Ranking.IMPORTANCE_MAX &&
                     isSystemNotification(nb);
-            int d = nb.getScore() - na.getScore();
 
             boolean isHeadsUp = a.row.isHeadsUp();
             if (isHeadsUp != b.row.isHeadsUp()) {
@@ -217,13 +228,8 @@
             } else if (aSystemMax != bSystemMax) {
                 // Upsort PRIORITY_MAX system notifications
                 return aSystemMax ? -1 : 1;
-            } else if (mRankingMap != null) {
-                // RankingMap as received from NoMan
-                mRankingMap.getRanking(a.key, mRankingA);
-                mRankingMap.getRanking(b.key, mRankingB);
-                return mRankingA.getRank() - mRankingB.getRank();
-            } if (d != 0) {
-                return d;
+            } else if (aRank != bRank) {
+                return aRank - bRank;
             } else {
                 return (int) (nb.getNotification().when - na.getNotification().when);
             }
@@ -303,6 +309,14 @@
         return Ranking.IMPORTANCE_UNSPECIFIED;
     }
 
+    public int getImportance(String key) {
+        if (mRankingMap != null) {
+            mRankingMap.getRanking(key, mTmpRanking);
+            return mTmpRanking.getImportance();
+        }
+        return Ranking.IMPORTANCE_UNSPECIFIED;
+    }
+
     private void updateRankingAndSort(RankingMap ranking) {
         if (ranking != null) {
             mRankingMap = ranking;
@@ -398,12 +412,13 @@
     }
 
     private void dumpEntry(PrintWriter pw, String indent, int i, Entry e) {
+        mRankingMap.getRanking(e.key, mTmpRanking);
         pw.print(indent);
         pw.println("  [" + i + "] key=" + e.key + " icon=" + e.icon);
         StatusBarNotification n = e.notification;
         pw.print(indent);
-        pw.println("      pkg=" + n.getPackageName() + " id=" + n.getId() + " score=" +
-                n.getScore());
+        pw.println("      pkg=" + n.getPackageName() + " id=" + n.getId() + " importance=" +
+                mTmpRanking.getImportance());
         pw.print(indent);
         pw.println("      notification=" + n.getNotification());
         pw.print(indent);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 181e6aa..b854c80 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -1266,7 +1266,7 @@
         if (shadeEntry == null) {
             return;
         }
-        boolean isHeadsUped = mUseHeadsUp && shouldInterrupt(shadeEntry);
+        boolean isHeadsUped = mUseHeadsUp && shouldPeek(shadeEntry);
         if (isHeadsUped) {
             mHeadsUpManager.showNotification(shadeEntry);
             // Mark as seen immediately
@@ -2111,17 +2111,17 @@
 
     }
 
-    protected void updateHeadsUp(String key, Entry entry, boolean shouldInterrupt,
+    protected void updateHeadsUp(String key, Entry entry, boolean shouldPeek,
             boolean alertAgain) {
         final boolean wasHeadsUp = isHeadsUp(key);
         if (wasHeadsUp) {
-            if (!shouldInterrupt) {
+            if (!shouldPeek) {
                 // We don't want this to be interrupting anymore, lets remove it
                 mHeadsUpManager.removeNotification(key);
             } else {
                 mHeadsUpManager.updateNotification(entry, alertAgain);
             }
-        } else if (shouldInterrupt && alertAgain) {
+        } else if (shouldPeek && alertAgain) {
             // This notification was updated to be a heads-up, show it!
             mHeadsUpManager.showNotification(entry);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
index 39a2986..856a774 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
@@ -175,7 +175,7 @@
     }
 
     @Override
-    protected void updateHeadsUp(String key, NotificationData.Entry entry, boolean shouldInterrupt,
+    protected void updateHeadsUp(String key, NotificationData.Entry entry, boolean shouldPeek,
             boolean alertAgain) {
     }
 
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index 7fcedc6..353b404 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -1176,6 +1176,9 @@
                             if ("media".equals(packageName)) {
                                 pkgUid = Process.MEDIA_UID;
                                 isPrivileged = false;
+                            } else if ("audioserver".equals(packageName)) {
+                                pkgUid = Process.AUDIOSERVER_UID;
+                                isPrivileged = false;
                             }
                         }
                     } catch (RemoteException e) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 26ece54..9a185bb 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -490,6 +490,8 @@
 
     // Used to indicate that a task is removed it should also be removed from recents.
     private static final boolean REMOVE_FROM_RECENTS = true;
+    // Used to indicate that an app transition should be animated.
+    private static final boolean ANIMATE = true;
 
     private static native int nativeMigrateToBoost();
     private static native int nativeMigrateFromBoost();
@@ -4333,7 +4335,7 @@
                 if (task.stack.mStackId != launchStackId) {
                     mStackSupervisor.moveTaskToStackLocked(
                             taskId, launchStackId, ON_TOP, FORCE_FOCUS, "startActivityFromRecents",
-                            true /* animate */);
+                            ANIMATE);
                 }
             }
 
@@ -9314,7 +9316,7 @@
                 if (DEBUG_STACK) Slog.d(TAG_STACK, "moveActivityToStack: moving r=" + r
                         + " to stackId=" + stackId);
                 mStackSupervisor.moveTaskToStackLocked(r.task.taskId, stackId, ON_TOP, !FORCE_FOCUS,
-                        "moveActivityToStack", true /* animate */);
+                        "moveActivityToStack", ANIMATE);
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
@@ -9335,7 +9337,7 @@
                 if (DEBUG_STACK) Slog.d(TAG_STACK, "moveTaskToStack: moving task=" + taskId
                         + " to stackId=" + stackId + " toTop=" + toTop);
                 mStackSupervisor.moveTaskToStackLocked(taskId, stackId, toTop, !FORCE_FOCUS,
-                        "moveTaskToStack", true /* animate */);
+                        "moveTaskToStack", ANIMATE);
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
@@ -17779,20 +17781,20 @@
     }
 
     @Override
-    public void removeStack(int stackId) {
+    public void moveTasksToFullscreenStack(int fromStackId) {
         enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
-                "detahStack()");
-        if (stackId == HOME_STACK_ID) {
-            throw new IllegalArgumentException("Removing home stack is not allowed.");
+                "moveTasksToFullscreenStack()");
+        if (fromStackId == HOME_STACK_ID) {
+            throw new IllegalArgumentException("You can't move tasks from the home stack.");
         }
         synchronized (this) {
-            long origId = Binder.clearCallingIdentity();
-            ActivityStack stack = mStackSupervisor.getStack(stackId);
+            final long origId = Binder.clearCallingIdentity();
+            final ActivityStack stack = mStackSupervisor.getStack(fromStackId);
             if (stack != null) {
-                ArrayList<TaskRecord> tasks = stack.getAllTasks();
+                final ArrayList<TaskRecord> tasks = stack.getAllTasks();
                 for (int i = tasks.size() - 1; i >= 0; i--) {
-                    removeTaskByIdLocked(tasks.get(i).taskId, false /* killProcess */,
-                            !REMOVE_FROM_RECENTS);
+                    mStackSupervisor.positionTaskInStackLocked(tasks.get(i).taskId,
+                            FULLSCREEN_WORKSPACE_STACK_ID, 0);
                 }
             }
             Binder.restoreCallingIdentity(origId);
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 9e32efa..b6fc0cc 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -1359,6 +1359,13 @@
         final ActivityStack focusedStack = mStackSupervisor.getFocusedStack();
         final int focusedStackId = focusedStack.mStackId;
 
+        if (mStackId == FULLSCREEN_WORKSPACE_STACK_ID
+                && hasVisibleBehindActivity() && focusedStackId == HOME_STACK_ID) {
+            // The fullscreen stack should be visible if it has a visible behind activity behind
+            // the home stack that will be translucent.
+            return true;
+        }
+
         if (mStackId == DOCKED_STACK_ID) {
             // Docked stack is always visible, except in the case where the home activity
             // is the top running activity in the focused home stack.
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 4f2f486..40d01e7 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -197,7 +197,7 @@
     private static final int MSG_SET_DEVICE_VOLUME = 0;
     private static final int MSG_PERSIST_VOLUME = 1;
     private static final int MSG_PERSIST_RINGER_MODE = 3;
-    private static final int MSG_MEDIA_SERVER_DIED = 4;
+    private static final int MSG_AUDIO_SERVER_DIED = 4;
     private static final int MSG_PLAY_SOUND_EFFECT = 5;
     private static final int MSG_BTA2DP_DOCK_TIMEOUT = 6;
     private static final int MSG_LOAD_SOUND_EFFECTS = 7;
@@ -358,7 +358,7 @@
         public void onError(int error) {
             switch (error) {
             case AudioSystem.AUDIO_STATUS_SERVER_DIED:
-                sendMsg(mAudioHandler, MSG_MEDIA_SERVER_DIED,
+                sendMsg(mAudioHandler, MSG_AUDIO_SERVER_DIED,
                         SENDMSG_NOOP, 0, 0, null, 0);
                 break;
             default:
@@ -772,15 +772,15 @@
                 INDICATE_SYSTEM_READY_RETRY_DELAY_MS);
     }
 
-    public void onMediaServerDied() {
+    public void onAudioServerDied() {
         if (!mSystemReady ||
                 (AudioSystem.checkAudioFlinger() != AudioSystem.AUDIO_STATUS_OK)) {
-            Log.e(TAG, "Media server died.");
-            sendMsg(mAudioHandler, MSG_MEDIA_SERVER_DIED, SENDMSG_NOOP, 0, 0,
+            Log.e(TAG, "Audioserver died.");
+            sendMsg(mAudioHandler, MSG_AUDIO_SERVER_DIED, SENDMSG_NOOP, 0, 0,
                     null, 500);
             return;
         }
-        Log.e(TAG, "Media server started.");
+        Log.e(TAG, "Audioserver started.");
 
         // indicate to audio HAL that we start the reconfiguration phase after a media
         // server crash
@@ -4406,8 +4406,8 @@
                     persistRingerMode(getRingerModeInternal());
                     break;
 
-                case MSG_MEDIA_SERVER_DIED:
-                    onMediaServerDied();
+                case MSG_AUDIO_SERVER_DIED:
+                    onAudioServerDied();
                     break;
 
                 case MSG_UNLOAD_SOUND_EFFECTS:
diff --git a/services/core/java/com/android/server/notification/NotificationComparator.java b/services/core/java/com/android/server/notification/NotificationComparator.java
index ec81fd2..32db000 100644
--- a/services/core/java/com/android/server/notification/NotificationComparator.java
+++ b/services/core/java/com/android/server/notification/NotificationComparator.java
@@ -32,11 +32,11 @@
             return -1 * Integer.compare(leftPackagePriority, rightPackagePriority);
         }
 
-        final int leftScore = left.sbn.getScore();
-        final int rightScore = right.sbn.getScore();
-        if (leftScore != rightScore) {
+        final int leftImportance = left.getImportance();
+        final int rightImportance = right.getImportance();
+        if (leftImportance != rightImportance) {
             // by priority, high to low
-            return -1 * Integer.compare(leftScore, rightScore);
+            return -1 * Integer.compare(leftImportance, rightImportance);
         }
 
         final float leftPeople = left.getContactAffinity();
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 87108a4..07343a9 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -34,6 +34,7 @@
 import static android.service.notification.NotificationListenerService.SUPPRESSED_EFFECT_PEEK;
 import static android.service.notification.NotificationListenerService.TRIM_FULL;
 import static android.service.notification.NotificationListenerService.TRIM_LIGHT;
+import static  android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_HIGH;
 import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
 import static org.xmlpull.v1.XmlPullParser.END_TAG;
 import static org.xmlpull.v1.XmlPullParser.START_TAG;
@@ -181,16 +182,6 @@
     static final int VIBRATE_PATTERN_MAXLEN = 8 * 2 + 1; // up to eight bumps
 
     static final int DEFAULT_STREAM_TYPE = AudioManager.STREAM_NOTIFICATION;
-    static final boolean SCORE_ONGOING_HIGHER = false;
-
-    static final int JUNK_SCORE = -1000;
-    static final int NOTIFICATION_PRIORITY_MULTIPLIER = 10;
-    static final int SCORE_DISPLAY_THRESHOLD = Notification.PRIORITY_MIN * NOTIFICATION_PRIORITY_MULTIPLIER;
-
-    // Notifications with scores below this will not interrupt the user, either via LED or
-    // sound or vibration
-    static final int SCORE_INTERRUPTION_THRESHOLD =
-            Notification.PRIORITY_LOW * NOTIFICATION_PRIORITY_MULTIPLIER;
 
     static final boolean ENABLE_BLOCKED_NOTIFICATIONS = true;
     static final boolean ENABLE_BLOCKED_TOASTS = true;
@@ -2158,31 +2149,15 @@
 
                 synchronized (mNotificationList) {
 
-                    // === Scoring ===
-
-                    // 0. Sanitize inputs
+                    // Sanitize inputs
                     notification.priority = clamp(notification.priority, Notification.PRIORITY_MIN,
                             Notification.PRIORITY_MAX);
-                    // Migrate notification flags to scores
-                    if (0 != (notification.flags & Notification.FLAG_HIGH_PRIORITY)) {
-                        if (notification.priority < Notification.PRIORITY_MAX) {
-                            notification.priority = Notification.PRIORITY_MAX;
-                        }
-                    } else if (SCORE_ONGOING_HIGHER &&
-                            0 != (notification.flags & Notification.FLAG_ONGOING_EVENT)) {
-                        if (notification.priority < Notification.PRIORITY_HIGH) {
-                            notification.priority = Notification.PRIORITY_HIGH;
-                        }
-                    }
 
-                    // 1. initial score: buckets of 10, around the app [-20..20]
-                    final int score = notification.priority * NOTIFICATION_PRIORITY_MULTIPLIER;
-
-                    // 2. extract ranking signals from the notification data
+                    // setup local book-keeping
                     final StatusBarNotification n = new StatusBarNotification(
-                            pkg, opPkg, id, tag, callingUid, callingPid, score, notification,
+                            pkg, opPkg, id, tag, callingUid, callingPid, 0, notification,
                             user);
-                    NotificationRecord r = new NotificationRecord(n, score);
+                    NotificationRecord r = new NotificationRecord(getContext(), n);
                     NotificationRecord old = mNotificationsByKey.get(n.getKey());
                     if (old != null) {
                         // Retain ranking information from previous record
@@ -2217,23 +2192,16 @@
                     mRankingHelper.extractSignals(r);
                     savePolicyFile();
 
-                    // 3. Apply local rules
-
                     // blocked apps
                     if (ENABLE_BLOCKED_NOTIFICATIONS && !noteNotificationOp(pkg, callingUid)) {
                         if (!isSystemNotification) {
-                            r.score = JUNK_SCORE;
                             Slog.e(TAG, "Suppressing notification from package " + pkg
                                     + " by user request.");
                             mUsageStats.registerBlocked(r);
+                            return;
                         }
                     }
 
-                    if (r.score < SCORE_DISPLAY_THRESHOLD) {
-                        // Notification will be blocked because the score is too low.
-                        return;
-                    }
-
                     int index = indexOfNotificationLocked(n.getKey());
                     if (index < 0) {
                         mNotificationList.add(r);
@@ -2385,7 +2353,7 @@
         final Notification notification = record.sbn.getNotification();
 
         // Should this notification make noise, vibe, or use the LED?
-        final boolean aboveThreshold = record.score >= SCORE_INTERRUPTION_THRESHOLD;
+        final boolean aboveThreshold = record.getImportance() >= IMPORTANCE_HIGH;
         final boolean canInterrupt = aboveThreshold && !record.isIntercepted();
         if (DBG || record.isIntercepted())
             Slog.v(TAG,
@@ -3251,24 +3219,29 @@
         final int N = mNotificationList.size();
         ArrayList<String> keys = new ArrayList<String>(N);
         ArrayList<String> interceptedKeys = new ArrayList<String>(N);
+        ArrayList<Integer> importance = new ArrayList<>(N);
         Bundle visibilityOverrides = new Bundle();
         Bundle suppressedVisualEffects = new Bundle();
+        Bundle explanation = new Bundle();
         for (int i = 0; i < N; i++) {
             NotificationRecord record = mNotificationList.get(i);
             if (!isVisibleToListener(record.sbn, info)) {
                 continue;
             }
-            keys.add(record.sbn.getKey());
+            final String key = record.sbn.getKey();
+            keys.add(key);
+            importance.add(record.getImportance());
+            if (record.getImportanceExplanation() != null) {
+                explanation.putCharSequence(key, record.getImportanceExplanation());
+            }
             if (record.isIntercepted()) {
-                interceptedKeys.add(record.sbn.getKey());
+                interceptedKeys.add(key);
 
             }
-            suppressedVisualEffects.putInt(
-                    record.sbn.getKey(), record.getSuppressedVisualEffects());
+            suppressedVisualEffects.putInt(key, record.getSuppressedVisualEffects());
             if (record.getPackageVisibilityOverride()
                     != NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE) {
-                visibilityOverrides.putInt(record.sbn.getKey(),
-                        record.getPackageVisibilityOverride());
+                visibilityOverrides.putInt(key, record.getPackageVisibilityOverride());
             }
             // Find first min-prio notification for speedbump placement.
             if (speedBumpIndex == -1 &&
@@ -3283,10 +3256,15 @@
                 speedBumpIndex = keys.size() - 1;
             }
         }
-        String[] keysAr = keys.toArray(new String[keys.size()]);
+        final int M = keys.size();
+        String[] keysAr = keys.toArray(new String[M]);
         String[] interceptedKeysAr = interceptedKeys.toArray(new String[interceptedKeys.size()]);
+        int[] importanceAr = new int[M];
+        for (int i = 0; i < M; i++) {
+            importanceAr[i] = importance.get(i);
+        }
         return new NotificationRankingUpdate(keysAr, interceptedKeysAr, visibilityOverrides,
-                speedBumpIndex, suppressedVisualEffects);
+                speedBumpIndex, suppressedVisualEffects, importanceAr, explanation);
     }
 
     private boolean isVisibleToListener(StatusBarNotification sbn, ManagedServiceInfo listener) {
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index 3b7384e..463c0b0 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -15,6 +15,11 @@
  */
 package com.android.server.notification;
 
+import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_DEFAULT;
+import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_HIGH;
+import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_LOW;
+import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_MAX;
+
 import android.app.Notification;
 import android.content.Context;
 import android.content.pm.PackageManager.NameNotFoundException;
@@ -49,10 +54,10 @@
 public final class NotificationRecord {
     final StatusBarNotification sbn;
     final int mOriginalFlags;
+    private final Context mContext;
 
     NotificationUsageStats.SingleNotificationStats stats;
     boolean isCanceled;
-    int score;
     /** Whether the notification was seen by the user via one of the notification listeners. */
     boolean mIsSeen;
 
@@ -84,18 +89,71 @@
     private String mGlobalSortKey;
     private int mPackageVisibility;
     private int mTopicImportance = NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED;
+    private int mImportance = NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED;
+    private CharSequence mImportanceExplanation = null;
 
     private int mSuppressedVisualEffects = 0;
+    private String mTopicExplanation;
+    private String mPeopleExplanation;
 
     @VisibleForTesting
-    public NotificationRecord(StatusBarNotification sbn, int score)
+    public NotificationRecord(Context context, StatusBarNotification sbn)
     {
         this.sbn = sbn;
-        this.score = score;
         mOriginalFlags = sbn.getNotification().flags;
         mRankingTimeMs = calculateRankingTimeMs(0L);
         mCreationTimeMs = sbn.getPostTime();
         mUpdateTimeMs = mCreationTimeMs;
+        mContext = context;
+        mImportance = defaultImportance();
+    }
+
+    private int defaultImportance() {
+        final Notification n = sbn.getNotification();
+        int importance = IMPORTANCE_DEFAULT;
+
+        // Migrate notification flags to scores
+        if (0 != (n.flags & Notification.FLAG_HIGH_PRIORITY)) {
+            n.priority = Notification.PRIORITY_MAX;
+        }
+
+        switch (n.priority) {
+            case Notification.PRIORITY_MIN:
+            case Notification.PRIORITY_LOW:
+                importance = IMPORTANCE_LOW;
+                break;
+            case Notification.PRIORITY_DEFAULT:
+                importance = IMPORTANCE_DEFAULT;
+                break;
+            case Notification.PRIORITY_HIGH:
+                importance = IMPORTANCE_HIGH;
+                break;
+            case Notification.PRIORITY_MAX:
+                importance = IMPORTANCE_MAX;
+                break;
+        }
+
+        boolean isNoisy = (n.defaults & Notification.DEFAULT_SOUND) != 0
+                || (n.defaults & Notification.DEFAULT_VIBRATE) != 0
+                || n.sound != null
+                || n.vibrate != null;
+        if (!isNoisy && importance > IMPORTANCE_DEFAULT) {
+            importance = IMPORTANCE_DEFAULT;
+        }
+        // maybe only do this for target API < N?
+        if (isNoisy) {
+            if (importance == IMPORTANCE_HIGH) {
+                importance = IMPORTANCE_MAX;
+            } else {
+                importance = IMPORTANCE_HIGH;
+            }
+        }
+
+        if (n.fullScreenIntent != null) {
+            importance = IMPORTANCE_MAX;
+        }
+
+        return importance;
     }
 
     // copy any notes that the ranking system may have made before the update
@@ -109,6 +167,8 @@
         mCreationTimeMs = previous.mCreationTimeMs;
         mVisibleSinceMs = previous.mVisibleSinceMs;
         mTopicImportance = previous.mTopicImportance;
+        mImportance = previous.mImportance;
+        mImportanceExplanation = previous.mImportanceExplanation;
         // Don't copy mGlobalSortKey, recompute it.
     }
 
@@ -129,7 +189,7 @@
         pw.println(prefix + this);
         pw.println(prefix + "  uid=" + sbn.getUid() + " userId=" + sbn.getUserId());
         pw.println(prefix + "  icon=" + iconStr);
-        pw.println(prefix + "  pri=" + notification.priority + " score=" + sbn.getScore());
+        pw.println(prefix + "  pri=" + notification.priority);
         pw.println(prefix + "  key=" + sbn.getKey());
         pw.println(prefix + "  seen=" + mIsSeen);
         pw.println(prefix + "  groupKey=" + getGroupKey());
@@ -158,6 +218,7 @@
                         action.actionIntent.toString()
                         ));
             }
+            }
             pw.println(prefix + "  }");
         }
         if (notification.extras != null && notification.extras.size() > 0) {
@@ -200,6 +261,9 @@
         pw.println(prefix + "  mPackageVisibility=" + mPackageVisibility);
         pw.println(prefix + "  mTopicImportance="
                 + NotificationListenerService.Ranking.importanceToString(mTopicImportance));
+        pw.println(prefix + "  mImportance="
+                + NotificationListenerService.Ranking.importanceToString(mImportance));
+        pw.println(prefix + "  mImportanceExplanation=" + mImportanceExplanation);
         pw.println(prefix + "  mIntercept=" + mIntercept);
         pw.println(prefix + "  mGlobalSortKey=" + mGlobalSortKey);
         pw.println(prefix + "  mRankingTimeMs=" + mRankingTimeMs);
@@ -234,15 +298,19 @@
     @Override
     public final String toString() {
         return String.format(
-                "NotificationRecord(0x%08x: pkg=%s user=%s id=%d tag=%s score=%d key=%s: %s)",
+                "NotificationRecord(0x%08x: pkg=%s user=%s id=%d tag=%s importance=%d key=%s: %s)",
                 System.identityHashCode(this),
                 this.sbn.getPackageName(), this.sbn.getUser(), this.sbn.getId(),
-                this.sbn.getTag(), this.sbn.getScore(), this.sbn.getKey(),
+                this.sbn.getTag(), this.mImportance, this.sbn.getKey(),
                 this.sbn.getNotification());
     }
 
     public void setContactAffinity(float contactAffinity) {
         mContactAffinity = contactAffinity;
+        if (mImportance < IMPORTANCE_DEFAULT &&
+                mContactAffinity > ValidateNotificationPeople.VALID_CONTACT) {
+            setImportance(IMPORTANCE_DEFAULT, getPeopleExplanation());
+        }
     }
 
     public float getContactAffinity() {
@@ -276,6 +344,30 @@
     public void setTopicImportance(int importance) {
         if (importance != NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED) {
             mTopicImportance = importance;
+            applyTopicImportance();
+        }
+    }
+
+    private String getTopicExplanation() {
+        if (mTopicExplanation == null) {
+            mTopicExplanation =
+                    mContext.getString(com.android.internal.R.string.importance_from_topic);
+        }
+        return mTopicExplanation;
+    }
+
+    private String getPeopleExplanation() {
+        if (mPeopleExplanation == null) {
+            mPeopleExplanation =
+                    mContext.getString(com.android.internal.R.string.importance_from_person);
+        }
+        return mPeopleExplanation;
+    }
+
+    private void applyTopicImportance() {
+        if (mTopicImportance != NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED) {
+            mImportance = mTopicImportance;
+            mImportanceExplanation = getTopicExplanation();
         }
     }
 
@@ -283,6 +375,22 @@
         return mTopicImportance;
     }
 
+    public void setImportance(int importance, CharSequence explanation) {
+        if (importance != NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED) {
+            mImportance = importance;
+            mImportanceExplanation = explanation;
+        }
+        applyTopicImportance();
+    }
+
+    public int getImportance() {
+        return mImportance;
+    }
+
+    public CharSequence getImportanceExplanation() {
+        return mImportanceExplanation;
+    }
+
     public boolean setIntercepted(boolean intercept) {
         mIntercept = intercept;
         return mIntercept;
diff --git a/services/core/java/com/android/server/os/SchedulingPolicyService.java b/services/core/java/com/android/server/os/SchedulingPolicyService.java
index c0123bf..80faf473 100644
--- a/services/core/java/com/android/server/os/SchedulingPolicyService.java
+++ b/services/core/java/com/android/server/os/SchedulingPolicyService.java
@@ -40,12 +40,13 @@
     public int requestPriority(int pid, int tid, int prio) {
         //Log.i(TAG, "requestPriority(pid=" + pid + ", tid=" + tid + ", prio=" + prio + ")");
 
-        // Verify that caller is mediaserver, priority is in range, and that the
-        // callback thread specified by app belongs to the app that called mediaserver.
-        // Once we've verified that the caller is mediaserver, we can trust the pid but
+        // Verify that the caller uid is permitted, priority is in range,
+        // and that the callback thread specified by app belongs to the app that
+        // called mediaserver or audioserver.
+        // Once we've verified that the caller uid is permitted, we can trust the pid but
         // we can't trust the tid.  No need to explicitly check for pid == 0 || tid == 0,
         // since if not the case then the getThreadGroupLeader() test will also fail.
-        if (Binder.getCallingUid() != Process.MEDIA_UID || prio < PRIORITY_MIN ||
+        if (!isPermittedCallingUid() || prio < PRIORITY_MIN ||
                 prio > PRIORITY_MAX || Process.getThreadGroupLeader(tid) != pid) {
             return PackageManager.PERMISSION_DENIED;
         }
@@ -61,4 +62,14 @@
         return PackageManager.PERMISSION_GRANTED;
     }
 
+    private boolean isPermittedCallingUid() {
+        final int callingUid = Binder.getCallingUid();
+        switch (callingUid) {
+        case Process.AUDIOSERVER_UID: // fastcapture, fastmixer
+        case Process.MEDIA_UID: // camera
+            return true;
+        default:
+            return false;
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
index 816903e..9bbc3c1 100644
--- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
+++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
@@ -209,11 +209,13 @@
     }
 
     /**
-     * @return true if a restriction is settable by profile owner.
+     * @return true if a restriction is settable by profile owner.  Note it takes a user ID because
+     * some restrictions can be changed by PO only when it's running on the system user.
      */
-    public static boolean canProfileOwnerChange(String restriction) {
-        return !(IMMUTABLE_BY_OWNERS.contains(restriction)
-                || DEVICE_OWNER_ONLY_RESTRICTIONS.contains(restriction));
+    public static boolean canProfileOwnerChange(String restriction, int userId) {
+        return !IMMUTABLE_BY_OWNERS.contains(restriction)
+                && !(userId != UserHandle.USER_SYSTEM
+                    && DEVICE_OWNER_ONLY_RESTRICTIONS.contains(restriction));
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 0fc7142..5a589e3 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -521,7 +521,7 @@
         }
 
         WindowState appWin = this;
-        while (appWin.mAttachedWindow != null) {
+        while (appWin.isChildWindow()) {
             appWin = appWin.mAttachedWindow;
         }
         WindowToken appToken = appWin.mToken;
@@ -854,7 +854,7 @@
     @Override
     public int getBaseType() {
         WindowState win = this;
-        while (win.mAttachedWindow != null) {
+        while (win.isChildWindow()) {
             win = win.mAttachedWindow;
         }
         return win.mAttrs.type;
@@ -1235,7 +1235,7 @@
     void removeLocked() {
         disposeInputChannel();
 
-        if (mAttachedWindow != null) {
+        if (isChildWindow()) {
             if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Removing " + this + " from " + mAttachedWindow);
             mAttachedWindow.mChildWindows.remove(this);
         }
@@ -1682,7 +1682,7 @@
             // first frame very fast. Saving surfaces are mostly a waste of memory.
             // Don't save if the window is not the topmost window.
             mSurfaceSaved = false;
-        } else if (mAttachedWindow != null) {
+        } else if (isChildWindow()) {
             mSurfaceSaved = false;
         } else {
             mSurfaceSaved = mAppToken.shouldSaveSurface();
@@ -1733,7 +1733,7 @@
     boolean isHiddenFromUserLocked() {
         // Attached windows are evaluated based on the window that they are attached to.
         WindowState win = this;
-        while (win.mAttachedWindow != null) {
+        while (win.isChildWindow()) {
             win = win.mAttachedWindow;
         }
         if (win.mAttrs.type < WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW
@@ -1997,7 +1997,7 @@
             pw.print(prefix); pw.print("LastRequested w="); pw.print(mLastRequestedWidth);
                     pw.print(" h="); pw.println(mLastRequestedHeight);
         }
-        if (mAttachedWindow != null || mLayoutAttached) {
+        if (isChildWindow() || mLayoutAttached) {
             pw.print(prefix); pw.print("mAttachedWindow="); pw.print(mAttachedWindow);
                     pw.print(" mLayoutAttached="); pw.println(mLayoutAttached);
         }
@@ -2255,4 +2255,8 @@
         // Now make sure the window fits in the overall display frame.
         Gravity.applyDisplay(mAttrs.gravity, mDisplayFrame, mFrame);
     }
+
+    boolean isChildWindow() {
+        return mAttachedWindow != null;
+    }
 }
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 7cd67d0..539810d 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -1135,17 +1135,19 @@
         final boolean isFreeformResizing =
                 w.isDragResizing() && w.getResizeMode() == DRAG_RESIZE_MODE_FREEFORM;
         final Rect clipRect = mTmpClipRect;
-        if (isFreeformResizing) {
-            // When we're doing a drag-resizing, the surface is set up to cover full screen.
-            // Set the clip rect to be the same size so that we don't get any scaling.
-            clipRect.set(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight);
-        } else {
-            // We use the clip rect as provided by the tranformation for non-fullscreen windows to
-            // avoid premature clipping with the system decor rect.
-            clipRect.set((mHasClipRect && !fullscreen) ? mClipRect : mSystemDecorRect);
-            if (DEBUG_WINDOW_CROP) Slog.d(TAG, "Initial clip rect: " + clipRect + ", mHasClipRect="
-                    + mHasClipRect + ", fullscreen=" + fullscreen);
+
+        // We use the clip rect as provided by the tranformation for non-fullscreen windows to
+        // avoid premature clipping with the system decor rect.
+        clipRect.set((mHasClipRect && !fullscreen) ? mClipRect : mSystemDecorRect);
+        if (DEBUG_WINDOW_CROP) Slog.d(TAG, "Initial clip rect: " + clipRect + ", mHasClipRect="
+                + mHasClipRect + ", fullscreen=" + fullscreen);
+
+        if (isFreeformResizing && !w.isChildWindow()) {
+            // For freeform resizing non child windows, we are using the big surface positioned
+            // at 0,0. Thus we must express the crop in that coordinate space.
+            clipRect.offset(w.mShownPosition.x, w.mShownPosition.y);
         }
+
         // Expand the clip rect for surface insets.
         final WindowManager.LayoutParams attrs = w.mAttrs;
         clipRect.left -= attrs.surfaceInsets.left;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 5cf8ac0..c540e05 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -109,8 +109,6 @@
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.Log;
-import android.util.PrintWriterPrinter;
-import android.util.Printer;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.Xml;
@@ -1752,11 +1750,7 @@
 
         try {
             return new DeviceAdminInfo(mContext, ri);
-        } catch (XmlPullParserException e) {
-            Slog.w(LOG_TAG, "Bad device admin requested for user=" + userHandle + ": " + adminName,
-                    e);
-            return null;
-        } catch (IOException e) {
+        } catch (XmlPullParserException | IOException e) {
             Slog.w(LOG_TAG, "Bad device admin requested for user=" + userHandle + ": " + adminName,
                     e);
             return null;
@@ -1994,18 +1988,11 @@
                     XmlUtils.skipCurrentTag(parser);
                 }
             }
-        } catch (NullPointerException e) {
-            Slog.w(LOG_TAG, "failed parsing " + file + " " + e);
-        } catch (NumberFormatException e) {
-            Slog.w(LOG_TAG, "failed parsing " + file + " " + e);
-        } catch (XmlPullParserException e) {
-            Slog.w(LOG_TAG, "failed parsing " + file + " " + e);
         } catch (FileNotFoundException e) {
             // Don't be noisy, this is normal if we haven't defined any policies.
-        } catch (IOException e) {
-            Slog.w(LOG_TAG, "failed parsing " + file + " " + e);
-        } catch (IndexOutOfBoundsException e) {
-            Slog.w(LOG_TAG, "failed parsing " + file + " " + e);
+        } catch (NullPointerException | NumberFormatException | XmlPullParserException | IOException
+                | IndexOutOfBoundsException e) {
+            Slog.w(LOG_TAG, "failed parsing " + file, e);
         }
         try {
             if (stream != null) {
@@ -5807,7 +5794,7 @@
                     throw new SecurityException("Device owner cannot set user restriction " + key);
                 }
             } else { // profile owner
-                if (!UserRestrictionsUtils.canProfileOwnerChange(key)) {
+                if (!UserRestrictionsUtils.canProfileOwnerChange(key, userHandle)) {
                     throw new SecurityException("Profile owner cannot set user restriction " + key);
                 }
             }
diff --git a/services/tests/servicestests/src/com/android/server/notification/RankingHelperTest.java b/services/tests/servicestests/src/com/android/server/notification/RankingHelperTest.java
index d0065cd..df7b412 100644
--- a/services/tests/servicestests/src/com/android/server/notification/RankingHelperTest.java
+++ b/services/tests/servicestests/src/com/android/server/notification/RankingHelperTest.java
@@ -64,8 +64,8 @@
                 .setWhen(1205)
                 .setTopic(new Notification.Topic("A", "a"))
                 .build();
-        mRecordGroupGSortA = new NotificationRecord(new StatusBarNotification(
-                "package", "package", 1, null, 0, 0, 0, mNotiGroupGSortA, user), 0);
+        mRecordGroupGSortA = new NotificationRecord(getContext(), new StatusBarNotification(
+                "package", "package", 1, null, 0, 0, 0, mNotiGroupGSortA, user));
 
         mNotiGroupGSortB = new Notification.Builder(getContext())
                 .setContentTitle("B")
@@ -74,24 +74,24 @@
                 .setWhen(1200)
                 .setTopic(new Notification.Topic("A", "a"))
                 .build();
-        mRecordGroupGSortB = new NotificationRecord(new StatusBarNotification(
-                "package", "package", 1, null, 0, 0, 0, mNotiGroupGSortB, user), 0);
+        mRecordGroupGSortB = new NotificationRecord(getContext(), new StatusBarNotification(
+                "package", "package", 1, null, 0, 0, 0, mNotiGroupGSortB, user));
 
         mNotiNoGroup = new Notification.Builder(getContext())
                 .setContentTitle("C")
                 .setWhen(1201)
                 .setTopic(new Notification.Topic("C", "c"))
                 .build();
-        mRecordNoGroup = new NotificationRecord(new StatusBarNotification(
-                "package", "package", 1, null, 0, 0, 0, mNotiNoGroup, user), 0);
+        mRecordNoGroup = new NotificationRecord(getContext(), new StatusBarNotification(
+                "package", "package", 1, null, 0, 0, 0, mNotiNoGroup, user));
 
         mNotiNoGroup2 = new Notification.Builder(getContext())
                 .setContentTitle("D")
                 .setWhen(1202)
                 .setTopic(new Notification.Topic("D", "d"))
                 .build();
-        mRecordNoGroup2 = new NotificationRecord(new StatusBarNotification(
-                "package", "package", 1, null, 0, 0, 0, mNotiNoGroup2, user), 0);
+        mRecordNoGroup2 = new NotificationRecord(getContext(), new StatusBarNotification(
+                "package", "package", 1, null, 0, 0, 0, mNotiNoGroup2, user));
 
         mNotiNoGroupSortA = new Notification.Builder(getContext())
                 .setContentTitle("E")
@@ -99,8 +99,8 @@
                 .setSortKey("A")
                 .setTopic(new Notification.Topic("E", "e"))
                 .build();
-        mRecordNoGroupSortA = new NotificationRecord(new StatusBarNotification(
-                "package", "package", 1, null, 0, 0, 0, mNotiNoGroupSortA, user), 0);
+        mRecordNoGroupSortA = new NotificationRecord(getContext(), new StatusBarNotification(
+                "package", "package", 1, null, 0, 0, 0, mNotiNoGroupSortA, user));
     }
 
     @SmallTest
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserRestrictionsUtilsTest.java b/services/tests/servicestests/src/com/android/server/pm/UserRestrictionsUtilsTest.java
index 5542a4f..5bdf6f7 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserRestrictionsUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserRestrictionsUtilsTest.java
@@ -16,6 +16,7 @@
 
 package com.android.server.pm;
 
+import android.os.UserHandle;
 import com.android.server.devicepolicy.DpmTestUtils;
 
 import android.os.Bundle;
@@ -87,10 +88,25 @@
     }
 
     public void testCanProfileOwnerChange() {
-        assertFalse(UserRestrictionsUtils.canProfileOwnerChange(UserManager.DISALLOW_RECORD_AUDIO));
-        assertFalse(UserRestrictionsUtils.canProfileOwnerChange(UserManager.DISALLOW_WALLPAPER));
-        assertFalse(UserRestrictionsUtils.canProfileOwnerChange(UserManager.DISALLOW_ADD_USER));
-        assertTrue(UserRestrictionsUtils.canProfileOwnerChange(UserManager.DISALLOW_ADJUST_VOLUME));
+        int user = UserHandle.USER_SYSTEM;
+        assertFalse(UserRestrictionsUtils.canProfileOwnerChange(
+                UserManager.DISALLOW_RECORD_AUDIO, user));
+        assertFalse(UserRestrictionsUtils.canProfileOwnerChange(
+                UserManager.DISALLOW_WALLPAPER, user));
+        assertTrue(UserRestrictionsUtils.canProfileOwnerChange(
+                UserManager.DISALLOW_ADD_USER, user));
+        assertTrue(UserRestrictionsUtils.canProfileOwnerChange(
+                UserManager.DISALLOW_ADJUST_VOLUME, user));
+
+        user = 10;
+        assertFalse(UserRestrictionsUtils.canProfileOwnerChange(
+                UserManager.DISALLOW_RECORD_AUDIO, user));
+        assertFalse(UserRestrictionsUtils.canProfileOwnerChange(
+                UserManager.DISALLOW_WALLPAPER, user));
+        assertFalse(UserRestrictionsUtils.canProfileOwnerChange(
+                UserManager.DISALLOW_ADD_USER, user));
+        assertTrue(UserRestrictionsUtils.canProfileOwnerChange(
+                UserManager.DISALLOW_ADJUST_VOLUME, user));
     }
 
     public void testSortToGlobalAndLocal() {
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderDrawable.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderDrawable.java
index 26f9000..d797eec 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderDrawable.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderDrawable.java
@@ -42,10 +42,6 @@
 import java.util.Collections;
 import java.util.List;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
 /**
  * Action to render a given Drawable provided through {@link DrawableParams#getDrawable()}.
  *
@@ -72,8 +68,12 @@
         BridgeContext context = getContext();
         drawableResource = context.getRenderResources().resolveResValue(drawableResource);
 
-        if (drawableResource == null ||
-                drawableResource.getResourceType() != ResourceType.DRAWABLE) {
+        if (drawableResource == null) {
+            return Status.ERROR_NOT_A_DRAWABLE.createResult();
+        }
+
+        ResourceType resourceType = drawableResource.getResourceType();
+        if (resourceType != ResourceType.DRAWABLE && resourceType != ResourceType.MIPMAP) {
             return Status.ERROR_NOT_A_DRAWABLE.createResult();
         }