Merge "Fixed some issues with tasks with the same affinity in different stacks"
diff --git a/Android.mk b/Android.mk
index a098379..51dfa57 100644
--- a/Android.mk
+++ b/Android.mk
@@ -226,6 +226,7 @@
 	core/java/android/service/carrier/ICarrierMessagingService.aidl \
 	core/java/android/service/gatekeeper/IGateKeeperService.aidl \
 	core/java/android/service/notification/INotificationListener.aidl \
+	core/java/android/service/notification/INotificationAssistant.aidl \
 	core/java/android/service/notification/IStatusBarNotificationHolder.aidl \
 	core/java/android/service/notification/IConditionListener.aidl \
 	core/java/android/service/notification/IConditionProvider.aidl \
diff --git a/api/current.txt b/api/current.txt
index 5421f05..e4962d8 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -30919,6 +30919,7 @@
     field public static final java.lang.String ACTION_LOCATION_SOURCE_SETTINGS = "android.settings.LOCATION_SOURCE_SETTINGS";
     field public static final java.lang.String ACTION_MANAGE_ALL_APPLICATIONS_SETTINGS = "android.settings.MANAGE_ALL_APPLICATIONS_SETTINGS";
     field public static final java.lang.String ACTION_MANAGE_APPLICATIONS_SETTINGS = "android.settings.MANAGE_APPLICATIONS_SETTINGS";
+    field public static final java.lang.String ACTION_MANAGE_DEFAULT_APPS_SETTINGS = "android.settings.MANAGE_DEFAULT_APPS_SETTINGS";
     field public static final java.lang.String ACTION_MANAGE_OVERLAY_PERMISSION = "android.settings.action.MANAGE_OVERLAY_PERMISSION";
     field public static final java.lang.String ACTION_MANAGE_WRITE_SETTINGS = "android.settings.action.MANAGE_WRITE_SETTINGS";
     field public static final java.lang.String ACTION_MEMORY_CARD_SETTINGS = "android.settings.MEMORY_CARD_SETTINGS";
@@ -33195,13 +33196,20 @@
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.ConditionProviderService";
   }
 
+  public class NotificationAdjustment implements android.os.Parcelable {
+    ctor public NotificationAdjustment(int, java.lang.CharSequence, android.net.Uri);
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.service.notification.NotificationAdjustment> CREATOR;
+  }
+
   public abstract class NotificationAssistantService extends android.service.notification.NotificationListenerService {
     ctor public NotificationAssistantService();
-    method public final void adjustImportance(java.lang.String, android.service.notification.NotificationAssistantService.Adjustment);
+    method public final void adjustImportance(java.lang.String, android.service.notification.NotificationAdjustment);
     method public final void clearAnnotation(java.lang.String);
     method public void onNotificationActionClick(java.lang.String, long, int);
     method public void onNotificationClick(java.lang.String, long);
-    method public abstract android.service.notification.NotificationAssistantService.Adjustment onNotificationEnqueued(android.service.notification.StatusBarNotification, int, boolean);
+    method public abstract android.service.notification.NotificationAdjustment onNotificationEnqueued(android.service.notification.StatusBarNotification, int, boolean);
     method public void onNotificationRemoved(java.lang.String, long, int);
     method public void onNotificationVisibilityChanged(java.lang.String, long, boolean);
     method public final void setAnnotation(java.lang.String, android.app.Notification);
@@ -33218,10 +33226,7 @@
     field public static final int REASON_PACKAGE_BANNED = 7; // 0x7
     field public static final int REASON_PACKAGE_CHANGED = 5; // 0x5
     field public static final int REASON_USER_STOPPED = 6; // 0x6
-  }
-
-  public class NotificationAssistantService.Adjustment {
-    ctor public NotificationAssistantService.Adjustment(int, java.lang.CharSequence, android.net.Uri);
+    field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.NotificationAssistantService";
   }
 
   public abstract class NotificationListenerService extends android.app.Service {
diff --git a/api/system-current.txt b/api/system-current.txt
index 3071fd9..586ea06 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -9656,7 +9656,6 @@
     method public void setAppLabel(java.lang.CharSequence);
     method public void setAppPackageName(java.lang.String);
     method public void setGrantedRuntimePermissions(java.lang.String[]);
-    method public void setInstallFlagsQuick();
     method public void setInstallLocation(int);
     method public void setOriginatingUid(int);
     method public void setOriginatingUri(android.net.Uri);
@@ -33062,6 +33061,7 @@
     field public static final java.lang.String ACTION_LOCATION_SOURCE_SETTINGS = "android.settings.LOCATION_SOURCE_SETTINGS";
     field public static final java.lang.String ACTION_MANAGE_ALL_APPLICATIONS_SETTINGS = "android.settings.MANAGE_ALL_APPLICATIONS_SETTINGS";
     field public static final java.lang.String ACTION_MANAGE_APPLICATIONS_SETTINGS = "android.settings.MANAGE_APPLICATIONS_SETTINGS";
+    field public static final java.lang.String ACTION_MANAGE_DEFAULT_APPS_SETTINGS = "android.settings.MANAGE_DEFAULT_APPS_SETTINGS";
     field public static final java.lang.String ACTION_MANAGE_OVERLAY_PERMISSION = "android.settings.action.MANAGE_OVERLAY_PERMISSION";
     field public static final java.lang.String ACTION_MANAGE_WRITE_SETTINGS = "android.settings.action.MANAGE_WRITE_SETTINGS";
     field public static final java.lang.String ACTION_MEMORY_CARD_SETTINGS = "android.settings.MEMORY_CARD_SETTINGS";
@@ -35339,13 +35339,20 @@
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.ConditionProviderService";
   }
 
+  public class NotificationAdjustment implements android.os.Parcelable {
+    ctor public NotificationAdjustment(int, java.lang.CharSequence, android.net.Uri);
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.service.notification.NotificationAdjustment> CREATOR;
+  }
+
   public abstract class NotificationAssistantService extends android.service.notification.NotificationListenerService {
     ctor public NotificationAssistantService();
-    method public final void adjustImportance(java.lang.String, android.service.notification.NotificationAssistantService.Adjustment);
+    method public final void adjustImportance(java.lang.String, android.service.notification.NotificationAdjustment);
     method public final void clearAnnotation(java.lang.String);
     method public void onNotificationActionClick(java.lang.String, long, int);
     method public void onNotificationClick(java.lang.String, long);
-    method public abstract android.service.notification.NotificationAssistantService.Adjustment onNotificationEnqueued(android.service.notification.StatusBarNotification, int, boolean);
+    method public abstract android.service.notification.NotificationAdjustment onNotificationEnqueued(android.service.notification.StatusBarNotification, int, boolean);
     method public void onNotificationRemoved(java.lang.String, long, int);
     method public void onNotificationVisibilityChanged(java.lang.String, long, boolean);
     method public final void setAnnotation(java.lang.String, android.app.Notification);
@@ -35362,10 +35369,7 @@
     field public static final int REASON_PACKAGE_BANNED = 7; // 0x7
     field public static final int REASON_PACKAGE_CHANGED = 5; // 0x5
     field public static final int REASON_USER_STOPPED = 6; // 0x6
-  }
-
-  public class NotificationAssistantService.Adjustment {
-    ctor public NotificationAssistantService.Adjustment(int, java.lang.CharSequence, android.net.Uri);
+    field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.NotificationAssistantService";
   }
 
   public abstract class NotificationListenerService extends android.app.Service {
diff --git a/api/test-current.txt b/api/test-current.txt
index f418d36..eccd8b0 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -30921,6 +30921,7 @@
     field public static final java.lang.String ACTION_LOCATION_SOURCE_SETTINGS = "android.settings.LOCATION_SOURCE_SETTINGS";
     field public static final java.lang.String ACTION_MANAGE_ALL_APPLICATIONS_SETTINGS = "android.settings.MANAGE_ALL_APPLICATIONS_SETTINGS";
     field public static final java.lang.String ACTION_MANAGE_APPLICATIONS_SETTINGS = "android.settings.MANAGE_APPLICATIONS_SETTINGS";
+    field public static final java.lang.String ACTION_MANAGE_DEFAULT_APPS_SETTINGS = "android.settings.MANAGE_DEFAULT_APPS_SETTINGS";
     field public static final java.lang.String ACTION_MANAGE_OVERLAY_PERMISSION = "android.settings.action.MANAGE_OVERLAY_PERMISSION";
     field public static final java.lang.String ACTION_MANAGE_WRITE_SETTINGS = "android.settings.action.MANAGE_WRITE_SETTINGS";
     field public static final java.lang.String ACTION_MEMORY_CARD_SETTINGS = "android.settings.MEMORY_CARD_SETTINGS";
@@ -33197,13 +33198,20 @@
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.ConditionProviderService";
   }
 
+  public class NotificationAdjustment implements android.os.Parcelable {
+    ctor public NotificationAdjustment(int, java.lang.CharSequence, android.net.Uri);
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.service.notification.NotificationAdjustment> CREATOR;
+  }
+
   public abstract class NotificationAssistantService extends android.service.notification.NotificationListenerService {
     ctor public NotificationAssistantService();
-    method public final void adjustImportance(java.lang.String, android.service.notification.NotificationAssistantService.Adjustment);
+    method public final void adjustImportance(java.lang.String, android.service.notification.NotificationAdjustment);
     method public final void clearAnnotation(java.lang.String);
     method public void onNotificationActionClick(java.lang.String, long, int);
     method public void onNotificationClick(java.lang.String, long);
-    method public abstract android.service.notification.NotificationAssistantService.Adjustment onNotificationEnqueued(android.service.notification.StatusBarNotification, int, boolean);
+    method public abstract android.service.notification.NotificationAdjustment onNotificationEnqueued(android.service.notification.StatusBarNotification, int, boolean);
     method public void onNotificationRemoved(java.lang.String, long, int);
     method public void onNotificationVisibilityChanged(java.lang.String, long, boolean);
     method public final void setAnnotation(java.lang.String, android.app.Notification);
@@ -33220,10 +33228,7 @@
     field public static final int REASON_PACKAGE_BANNED = 7; // 0x7
     field public static final int REASON_PACKAGE_CHANGED = 5; // 0x5
     field public static final int REASON_USER_STOPPED = 6; // 0x6
-  }
-
-  public class NotificationAssistantService.Adjustment {
-    ctor public NotificationAssistantService.Adjustment(int, java.lang.CharSequence, android.net.Uri);
+    field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.NotificationAssistantService";
   }
 
   public abstract class NotificationListenerService extends android.app.Service {
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 571bc6e..4ed2fd7 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -5300,8 +5300,7 @@
      */
     public boolean isTaskRoot() {
         try {
-            return ActivityManagerNative.getDefault()
-                .getTaskForActivity(mToken, true) >= 0;
+            return ActivityManagerNative.getDefault().getTaskForActivity(mToken, true) >= 0;
         } catch (RemoteException e) {
             return false;
         }
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 136b810..bce5bf3 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -54,6 +54,7 @@
     int getTopicPriority(String pkg, int uid, in Notification.Topic topic);
     void setTopicImportance(String pkg, int uid, in Notification.Topic topic, int importance);
     int getTopicImportance(String pkg, int uid, in Notification.Topic topic);
+    void setAppImportance(String pkg, int uid, int importance);
 
     // TODO: Remove this when callers have been migrated to the equivalent
     // INotificationListener method.
diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java
index cbce22c..6bf3fab 100644
--- a/core/java/android/bluetooth/BluetoothProfile.java
+++ b/core/java/android/bluetooth/BluetoothProfile.java
@@ -131,6 +131,18 @@
     public static final int HEADSET_CLIENT = 16;
 
     /**
+     * HID Profile
+     * @hide
+     */
+    public static final int HID = 17;
+
+    /**
+     * HDP Profile
+     * @hide
+     */
+    public static final int HDP = 18;
+
+    /**
      * Default priority for devices that we try to auto-connect to and
      * and allow incoming connections for the profile
      * @hide
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index d6d395b..3283005 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -1042,12 +1042,6 @@
         }
 
         /** {@hide} */
-        @SystemApi
-        public void setInstallFlagsQuick() {
-            installFlags |= PackageManager.INSTALL_QUICK;
-        }
-
-        /** {@hide} */
         public void dump(IndentingPrintWriter pw) {
             pw.printPair("mode", mode);
             pw.printHexPair("installFlags", installFlags);
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 3e7deb9..40bcc7e 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -457,19 +457,11 @@
 
     /**
      * Flag parameter for {@link #installPackage} to indicate that this package is
-     * to be installed quickly.
-     *
-     * @hide
-     */
-    public static final int INSTALL_QUICK = 0x00000800;
-
-    /**
-     * Flag parameter for {@link #installPackage} to indicate that this package is
      * to be installed as a lightweight "ephemeral" app.
      *
      * @hide
      */
-    public static final int INSTALL_EPHEMERAL = 0x00001000;
+    public static final int INSTALL_EPHEMERAL = 0x00000800;
 
     /**
      * Flag parameter for
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 019ed2b..f445cf8 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -625,9 +625,7 @@
     public final static int PARSE_COLLECT_CERTIFICATES = 1<<8;
     public final static int PARSE_TRUSTED_OVERLAY = 1<<9;
     public final static int PARSE_ENFORCE_CODE = 1<<10;
-    // TODO: fix b/25118622; remove this entirely once signature processing is quick
-    public final static int PARSE_SKIP_VERIFICATION = 1<<11;
-    public final static int PARSE_IS_EPHEMERAL = 1<<12;
+    public final static int PARSE_IS_EPHEMERAL = 1<<11;
 
     private static final Comparator<String> sSplitNameComparator = new SplitNameComparator();
 
@@ -1060,8 +1058,7 @@
 
     /**
      * Collect certificates from all the APKs described in the given package,
-     * populating {@link Package#mSignatures}.
-     * <p>Depending upon the parser flags, this may also asserts that all APK
+     * populating {@link Package#mSignatures}. Also asserts that all APK
      * contents are signed correctly and consistently.
      */
     public void collectCertificates(Package pkg, int parseFlags) throws PackageParserException {
@@ -1084,10 +1081,8 @@
         final boolean hasCode = (apkFlags & ApplicationInfo.FLAG_HAS_CODE) != 0;
         final boolean requireCode = ((parseFlags & PARSE_ENFORCE_CODE) != 0) && hasCode;
         final String apkPath = apkFile.getAbsolutePath();
-        final boolean skipVerification = Build.IS_DEBUGGABLE
-                && ((parseFlags & PARSE_SKIP_VERIFICATION) != 0);
 
-        boolean codeFound = skipVerification;
+        boolean codeFound = false;
         StrictJarFile jarFile = null;
         try {
             Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "strictJarFileCtor");
@@ -1106,7 +1101,7 @@
             toVerify.add(manifestEntry);
 
             // If we're parsing an untrusted package, verify all contents
-            if (!skipVerification && (parseFlags & PARSE_IS_SYSTEM) == 0) {
+            if ((parseFlags & PARSE_IS_SYSTEM) == 0) {
                 final Iterator<ZipEntry> i = jarFile.iterator();
                 while (i.hasNext()) {
                     final ZipEntry entry = i.next();
@@ -1150,9 +1145,6 @@
                     for (int i=0; i < entryCerts.length; i++) {
                         pkg.mSigningKeys.add(entryCerts[i][0].getPublicKey());
                     }
-                    if (skipVerification) {
-                        break;
-                    }
                 } else {
                     if (!Signature.areExactMatch(pkg.mSignatures, entrySignatures)) {
                         throw new PackageParserException(
@@ -1218,9 +1210,7 @@
             if ((flags & PARSE_COLLECT_CERTIFICATES) != 0) {
                 // TODO: factor signature related items out of Package object
                 final Package tempPkg = new Package(null);
-                // TODO: fix b/25118622; pass in '0' for parse flags
-                collectCertificates(tempPkg, apkFile, 0 /*apkFlags*/,
-                        flags & PARSE_SKIP_VERIFICATION);
+                collectCertificates(tempPkg, apkFile, 0 /*apkFlags*/, 0 /*flags*/);
                 signatures = tempPkg.mSignatures;
             } else {
                 signatures = null;
diff --git a/core/java/android/os/BaseBundle.java b/core/java/android/os/BaseBundle.java
index cd483b1..ee7bd9a 100644
--- a/core/java/android/os/BaseBundle.java
+++ b/core/java/android/os/BaseBundle.java
@@ -32,7 +32,9 @@
     private static final String TAG = "Bundle";
     static final boolean DEBUG = false;
 
+    // Keep in sync with frameworks/native/libs/binder/PersistableBundle.cpp.
     static final int BUNDLE_MAGIC = 0x4C444E42; // 'B' 'N' 'D' 'L'
+
     static final Parcel EMPTY_PARCEL;
 
     static {
@@ -1308,6 +1310,8 @@
      * @param parcel The parcel to copy this bundle to.
      */
     void writeToParcelInner(Parcel parcel, int flags) {
+        // Keep implementation in sync with writeToParcel() in
+        // frameworks/native/libs/binder/PersistableBundle.cpp.
         if (mParcelledData != null) {
             if (mParcelledData == EMPTY_PARCEL) {
                 parcel.writeInt(0);
@@ -1345,6 +1349,8 @@
      * @param parcel The parcel to overwrite this bundle from.
      */
     void readFromParcelInner(Parcel parcel) {
+        // Keep implementation in sync with readFromParcel() in
+        // frameworks/native/libs/binder/PersistableBundle.cpp.
         int length = parcel.readInt();
         readFromParcelInner(parcel, length);
     }
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 9b68f90..2631247 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -204,6 +204,7 @@
     private static final Parcel[] sOwnedPool = new Parcel[POOL_SIZE];
     private static final Parcel[] sHolderPool = new Parcel[POOL_SIZE];
 
+    // Keep in sync with frameworks/native/libs/binder/PersistableBundle.cpp.
     private static final int VAL_NULL = -1;
     private static final int VAL_STRING = 0;
     private static final int VAL_INTEGER = 1;
@@ -704,6 +705,8 @@
             writeInt(-1);
             return;
         }
+        // Keep the format of this Parcel in sync with writeToParcelInner() in
+        // frameworks/native/libs/binder/PersistableBundle.cpp.
         final int N = val.size();
         writeInt(N);
         if (DEBUG_ARRAY_MAP) {
@@ -1370,7 +1373,13 @@
             // Must be before Parcelable
             writeInt(VAL_BUNDLE);
             writeBundle((Bundle) v);
+        } else if (v instanceof PersistableBundle) {
+            writeInt(VAL_PERSISTABLEBUNDLE);
+            writePersistableBundle((PersistableBundle) v);
         } else if (v instanceof Parcelable) {
+            // IMPOTANT: cases for classes that implement Parcelable must
+            // come before the Parcelable case, so that their specific VAL_*
+            // types will be written.
             writeInt(VAL_PARCELABLE);
             writeParcelable((Parcelable) v, 0);
         } else if (v instanceof Short) {
@@ -1426,9 +1435,6 @@
         } else if (v instanceof Byte) {
             writeInt(VAL_BYTE);
             writeInt((Byte) v);
-        } else if (v instanceof PersistableBundle) {
-            writeInt(VAL_PERSISTABLEBUNDLE);
-            writePersistableBundle((PersistableBundle) v);
         } else if (v instanceof Size) {
             writeInt(VAL_SIZE);
             writeSize((Size) v);
diff --git a/core/java/android/os/PersistableBundle.aidl b/core/java/android/os/PersistableBundle.aidl
index 5b05873..94e8607 100644
--- a/core/java/android/os/PersistableBundle.aidl
+++ b/core/java/android/os/PersistableBundle.aidl
@@ -2,19 +2,19 @@
 **
 ** Copyright 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 
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
 **
-**     http://www.apache.org/licenses/LICENSE-2.0 
+**     http://www.apache.org/licenses/LICENSE-2.0
 **
-** Unless required by applicable law or agreed to in writing, software 
-** distributed under the License is distributed on an "AS IS" BASIS, 
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
-** See the License for the specific language governing permissions and 
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
 ** limitations under the License.
 */
 
 package android.os;
 
-parcelable PersistableBundle;
+parcelable PersistableBundle cpp_header "binder/PersistableBundle.h";
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index c5adafe..ddd16e2 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -852,9 +852,14 @@
      * @param user to retrieve the unlocked state for.
      */
     public boolean isUserUnlocked(UserHandle user) {
+        return isUserUnlocked(user.getIdentifier());
+    }
+
+    /** {@hide} */
+    public boolean isUserUnlocked(int userId) {
         try {
-            return ActivityManagerNative.getDefault().isUserRunning(
-                    user.getIdentifier(), ActivityManager.FLAG_AND_UNLOCKED);
+            return ActivityManagerNative.getDefault().isUserRunning(userId,
+                    ActivityManager.FLAG_AND_UNLOCKED);
         } catch (RemoteException e) {
             return false;
         }
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index a1e5510..b883f9c 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1092,6 +1092,22 @@
     public static final String ACTION_HOME_SETTINGS
             = "android.settings.HOME_SETTINGS";
 
+
+
+    /**
+     * Activity Action: Show Default apps settings.
+     * <p>
+     * In some cases, a matching Activity may not exist, so ensure you
+     * safeguard against this.
+     * <p>
+     * Input: Nothing.
+     * <p>
+     * Output: Nothing.
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_MANAGE_DEFAULT_APPS_SETTINGS
+            = "android.settings.MANAGE_DEFAULT_APPS_SETTINGS";
+
     /**
      * Activity Action: Show notification settings.
      *
@@ -5617,6 +5633,15 @@
         public static final String ASSIST_SCREENSHOT_ENABLED = "assist_screenshot_enabled";
 
         /**
+         * Names of the service component that the current user has explicitly allowed to
+         * see and change the importance of all of the user's notifications.
+         *
+         * @hide
+         */
+        public static final String ENABLED_NOTIFICATION_ASSISTANT
+                = "enabled_notification_assistant";
+
+        /**
          * Names of the service components that the current user has explicitly allowed to
          * see all of the user's notifications, separated by ':'.
          *
@@ -6108,6 +6133,13 @@
         public static final String AIRPLANE_MODE_TOGGLEABLE_RADIOS = "airplane_mode_toggleable_radios";
 
         /**
+         * A Long representing a bitmap of profiles that should be disabled when bluetooth starts.
+         * See {@link android.bluetooth.BluetoothProfile}.
+         * {@hide}
+         */
+        public static final String BLUETOOTH_DISABLED_PROFILES = "bluetooth_disabled_profiles";
+
+        /**
          * The policy for deciding when Wi-Fi should go to sleep (which will in
          * turn switch to using the mobile data as an Internet connection).
          * <p>
diff --git a/core/java/android/service/notification/INotificationAssistant.aidl b/core/java/android/service/notification/INotificationAssistant.aidl
new file mode 100644
index 0000000..5c5f358
--- /dev/null
+++ b/core/java/android/service/notification/INotificationAssistant.aidl
@@ -0,0 +1,37 @@
+/**
+ * Copyright (c) 2015, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.notification;
+
+import android.service.notification.NotificationAdjustment;
+import android.service.notification.IStatusBarNotificationHolder;
+import android.service.notification.NotificationRankingUpdate;
+
+/** @hide */
+interface INotificationAssistant
+{
+    void onListenerConnected(in NotificationRankingUpdate update);
+    void onNotificationPosted(in IStatusBarNotificationHolder notificationHolder,
+            in NotificationRankingUpdate update);
+    void onNotificationRankingUpdate(in NotificationRankingUpdate update);
+    void onListenerHintsChanged(int hints);
+    void onInterruptionFilterChanged(int interruptionFilter);
+    NotificationAdjustment onNotificationEnqueued(in IStatusBarNotificationHolder notificationHolder, int importance, boolean user);
+    void onNotificationVisibilityChanged(String key, long time, boolean visible);
+    void onNotificationClick(String key, long time);
+    void onNotificationActionClick(String key, long time, int actionIndex);
+    void onNotificationRemoved(String key, long time, int reason);
+}
\ No newline at end of file
diff --git a/core/java/android/service/notification/NotificationAdjustment.aidl b/core/java/android/service/notification/NotificationAdjustment.aidl
new file mode 100644
index 0000000..805fe2c
--- /dev/null
+++ b/core/java/android/service/notification/NotificationAdjustment.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2015, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.notification;
+
+parcelable NotificationAdjustment;
\ No newline at end of file
diff --git a/core/java/android/service/notification/NotificationAdjustment.java b/core/java/android/service/notification/NotificationAdjustment.java
new file mode 100644
index 0000000..c5f0db9
--- /dev/null
+++ b/core/java/android/service/notification/NotificationAdjustment.java
@@ -0,0 +1,57 @@
+package android.service.notification;
+
+import android.net.Uri;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+public class NotificationAdjustment implements Parcelable {
+    int mImportance;
+    CharSequence mExplanation;
+    Uri mReference;
+
+    /**
+     * Create a notification importance adjustment.
+     *
+     * @param importance The final importance of the notification.
+     * @param explanation A human-readable justification for the adjustment.
+     * @param reference A reference to an external object that augments the
+     *                  explanation, such as a
+     *                  {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI},
+     *                  or null.
+     */
+    public NotificationAdjustment(int importance, CharSequence explanation, Uri reference) {
+        mImportance = importance;
+        mExplanation = explanation;
+        mReference = reference;
+    }
+
+    private NotificationAdjustment(Parcel source) {
+        this(source.readInt(), source.readCharSequence(),
+                (Uri) source.readParcelable(NotificationAdjustment.class.getClassLoader()));
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(mImportance);
+        dest.writeCharSequence(mExplanation);
+        dest.writeParcelable(mReference, 0);
+    }
+
+    public static final Parcelable.Creator<NotificationAdjustment> CREATOR
+            = new Parcelable.Creator<NotificationAdjustment>() {
+        @Override
+        public NotificationAdjustment createFromParcel(Parcel source) {
+            return new NotificationAdjustment(source);
+        }
+
+        @Override
+        public NotificationAdjustment[] newArray(int size) {
+            return new NotificationAdjustment[size];
+        }
+    };
+}
diff --git a/core/java/android/service/notification/NotificationAssistantService.java b/core/java/android/service/notification/NotificationAssistantService.java
index 5d1317c..7ce5e1f 100644
--- a/core/java/android/service/notification/NotificationAssistantService.java
+++ b/core/java/android/service/notification/NotificationAssistantService.java
@@ -16,8 +16,12 @@
 
 package android.service.notification;
 
+import android.annotation.SdkConstant;
 import android.app.Notification;
+import android.content.Intent;
 import android.net.Uri;
+import android.os.Parcel;
+import android.os.Parcelable;
 
 /**
  * A service that helps the user manage notifications by modifying the
@@ -35,6 +39,13 @@
  * &lt;/service></pre>
  */
 public abstract class NotificationAssistantService extends NotificationListenerService {
+    /**
+     * The {@link Intent} that must be declared as handled by the service.
+     */
+    @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
+    public static final String SERVICE_INTERFACE
+            = "android.service.notification.NotificationAssistantService";
+
     /** Notification was canceled by the status bar reporting a click. */
     public static final int REASON_DELEGATE_CLICK = 1;
 
@@ -74,28 +85,6 @@
     /** Notification was canceled because it was an invisible member of a group. */
     public static final int REASON_GROUP_OPTIMIZATION = 13;
 
-    public class Adjustment {
-        int mImportance;
-        CharSequence mExplanation;
-        Uri mReference;
-
-        /**
-         * Create a notification importance adjustment.
-         *
-         * @param importance The final importance of the notification.
-         * @param explanation A human-readable justification for the adjustment.
-         * @param reference A reference to an external object that augments the
-         *                  explanation, such as a
-         *                  {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI},
-         *                  or null.
-         */
-        public Adjustment(int importance, CharSequence explanation, Uri reference) {
-            mImportance = importance;
-            mExplanation = explanation;
-            mReference = reference;
-        }
-    }
-
     /**
      * A notification was posted by an app. Called before alert.
      *
@@ -104,7 +93,7 @@
      * @param user true if the initial importance reflects an explicit user preference.
      * @return an adjustment or null to take no action, within 100ms.
      */
-    abstract public Adjustment onNotificationEnqueued(StatusBarNotification sbn,
+    abstract public NotificationAdjustment onNotificationEnqueued(StatusBarNotification sbn,
           int importance, boolean user);
 
     /**
@@ -161,7 +150,7 @@
      * @param key the notification key
      * @param adjustment the new importance with an explanation
      */
-    public final void adjustImportance(String key, Adjustment adjustment)
+    public final void adjustImportance(String key, NotificationAdjustment adjustment)
     {
         // TODO: pack up the adjustment and send it to the NotificationManager.
     }
diff --git a/core/java/android/service/quicksettings/TileService.java b/core/java/android/service/quicksettings/TileService.java
index fd2d5b0..d8787b4 100644
--- a/core/java/android/service/quicksettings/TileService.java
+++ b/core/java/android/service/quicksettings/TileService.java
@@ -77,6 +77,15 @@
     private Tile mTile;
     private IBinder mToken;
 
+    @Override
+    public void onDestroy() {
+        if (mListening) {
+            onStopListening();
+            mListening = false;
+        }
+        super.onDestroy();
+    }
+
     /**
      * Called when the user adds this tile to Quick Settings.
      * <p/>
@@ -197,10 +206,10 @@
                     mTile = (Tile) msg.obj;
                     break;
                 case MSG_TILE_ADDED:
-                    TileService.this.onTileRemoved();
+                    TileService.this.onTileAdded();
                     break;
                 case MSG_TILE_REMOVED:
-                    TileService.this.onTileAdded();
+                    TileService.this.onTileRemoved();
                     break;
                 case MSG_STOP_LISTENING:
                     if (mListening) {
diff --git a/core/java/android/util/StateSet.java b/core/java/android/util/StateSet.java
index c2a6a7a..051de8a 100644
--- a/core/java/android/util/StateSet.java
+++ b/core/java/android/util/StateSet.java
@@ -260,6 +260,12 @@
             case R.attr.state_enabled:
                 sb.append("E ");
                 break;
+            case R.attr.state_checked:
+                sb.append("C ");
+                break;
+            case R.attr.state_activated:
+                sb.append("A ");
+                break;
             }
         }
 
diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java
index 01d1566..6aa5e2f 100644
--- a/core/java/android/webkit/WebViewFactory.java
+++ b/core/java/android/webkit/WebViewFactory.java
@@ -134,6 +134,25 @@
     private static String TAG_SIGNATURE = "signature";
 
     /**
+     * Reads all signatures at the current depth (within the current provider) from the XML parser.
+     */
+    private static String[] readSignatures(XmlResourceParser parser) throws IOException,
+            XmlPullParserException {
+        List<String> signatures = new ArrayList<String>();
+        int outerDepth = parser.getDepth();
+        while(XmlUtils.nextElementWithin(parser, outerDepth)) {
+            if (parser.getName().equals(TAG_SIGNATURE)) {
+                // Parse the value within the signature tag
+                String signature = parser.nextText();
+                signatures.add(signature);
+            } else {
+                Log.e(LOGTAG, "Found an element in a webview provider that is not a signature");
+            }
+        }
+        return signatures.toArray(new String[signatures.size()]);
+    }
+
+    /**
      * Returns all packages declared in the framework resources as potential WebView providers.
      * @hide
      * */
@@ -161,9 +180,9 @@
                         throw new MissingWebViewPackageException(
                                 "WebView provider in framework resources missing description");
                     }
-                    String signature = parser.getAttributeValue(null, TAG_SIGNATURE);
                     webViewProviders.add(
-                            new WebViewProviderInfo(packageName, description, signature));
+                            new WebViewProviderInfo(packageName, description,
+                                readSignatures(parser)));
                 }
                 else {
                     Log.e(LOGTAG, "Found an element that is not a webview provider");
diff --git a/core/java/android/webkit/WebViewProviderInfo.java b/core/java/android/webkit/WebViewProviderInfo.java
index d5e3a230..7bad652 100644
--- a/core/java/android/webkit/WebViewProviderInfo.java
+++ b/core/java/android/webkit/WebViewProviderInfo.java
@@ -40,10 +40,10 @@
         public WebViewPackageNotFoundException(Exception e) { super(e); }
     }
 
-    public WebViewProviderInfo(String packageName, String description, String signature) {
+    public WebViewProviderInfo(String packageName, String description, String[] signatures) {
         this.packageName = packageName;
         this.description = description;
-        this.signature = signature;
+        this.signatures = signatures;
     }
 
     private boolean hasValidSignature() {
@@ -53,7 +53,7 @@
         try {
             // If no signature is declared, instead check whether the package is included in the
             // system.
-            if (signature == null)
+            if (signatures == null || signatures.length == 0)
                 return getPackageInfo().applicationInfo.isSystemApp();
 
             packageSignatures = getPackageInfo().signatures;
@@ -62,8 +62,15 @@
         }
         if (packageSignatures.length != 1)
             return false;
-        final byte[] releaseSignature = Base64.decode(signature, Base64.DEFAULT);
-        return Arrays.equals(releaseSignature, packageSignatures[0].toByteArray());
+
+        final byte[] packageSignature = packageSignatures[0].toByteArray();
+        // Return whether the package signature matches any of the valid signatures
+        for (String signature : signatures) {
+            final byte[] validSignature = Base64.decode(signature, Base64.DEFAULT);
+            if (Arrays.equals(packageSignature, validSignature))
+                return true;
+        }
+        return false;
     }
 
     /**
@@ -109,7 +116,7 @@
     private WebViewProviderInfo(Parcel in) {
         packageName = in.readString();
         description = in.readString();
-        signature = in.readString();
+        signatures = in.createStringArray();
         packageInfo = null;
     }
 
@@ -122,14 +129,14 @@
     public void writeToParcel(Parcel out, int flags) {
         out.writeString(packageName);
         out.writeString(description);
-        out.writeString(signature);
+        out.writeStringArray(signatures);
     }
 
     // fields read from framework resource
     public String packageName;
     public String description;
 
-    private String signature;
+    private String[] signatures;
 
     private PackageInfo packageInfo;
     // flags declaring we want extra info from the package manager
diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java
index ad939be..f6e6186 100644
--- a/core/java/android/widget/LinearLayout.java
+++ b/core/java/android/widget/LinearLayout.java
@@ -359,7 +359,6 @@
         final int count = getVirtualChildCount();
         for (int i = 0; i < count; i++) {
             final View child = getVirtualChildAt(i);
-
             if (child != null && child.getVisibility() != GONE) {
                 if (hasDividerBeforeChildAt(i)) {
                     final LayoutParams lp = (LayoutParams) child.getLayoutParams();
@@ -388,7 +387,7 @@
      */
     private View getLastNonGoneChild() {
         for (int i = getVirtualChildCount() - 1; i >= 0; i--) {
-            View child = getVirtualChildAt(i);
+            final View child = getVirtualChildAt(i);
             if (child != null && child.getVisibility() != GONE) {
                 return child;
             }
@@ -401,7 +400,6 @@
         final boolean isLayoutRtl = isLayoutRtl();
         for (int i = 0; i < count; i++) {
             final View child = getVirtualChildAt(i);
-
             if (child != null && child.getVisibility() != GONE) {
                 if (hasDividerBeforeChildAt(i)) {
                     final LayoutParams lp = (LayoutParams) child.getLayoutParams();
@@ -588,8 +586,9 @@
      * for an example.</p>
      *
      * @param index the child's index
-     * @return the child at the specified index
+     * @return the child at the specified index, may be {@code null}
      */
+    @Nullable
     View getVirtualChildAt(int index) {
         return getChildAt(index);
     }
@@ -670,7 +669,7 @@
      */
     private boolean allViewsAreGoneBefore(int childIndex) {
         for (int i = childIndex - 1; i >= 0; i--) {
-            View child = getVirtualChildAt(i);
+            final View child = getVirtualChildAt(i);
             if (child != null && child.getVisibility() != GONE) {
                 return false;
             }
@@ -715,7 +714,6 @@
         // See how tall everyone is. Also remember max width.
         for (int i = 0; i < count; ++i) {
             final View child = getVirtualChildAt(i);
-
             if (child == null) {
                 mTotalLength += measureNullChild(i);
                 continue;
@@ -837,7 +835,6 @@
 
             for (int i = 0; i < count; ++i) {
                 final View child = getVirtualChildAt(i);
-
                 if (child == null) {
                     mTotalLength += measureNullChild(i);
                     continue;
@@ -943,7 +940,6 @@
             if (useLargestChild && heightMode != MeasureSpec.EXACTLY) {
                 for (int i = 0; i < count; i++) {
                     final View child = getVirtualChildAt(i);
-
                     if (child == null || child.getVisibility() == View.GONE) {
                         continue;
                     }
@@ -986,7 +982,7 @@
                 MeasureSpec.EXACTLY);
         for (int i = 0; i< count; ++i) {
            final View child = getVirtualChildAt(i);
-           if (child.getVisibility() != GONE) { 
+           if (child != null && child.getVisibility() != GONE) {
                LinearLayout.LayoutParams lp = ((LinearLayout.LayoutParams)child.getLayoutParams());
                
                if (lp.width == LayoutParams.MATCH_PARENT) {
@@ -1053,7 +1049,6 @@
         // See how wide everyone is. Also remember max height.
         for (int i = 0; i < count; ++i) {
             final View child = getVirtualChildAt(i);
-
             if (child == null) {
                 mTotalLength += measureNullChild(i);
                 continue;
@@ -1211,7 +1206,6 @@
 
             for (int i = 0; i < count; ++i) {
                 final View child = getVirtualChildAt(i);
-
                 if (child == null) {
                     mTotalLength += measureNullChild(i);
                     continue;
@@ -1357,7 +1351,6 @@
             if (useLargestChild && widthMode != MeasureSpec.EXACTLY) {
                 for (int i = 0; i < count; i++) {
                     final View child = getVirtualChildAt(i);
-
                     if (child == null || child.getVisibility() == View.GONE) {
                         continue;
                     }
@@ -1402,7 +1395,7 @@
                 MeasureSpec.EXACTLY);
         for (int i = 0; i < count; ++i) {
            final View child = getVirtualChildAt(i);
-           if (child.getVisibility() != GONE) { 
+           if (child != null && child.getVisibility() != GONE) {
                LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) child.getLayoutParams();
                
                if (lp.height == LayoutParams.MATCH_PARENT) {
@@ -1662,9 +1655,8 @@
         }
 
         for (int i = 0; i < count; i++) {
-            int childIndex = start + dir * i;
+            final int childIndex = start + dir * i;
             final View child = getVirtualChildAt(childIndex);
-
             if (child == null) {
                 childLeft += measureNullChild(childIndex);
             } else if (child.getVisibility() != GONE) {
diff --git a/core/java/android/widget/TableRow.java b/core/java/android/widget/TableRow.java
index f7f9c91..22931fc 100644
--- a/core/java/android/widget/TableRow.java
+++ b/core/java/android/widget/TableRow.java
@@ -98,7 +98,7 @@
      * {@hide}
      */
     void setColumnCollapsed(int columnIndex, boolean collapsed) {
-        View child = getVirtualChildAt(columnIndex);
+        final View child = getVirtualChildAt(columnIndex);
         if (child != null) {
             child.setVisibility(collapsed ? GONE : VISIBLE);
         }
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 89888f0..d46c6f9 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -394,7 +394,17 @@
             mOverride = false;
         }
 
-        public void resolveWithLayoutDirection(int layoutDirection) {
+        /**
+         * Updates the list of displayed drawables to account for the current
+         * layout direction.
+         *
+         * @param layoutDirection the current layout direction
+         * @return {@code true} if the displayed drawables changed
+         */
+        public boolean resolveWithLayoutDirection(int layoutDirection) {
+            final Drawable previousLeft = mShowing[Drawables.LEFT];
+            final Drawable previousRight = mShowing[Drawables.RIGHT];
+
             // First reset "left" and "right" drawables to their initial values
             mShowing[Drawables.LEFT] = mDrawableLeftInitial;
             mShowing[Drawables.RIGHT] = mDrawableRightInitial;
@@ -442,16 +452,11 @@
                         break;
                 }
             }
-            applyErrorDrawableIfNeeded(layoutDirection);
-            updateDrawablesLayoutDirection(layoutDirection);
-        }
 
-        private void updateDrawablesLayoutDirection(int layoutDirection) {
-            for (Drawable dr : mShowing) {
-                if (dr != null) {
-                    dr.setLayoutDirection(layoutDirection);
-                }
-            }
+            applyErrorDrawableIfNeeded(layoutDirection);
+
+            return mShowing[Drawables.LEFT] != previousLeft
+                    || mShowing[Drawables.RIGHT] != previousRight;
         }
 
         public void setErrorDrawable(Drawable dr, TextView tv) {
@@ -9846,7 +9851,30 @@
 
         // Resolve drawables
         if (mDrawables != null) {
-            mDrawables.resolveWithLayoutDirection(layoutDirection);
+            if (mDrawables.resolveWithLayoutDirection(layoutDirection)) {
+                prepareDrawableForDisplay(mDrawables.mShowing[Drawables.LEFT]);
+                prepareDrawableForDisplay(mDrawables.mShowing[Drawables.RIGHT]);
+                applyCompoundDrawableTint();
+            }
+        }
+    }
+
+    /**
+     * Prepares a drawable for display by propagating layout direction and
+     * drawable state.
+     *
+     * @param dr the drawable to prepare
+     */
+    private void prepareDrawableForDisplay(@Nullable Drawable dr) {
+        if (dr == null) {
+            return;
+        }
+
+        dr.setLayoutDirection(getLayoutDirection());
+
+        if (dr.isStateful()) {
+            dr.setState(getDrawableState());
+            dr.jumpToCurrentState();
         }
     }
 
diff --git a/core/jni/android_view_DisplayListCanvas.cpp b/core/jni/android_view_DisplayListCanvas.cpp
index 9b41eb3..d2c99fd 100644
--- a/core/jni/android_view_DisplayListCanvas.cpp
+++ b/core/jni/android_view_DisplayListCanvas.cpp
@@ -27,7 +27,13 @@
 #include <SkBitmap.h>
 #include <SkRegion.h>
 
+#if HWUI_NEW_OPS
+#include <RecordingCanvas.h>
+typedef android::uirenderer::RecordingCanvas canvas_t;
+#else
 #include <DisplayListCanvas.h>
+typedef android::uirenderer::DisplayListCanvas canvas_t;
+#endif
 #include <Rect.h>
 #include <RenderNode.h>
 #include <CanvasProperty.h>
@@ -46,7 +52,7 @@
 
 static void android_view_DisplayListCanvas_insertReorderBarrier(JNIEnv* env, jobject clazz,
         jlong canvasPtr, jboolean reorderEnable) {
-    DisplayListCanvas* canvas = reinterpret_cast<DisplayListCanvas*>(canvasPtr);
+    canvas_t* canvas = reinterpret_cast<canvas_t*>(canvasPtr);
     canvas->insertReorderBarrier(reorderEnable);
 }
 
@@ -56,7 +62,7 @@
 
 static void android_view_DisplayListCanvas_callDrawGLFunction(JNIEnv* env, jobject clazz,
         jlong canvasPtr, jlong functorPtr) {
-    DisplayListCanvas* canvas = reinterpret_cast<DisplayListCanvas*>(canvasPtr);
+    canvas_t* canvas = reinterpret_cast<canvas_t*>(canvasPtr);
     Functor* functor = reinterpret_cast<Functor*>(functorPtr);
     canvas->callDrawGLFunction(functor);
 }
@@ -80,7 +86,7 @@
 static void android_view_DisplayListCanvas_drawRoundRectProps(JNIEnv* env, jobject clazz,
         jlong canvasPtr, jlong leftPropPtr, jlong topPropPtr, jlong rightPropPtr,
         jlong bottomPropPtr, jlong rxPropPtr, jlong ryPropPtr, jlong paintPropPtr) {
-    DisplayListCanvas* canvas = reinterpret_cast<DisplayListCanvas*>(canvasPtr);
+    canvas_t* canvas = reinterpret_cast<canvas_t*>(canvasPtr);
     CanvasPropertyPrimitive* leftProp = reinterpret_cast<CanvasPropertyPrimitive*>(leftPropPtr);
     CanvasPropertyPrimitive* topProp = reinterpret_cast<CanvasPropertyPrimitive*>(topPropPtr);
     CanvasPropertyPrimitive* rightProp = reinterpret_cast<CanvasPropertyPrimitive*>(rightPropPtr);
@@ -93,7 +99,7 @@
 
 static void android_view_DisplayListCanvas_drawCircleProps(JNIEnv* env, jobject clazz,
         jlong canvasPtr, jlong xPropPtr, jlong yPropPtr, jlong radiusPropPtr, jlong paintPropPtr) {
-    DisplayListCanvas* canvas = reinterpret_cast<DisplayListCanvas*>(canvasPtr);
+    canvas_t* canvas = reinterpret_cast<canvas_t*>(canvasPtr);
     CanvasPropertyPrimitive* xProp = reinterpret_cast<CanvasPropertyPrimitive*>(xPropPtr);
     CanvasPropertyPrimitive* yProp = reinterpret_cast<CanvasPropertyPrimitive*>(yPropPtr);
     CanvasPropertyPrimitive* radiusProp = reinterpret_cast<CanvasPropertyPrimitive*>(radiusPropPtr);
@@ -107,25 +113,25 @@
 
 static jlong android_view_DisplayListCanvas_finishRecording(JNIEnv* env,
         jobject clazz, jlong canvasPtr) {
-    DisplayListCanvas* canvas = reinterpret_cast<DisplayListCanvas*>(canvasPtr);
+    canvas_t* canvas = reinterpret_cast<canvas_t*>(canvasPtr);
     return reinterpret_cast<jlong>(canvas->finishRecording());
 }
 
 static jlong android_view_DisplayListCanvas_createDisplayListCanvas(JNIEnv* env, jobject clazz,
         jint width, jint height) {
-    return reinterpret_cast<jlong>(new DisplayListCanvas(width, height));
+    return reinterpret_cast<jlong>(new canvas_t(width, height));
 }
 
 static void android_view_DisplayListCanvas_resetDisplayListCanvas(JNIEnv* env, jobject clazz,
         jlong canvasPtr, jint width, jint height) {
-    DisplayListCanvas* canvas = reinterpret_cast<DisplayListCanvas*>(canvasPtr);
+    canvas_t* canvas = reinterpret_cast<canvas_t*>(canvasPtr);
     canvas->reset(width, height);
 }
 
 
 static void android_view_DisplayListCanvas_drawRenderNode(JNIEnv* env,
         jobject clazz, jlong canvasPtr, jlong renderNodePtr) {
-    DisplayListCanvas* canvas = reinterpret_cast<DisplayListCanvas*>(canvasPtr);
+    canvas_t* canvas = reinterpret_cast<canvas_t*>(canvasPtr);
     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
     canvas->drawRenderNode(renderNode);
 }
@@ -136,7 +142,7 @@
 
 static void android_view_DisplayListCanvas_drawLayer(JNIEnv* env, jobject clazz,
         jlong canvasPtr, jlong layerPtr) {
-    DisplayListCanvas* canvas = reinterpret_cast<DisplayListCanvas*>(canvasPtr);
+    canvas_t* canvas = reinterpret_cast<canvas_t*>(canvasPtr);
     DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
     canvas->drawLayer(layer);
 }
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 313987a..c03d471 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2370,7 +2370,7 @@
     <!-- Set initial MaxRetry value for operators -->
     <integer name="config_mdc_initial_max_retry">1</integer>
 
-    <!-- The OEM specified sensor type for the gesture to launch the camear app. -->
+    <!-- The OEM specified sensor type for the gesture to launch the camera app. -->
     <integer name="config_cameraLaunchGestureSensorType">-1</integer>
     <!-- The OEM specified sensor string type for the gesture to launch camera app, this value
          must match the value of config_cameraLaunchGestureSensorType in OEM's HAL -->
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index f726860..4843879 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3078,6 +3078,9 @@
     <string name="notification_listener_binding_label">Notification listener</string>
     <!-- Label to show for a service that is running because it is providing conditions. -->
     <string name="condition_provider_service_binding_label">Condition provider</string>
+    <!-- Label to show for a service that is running because it is observing and modifying the
+         importance of the user's notifications. -->
+    <string name="notification_assistant_binding_label">Notification assistant</string>
 
     <!-- Do Not Translate: Alternate eri.xml -->
     <string name="alternate_eri_file">/data/eri.xml</string>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 9a4016b..937d83d 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -1235,7 +1235,7 @@
         <item name="subtitleTextAppearance">@style/TextAppearance.Widget.Toolbar.Subtitle</item>
         <item name="minHeight">?attr/actionBarSize</item>
         <item name="titleMargin">4dp</item>
-        <item name="maxButtonHeight">56dp</item>
+        <item name="maxButtonHeight">@dimen/action_bar_default_height_material</item>
         <item name="buttonGravity">top</item>
         <item name="navigationButtonStyle">@style/Widget.Toolbar.Button.Navigation</item>
         <item name="collapseIcon">?attr/homeAsUpIndicator</item>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 640f90b..f257f14 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1810,6 +1810,7 @@
   <java-symbol type="string" name="low_internal_storage_view_title" />
   <java-symbol type="string" name="notification_listener_binding_label" />
   <java-symbol type="string" name="condition_provider_service_binding_label" />
+  <java-symbol type="string" name="notification_assistant_binding_label" />
   <java-symbol type="string" name="report" />
   <java-symbol type="string" name="select_input_method" />
   <java-symbol type="string" name="select_keyboard_layout_notification_title" />
diff --git a/core/res/res/xml/config_webview_packages.xml b/core/res/res/xml/config_webview_packages.xml
index 6f9c58d..fd443c1 100644
--- a/core/res/res/xml/config_webview_packages.xml
+++ b/core/res/res/xml/config_webview_packages.xml
@@ -16,5 +16,6 @@
 
 <webviewproviders>
     <!-- The default WebView implementation -->
-    <webviewprovider description="Android WebView" packageName="com.android.webview" />
+    <webviewprovider description="Android WebView" packageName="com.android.webview">
+    </webviewprovider>
 </webviewproviders>
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index 5acc1a3..d5166ab 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -1079,11 +1079,12 @@
      *                 (count >> 2).
      * @param paint    The paint used to draw the points
      */
-    public void drawLines(@Size(min=4,multiple=2) float[] pts, int offset, int count, Paint paint) {
+    public void drawLines(@Size(multiple=4) @NonNull float[] pts, int offset, int count,
+            @NonNull Paint paint) {
         native_drawLines(mNativeCanvasWrapper, pts, offset, count, paint.getNativeInstance());
     }
 
-    public void drawLines(@Size(min=4,multiple=2) @NonNull float[] pts, @NonNull Paint paint) {
+    public void drawLines(@Size(multiple=4) @NonNull float[] pts, @NonNull Paint paint) {
         drawLines(pts, 0, pts.length, paint);
     }
 
diff --git a/libs/hwui/CanvasState.cpp b/libs/hwui/CanvasState.cpp
index 6a6cc42..cf76e6b 100644
--- a/libs/hwui/CanvasState.cpp
+++ b/libs/hwui/CanvasState.cpp
@@ -192,7 +192,7 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 bool CanvasState::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) {
-    mSnapshot->clip(left, top, right, bottom, op);
+    mSnapshot->clip(Rect(left, top, right, bottom), op);
     mDirtyClip = true;
     return !mSnapshot->clipIsEmpty();
 }
diff --git a/libs/hwui/ClipArea.cpp b/libs/hwui/ClipArea.cpp
index fd6f0b5..5f166ca 100644
--- a/libs/hwui/ClipArea.cpp
+++ b/libs/hwui/ClipArea.cpp
@@ -201,12 +201,6 @@
     mClipRegion.setEmpty();
 }
 
-void ClipArea::clipRectWithTransform(float left, float top, float right,
-        float bottom, const mat4* transform, SkRegion::Op op) {
-    Rect r(left, top, right, bottom);
-    clipRectWithTransform(r, transform, op);
-}
-
 void ClipArea::clipRectWithTransform(const Rect& r, const mat4* transform,
         SkRegion::Op op) {
     switch (mMode) {
@@ -274,13 +268,6 @@
     rectangleListModeClipRectWithTransform(r, transform, op);
 }
 
-void ClipArea::rectangleModeClipRectWithTransform(float left, float top,
-        float right, float bottom, const mat4* transform, SkRegion::Op op) {
-    Rect r(left, top, right, bottom);
-    rectangleModeClipRectWithTransform(r, transform, op);
-    mClipRect = mRectangleList.calculateBounds();
-}
-
 /*
  * RectangleList mode implementation
  */
@@ -303,12 +290,6 @@
     }
 }
 
-void ClipArea::rectangleListModeClipRectWithTransform(float left, float top,
-        float right, float bottom, const mat4* transform, SkRegion::Op op) {
-    Rect r(left, top, right, bottom);
-    rectangleListModeClipRectWithTransform(r, transform, op);
-}
-
 /*
  * Region mode implementation
  */
@@ -336,11 +317,6 @@
     onClipRegionUpdated();
 }
 
-void ClipArea::regionModeClipRectWithTransform(float left, float top,
-        float right, float bottom, const mat4* transform, SkRegion::Op op) {
-    regionModeClipRectWithTransform(Rect(left, top, right, bottom), transform, op);
-}
-
 void ClipArea::onClipRegionUpdated() {
     if (!mClipRegion.isEmpty()) {
         mClipRect.set(mClipRegion.getBounds());
diff --git a/libs/hwui/ClipArea.h b/libs/hwui/ClipArea.h
index f88fd92..268301c 100644
--- a/libs/hwui/ClipArea.h
+++ b/libs/hwui/ClipArea.h
@@ -98,8 +98,6 @@
 
     void setEmpty();
     void setClip(float left, float top, float right, float bottom);
-    void clipRectWithTransform(float left, float top, float right, float bottom,
-            const mat4* transform, SkRegion::Op op);
     void clipRectWithTransform(const Rect& r, const mat4* transform,
             SkRegion::Op op);
     void clipRegion(const SkRegion& region, SkRegion::Op op);
@@ -133,12 +131,8 @@
 private:
     void enterRectangleMode();
     void rectangleModeClipRectWithTransform(const Rect& r, const mat4* transform, SkRegion::Op op);
-    void rectangleModeClipRectWithTransform(float left, float top, float right,
-            float bottom, const mat4* transform, SkRegion::Op op);
 
     void enterRectangleListMode();
-    void rectangleListModeClipRectWithTransform(float left, float top,
-            float right, float bottom, const mat4* transform, SkRegion::Op op);
     void rectangleListModeClipRectWithTransform(const Rect& r,
             const mat4* transform, SkRegion::Op op);
 
@@ -147,8 +141,6 @@
     void enterRegionMode();
     void regionModeClipRectWithTransform(const Rect& r, const mat4* transform,
             SkRegion::Op op);
-    void regionModeClipRectWithTransform(float left, float top, float right,
-            float bottom, const mat4* transform, SkRegion::Op op);
 
     void ensureClipRegion();
     void onClipRegionUpdated();
diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h
index 48cc91a..470f9ec 100644
--- a/libs/hwui/RecordingCanvas.h
+++ b/libs/hwui/RecordingCanvas.h
@@ -39,7 +39,7 @@
 class DeferredLayerUpdater;
 struct RecordedOp;
 
-class RecordingCanvas: public Canvas, public CanvasStateClient {
+class ANDROID_API RecordingCanvas: public Canvas, public CanvasStateClient {
     enum class DeferredBarrierType {
         None,
         InOrder,
diff --git a/libs/hwui/Snapshot.cpp b/libs/hwui/Snapshot.cpp
index 2f535bb..c6d8977 100644
--- a/libs/hwui/Snapshot.cpp
+++ b/libs/hwui/Snapshot.cpp
@@ -88,9 +88,9 @@
     mClipArea->clipRegion(region, op);
 }
 
-void Snapshot::clip(float left, float top, float right, float bottom, SkRegion::Op op) {
+void Snapshot::clip(const Rect& localClip, SkRegion::Op op) {
     flags |= Snapshot::kFlagClipSet;
-    mClipArea->clipRectWithTransform(left, top, right, bottom, transform, op);
+    mClipArea->clipRectWithTransform(localClip, transform, op);
 }
 
 void Snapshot::clipPath(const SkPath& path, SkRegion::Op op) {
diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h
index 4789b33..194aa57 100644
--- a/libs/hwui/Snapshot.h
+++ b/libs/hwui/Snapshot.h
@@ -124,7 +124,7 @@
      * the specified operation. The specified rectangle is transformed
      * by this snapshot's trasnformation.
      */
-    void clip(float left, float top, float right, float bottom, SkRegion::Op op);
+    void clip(const Rect& localClip, SkRegion::Op op);
 
     /**
      * Modifies the current clip with the new clip rectangle and
diff --git a/libs/hwui/tests/common/TestUtils.h b/libs/hwui/tests/common/TestUtils.h
index d37fad4..ac14fc8 100644
--- a/libs/hwui/tests/common/TestUtils.h
+++ b/libs/hwui/tests/common/TestUtils.h
@@ -98,7 +98,7 @@
 
     static std::unique_ptr<Snapshot> makeSnapshot(const Matrix4& transform, const Rect& clip) {
         std::unique_ptr<Snapshot> snapshot(new Snapshot());
-        snapshot->clip(clip.left, clip.top, clip.right, clip.bottom, SkRegion::kReplace_Op);
+        snapshot->clip(clip, SkRegion::kReplace_Op); // store clip first, so it isn't transformed
         *(snapshot->transform) = transform;
         return snapshot;
     }
diff --git a/packages/DocumentsUI/AndroidManifest.xml b/packages/DocumentsUI/AndroidManifest.xml
index 8cc79a4c..5e634a4 100644
--- a/packages/DocumentsUI/AndroidManifest.xml
+++ b/packages/DocumentsUI/AndroidManifest.xml
@@ -40,7 +40,7 @@
 
         <activity
             android:name=".DownloadsActivity"
-            android:theme="@style/DocumentsFullScreenTheme"
+            android:theme="@style/DocumentsTheme"
             android:label="@string/downloads_label"
             android:icon="@drawable/ic_doc_text">
             <intent-filter>
@@ -64,7 +64,7 @@
 
         <activity
             android:name=".FilesActivity"
-            android:theme="@style/DocumentsFullScreenTheme"
+            android:theme="@style/DocumentsTheme"
             android:icon="@drawable/ic_files_app"
             android:label="@string/files_label"
             android:documentLaunchMode="intoExisting">
diff --git a/packages/DocumentsUI/res/values-sw720dp/dimens.xml b/packages/DocumentsUI/res/values-sw720dp/dimens.xml
index f393d88..83ceb55 100644
--- a/packages/DocumentsUI/res/values-sw720dp/dimens.xml
+++ b/packages/DocumentsUI/res/values-sw720dp/dimens.xml
@@ -15,10 +15,6 @@
 -->
 
 <resources>
-    <bool name="show_as_dialog">true</bool>
-
-    <item type="dimen" name="dialog_width">85%</item>
-
     <dimen name="grid_padding_horiz">16dp</dimen>
     <dimen name="grid_padding_vert">16dp</dimen>
 
diff --git a/packages/DocumentsUI/res/values-sw720dp/layouts.xml b/packages/DocumentsUI/res/values-sw720dp/layouts.xml
deleted file mode 100644
index 7d28f9c..0000000
--- a/packages/DocumentsUI/res/values-sw720dp/layouts.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<resources>
-    <item name="docs_activity" type="layout">@layout/fixed_layout</item>
-</resources>
diff --git a/packages/DocumentsUI/res/values-sw720dp/styles.xml b/packages/DocumentsUI/res/values-sw720dp/styles.xml
deleted file mode 100644
index a8dcbb0..0000000
--- a/packages/DocumentsUI/res/values-sw720dp/styles.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?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.
--->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android">
-
-    <style name="DocumentsBaseTheme" parent="@style/Theme.AppCompat.Light.Dialog">
-        <!-- We do not specify width of window here because the max size of
-             floating window specified by windowFixedWidthis is limited. -->
-        <item name="*android:windowFixedHeightMajor">80%</item>
-        <item name="*android:windowFixedHeightMinor">90%</item>
-    </style>
-
-</resources>
diff --git a/packages/DocumentsUI/res/values/attrs.xml b/packages/DocumentsUI/res/values/attrs.xml
index 0afc3a2..9e13001 100644
--- a/packages/DocumentsUI/res/values/attrs.xml
+++ b/packages/DocumentsUI/res/values/attrs.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <resources>
-    <declare-styleable name="DocumentsBaseTheme">
+    <declare-styleable name="DocumentsTheme">
         <attr name="colorActionMode" format="color"/>
     </declare-styleable>
 </resources>
diff --git a/packages/DocumentsUI/res/values/dimens.xml b/packages/DocumentsUI/res/values/dimens.xml
index f94a00e..060871d 100644
--- a/packages/DocumentsUI/res/values/dimens.xml
+++ b/packages/DocumentsUI/res/values/dimens.xml
@@ -35,7 +35,6 @@
     <dimen name="list_divider_inset">72dp</dimen>
     <bool name="list_divider_inset_left">true</bool>
 
-    <bool name="show_as_dialog">false</bool>
     <bool name="always_show_summary">false</bool>
 
     <dimen name="dir_elevation">8dp</dimen>
diff --git a/packages/DocumentsUI/res/values/styles.xml b/packages/DocumentsUI/res/values/styles.xml
index 6712e2d..d14631d 100644
--- a/packages/DocumentsUI/res/values/styles.xml
+++ b/packages/DocumentsUI/res/values/styles.xml
@@ -16,31 +16,10 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android">
 
-    <style name="DocumentsBaseTheme" parent="@style/Theme.AppCompat.Light.DarkActionBar" />
     <style name="ActionBarTheme" parent="@*android:style/ThemeOverlay.Material.Dark.ActionBar" />
     <style name="ActionBarPopupTheme" parent="@*android:style/ThemeOverlay.Material.Light" />
 
-    <style name="DocumentsTheme" parent="@style/DocumentsBaseTheme">
-        <item name="actionBarWidgetTheme">@null</item>
-        <item name="actionBarTheme">@style/ActionBarTheme</item>
-        <item name="actionBarPopupTheme">@style/ActionBarPopupTheme</item>
-
-        <item name="android:windowBackground">@color/window_background</item>
-        <item name="android:colorPrimaryDark">@color/primary_dark</item>
-        <item name="android:colorPrimary">@color/primary</item>
-        <item name="android:colorAccent">@color/accent</item>
-        <item name="colorActionMode">@color/action_mode</item>
-
-        <item name="android:listDivider">@*android:drawable/list_divider_material</item>
-
-        <item name="android:windowActionBar">false</item>
-        <item name="android:windowActionModeOverlay">true</item>
-        <item name="android:windowNoTitle">true</item>
-
-        <item name="android:windowSoftInputMode">stateUnspecified|adjustUnspecified</item>
-    </style>
-
-    <style name="DocumentsFullScreenTheme" parent="@style/Theme.AppCompat.Light.DarkActionBar">
+    <style name="DocumentsTheme" parent="@style/Theme.AppCompat.Light.DarkActionBar">
         <item name="actionBarWidgetTheme">@null</item>
         <item name="actionBarTheme">@style/ActionBarTheme</item>
         <item name="actionBarPopupTheme">@style/ActionBarPopupTheme</item>
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
index 313d303..8ca2cfb 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
@@ -34,7 +34,6 @@
 import android.content.Intent;
 import android.content.pm.ResolveInfo;
 import android.content.res.Resources;
-import android.graphics.Point;
 import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.Bundle;
@@ -45,7 +44,6 @@
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.View;
-import android.view.WindowManager;
 import android.widget.BaseAdapter;
 import android.widget.Spinner;
 import android.widget.Toolbar;
@@ -64,8 +62,6 @@
     private static final int CODE_FORWARD = 42;
     private static final String TAG = "DocumentsActivity";
 
-    private boolean mShowAsDialog;
-
     private Toolbar mToolbar;
     private Spinner mToolbarStack;
 
@@ -83,29 +79,8 @@
         super.onCreate(icicle);
 
         final Resources res = getResources();
-        mShowAsDialog = res.getBoolean(R.bool.show_as_dialog);
 
-        if (!mShowAsDialog) {
-            setTheme(R.style.DocumentsFullScreenTheme);
-        }
-
-        if (mShowAsDialog) {
-            mDrawer = DrawerController.createDummy();
-
-            // Strongly define our horizontal dimension; we leave vertical as
-            // WRAP_CONTENT so that system resizes us when IME is showing.
-            final WindowManager.LayoutParams a = getWindow().getAttributes();
-
-            final Point size = new Point();
-            getWindowManager().getDefaultDisplay().getSize(size);
-            a.width = (int) res.getFraction(R.dimen.dialog_width, size.x, size.x);
-
-            getWindow().setAttributes(a);
-
-        } else {
-            mDrawer = DrawerController.create(this);
-        }
-
+        mDrawer = DrawerController.create(this);
         mToolbar = (Toolbar) findViewById(R.id.toolbar);
 
         mStackAdapter = new StackAdapter();
@@ -267,15 +242,16 @@
             }
         }
 
-        if (!mShowAsDialog && mDrawer.isUnlocked()) {
+        if (mDrawer.isUnlocked()) {
             mToolbar.setNavigationIcon(R.drawable.ic_hamburger);
             mToolbar.setNavigationContentDescription(R.string.drawer_open);
-            mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
-                @Override
-                public void onClick(View v) {
-                    setRootsDrawerOpen(true);
-                }
-            });
+            mToolbar.setNavigationOnClickListener(
+                    new View.OnClickListener() {
+                        @Override
+                        public void onClick(View v) {
+                            setRootsDrawerOpen(true);
+                        }
+                    });
         } else {
             mToolbar.setNavigationIcon(null);
             mToolbar.setNavigationContentDescription(R.string.drawer_open);
@@ -306,10 +282,7 @@
     public boolean onCreateOptionsMenu(Menu menu) {
         boolean showMenu = super.onCreateOptionsMenu(menu);
 
-        // Most actions are visible when showing as dialog
-        if (mShowAsDialog) {
-            expandMenus(menu);
-        }
+        expandMenus(menu);
         return showMenu;
     }
 
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/StubProvider.java b/packages/DocumentsUI/tests/src/com/android/documentsui/StubProvider.java
index 63a519f..2c311a7 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/StubProvider.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/StubProvider.java
@@ -493,30 +493,6 @@
     }
 
     @VisibleForTesting
-    public File createFile(String rootId, String path, String mimeType, byte[] content)
-            throws FileNotFoundException, IOException {
-        Log.d(TAG, "Creating test file " + rootId + ":" + path);
-        StubDocument root = mRoots.get(rootId).document;
-        if (root == null) {
-            throw new FileNotFoundException("No roots with the ID " + rootId + " were found");
-        }
-        final File file = new File(root.file, path.substring(1));
-        if (DocumentsContract.Document.MIME_TYPE_DIR.equals(mimeType)) {
-            if (!file.mkdirs()) {
-                throw new FileNotFoundException("Couldn't create directory " + file.getPath());
-            }
-        } else {
-            if (!file.createNewFile()) {
-                throw new FileNotFoundException("Couldn't create file " + file.getPath());
-            }
-            try (final FileOutputStream fout = new FileOutputStream(file)) {
-                fout.write(content);
-            }
-        }
-        return file;
-    }
-
-    @VisibleForTesting
     public Uri createRegularFile(String rootId, String path, String mimeType, byte[] content)
             throws FileNotFoundException, IOException {
         final File file = createFile(rootId, path, mimeType, content);
@@ -560,6 +536,29 @@
         return found.file;
     }
 
+    private File createFile(String rootId, String path, String mimeType, byte[] content)
+            throws FileNotFoundException, IOException {
+        Log.d(TAG, "Creating test file " + rootId + ":" + path);
+        StubDocument root = mRoots.get(rootId).document;
+        if (root == null) {
+            throw new FileNotFoundException("No roots with the ID " + rootId + " were found");
+        }
+        final File file = new File(root.file, path.substring(1));
+        if (DocumentsContract.Document.MIME_TYPE_DIR.equals(mimeType)) {
+            if (!file.mkdirs()) {
+                throw new FileNotFoundException("Couldn't create directory " + file.getPath());
+            }
+        } else {
+            if (!file.createNewFile()) {
+                throw new FileNotFoundException("Couldn't create file " + file.getPath());
+            }
+            try (final FileOutputStream fout = new FileOutputStream(file)) {
+                fout.write(content);
+            }
+        }
+        return file;
+    }
+
     final static class RootInfo {
         public final String name;
         public final StubDocument document;
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 6680d88..51d8ca0 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -25,6 +25,7 @@
     <!-- Comma-separated list of bluetooth, wifi, and cell. -->
     <string name="def_airplane_mode_radios" translatable="false">cell,bluetooth,wifi,nfc,wimax</string>
     <string name="airplane_mode_toggleable_radios" translatable="false">bluetooth,wifi,nfc</string>
+    <string name="def_bluetooth_disabled_profiles" translatable="false">0</string>
     <bool name="def_auto_time">true</bool>
     <bool name="def_auto_time_zone">true</bool>
     <bool name="def_accelerometer_rotation">true</bool>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 7365e66..bcb459a 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -1890,7 +1890,7 @@
         }
 
         private final class UpgradeController {
-            private static final int SETTINGS_VERSION = 123;
+            private static final int SETTINGS_VERSION = 124;
 
             private final int mUserId;
 
@@ -2060,6 +2060,16 @@
                     }
                     currentVersion = 123;
                 }
+
+                if (currentVersion == 123) {
+                    final SettingsState globalSettings = getGlobalSettingsLocked();
+                    String defaultDisabledProfiles = (getContext().getResources().getString(
+                            R.string.def_bluetooth_disabled_profiles));
+                    globalSettings.insertSettingLocked(Settings.Global.BLUETOOTH_DISABLED_PROFILES,
+                            defaultDisabledProfiles, SettingsState.SYSTEM_PACKAGE_NAME);
+                    currentVersion = 124;
+                }
+
                 // vXXX: Add new settings above this point.
 
                 // Return the current version.
diff --git a/packages/SystemUI/res/layout/notification_guts.xml b/packages/SystemUI/res/layout/notification_guts.xml
index c9dbc79..f15c97e 100644
--- a/packages/SystemUI/res/layout/notification_guts.xml
+++ b/packages/SystemUI/res/layout/notification_guts.xml
@@ -24,35 +24,23 @@
         android:clickable="true"
         android:gravity="top|start"
         android:orientation="vertical"
-        android:paddingEnd="8dp"
+        android:paddingStart="@*android:dimen/notification_content_margin_start"
+        android:paddingEnd="@*android:dimen/notification_content_margin_end"
         android:background="@color/notification_guts_text_color" >
 
     <!-- header -->
     <FrameLayout
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:paddingStart="@*android:dimen/notification_content_margin_start"
-            android:paddingTop="8dp"
-            android:paddingBottom="16dp" >
+            android:paddingBottom="8dp" >
 
         <LinearLayout
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:id="@+id/notification_guts_header"
-                android:orientation="vertical"
+                android:orientation="horizontal"
                 android:layout_gravity="center_vertical|start"
                 android:layout_marginEnd="52dp">
-
-                <LinearLayout
-                        android:id="@+id/notification_guts_app_details"
-                        android:orientation="horizontal"
-                        android:layout_width="match_parent"
-                        android:layout_height="wrap_content"
-                        android:clipChildren="false"
-                        android:layout_gravity="start|top"
-                        android:gravity="center_vertical"
-                        >
-
                     <ImageView
                             android:id="@android:id/icon"
                             android:layout_width="18dp"
@@ -76,22 +64,12 @@
                             android:layout_gravity="bottom|start"
                             android:visibility="gone"
                             android:textColor="#ffffff" />
-                </LinearLayout>
-
-                <TextView
-                        android:id="@+id/topic_details"
-                        android:layout_width="match_parent"
-                        android:layout_height="wrap_content"
-                        android:textAppearance="@android:style/TextAppearance.Material.Notification.Title"
-                        android:textColor="@color/notification_guts_text_color"
-                        android:layout_alignParentBottom="true"
-                        android:layout_alignParentStart="true" />
-            </LinearLayout>
+        </LinearLayout>
 
         <ImageButton style="@android:style/Widget.Material.Light.Button.Borderless.Small"
                 android:id="@+id/notification_inspect_item"
                 android:layout_width="52dp"
-                android:layout_height="match_parent"
+                android:layout_height="wrap_content"
                 android:layout_weight="0"
                 android:gravity="center"
                 android:layout_gravity="center_vertical|end"
@@ -103,7 +81,6 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:gravity="center_vertical"
-            android:paddingStart="@*android:dimen/notification_content_margin_start"
             android:orientation="vertical"
             android:clickable="false"
             android:focusable="false"
@@ -116,8 +93,7 @@
                 android:textAppearance="@android:style/TextAppearance.Material.Subhead"
                 android:textColor="@color/notification_guts_text_color"
                 android:ellipsize="marquee"
-                android:fadingEdge="horizontal"
-                android:text="@*android:string/notification_importance_title"/>
+                android:fadingEdge="horizontal"/>
 
         <TextView
                 android:id="@+id/summary"
@@ -133,7 +109,7 @@
         <FrameLayout
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:paddingTop="6dp" >
+                android:paddingTop="8dp" >
 
             <ImageView
                     android:id="@+id/low_importance"
@@ -162,5 +138,21 @@
                     android:layout_height="24dp"/>
 
         </FrameLayout>
+
+        <RadioGroup android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:paddingTop="8dp">
+            <RadioButton android:id="@+id/apply_to_topic"
+                         android:layout_width="wrap_content"
+                         android:layout_height="wrap_content"
+                         android:textColor="@color/notification_guts_text_color"
+                         android:visibility="gone"/>
+            <RadioButton android:id="@+id/apply_to_app"
+                         android:layout_width="wrap_content"
+                         android:layout_height="wrap_content"
+                         android:text="@string/apply_to_app"
+                         android:textColor="@color/notification_guts_text_color"
+                         android:visibility="gone"/>
+        </RadioGroup>
     </LinearLayout>
 </com.android.systemui.statusbar.NotificationGuts>
diff --git a/packages/SystemUI/res/layout/recents_task_view_header.xml b/packages/SystemUI/res/layout/recents_task_view_header.xml
index b8caf23..04f18c5 100644
--- a/packages/SystemUI/res/layout/recents_task_view_header.xml
+++ b/packages/SystemUI/res/layout/recents_task_view_header.xml
@@ -20,7 +20,7 @@
     android:layout_height="@dimen/recents_task_bar_height"
     android:layout_gravity="top|center_horizontal">
     <com.android.systemui.recents.views.FixedSizeImageView
-        android:id="@+id/application_icon"
+        android:id="@+id/icon"
         android:contentDescription="@string/recents_app_info_button_label"
         android:layout_width="@dimen/recents_task_view_application_icon_size"
         android:layout_height="@dimen/recents_task_view_application_icon_size"
@@ -29,7 +29,7 @@
         android:padding="8dp"
         android:background="@drawable/recents_button_bg" />
     <TextView
-        android:id="@+id/activity_description"
+        android:id="@+id/title"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_gravity="center_vertical|start"
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index f71a71a..50e0661 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1201,4 +1201,34 @@
     <!-- Bluetooth enablement ok text [CHAR LIMIT=40] -->
     <string name="enable_bluetooth_confirmation_ok">Turn on</string>
 
+    <!-- Apply notification importance setting to a topic [CHAR LIMIT=NONE] -->
+    <string name="apply_to_topic">Apply to <xliff:g id="topic_name" example="Friend Request">%1$s</xliff:g> notifications</string>
+    <!-- Apply notification importance setting to an app [CHAR LIMIT=NONE] -->
+    <string name="apply_to_app">Apply to all notifications from this app</string>
+    <!-- Notification importance title, blocked status-->
+    <string name="blocked_importance">Blocked</string>
+    <!-- Notification importance title, low status-->
+    <string name="low_importance">Low importance</string>
+    <!-- Notification importance title, normal status-->
+    <string name="default_importance">Normal importance</string>
+    <!-- Notification importance title, high status-->
+    <string name="high_importance">High importance</string>
+    <!-- Notification importance title, max status-->
+    <string name="max_importance">Urgent importance</string>
+
+    <!-- [CHAR LIMIT=100] Notification Importance slider: blocked importance level description -->
+    <string name="notification_importance_blocked">Never show these notifications</string>
+
+    <!-- [CHAR LIMIT=100] Notification Importance slider: low importance level description -->
+    <string name="notification_importance_low">Silently show at the bottom of the notification list</string>
+
+    <!-- [CHAR LIMIT=100] Notification Importance slider: normal importance level description -->
+    <string name="notification_importance_default">Silently show these notifications</string>
+
+    <!-- [CHAR LIMIT=100] Notification Importance slider: high importance level description -->
+    <string name="notification_importance_high">Show at the top of the notifications list and make sound</string>
+
+    <!-- [CHAR LIMIT=100] Notification Importance slider: max importance level description -->
+    <string name="notification_importance_max">Peek onto the screen and make sound</string>
+
 </resources>
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index b3ce4a6..ffcc805 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -246,10 +246,7 @@
     boolean dismissHistory() {
         // Try and hide the history view first
         if (mHistoryView != null && mHistoryView.isVisible()) {
-            ReferenceCountedTrigger t = new ReferenceCountedTrigger(this);
-            t.increment();
-            EventBus.getDefault().send(new HideHistoryEvent(true /* animate */, t));
-            t.decrement();
+            EventBus.getDefault().send(new HideHistoryEvent(true /* animate */));
             return true;
         }
         return false;
@@ -301,8 +298,8 @@
      */
     void dismissRecentsToHome(boolean animated) {
         if (animated) {
-            ReferenceCountedTrigger exitTrigger = new ReferenceCountedTrigger(this,
-                    null, mFinishLaunchHomeRunnable, null);
+            ReferenceCountedTrigger exitTrigger = new ReferenceCountedTrigger(null,
+                    mFinishLaunchHomeRunnable, null);
             mRecentsView.startExitToHomeAnimation(
                     new ViewAnimation.TaskViewExitContext(exitTrigger));
         } else {
@@ -439,10 +436,7 @@
         // Reset some states
         mIgnoreAltTabRelease = false;
         if (mHistoryView != null) {
-            ReferenceCountedTrigger t = new ReferenceCountedTrigger(this);
-            t.increment();
-            EventBus.getDefault().send(new HideHistoryEvent(false /* animate */, t));
-            t.decrement();
+            EventBus.getDefault().send(new HideHistoryEvent(false /* animate */));
         }
 
         // Notify that recents is now hidden
@@ -511,11 +505,7 @@
     protected void onRestoreInstanceState(Bundle savedInstanceState) {
         super.onRestoreInstanceState(savedInstanceState);
         if (savedInstanceState.getBoolean(KEY_SAVED_STATE_HISTORY_VISIBLE, false)) {
-            ReferenceCountedTrigger postHideStackAnimationTrigger =
-                    new ReferenceCountedTrigger(this);
-            postHideStackAnimationTrigger.increment();
-            EventBus.getDefault().send(new ShowHistoryEvent(postHideStackAnimationTrigger));
-            postHideStackAnimationTrigger.decrement();
+            EventBus.getDefault().send(new ShowHistoryEvent());
         }
     }
 
@@ -644,16 +634,14 @@
         } else if (event.triggeredFromHomeKey) {
             // Otherwise, dismiss Recents to Home
             if (mHistoryView != null && mHistoryView.isVisible()) {
-                ReferenceCountedTrigger t = new ReferenceCountedTrigger(this);
-                t.increment();
-                t.addLastDecrementRunnable(new Runnable() {
+                HideHistoryEvent hideEvent = new HideHistoryEvent(true /* animate */);
+                hideEvent.addPostAnimationCallback(new Runnable() {
                     @Override
                     public void run() {
                         dismissRecentsToHome(true /* animated */);
                     }
                 });
-                EventBus.getDefault().send(new HideHistoryEvent(true, t));
-                t.decrement();
+                EventBus.getDefault().send(hideEvent);
 
             } else {
                 dismissRecentsToHome(true /* animated */);
@@ -665,7 +653,7 @@
 
     public final void onBusEvent(EnterRecentsWindowAnimationCompletedEvent event) {
         // Try and start the enter animation (or restart it on configuration changed)
-        ReferenceCountedTrigger t = new ReferenceCountedTrigger(this);
+        ReferenceCountedTrigger t = new ReferenceCountedTrigger();
         ViewAnimation.TaskViewEnterContext ctx = new ViewAnimation.TaskViewEnterContext(t);
         ctx.postAnimationTrigger.increment();
         if (mSearchWidgetInfo != null) {
@@ -784,11 +772,11 @@
             // provided.
             mHistoryView.setSystemInsets(mRecentsView.getSystemInsets());
         }
-        mHistoryView.show(mRecentsView.getTaskStack(), event.postHideStackAnimationTrigger);
+        mHistoryView.show(mRecentsView.getTaskStack(), event.getAnimationTrigger());
     }
 
     public final void onBusEvent(HideHistoryEvent event) {
-        mHistoryView.hide(event.animate, event.postHideHistoryAnimationTrigger);
+        mHistoryView.hide(event.animate, event.getAnimationTrigger());
     }
 
     private void refreshSearchWidgetView() {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index 8a0a043..949fb86 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -207,7 +207,7 @@
         RecentsTaskLoadPlan plan = loader.createLoadPlan(mContext);
         loader.preloadTasks(plan, true /* isTopTaskHome */);
         RecentsTaskLoadPlan.Options launchOpts = new RecentsTaskLoadPlan.Options();
-        launchOpts.numVisibleTasks = loader.getApplicationIconCacheSize();
+        launchOpts.numVisibleTasks = loader.getIconCacheSize();
         launchOpts.numVisibleTaskThumbnails = loader.getThumbnailCacheSize();
         launchOpts.onlyLoadForCache = true;
         loader.loadTasks(mContext, plan, launchOpts);
@@ -452,7 +452,7 @@
         }
 
         // Launch the task
-        ssp.startActivityFromRecents(mContext, toTask.key.id, toTask.activityLabel, launchOpts);
+        ssp.startActivityFromRecents(mContext, toTask.key.id, toTask.title, launchOpts);
     }
 
     /**
@@ -524,7 +524,7 @@
         MetricsLogger.count(mContext, "overview_affiliated_task_launch", 1);
 
         // Launch the task
-        ssp.startActivityFromRecents(mContext, toTask.key.id, toTask.activityLabel, launchOpts);
+        ssp.startActivityFromRecents(mContext, toTask.key.id, toTask.title, launchOpts);
     }
 
     public void showNextAffiliatedTask() {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/EventBus.java b/packages/SystemUI/src/com/android/systemui/recents/events/EventBus.java
index d72218f..5c49ac3 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/EventBus.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/EventBus.java
@@ -28,6 +28,8 @@
 import android.util.Log;
 import android.util.MutableBoolean;
 
+import com.android.systemui.recents.misc.ReferenceCountedTrigger;
+
 import java.lang.ref.WeakReference;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
@@ -220,6 +222,20 @@
         // Only accessible from derived events
         protected Event() {}
 
+        /**
+         * Called by the EventBus prior to dispatching this event to any subscriber of this event.
+         */
+        void onPreDispatch() {
+            // Do nothing
+        }
+
+        /**
+         * Called by the EventBus after dispatching this event to every subscriber of this event.
+         */
+        void onPostDispatch() {
+            // Do nothing
+        }
+
         @Override
         protected Object clone() throws CloneNotSupportedException {
             Event evt = (Event) super.clone();
@@ -230,6 +246,51 @@
     }
 
     /**
+     * An event that represents an animated state change, which allows subscribers to coordinate
+     * callbacks which happen after the animation has taken place.
+     *
+     * Internally, it is guaranteed that increment() and decrement() will be called before and the
+     * after the event is dispatched.
+     */
+    public static class AnimatedEvent extends Event {
+
+        private final ReferenceCountedTrigger mTrigger = new ReferenceCountedTrigger();
+
+        // Only accessible from derived events
+        protected AnimatedEvent() {}
+
+        /**
+         * Returns the reference counted trigger that coordinates the animations for this event.
+         */
+        public ReferenceCountedTrigger getAnimationTrigger() {
+            return mTrigger;
+        }
+
+        /**
+         * Adds a callback that is guaranteed to be called after the state has changed regardless of
+         * whether an actual animation took place.
+         */
+        public void addPostAnimationCallback(Runnable r) {
+            mTrigger.addLastDecrementRunnable(r);
+        }
+
+        @Override
+        void onPreDispatch() {
+            mTrigger.increment();
+        }
+
+        @Override
+        void onPostDispatch() {
+            mTrigger.decrement();
+        }
+
+        @Override
+        protected Object clone() throws CloneNotSupportedException {
+            throw new CloneNotSupportedException();
+        }
+    }
+
+    /**
      * An inter-process event super class that allows us to track user state across subscriber
      * invocations.
      */
@@ -706,6 +767,11 @@
         if (eventHandlers == null) {
             return;
         }
+
+        // Prepare this event
+        boolean hasPostedEvent = false;
+        event.onPreDispatch();
+
         // We need to clone the list in case a subscriber unregisters itself during traversal
         eventHandlers = (ArrayList<EventHandler>) eventHandlers.clone();
         for (final EventHandler eventHandler : eventHandlers) {
@@ -717,11 +783,24 @@
                             processEvent(eventHandler, event);
                         }
                     });
+                    hasPostedEvent = true;
                 } else {
                     processEvent(eventHandler, event);
                 }
             }
         }
+
+        // Clean up after this event, deferring until all subscribers have been called
+        if (hasPostedEvent) {
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    event.onPostDispatch();
+                }
+            });
+        } else {
+            event.onPostDispatch();
+        }
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/HideHistoryEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/HideHistoryEvent.java
index 3412852..e85dea3 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/HideHistoryEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/HideHistoryEvent.java
@@ -22,17 +22,11 @@
 /**
  * This is sent when the history view will be closed.
  */
-public class HideHistoryEvent extends EventBus.Event {
+public class HideHistoryEvent extends EventBus.AnimatedEvent {
 
     public final boolean animate;
-    public final ReferenceCountedTrigger postHideHistoryAnimationTrigger;
 
-    /**
-     * @param postHideHistoryAnimationTrigger the trigger that gets called when all the history animations are finished
-     *                                        when transitioning from the history view
-     */
-    public HideHistoryEvent(boolean animate, ReferenceCountedTrigger postHideHistoryAnimationTrigger) {
+    public HideHistoryEvent(boolean animate) {
         this.animate = animate;
-        this.postHideHistoryAnimationTrigger = postHideHistoryAnimationTrigger;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowHistoryEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowHistoryEvent.java
index c91752e..94e5a97 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowHistoryEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowHistoryEvent.java
@@ -22,15 +22,8 @@
 /**
  * This is sent when the history view button is clicked.
  */
-public class ShowHistoryEvent extends EventBus.Event {
+public class ShowHistoryEvent extends EventBus.AnimatedEvent {
 
-    public final ReferenceCountedTrigger postHideStackAnimationTrigger;
+    // Simple event
 
-    /**
-     * @param postHideStackAnimationTrigger the trigger that gets called when all the task animations are finished when
-     *                                      transitioning to the history view
-     */
-    public ShowHistoryEvent(ReferenceCountedTrigger postHideStackAnimationTrigger) {
-        this.postHideStackAnimationTrigger = postHideStackAnimationTrigger;
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/dragndrop/DragEndEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/dragndrop/DragEndEvent.java
index 3deeb47..8aa4631 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/ui/dragndrop/DragEndEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/ui/dragndrop/DragEndEvent.java
@@ -25,18 +25,15 @@
 /**
  * This event is sent whenever a drag ends.
  */
-public class DragEndEvent extends EventBus.Event {
+public class DragEndEvent extends EventBus.AnimatedEvent {
 
     public final Task task;
     public final TaskView taskView;
     public final DropTarget dropTarget;
-    public final ReferenceCountedTrigger postAnimationTrigger;
 
-    public DragEndEvent(Task task, TaskView taskView, DropTarget dropTarget,
-            ReferenceCountedTrigger postAnimationTrigger) {
+    public DragEndEvent(Task task, TaskView taskView, DropTarget dropTarget) {
         this.task = task;
         this.taskView = taskView;
         this.dropTarget = dropTarget;
-        this.postAnimationTrigger = postAnimationTrigger;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryAdapter.java b/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryAdapter.java
index 76439c0..72ec7b7 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryAdapter.java
@@ -31,7 +31,6 @@
 import com.android.systemui.recents.events.EventBus;
 import com.android.systemui.recents.events.activity.HideHistoryButtonEvent;
 import com.android.systemui.recents.events.activity.HideHistoryEvent;
-import com.android.systemui.recents.misc.ReferenceCountedTrigger;
 import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.recents.model.RecentsTaskLoader;
 import com.android.systemui.recents.model.Task;
@@ -72,7 +71,7 @@
         public void onTaskDataLoaded(Task task) {
             // This callback is only made for TaskRow view holders
             ImageView iv = (ImageView) content.findViewById(R.id.icon);
-            iv.setImageDrawable(task.applicationIcon);
+            iv.setImageDrawable(task.icon);
         }
 
         @Override
@@ -128,7 +127,7 @@
         @Override
         public void onClick(View v) {
             SystemServicesProxy ssp = Recents.getSystemServices();
-            ssp.startActivityFromRecents(v.getContext(), task.key.id, task.activityLabel,
+            ssp.startActivityFromRecents(v.getContext(), task.key.id, task.title,
                     ActivityOptions.makeBasic());
         }
 
@@ -240,7 +239,7 @@
                 TaskRow taskRow = (TaskRow) row;
                 taskRow.task.addCallback(holder);
                 TextView tv = (TextView) holder.content.findViewById(R.id.description);
-                tv.setText(taskRow.task.activityLabel);
+                tv.setText(taskRow.task.title);
                 holder.content.setOnClickListener(taskRow);
                 loader.loadTaskData(taskRow.task);
                 break;
@@ -313,10 +312,7 @@
      * Dismisses history back to the stack view.
      */
     private void dismissHistory() {
-        ReferenceCountedTrigger t = new ReferenceCountedTrigger(mContext);
-        t.increment();
-        EventBus.getDefault().send(new HideHistoryEvent(true /* animate */, t));
-        t.decrement();
+        EventBus.getDefault().send(new HideHistoryEvent(true /* animate */));
         EventBus.getDefault().send(new HideHistoryButtonEvent());
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/ReferenceCountedTrigger.java b/packages/SystemUI/src/com/android/systemui/recents/misc/ReferenceCountedTrigger.java
index b06539a..367f2e2 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/ReferenceCountedTrigger.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/ReferenceCountedTrigger.java
@@ -29,9 +29,6 @@
  */
 public class ReferenceCountedTrigger {
 
-    private static final String TAG = "ReferenceCountedTrigger";
-
-    Context mContext;
     int mCount;
     ArrayList<Runnable> mFirstIncRunnables = new ArrayList<Runnable>();
     ArrayList<Runnable> mLastDecRunnables = new ArrayList<Runnable>();
@@ -51,13 +48,12 @@
         }
     };
 
-    public ReferenceCountedTrigger(Context context) {
-        this(context, null, null, null);
+    public ReferenceCountedTrigger() {
+        this(null, null, null);
     }
 
-    public ReferenceCountedTrigger(Context context, Runnable firstIncRunnable,
-                                   Runnable lastDecRunnable, Runnable errorRunanable) {
-        mContext = context;
+    public ReferenceCountedTrigger(Runnable firstIncRunnable, Runnable lastDecRunnable,
+            Runnable errorRunanable) {
         if (firstIncRunnable != null) mFirstIncRunnables.add(firstIncRunnable);
         if (lastDecRunnable != null) mLastDecRunnables.add(lastDecRunnable);
         mErrorRunnable = errorRunanable;
@@ -81,22 +77,14 @@
 
     /** Adds a runnable to the last-decrement runnables list. */
     public void addLastDecrementRunnable(Runnable r) {
-        // To ensure that the last decrement always calls, we increment and decrement after setting
-        // the last decrement runnable
-        boolean ensureLastDecrement = (mCount == 0);
-        if (ensureLastDecrement) increment();
         mLastDecRunnables.add(r);
-        if (ensureLastDecrement) decrement();
     }
 
     /** Decrements the ref count */
     public void decrement() {
         mCount--;
-        if (mCount == 0 && !mLastDecRunnables.isEmpty()) {
-            int numRunnables = mLastDecRunnables.size();
-            for (int i = 0; i < numRunnables; i++) {
-                mLastDecRunnables.get(i).run();
-            }
+        if (mCount == 0) {
+            flushLastDecrementRunnables();
         } else if (mCount < 0) {
             if (mErrorRunnable != null) {
                 mErrorRunnable.run();
@@ -106,6 +94,19 @@
         }
     }
 
+    /**
+     * Runs and clears all the last-decrement runnables now.
+     */
+    public void flushLastDecrementRunnables() {
+        if (!mLastDecRunnables.isEmpty()) {
+            int numRunnables = mLastDecRunnables.size();
+            for (int i = 0; i < numRunnables; i++) {
+                mLastDecRunnables.get(i).run();
+            }
+        }
+        mLastDecRunnables.clear();
+    }
+
     /** Convenience method to decrement this trigger as a runnable. */
     public Runnable decrementAsRunnable() {
         return mDecrementRunnable;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index 5888b30..6a9268a8 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -43,6 +43,7 @@
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffXfermode;
 import android.graphics.Rect;
+import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
@@ -572,7 +573,7 @@
      * Returns the activity icon for the ActivityInfo for a user, badging if
      * necessary.
      */
-    public Drawable getActivityIcon(ActivityInfo info, int userId) {
+    public Drawable getBadgedActivityIcon(ActivityInfo info, int userId) {
         if (mPm == null) return null;
 
         // If we are mocking, then return a mock label
@@ -585,9 +586,31 @@
     }
 
     /**
+     * Returns the task description icon, loading and badging it if it necessary.
+     */
+    public Drawable getBadgedTaskDescriptionIcon(ActivityManager.TaskDescription taskDescription,
+            int userId, Resources res) {
+
+        // If we are mocking, then return a mock label
+        if (RecentsDebugFlags.Static.EnableSystemServicesProxy) {
+            return new ColorDrawable(0xFF666666);
+        }
+
+        Bitmap tdIcon = taskDescription.getInMemoryIcon();
+        if (tdIcon == null) {
+            tdIcon = ActivityManager.TaskDescription.loadTaskDescriptionIcon(
+                    taskDescription.getIconFilename(), userId);
+        }
+        if (tdIcon != null) {
+            return getBadgedIcon(new BitmapDrawable(res, tdIcon), userId);
+        }
+        return null;
+    }
+
+    /**
      * Returns the given icon for a user, badging if necessary.
      */
-    public Drawable getBadgedIcon(Drawable icon, int userId) {
+    private Drawable getBadgedIcon(Drawable icon, int userId) {
         if (userId != UserHandle.myUserId()) {
             icon = mPm.getUserBadgedIcon(icon, new UserHandle(userId));
         }
@@ -597,7 +620,7 @@
     /**
      * Returns the given label for a user, badging if necessary.
      */
-    public String getBadgedLabel(String label, int userId) {
+    private String getBadgedLabel(String label, int userId) {
         if (userId != UserHandle.myUserId()) {
             label = mPm.getUserBadgedLabel(label, new UserHandle(userId)).toString();
         }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
index 1d18087..7a92b2a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
@@ -29,7 +29,6 @@
 import com.android.systemui.Prefs;
 import com.android.systemui.recents.Recents;
 import com.android.systemui.recents.RecentsConfiguration;
-import com.android.systemui.recents.RecentsDebugFlags;
 import com.android.systemui.recents.misc.SystemServicesProxy;
 
 import java.util.ArrayList;
@@ -47,9 +46,6 @@
  */
 public class RecentsTaskLoadPlan {
 
-    private static String TAG = "RecentsTaskLoadPlan";
-    private static boolean DEBUG = false;
-
     private static int MIN_NUM_TASKS = 5;
     private static int SESSION_BEGIN_TIME = 1000 /* ms/s */ * 60 /* s/min */ * 60 /* min/hr */ *
             6 /* hrs */;
@@ -107,13 +103,6 @@
 
         // Since the raw tasks are given in most-recent to least-recent order, we need to reverse it
         Collections.reverse(mRawTasks);
-
-        if (DEBUG) {
-            Log.d(TAG, "preloadRawTasks, tasks: " + mRawTasks.size());
-            for (ActivityManager.RecentTaskInfo info : mRawTasks) {
-                Log.d(TAG, "  " + info.baseIntent + ", " + info.lastActiveTime);
-            }
-        }
     }
 
     /**
@@ -126,8 +115,6 @@
      * - least-recent to most-recent freeform tasks
      */
     public synchronized void preloadPlan(RecentsTaskLoader loader, boolean isTopTaskHome) {
-        if (DEBUG) Log.d(TAG, "preloadPlan");
-
         RecentsConfiguration config = Recents.getConfiguration();
         SystemServicesProxy ssp = Recents.getSystemServices();
         Resources res = mContext.getResources();
@@ -149,38 +136,26 @@
 
             // This task is only shown in the stack if it statisfies the historical time or min
             // number of tasks constraints. Freeform tasks are also always shown.
-            boolean isStackTask = true;
             boolean isFreeformTask = SystemServicesProxy.isFreeformStack(t.stackId);
-            isStackTask = isFreeformTask || (!isHistoricalTask(t) ||
-                    (t.lastActiveTime >= lastStackActiveTime &&
-                            i >= (taskCount - MIN_NUM_TASKS)));
+            boolean isStackTask = isFreeformTask || (!isHistoricalTask(t) ||
+                    (t.lastActiveTime >= lastStackActiveTime && i >= (taskCount - MIN_NUM_TASKS)));
             if (isStackTask && newLastStackActiveTime < 0) {
                 newLastStackActiveTime = t.lastActiveTime;
             }
 
-            // Load the label, icon, and color
-            String activityLabel = loader.getAndUpdateActivityLabel(taskKey, t.taskDescription,
-                    ssp);
-            String contentDescription = loader.getAndUpdateContentDescription(taskKey,
-                    activityLabel, ssp, res);
-            Drawable activityIcon = isStackTask
-                    ? loader.getAndUpdateActivityIcon(taskKey, t.taskDescription, ssp, res, false)
+            // Load the title, icon, and color
+            String title = loader.getAndUpdateActivityTitle(taskKey, t.taskDescription);
+            String contentDescription = loader.getAndUpdateContentDescription(taskKey, title, res);
+            Drawable icon = isStackTask
+                    ? loader.getAndUpdateActivityIcon(taskKey, t.taskDescription, res, false)
                     : null;
+            Bitmap thumbnail = loader.getAndUpdateThumbnail(taskKey, false);
             int activityColor = loader.getActivityPrimaryColor(t.taskDescription);
 
-            Bitmap icon = t.taskDescription != null
-                    ? t.taskDescription.getInMemoryIcon() : null;
-            String iconFilename = t.taskDescription != null
-                    ? t.taskDescription.getIconFilename() : null;
-
             // Add the task to the stack
-            Task task = new Task(taskKey, t.affiliatedTaskId, t.affiliatedTaskColor, activityLabel,
-                    contentDescription, activityIcon, activityColor, (i == (taskCount - 1)),
-                    config.lockToAppEnabled, !isStackTask, icon, iconFilename, t.bounds);
-            task.thumbnail = loader.getAndUpdateThumbnail(taskKey, ssp, false);
-            if (DEBUG) {
-                Log.d(TAG, activityLabel + " bounds: " + t.bounds);
-            }
+            Task task = new Task(taskKey, t.affiliatedTaskId, t.affiliatedTaskColor, icon,
+                    thumbnail, title, contentDescription, activityColor, !isStackTask,
+                    (i == (taskCount - 1)), config.lockToAppEnabled, t.bounds, t.taskDescription);
 
             allTasks.add(task);
         }
@@ -200,19 +175,13 @@
      */
     public synchronized void executePlan(Options opts, RecentsTaskLoader loader,
             TaskResourceLoadQueue loadQueue) {
-        if (DEBUG) Log.d(TAG, "executePlan, # tasks: " + opts.numVisibleTasks +
-                ", # thumbnails: " + opts.numVisibleTaskThumbnails +
-                ", running task id: " + opts.runningTaskId);
-
         RecentsConfiguration config = Recents.getConfiguration();
-        SystemServicesProxy ssp = Recents.getSystemServices();
         Resources res = mContext.getResources();
 
         // Iterate through each of the tasks and load them according to the load conditions.
         ArrayList<Task> tasks = mStack.getStackTasks();
         int taskCount = tasks.size();
         for (int i = 0; i < taskCount; i++) {
-            ActivityManager.RecentTaskInfo t = mRawTasks.get(i);
             Task task = tasks.get(i);
             Task.TaskKey taskKey = task.key;
 
@@ -226,17 +195,15 @@
             }
 
             if (opts.loadIcons && (isRunningTask || isVisibleTask)) {
-                if (task.activityIcon == null) {
-                    if (DEBUG) Log.d(TAG, "\tLoading icon: " + taskKey);
-                    task.activityIcon = loader.getAndUpdateActivityIcon(taskKey, t.taskDescription,
-                            ssp, res, true);
+                if (task.icon == null) {
+                    task.icon = loader.getAndUpdateActivityIcon(taskKey, task.taskDescription,
+                            res, true);
                 }
             }
             if (opts.loadThumbnails && (isRunningTask || isVisibleThumbnail)) {
                 if (task.thumbnail == null || isRunningTask) {
-                    if (DEBUG) Log.d(TAG, "\tLoading thumbnail: " + taskKey);
                     if (config.svelteLevel <= RecentsConfiguration.SVELTE_LIMIT_CACHE) {
-                        task.thumbnail = loader.getAndUpdateThumbnail(taskKey, ssp, true);
+                        task.thumbnail = loader.getAndUpdateThumbnail(taskKey, true);
                     } else if (config.svelteLevel == RecentsConfiguration.SVELTE_DISABLE_CACHE) {
                         loadQueue.addTask(task);
                     }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
index c72d166..28338d83 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
@@ -93,23 +93,23 @@
     Handler mMainThreadHandler;
 
     TaskResourceLoadQueue mLoadQueue;
-    TaskKeyLruCache<Drawable> mApplicationIconCache;
+    TaskKeyLruCache<Drawable> mIconCache;
     TaskKeyLruCache<Bitmap> mThumbnailCache;
     Bitmap mDefaultThumbnail;
-    BitmapDrawable mDefaultApplicationIcon;
+    BitmapDrawable mDefaultIcon;
 
     boolean mCancelled;
     boolean mWaitingOnLoadQueue;
 
     /** Constructor, creates a new loading thread that loads task resources in the background */
     public BackgroundTaskLoader(TaskResourceLoadQueue loadQueue,
-            TaskKeyLruCache<Drawable> applicationIconCache, TaskKeyLruCache<Bitmap> thumbnailCache,
-            Bitmap defaultThumbnail, BitmapDrawable defaultApplicationIcon) {
+            TaskKeyLruCache<Drawable> iconCache, TaskKeyLruCache<Bitmap> thumbnailCache,
+            Bitmap defaultThumbnail, BitmapDrawable defaultIcon) {
         mLoadQueue = loadQueue;
-        mApplicationIconCache = applicationIconCache;
+        mIconCache = iconCache;
         mThumbnailCache = thumbnailCache;
         mDefaultThumbnail = defaultThumbnail;
-        mDefaultApplicationIcon = defaultApplicationIcon;
+        mDefaultIcon = defaultIcon;
         mMainThreadHandler = new Handler();
         mLoadThread = new HandlerThread("Recents-TaskResourceLoader",
                 android.os.Process.THREAD_PRIORITY_BACKGROUND);
@@ -163,30 +163,30 @@
                     // Load the next item from the queue
                     final Task t = mLoadQueue.nextTask();
                     if (t != null) {
-                        Drawable cachedIcon = mApplicationIconCache.get(t.key);
+                        Drawable cachedIcon = mIconCache.get(t.key);
                         Bitmap cachedThumbnail = mThumbnailCache.get(t.key);
 
-                        // Load the application icon if it is stale or we haven't cached one yet
+                        // Load the icon if it is stale or we haven't cached one yet
                         if (cachedIcon == null) {
-                            cachedIcon = getTaskDescriptionIcon(t.key, t.icon, t.iconFilename, ssp,
-                                    mContext.getResources());
+                            cachedIcon = ssp.getBadgedTaskDescriptionIcon(t.taskDescription,
+                                    t.key.userId, mContext.getResources());
 
                             if (cachedIcon == null) {
                                 ActivityInfo info = ssp.getActivityInfo(
                                         t.key.getComponent(), t.key.userId);
                                 if (info != null) {
                                     if (DEBUG) Log.d(TAG, "Loading icon: " + t.key);
-                                    cachedIcon = ssp.getActivityIcon(info, t.key.userId);
+                                    cachedIcon = ssp.getBadgedActivityIcon(info, t.key.userId);
                                 }
                             }
 
                             if (cachedIcon == null) {
-                                cachedIcon = mDefaultApplicationIcon;
+                                cachedIcon = mDefaultIcon;
                             }
 
                             // At this point, even if we can't load the icon, we will set the
                             // default icon.
-                            mApplicationIconCache.put(t.key, cachedIcon);
+                            mIconCache.put(t.key, cachedIcon);
                         }
                         // Load the thumbnail if it is stale or we haven't cached one yet
                         if (cachedThumbnail == null) {
@@ -234,25 +234,6 @@
             }
         }
     }
-
-    Drawable getTaskDescriptionIcon(Task.TaskKey taskKey, Bitmap iconBitmap, String iconFilename,
-            SystemServicesProxy ssp, Resources res) {
-        Bitmap tdIcon = null;
-        if (iconBitmap != null) {
-            tdIcon = iconBitmap;
-        } else {
-            try {
-                tdIcon = ActivityManager.TaskDescription.loadTaskDescriptionIcon(iconFilename,
-                        taskKey.userId);
-            } catch (Exception e) {
-                // TODO: Investigate for b/26221779
-            }
-        }
-        if (tdIcon != null) {
-            return ssp.getBadgedIcon(new BitmapDrawable(res, tdIcon), taskKey.userId);
-        }
-        return null;
-    }
 }
 
 /**
@@ -269,7 +250,7 @@
     // active time.  Instead, we rely on the RecentsPackageMonitor to keep us informed whenever a
     // package in the cache has been updated, so that we may remove it.
     private final LruCache<ComponentName, ActivityInfo> mActivityInfoCache;
-    private final TaskKeyLruCache<Drawable> mApplicationIconCache;
+    private final TaskKeyLruCache<Drawable> mIconCache;
     private final TaskKeyLruCache<Bitmap> mThumbnailCache;
     private final TaskKeyLruCache<String> mActivityLabelCache;
     private final TaskKeyLruCache<String> mContentDescriptionCache;
@@ -282,7 +263,7 @@
     private int mNumVisibleThumbnailsLoaded;
 
     int mDefaultTaskBarBackgroundColor;
-    BitmapDrawable mDefaultApplicationIcon;
+    BitmapDrawable mDefaultIcon;
     Bitmap mDefaultThumbnail;
 
     public RecentsTaskLoader(Context context) {
@@ -302,22 +283,22 @@
         mDefaultThumbnail = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
         mDefaultThumbnail.setHasAlpha(false);
         mDefaultThumbnail.eraseColor(0xFFffffff);
-        mDefaultApplicationIcon = new BitmapDrawable(context.getResources(), icon);
+        mDefaultIcon = new BitmapDrawable(context.getResources(), icon);
 
         // Initialize the proxy, cache and loaders
         int numRecentTasks = ActivityManager.getMaxRecentTasksStatic();
         mLoadQueue = new TaskResourceLoadQueue();
-        mApplicationIconCache = new TaskKeyLruCache<>(iconCacheSize);
+        mIconCache = new TaskKeyLruCache<>(iconCacheSize);
         mThumbnailCache = new TaskKeyLruCache<>(thumbnailCacheSize);
         mActivityLabelCache = new TaskKeyLruCache<>(numRecentTasks);
         mContentDescriptionCache = new TaskKeyLruCache<>(numRecentTasks);
         mActivityInfoCache = new LruCache(numRecentTasks);
-        mLoader = new BackgroundTaskLoader(mLoadQueue, mApplicationIconCache, mThumbnailCache,
-                mDefaultThumbnail, mDefaultApplicationIcon);
+        mLoader = new BackgroundTaskLoader(mLoadQueue, mIconCache, mThumbnailCache,
+                mDefaultThumbnail, mDefaultIcon);
     }
 
     /** Returns the size of the app icon cache. */
-    public int getApplicationIconCacheSize() {
+    public int getIconCacheSize() {
         return mMaxIconCacheSize;
     }
 
@@ -355,33 +336,33 @@
 
     /** Acquires the task resource data directly from the pool. */
     public void loadTaskData(Task t) {
-        Drawable applicationIcon = mApplicationIconCache.getAndInvalidateIfModified(t.key);
+        Drawable icon = mIconCache.getAndInvalidateIfModified(t.key);
         Bitmap thumbnail = mThumbnailCache.getAndInvalidateIfModified(t.key);
 
         // Grab the thumbnail/icon from the cache, if either don't exist, then trigger a reload and
         // use the default assets in their place until they load
-        boolean requiresLoad = (applicationIcon == null) || (thumbnail == null);
-        applicationIcon = applicationIcon != null ? applicationIcon : mDefaultApplicationIcon;
+        boolean requiresLoad = (icon == null) || (thumbnail == null);
+        icon = icon != null ? icon : mDefaultIcon;
         if (requiresLoad) {
             mLoadQueue.addTask(t);
         }
-        t.notifyTaskDataLoaded(thumbnail == mDefaultThumbnail ? null : thumbnail, applicationIcon);
+        t.notifyTaskDataLoaded(thumbnail == mDefaultThumbnail ? null : thumbnail, icon);
     }
 
     /** Releases the task resource data back into the pool. */
     public void unloadTaskData(Task t) {
         mLoadQueue.removeTask(t);
-        t.notifyTaskDataUnloaded(null, mDefaultApplicationIcon);
+        t.notifyTaskDataUnloaded(null, mDefaultIcon);
     }
 
     /** Completely removes the resource data from the pool. */
     public void deleteTaskData(Task t, boolean notifyTaskDataUnloaded) {
         mLoadQueue.removeTask(t);
         mThumbnailCache.remove(t.key);
-        mApplicationIconCache.remove(t.key);
+        mIconCache.remove(t.key);
         mActivityInfoCache.remove(t.key.getComponent());
         if (notifyTaskDataUnloaded) {
-            t.notifyTaskDataUnloaded(null, mDefaultApplicationIcon);
+            t.notifyTaskDataUnloaded(null, mDefaultIcon);
         }
     }
 
@@ -403,14 +384,14 @@
                 } else if (config.svelteLevel >= RecentsConfiguration.SVELTE_DISABLE_CACHE) {
                     mThumbnailCache.evictAll();
                 }
-                mApplicationIconCache.trimToSize(Math.max(mNumVisibleTasksLoaded,
+                mIconCache.trimToSize(Math.max(mNumVisibleTasksLoaded,
                         mMaxIconCacheSize / 2));
                 break;
             case ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE:
             case ComponentCallbacks2.TRIM_MEMORY_BACKGROUND:
                 // We are leaving recents, so trim the data a bit
                 mThumbnailCache.trimToSize(Math.max(1, mMaxThumbnailCacheSize / 2));
-                mApplicationIconCache.trimToSize(Math.max(1, mMaxIconCacheSize / 2));
+                mIconCache.trimToSize(Math.max(1, mMaxIconCacheSize / 2));
                 mActivityInfoCache.trimToSize(Math.max(1,
                         ActivityManager.getMaxRecentTasksStatic() / 2));
                 break;
@@ -418,7 +399,7 @@
             case ComponentCallbacks2.TRIM_MEMORY_MODERATE:
                 // We are going to be low on memory
                 mThumbnailCache.trimToSize(Math.max(1, mMaxThumbnailCacheSize / 4));
-                mApplicationIconCache.trimToSize(Math.max(1, mMaxIconCacheSize / 4));
+                mIconCache.trimToSize(Math.max(1, mMaxIconCacheSize / 4));
                 mActivityInfoCache.trimToSize(Math.max(1,
                         ActivityManager.getMaxRecentTasksStatic() / 4));
                 break;
@@ -426,7 +407,7 @@
             case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:
                 // We are low on memory, so release everything
                 mThumbnailCache.evictAll();
-                mApplicationIconCache.evictAll();
+                mIconCache.evictAll();
                 mActivityInfoCache.evictAll();
                 // The cache is small, only clear the label cache when we are critical
                 mActivityLabelCache.evictAll();
@@ -440,8 +421,9 @@
     /**
      * Returns the cached task label if the task key is not expired, updating the cache if it is.
      */
-    String getAndUpdateActivityLabel(Task.TaskKey taskKey, ActivityManager.TaskDescription td,
-                                     SystemServicesProxy ssp) {
+    String getAndUpdateActivityTitle(Task.TaskKey taskKey, ActivityManager.TaskDescription td) {
+        SystemServicesProxy ssp = Recents.getSystemServices();
+
         // Return the task description label if it exists
         if (td != null && td.getLabel() != null) {
             return td.getLabel();
@@ -452,7 +434,7 @@
             return label;
         }
         // All short paths failed, load the label from the activity info and cache it
-        ActivityInfo activityInfo = getAndUpdateActivityInfo(taskKey, ssp);
+        ActivityInfo activityInfo = getAndUpdateActivityInfo(taskKey);
         if (activityInfo != null) {
             label = ssp.getActivityLabel(activityInfo);
             mActivityLabelCache.put(taskKey, label);
@@ -468,7 +450,9 @@
      * cache if it is.
      */
     String getAndUpdateContentDescription(Task.TaskKey taskKey, String activityLabel,
-            SystemServicesProxy ssp, Resources res) {
+            Resources res) {
+        SystemServicesProxy ssp = Recents.getSystemServices();
+
         // Return the cached content description if it exists
         String label = mContentDescriptionCache.getAndInvalidateIfModified(taskKey);
         if (label != null) {
@@ -493,28 +477,29 @@
      * Returns the cached task icon if the task key is not expired, updating the cache if it is.
      */
     Drawable getAndUpdateActivityIcon(Task.TaskKey taskKey, ActivityManager.TaskDescription td,
-            SystemServicesProxy ssp, Resources res, boolean loadIfNotCached) {
+            Resources res, boolean loadIfNotCached) {
+        SystemServicesProxy ssp = Recents.getSystemServices();
+
         // Return the cached activity icon if it exists
-        Drawable icon = mApplicationIconCache.getAndInvalidateIfModified(taskKey);
+        Drawable icon = mIconCache.getAndInvalidateIfModified(taskKey);
         if (icon != null) {
             return icon;
         }
 
         if (loadIfNotCached) {
             // Return and cache the task description icon if it exists
-            icon = mLoader.getTaskDescriptionIcon(taskKey, td.getInMemoryIcon(),
-                    td.getIconFilename(), ssp, res);
+            icon = ssp.getBadgedTaskDescriptionIcon(td, taskKey.userId, res);
             if (icon != null) {
-                mApplicationIconCache.put(taskKey, icon);
+                mIconCache.put(taskKey, icon);
                 return icon;
             }
 
             // Load the icon from the activity info and cache it
-            ActivityInfo activityInfo = getAndUpdateActivityInfo(taskKey, ssp);
+            ActivityInfo activityInfo = getAndUpdateActivityInfo(taskKey);
             if (activityInfo != null) {
-                icon = ssp.getActivityIcon(activityInfo, taskKey.userId);
+                icon = ssp.getBadgedActivityIcon(activityInfo, taskKey.userId);
                 if (icon != null) {
-                    mApplicationIconCache.put(taskKey, icon);
+                    mIconCache.put(taskKey, icon);
                     return icon;
                 }
             }
@@ -526,8 +511,9 @@
     /**
      * Returns the cached thumbnail if the task key is not expired, updating the cache if it is.
      */
-    Bitmap getAndUpdateThumbnail(Task.TaskKey taskKey, SystemServicesProxy ssp,
-            boolean loadIfNotCached) {
+    Bitmap getAndUpdateThumbnail(Task.TaskKey taskKey, boolean loadIfNotCached) {
+        SystemServicesProxy ssp = Recents.getSystemServices();
+
         // Return the cached thumbnail if it exists
         Bitmap thumbnail = mThumbnailCache.getAndInvalidateIfModified(taskKey);
         if (thumbnail != null) {
@@ -550,7 +536,8 @@
     }
 
     /**
-     * Returns the task's primary color.
+     * Returns the task's primary color if possible, defaulting to the default color if there is
+     * no specified primary color.
      */
     int getActivityPrimaryColor(ActivityManager.TaskDescription td) {
         if (td != null && td.getPrimaryColor() != 0) {
@@ -563,7 +550,8 @@
      * Returns the activity info for the given task key, retrieving one from the system if the
      * task key is expired.
      */
-    private ActivityInfo getAndUpdateActivityInfo(Task.TaskKey taskKey, SystemServicesProxy ssp) {
+    private ActivityInfo getAndUpdateActivityInfo(Task.TaskKey taskKey) {
+        SystemServicesProxy ssp = Recents.getSystemServices();
         ComponentName cn = taskKey.getComponent();
         ActivityInfo activityInfo = mActivityInfoCache.get(cn);
         if (activityInfo == null) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
index 73c0adb..34a0e52 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.recents.model;
 
+import android.app.ActivityManager;
 import android.content.ComponentName;
 import android.content.Intent;
 import android.graphics.Bitmap;
@@ -92,24 +93,46 @@
     }
 
     public TaskKey key;
+
+    /**
+     * The group will be computed separately from the initialization of the task
+     */
     public TaskGrouping group;
-    // The taskAffiliationId is the task id of the parent task or itself if it is not affiliated with any task
-    public int taskAffiliationId;
-    public int taskAffiliationColor;
-    public boolean isLaunchTarget;
-    public Drawable applicationIcon;
-    public Drawable activityIcon;
+    /**
+     * The affiliationTaskId is the task id of the parent task or itself if it is not affiliated
+     * with any task.
+     */
+    public int affiliationTaskId;
+    public int affiliationColor;
+
+    /**
+     * The icon is the task description icon (if provided), which falls back to the activity icon,
+     * which can then fall back to the application icon.
+     */
+    public Drawable icon;
+    public Bitmap thumbnail;
+    public String title;
     public String contentDescription;
-    public String activityLabel;
     public int colorPrimary;
     public boolean useLightOnPrimaryColor;
-    public Bitmap thumbnail;
+
+    /**
+     * The bounds of the task, used only if it is a freeform task.
+     */
+    public Rect bounds;
+
+    /**
+     * The task description for this task, only used to reload task icons.
+     */
+    public ActivityManager.TaskDescription taskDescription;
+
+    /**
+     * The state isLaunchTarget will be set for the correct task upon launching Recents.
+     */
+    public boolean isLaunchTarget;
+    public boolean isHistorical;
     public boolean lockToThisTask;
     public boolean lockToTaskEnabled;
-    public boolean isHistorical;
-    public Bitmap icon;
-    public String iconFilename;
-    public Rect bounds;
 
     private ArrayList<TaskCallbacks> mCallbacks = new ArrayList<>();
 
@@ -117,45 +140,46 @@
         // Do nothing
     }
 
-    public Task(TaskKey key, int taskAffiliation, int taskAffiliationColor,
-                String activityTitle, String contentDescription, Drawable activityIcon,
-                int colorPrimary, boolean lockToThisTask, boolean lockToTaskEnabled,
-                boolean isHistorical, Bitmap icon, String iconFilename, Rect bounds) {
-        boolean isInAffiliationGroup = (taskAffiliation != key.id);
-        boolean hasAffiliationGroupColor = isInAffiliationGroup && (taskAffiliationColor != 0);
+    public Task(TaskKey key, int affiliationTaskId, int affiliationColor, Drawable icon,
+                Bitmap thumbnail, String title, String contentDescription, int colorPrimary,
+                boolean isHistorical, boolean lockToThisTask, boolean lockToTaskEnabled,
+                Rect bounds, ActivityManager.TaskDescription taskDescription) {
+        boolean isInAffiliationGroup = (affiliationTaskId != key.id);
+        boolean hasAffiliationGroupColor = isInAffiliationGroup && (affiliationColor != 0);
         this.key = key;
-        this.taskAffiliationId = taskAffiliation;
-        this.taskAffiliationColor = taskAffiliationColor;
-        this.activityLabel = activityTitle;
+        this.affiliationTaskId = affiliationTaskId;
+        this.affiliationColor = affiliationColor;
+        this.icon = icon;
+        this.thumbnail = thumbnail;
+        this.title = title;
         this.contentDescription = contentDescription;
-        this.activityIcon = activityIcon;
-        this.colorPrimary = hasAffiliationGroupColor ? taskAffiliationColor : colorPrimary;
+        this.colorPrimary = hasAffiliationGroupColor ? affiliationColor : colorPrimary;
         this.useLightOnPrimaryColor = Utilities.computeContrastBetweenColors(this.colorPrimary,
                 Color.WHITE) > 3f;
+        this.bounds = bounds;
+        this.taskDescription = taskDescription;
+        this.isHistorical = isHistorical;
         this.lockToThisTask = lockToTaskEnabled && lockToThisTask;
         this.lockToTaskEnabled = lockToTaskEnabled;
-        this.isHistorical = isHistorical;
-        this.icon = icon;
-        this.iconFilename = iconFilename;
-        this.bounds = bounds;
     }
 
     /** Copies the other task. */
     public void copyFrom(Task o) {
         this.key = o.key;
-        this.taskAffiliationId = o.taskAffiliationId;
-        this.taskAffiliationColor = o.taskAffiliationColor;
-        this.activityLabel = o.activityLabel;
+        this.group = o.group;
+        this.affiliationTaskId = o.affiliationTaskId;
+        this.affiliationColor = o.affiliationColor;
+        this.icon = o.icon;
+        this.thumbnail = o.thumbnail;
+        this.title = o.title;
         this.contentDescription = o.contentDescription;
-        this.activityIcon = o.activityIcon;
         this.colorPrimary = o.colorPrimary;
         this.useLightOnPrimaryColor = o.useLightOnPrimaryColor;
+        this.bounds = o.bounds;
+        this.isLaunchTarget = o.isLaunchTarget;
+        this.isHistorical = o.isHistorical;
         this.lockToThisTask = o.lockToThisTask;
         this.lockToTaskEnabled = o.lockToTaskEnabled;
-        this.isHistorical = o.isHistorical;
-        this.icon = o.icon;
-        this.iconFilename = o.iconFilename;
-        this.bounds = o.bounds;
     }
 
     /**
@@ -200,7 +224,7 @@
 
     /** Notifies the callback listeners that this task has been loaded */
     public void notifyTaskDataLoaded(Bitmap thumbnail, Drawable applicationIcon) {
-        this.applicationIcon = applicationIcon;
+        this.icon = applicationIcon;
         this.thumbnail = thumbnail;
         int callbackCount = mCallbacks.size();
         for (int i = 0; i < callbackCount; i++) {
@@ -210,7 +234,7 @@
 
     /** Notifies the callback listeners that this task has been unloaded */
     public void notifyTaskDataUnloaded(Bitmap defaultThumbnail, Drawable defaultApplicationIcon) {
-        applicationIcon = defaultApplicationIcon;
+        icon = defaultApplicationIcon;
         thumbnail = defaultThumbnail;
         int callbackCount = mCallbacks.size();
         for (int i = 0; i < callbackCount; i++) {
@@ -222,7 +246,7 @@
      * Returns whether this task is affiliated with another task.
      */
     public boolean isAffiliatedTask() {
-        return key.id != taskAffiliationId;
+        return key.id != affiliationTaskId;
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
index ad03b4e..d06012e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
@@ -354,7 +354,7 @@
                 if (t.isAffiliatedTask()) {
                     // If this task is affiliated with another parent in the stack, then the historical state of this
                     // task depends on the state of the parent task
-                    Task parentTask = taskIdMap.get(t.taskAffiliationId);
+                    Task parentTask = taskIdMap.get(t.affiliationTaskId);
                     if (parentTask != null) {
                         t = parentTask;
                     }
@@ -368,7 +368,7 @@
                 if (t.isAffiliatedTask()) {
                     // If this task is affiliated with another parent in the stack, then the historical state of this
                     // task depends on the state of the parent task
-                    Task parentTask = taskIdMap.get(t.taskAffiliationId);
+                    Task parentTask = taskIdMap.get(t.affiliationTaskId);
                     if (parentTask != null) {
                         t = parentTask;
                     }
@@ -716,7 +716,7 @@
             for (int i = 0; i < taskCount; i++) {
                 Task t = tasks.get(i);
                 TaskGrouping group;
-                int affiliation = t.taskAffiliationId > 0 ? t.taskAffiliationId :
+                int affiliation = t.affiliationTaskId > 0 ? t.affiliationTaskId :
                         IndividualTaskIdOffset + t.key.id;
                 if (mAffinitiesGroups.containsKey(affiliation)) {
                     group = getGroupWithAffiliation(affiliation);
@@ -737,7 +737,7 @@
                 // Ignore the groups that only have one task
                 if (taskCount <= 1) continue;
                 // Calculate the group color distribution
-                int affiliationColor = tasksMap.get(group.mTaskKeys.get(0)).taskAffiliationColor;
+                int affiliationColor = tasksMap.get(group.mTaskKeys.get(0)).affiliationColor;
                 float alphaStep = (1f - minAlpha) / taskCount;
                 float alpha = 1f;
                 for (int j = 0; j < taskCount; j++) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
index 135f0f9..0af7c1e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
@@ -157,7 +157,7 @@
             ActivityOptions opts, IAppTransitionAnimationSpecsFuture transitionFuture,
             final ActivityOptions.OnAnimationStartedListener animStartedListener) {
         SystemServicesProxy ssp = Recents.getSystemServices();
-        if (ssp.startActivityFromRecents(mContext, task.key.id, task.activityLabel, opts)) {
+        if (ssp.startActivityFromRecents(mContext, task.key.id, task.title, opts)) {
             // Keep track of the index of the task launch
             int taskIndexFromFront = 0;
             int taskIndex = stack.indexOfStackTask(task);
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 53c02cb..9b1315a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -132,10 +132,7 @@
         mHistoryButton.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
-                ReferenceCountedTrigger postHideStackAnimationTrigger = new ReferenceCountedTrigger(v.getContext());
-                postHideStackAnimationTrigger.increment();
-                EventBus.getDefault().send(new ShowHistoryEvent(postHideStackAnimationTrigger));
-                postHideStackAnimationTrigger.decrement();
+                EventBus.getDefault().send(new ShowHistoryEvent());
             }
         });
         addView(mHistoryButton);
@@ -576,8 +573,8 @@
     public final void onBusEvent(ShowHistoryEvent event) {
         // Hide the history button when the history view is shown
         hideHistoryButton(getResources().getInteger(R.integer.recents_history_transition_duration),
-                event.postHideStackAnimationTrigger);
-        event.postHideStackAnimationTrigger.addLastDecrementRunnable(new Runnable() {
+                event.getAnimationTrigger());
+        event.addPostAnimationCallback(new Runnable() {
             @Override
             public void run() {
                 setAlpha(0f);
@@ -589,7 +586,7 @@
         // Show the history button when the history view is hidden
         setAlpha(1f);
         showHistoryButton(getResources().getInteger(R.integer.recents_history_transition_duration),
-                event.postHideHistoryAnimationTrigger);
+                event.getAnimationTrigger());
     }
 
     public final void onBusEvent(ShowHistoryButtonEvent event) {
@@ -609,10 +606,9 @@
      * Shows the history button.
      */
     private void showHistoryButton(final int duration) {
-        ReferenceCountedTrigger postAnimationTrigger = new ReferenceCountedTrigger(getContext());
-        postAnimationTrigger.increment();
+        ReferenceCountedTrigger postAnimationTrigger = new ReferenceCountedTrigger();
         showHistoryButton(duration, postAnimationTrigger);
-        postAnimationTrigger.decrement();
+        postAnimationTrigger.flushLastDecrementRunnables();
     }
 
     private void showHistoryButton(final int duration,
@@ -638,10 +634,9 @@
      * Hides the history button.
      */
     private void hideHistoryButton(int duration) {
-        ReferenceCountedTrigger postAnimationTrigger = new ReferenceCountedTrigger(getContext());
-        postAnimationTrigger.increment();
+        ReferenceCountedTrigger postAnimationTrigger = new ReferenceCountedTrigger();
         hideHistoryButton(duration, postAnimationTrigger);
-        postAnimationTrigger.decrement();
+        postAnimationTrigger.flushLastDecrementRunnables();
     }
 
     private void hideHistoryButton(int duration,
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java
index 37a0194..318801d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java
@@ -188,12 +188,8 @@
             case MotionEvent.ACTION_UP:
             case MotionEvent.ACTION_CANCEL: {
                 if (mDragging) {
-                    ReferenceCountedTrigger postAnimationTrigger = new ReferenceCountedTrigger(
-                            mRv.getContext());
-                    postAnimationTrigger.increment();
                     EventBus.getDefault().send(new DragEndEvent(mDragTask, mTaskView,
-                            mLastDropTarget, postAnimationTrigger));
-                    postAnimationTrigger.decrement();
+                            mLastDropTarget));
                     break;
                 }
             }
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 421e6a0..830d607 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -44,7 +44,6 @@
 import com.android.systemui.recents.RecentsActivity;
 import com.android.systemui.recents.RecentsActivityLaunchState;
 import com.android.systemui.recents.RecentsConfiguration;
-import com.android.systemui.recents.RecentsDebugFlags;
 import com.android.systemui.recents.events.EventBus;
 import com.android.systemui.recents.events.activity.CancelEnterRecentsWindowAnimationEvent;
 import com.android.systemui.recents.events.activity.EnterRecentsWindowAnimationCompletedEvent;
@@ -798,7 +797,7 @@
             TaskView frontMostTask = taskViews.get(taskViewCount - 1);
             event.setFromIndex(mStack.indexOfStackTask(backMostTask.getTask()));
             event.setToIndex(mStack.indexOfStackTask(frontMostTask.getTask()));
-            event.setContentDescription(frontMostTask.getTask().activityLabel);
+            event.setContentDescription(frontMostTask.getTask().title);
         }
         event.setItemCount(mStack.getStackTaskCount());
         event.setScrollY(mStackScroller.mScroller.getCurrY());
@@ -1022,8 +1021,7 @@
             if (launchTargetTask != null) {
                 occludesLaunchTarget = launchTargetTask.group.isTaskAboveTask(task,
                         launchTargetTask);
-                hideTask = SystemServicesProxy.isFreeformStack(launchTargetTask.key.stackId) &&
-                        SystemServicesProxy.isFreeformStack(task.key.stackId);
+                hideTask = launchTargetTask.isFreeformTask() && task.isFreeformTask();
             }
             tv.prepareEnterRecentsAnimation(task.isLaunchTarget, hideTask, occludesLaunchTarget,
                     offscreenY);
@@ -1495,7 +1493,6 @@
                 (!isFreeformTask && event.dropTarget == mFreeformWorkspaceDropTarget) ||
                         (isFreeformTask && event.dropTarget == mStackDropTarget);
 
-        event.postAnimationTrigger.increment();
         if (hasChangedStacks) {
             // Move the task to the right position in the stack (ie. the front of the stack if
             // freeform or the front of the stack if fullscreen).  Note, we MUST move the tasks
@@ -1508,7 +1505,7 @@
             updateLayout(true);
 
             // Move the task to the new stack in the system after the animation completes
-            event.postAnimationTrigger.addLastDecrementRunnable(new Runnable() {
+            event.addPostAnimationCallback(new Runnable() {
                 @Override
                 public void run() {
                     SystemServicesProxy ssp = Recents.getSystemServices();
@@ -1516,8 +1513,8 @@
                 }
             });
         }
-        event.taskView.animate()
-                .withEndAction(event.postAnimationTrigger.decrementAsRunnable());
+        event.getAnimationTrigger().increment();
+        event.taskView.animate().withEndAction(event.getAnimationTrigger().decrementAsRunnable());
 
         // We translated the view but we need to animate it back from the current layout-space rect
         // to its final layout-space rect
@@ -1557,7 +1554,7 @@
         for (int i = 0; i < taskViewCount; i++) {
             TaskView tv = taskViews.get(i);
             Task task = tv.getTask();
-            if (SystemServicesProxy.isFreeformStack(task.key.stackId)) {
+            if (task.isFreeformTask()) {
                 tv.setVisibility(event.visible ? View.VISIBLE : View.INVISIBLE);
             }
         }
@@ -1578,9 +1575,9 @@
                     .setUpdateListener(null)
                     .setListener(null)
                     .withLayer()
-                    .withEndAction(event.postHideStackAnimationTrigger.decrementAsRunnable())
+                    .withEndAction(event.getAnimationTrigger().decrementAsRunnable())
                     .start();
-            event.postHideStackAnimationTrigger.increment();
+            event.getAnimationTrigger().increment();
         }
     }
 
@@ -1593,7 +1590,7 @@
         int taskViewCount = taskViews.size();
         for (int i = taskViewCount - 1; i >= 0; i--) {
             final TaskView tv = taskViews.get(i);
-            event.postHideHistoryAnimationTrigger.addLastDecrementRunnable(new Runnable() {
+            event.addPostAnimationCallback(new Runnable() {
                 @Override
                 public void run() {
                     tv.animate()
@@ -1617,7 +1614,7 @@
 
         // Announce for accessibility
         tv.announceForAccessibility(getContext().getString(
-                R.string.accessibility_recents_item_dismissed, tv.getTask().activityLabel));
+                R.string.accessibility_recents_item_dismissed, tv.getTask().title));
 
         // Remove the task from the stack
         mStack.removeTask(task);
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 df7b9a6..a3e8b2d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -651,7 +651,7 @@
      */
     public void setFocusedState(boolean isFocused, boolean animated, boolean requestViewFocus) {
         if (DEBUG) {
-            Log.d(TAG, "setFocusedState: " + mTask.activityLabel + " focused: " + isFocused +
+            Log.d(TAG, "setFocusedState: " + mTask.title + " focused: " + isFocused +
                     " animated: " + animated + " requestViewFocus: " + requestViewFocus +
                     " isFocused(): " + isFocused() +
                     " isAccessibilityFocused(): " + isAccessibilityFocused());
@@ -771,7 +771,7 @@
 
     public final void onBusEvent(DragEndEvent event) {
         if (!(event.dropTarget instanceof TaskStack.DockState)) {
-            event.postAnimationTrigger.addLastDecrementRunnable(new Runnable() {
+            event.addPostAnimationCallback(new Runnable() {
                 @Override
                 public void run() {
                     // Animate the drag view back from where it is, to the view location, then after
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 0271ccd..9a2ffe7 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
@@ -60,8 +60,8 @@
     // Header views
     ImageView mMoveTaskButton;
     ImageView mDismissButton;
-    ImageView mApplicationIcon;
-    TextView mActivityDescription;
+    ImageView mIconView;
+    TextView mTitleView;
     int mMoveTaskTargetStackId = INVALID_STACK_ID;
 
     // Header drawables
@@ -128,16 +128,16 @@
     @Override
     protected void onFinishInflate() {
         // Initialize the icon and description views
-        mApplicationIcon = (ImageView) findViewById(R.id.application_icon);
-        mApplicationIcon.setOnLongClickListener(this);
-        mActivityDescription = (TextView) findViewById(R.id.activity_description);
+        mIconView = (ImageView) findViewById(R.id.icon);
+        mIconView.setOnLongClickListener(this);
+        mTitleView = (TextView) findViewById(R.id.title);
         mDismissButton = (ImageView) findViewById(R.id.dismiss_task);
         mDismissButton.setOnClickListener(this);
         mMoveTaskButton = (ImageView) findViewById(R.id.move_task);
 
         // Hide the backgrounds if they are ripple drawables
-        if (mApplicationIcon.getBackground() instanceof RippleDrawable) {
-            mApplicationIcon.setBackground(null);
+        if (mIconView.getBackground() instanceof RippleDrawable) {
+            mIconView.setBackground(null);
         }
 
         mBackgroundColorDrawable = (GradientDrawable) getContext().getDrawable(
@@ -158,8 +158,8 @@
     public void onTaskViewSizeChanged(int width, int height) {
         mTaskViewRect.set(0, 0, width, height);
         boolean updateMoveTaskButton = mMoveTaskButton.getVisibility() != View.GONE;
-        int appIconWidth = mApplicationIcon.getMeasuredWidth();
-        int activityDescWidth = mActivityDescription.getMeasuredWidth();
+        int appIconWidth = mIconView.getMeasuredWidth();
+        int activityDescWidth = mTitleView.getMeasuredWidth();
         int dismissIconWidth = mDismissButton.getMeasuredWidth();
         int moveTaskIconWidth = mMoveTaskButton.getVisibility() == View.VISIBLE
                 ? mMoveTaskButton.getMeasuredWidth()
@@ -168,26 +168,26 @@
         // Priority-wise, we show the activity icon first, the dismiss icon if there is room, the
         // move-task icon if there is room, and then finally, the activity label if there is room
         if (width < (appIconWidth + dismissIconWidth)) {
-            mActivityDescription.setVisibility(View.INVISIBLE);
+            mTitleView.setVisibility(View.INVISIBLE);
             if (updateMoveTaskButton) {
                 mMoveTaskButton.setVisibility(View.INVISIBLE);
             }
             mDismissButton.setVisibility(View.INVISIBLE);
         } else if (width < (appIconWidth + dismissIconWidth + moveTaskIconWidth)) {
-            mActivityDescription.setVisibility(View.INVISIBLE);
+            mTitleView.setVisibility(View.INVISIBLE);
             if (updateMoveTaskButton) {
                 mMoveTaskButton.setVisibility(View.INVISIBLE);
             }
             mDismissButton.setVisibility(View.VISIBLE);
         } else if (width < (appIconWidth + dismissIconWidth + moveTaskIconWidth +
                 activityDescWidth)) {
-            mActivityDescription.setVisibility(View.INVISIBLE);
+            mTitleView.setVisibility(View.INVISIBLE);
             if (updateMoveTaskButton) {
                 mMoveTaskButton.setVisibility(View.VISIBLE);
             }
             mDismissButton.setVisibility(View.VISIBLE);
         } else {
-            mActivityDescription.setVisibility(View.VISIBLE);
+            mTitleView.setVisibility(View.VISIBLE);
             if (updateMoveTaskButton) {
                 mMoveTaskButton.setVisibility(View.VISIBLE);
             }
@@ -233,15 +233,13 @@
 
         // If an activity icon is defined, then we use that as the primary icon to show in the bar,
         // otherwise, we fall back to the application icon
-        if (t.activityIcon != null) {
-            mApplicationIcon.setImageDrawable(t.activityIcon);
-        } else if (t.applicationIcon != null) {
-            mApplicationIcon.setImageDrawable(t.applicationIcon);
+        if (t.icon != null) {
+            mIconView.setImageDrawable(t.icon);
         }
-        if (!mActivityDescription.getText().toString().equals(t.activityLabel)) {
-            mActivityDescription.setText(t.activityLabel);
+        if (!mTitleView.getText().toString().equals(t.title)) {
+            mTitleView.setText(t.title);
         }
-        mActivityDescription.setContentDescription(t.contentDescription);
+        mTitleView.setContentDescription(t.contentDescription);
 
         // Try and apply the system ui tint
         int existingBgColor = (getBackground() instanceof ColorDrawable) ?
@@ -254,7 +252,7 @@
                 R.color.recents_task_bar_light_text_color);
         int taskBarViewDarkTextColor = getResources().getColor(
                 R.color.recents_task_bar_dark_text_color);
-        mActivityDescription.setTextColor(t.useLightOnPrimaryColor ?
+        mTitleView.setTextColor(t.useLightOnPrimaryColor ?
                 taskBarViewLightTextColor : taskBarViewDarkTextColor);
         mDismissButton.setImageDrawable(t.useLightOnPrimaryColor ?
                 mLightDismissDrawable : mDarkDismissDrawable);
@@ -281,15 +279,15 @@
 
         // In accessibility, a single click on the focused app info button will show it
         if (ssp.isTouchExplorationEnabled()) {
-            mApplicationIcon.setOnClickListener(this);
+            mIconView.setOnClickListener(this);
         }
     }
 
     /** Unbinds the bar view from the task */
     void unbindFromTask() {
         mTask = null;
-        mApplicationIcon.setImageDrawable(null);
-        mApplicationIcon.setOnClickListener(null);
+        mIconView.setImageDrawable(null);
+        mIconView.setOnClickListener(null);
         mMoveTaskButton.setOnClickListener(null);
     }
 
@@ -357,7 +355,7 @@
 
     @Override
     public void onClick(View v) {
-        if (v == mApplicationIcon) {
+        if (v == mIconView) {
             // In accessibility, a single click on the focused app info button will show it
             EventBus.getDefault().send(new ShowApplicationInfoEvent(mTask));
         } else if (v == mDismissButton) {
@@ -379,7 +377,7 @@
 
     @Override
     public boolean onLongClick(View v) {
-        if (v == mApplicationIcon) {
+        if (v == mIconView) {
             EventBus.getDefault().send(new ShowApplicationInfoEvent(mTask));
             return true;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 6d4dc872..a6ca50a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -947,7 +947,7 @@
         final StatusBarNotification sbn = row.getStatusBarNotification();
         PackageManager pmUser = getPackageManagerForUser(mContext, sbn.getUser().getIdentifier());
         row.setTag(sbn.getPackageName());
-        final View guts = row.getGuts();
+        final NotificationGuts guts = row.getGuts();
         final String pkg = sbn.getPackageName();
         String appname = pkg;
         Drawable pkgicon = null;
@@ -969,8 +969,6 @@
         ((ImageView) row.findViewById(android.R.id.icon)).setImageDrawable(pkgicon);
         ((TextView) row.findViewById(R.id.pkgname)).setText(appname);
 
-        bindTopicImportance(sbn, row);
-
         final View settingsButton = guts.findViewById(R.id.notification_inspect_item);
         if (appUid >= 0) {
             final int appUidF = appUid;
@@ -983,69 +981,8 @@
         } else {
             settingsButton.setVisibility(View.GONE);
         }
-    }
 
-    private void bindTopicImportance(final StatusBarNotification sbn,
-            ExpandableNotificationRow row) {
-        final INotificationManager sINM = INotificationManager.Stub.asInterface(
-                ServiceManager.getService(Context.NOTIFICATION_SERVICE));
-        final Notification.Topic topic = sbn.getNotification().getTopic() == null
-                ? new Notification.Topic(Notification.TOPIC_DEFAULT, mContext.getString(
-                        com.android.internal.R.string.default_notification_topic_label))
-                : sbn.getNotification().getTopic();
-
-        ((TextView) row.findViewById(R.id.topic_details)).setText(topic.getLabel());
-        final TextView topicSummary = ((TextView) row.findViewById(R.id.summary));
-        int importance = mNotificationData.getImportance(sbn.getKey());
-        SeekBar seekBar = (SeekBar) row.findViewById(R.id.seekbar);
-        seekBar.setMax(4);
-        seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
-            @Override
-            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
-                topicSummary.setText(getProgressSummary(progress));
-                if (fromUser) {
-                    try {
-                        sINM.setTopicImportance(sbn.getPackageName(), sbn.getUid(), topic,
-                                progress);
-                    } catch (RemoteException e) {
-                        // :(
-                    }
-                }
-            }
-
-            @Override
-            public void onStartTrackingTouch(SeekBar seekBar) {
-                // no-op
-            }
-
-            @Override
-            public void onStopTrackingTouch(SeekBar seekBar) {
-                // no-op
-            }
-
-            private String getProgressSummary(int progress) {
-                switch (progress) {
-                    case NotificationListenerService.Ranking.IMPORTANCE_NONE:
-                        return mContext.getString(
-                                com.android.internal.R.string.notification_importance_blocked);
-                    case NotificationListenerService.Ranking.IMPORTANCE_LOW:
-                        return mContext.getString(
-                                com.android.internal.R.string.notification_importance_low);
-                    case NotificationListenerService.Ranking.IMPORTANCE_DEFAULT:
-                        return mContext.getString(
-                                com.android.internal.R.string.notification_importance_default);
-                    case NotificationListenerService.Ranking.IMPORTANCE_HIGH:
-                        return mContext.getString(
-                                com.android.internal.R.string.notification_importance_high);
-                    case NotificationListenerService.Ranking.IMPORTANCE_MAX:
-                        return mContext.getString(
-                                com.android.internal.R.string.notification_importance_max);
-                    default:
-                        return "";
-                }
-            }
-        });
-        seekBar.setProgress(importance);
+        guts.bindImportance(sbn, row, mNotificationData.getImportance(sbn.getKey()));
     }
 
     protected SwipeHelper.LongPressListener getNotificationLongClicker() {
@@ -1612,8 +1549,14 @@
 
             for (int i = 0; i < numActions; i++) {
                 Notification.Action action = actions.get(i);
+                if (action == null) {
+                    continue;
+                }
                 RemoteInput[] remoteInputs = action.getRemoteInputs();
-                for (RemoteInput ri : action.getRemoteInputs()) {
+                if (remoteInputs == null) {
+                    continue;
+                }
+                for (RemoteInput ri : remoteInputs) {
                     if (ri.getAllowFreeFormInput()) {
                         viableAction = action;
                         break;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
index 0081496..57db80a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
@@ -16,12 +16,22 @@
 
 package com.android.systemui.statusbar;
 
+import android.app.INotificationManager;
+import android.app.Notification;
 import android.content.Context;
 import android.graphics.Canvas;
 import android.graphics.drawable.Drawable;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.service.notification.NotificationListenerService;
+import android.service.notification.StatusBarNotification;
 import android.util.AttributeSet;
+import android.view.View;
 import android.widget.FrameLayout;
 import android.widget.LinearLayout;
+import android.widget.RadioButton;
+import android.widget.SeekBar;
+import android.widget.TextView;
 
 import com.android.systemui.R;
 
@@ -83,6 +93,88 @@
         }
     }
 
+    void bindImportance(final StatusBarNotification sbn, final ExpandableNotificationRow row,
+            final int importance) {
+        final INotificationManager sINM = INotificationManager.Stub.asInterface(
+                ServiceManager.getService(Context.NOTIFICATION_SERVICE));
+        final Notification.Topic topic = sbn.getNotification().getTopic() == null
+                ? new Notification.Topic(Notification.TOPIC_DEFAULT, mContext.getString(
+                com.android.internal.R.string.default_notification_topic_label))
+                : sbn.getNotification().getTopic();
+
+        final RadioButton applyToTopic = (RadioButton) row.findViewById(R.id.apply_to_topic);
+        if (sbn.getNotification().getTopic() != null) {
+            applyToTopic.setVisibility(View.VISIBLE);
+            applyToTopic.setChecked(true);
+            applyToTopic.setText(mContext.getString(R.string.apply_to_topic, topic.getLabel()));
+            row.findViewById(R.id.apply_to_app).setVisibility(View.VISIBLE);
+        }
+
+        final TextView topicSummary = ((TextView) row.findViewById(R.id.summary));
+        final TextView topicTitle = ((TextView) row.findViewById(R.id.title));
+        SeekBar seekBar = (SeekBar) row.findViewById(R.id.seekbar);
+        seekBar.setMax(4);
+        seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
+            @Override
+            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+                updateTitleAndSummary(progress);
+                if (fromUser) {
+                    try {
+                        if (applyToTopic.isChecked()) {
+                            sINM.setTopicImportance(sbn.getPackageName(), sbn.getUid(), topic,
+                                    progress);
+                        } else {
+                            sINM.setAppImportance(sbn.getPackageName(), sbn.getUid(), progress);
+                        }
+                    } catch (RemoteException e) {
+                        // :(
+                    }
+                }
+            }
+
+            @Override
+            public void onStartTrackingTouch(SeekBar seekBar) {
+                // no-op
+            }
+
+            @Override
+            public void onStopTrackingTouch(SeekBar seekBar) {
+                // no-op
+            }
+
+            private void updateTitleAndSummary(int progress) {
+                switch (progress) {
+                    case NotificationListenerService.Ranking.IMPORTANCE_NONE:
+                        topicSummary.setText(mContext.getString(
+                                R.string.notification_importance_blocked));
+                        topicTitle.setText(mContext.getString(R.string.blocked_importance));
+                        break;
+                    case NotificationListenerService.Ranking.IMPORTANCE_LOW:
+                        topicSummary.setText(mContext.getString(
+                                R.string.notification_importance_low));
+                        topicTitle.setText(mContext.getString(R.string.low_importance));
+                        break;
+                    case NotificationListenerService.Ranking.IMPORTANCE_DEFAULT:
+                        topicSummary.setText(mContext.getString(
+                                R.string.notification_importance_default));
+                        topicTitle.setText(mContext.getString(R.string.default_importance));
+                        break;
+                    case NotificationListenerService.Ranking.IMPORTANCE_HIGH:
+                        topicSummary.setText(mContext.getString(
+                                R.string.notification_importance_high));
+                        topicTitle.setText(mContext.getString(R.string.high_importance));
+                        break;
+                    case NotificationListenerService.Ranking.IMPORTANCE_MAX:
+                        topicSummary.setText(mContext.getString(
+                                R.string.notification_importance_max));
+                        topicTitle.setText(mContext.getString(R.string.max_importance));
+                        break;
+                }
+            }
+        });
+        seekBar.setProgress(importance);
+    }
+
     public void setActualHeight(int actualHeight) {
         mActualHeight = actualHeight;
         invalidate();
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index df18d3e..6f8f8eb 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -16,6 +16,7 @@
 
 package com.android.server.appwidget;
 
+import android.app.ActivityManager;
 import android.app.AlarmManager;
 import android.app.AppGlobals;
 import android.app.AppOpsManager;
@@ -76,6 +77,7 @@
 import android.view.WindowManager;
 import android.widget.RemoteViews;
 
+import com.android.internal.R;
 import com.android.internal.appwidget.IAppWidgetHost;
 import com.android.internal.appwidget.IAppWidgetService;
 import com.android.internal.os.BackgroundThread;
@@ -83,7 +85,6 @@
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.widget.IRemoteViewsAdapterConnection;
 import com.android.internal.widget.IRemoteViewsFactory;
-import com.android.internal.R;
 import com.android.server.LocalServices;
 import com.android.server.WidgetBackupProvider;
 
@@ -139,8 +140,10 @@
     private static final int CURRENT_VERSION = 1;
 
     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+        @Override
         public void onReceive(Context context, Intent intent) {
-            String action = intent.getAction();
+            final String action = intent.getAction();
+            final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
 
             if (DEBUG) {
                 Slog.i(TAG, "Received broadcast: " + action);
@@ -148,23 +151,16 @@
 
             if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) {
                 onConfigurationChanged();
-            } else if (Intent.ACTION_USER_STARTED.equals(action)) {
-                onUserStarted(intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
-                        UserHandle.USER_NULL));
+            } else if (Intent.ACTION_USER_UNLOCKED.equals(action)) {
+                onUserUnlocked(userId);
             } else if (Intent.ACTION_USER_STOPPED.equals(action)) {
-                onUserStopped(intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
-                        UserHandle.USER_NULL));
+                onUserStopped(userId);
             } else if (Intent.ACTION_USER_SWITCHED.equals(action)) {
-                refreshProfileWidgetsMaskedState(intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
-                        UserHandle.USER_NULL));
+                refreshProfileWidgetsMaskedState(userId);
             } else if (Intent.ACTION_MANAGED_PROFILE_AVAILABILITY_CHANGED.equals(action)) {
-                UserHandle profile = (UserHandle)intent.getParcelableExtra(Intent.EXTRA_USER);
-                if (profile != null) {
-                    refreshWidgetMaskedState(profile.getIdentifier());
-                }
+                refreshWidgetMaskedState(userId);
             } else {
-                onPackageBroadcastReceived(intent, intent.getIntExtra(
-                        Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL));
+                onPackageBroadcastReceived(intent, userId);
             }
         }
     };
@@ -263,7 +259,7 @@
                 sdFilter, null, null);
 
         IntentFilter userFilter = new IntentFilter();
-        userFilter.addAction(Intent.ACTION_USER_STARTED);
+        userFilter.addAction(Intent.ACTION_USER_UNLOCKED);
         userFilter.addAction(Intent.ACTION_USER_STOPPED);
         userFilter.addAction(Intent.ACTION_USER_SWITCHED);
         mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
@@ -340,6 +336,8 @@
     }
 
     private void onPackageBroadcastReceived(Intent intent, int userId) {
+        if (!mUserManager.isUserUnlocked(userId)) return;
+
         final String action = intent.getAction();
         boolean added = false;
         boolean changed = false;
@@ -419,9 +417,7 @@
      * Refresh the masked state for all profiles under the given user.
      */
     private void refreshProfileWidgetsMaskedState(int userId) {
-        if (userId == UserHandle.USER_NULL) {
-            return;
-        }
+        if (!mUserManager.isUserUnlocked(userId)) return;
         List<UserInfo> profiles = mUserManager.getEnabledProfiles(userId);
         if (profiles != null) {
             for (int i = 0; i < profiles.size(); i++) {
@@ -435,6 +431,7 @@
      * Mask/unmask widgets in the given profile, depending on the quiet state of the profile.
      */
     private void refreshWidgetMaskedState(int profileId) {
+        if (!mUserManager.isUserUnlocked(profileId)) return;
         final long identity = Binder.clearCallingIdentity();
         try {
             UserInfo user  = mUserManager.getUserInfo(profileId);
@@ -484,6 +481,11 @@
     }
 
     private void ensureGroupStateLoadedLocked(int userId) {
+        if (!mUserManager.isUserUnlocked(userId)) {
+            throw new IllegalStateException(
+                    "User " + userId + " must be unlocked for widgets to be available");
+        }
+
         final int[] profileIds = mSecurityPolicy.getEnabledGroupProfileIds(userId);
 
         // Careful lad, we may have already loaded the state for some
@@ -2321,7 +2323,7 @@
         }
     }
 
-    private void onUserStarted(int userId) {
+    private void onUserUnlocked(int userId) {
         synchronized (mLock) {
             ensureGroupStateLoadedLocked(userId);
 
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index b805c10..1d555c6 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -17061,6 +17061,8 @@
             }
         }
 
+        // Verify that protected broadcasts are only being sent by system code,
+        // and that system code is only sending protected broadcasts.
         final String action = intent.getAction();
         final boolean isProtectedBroadcast;
         try {
@@ -17070,35 +17072,47 @@
             return ActivityManager.BROADCAST_SUCCESS;
         }
 
-        /*
-         * Prevent non-system code (defined here to be non-persistent
-         * processes) from sending protected broadcasts.
-         */
-        int callingAppId = UserHandle.getAppId(callingUid);
-        if (callingAppId == Process.SYSTEM_UID || callingAppId == Process.PHONE_UID
-            || callingAppId == Process.SHELL_UID || callingAppId == Process.BLUETOOTH_UID
-            || callingAppId == Process.NFC_UID || callingUid == 0) {
-            // Always okay.
+        final boolean isCallerSystem;
+        switch (UserHandle.getAppId(callingUid)) {
+            case Process.ROOT_UID:
+            case Process.SYSTEM_UID:
+            case Process.PHONE_UID:
+            case Process.SHELL_UID:
+            case Process.BLUETOOTH_UID:
+            case Process.NFC_UID:
+                isCallerSystem = true;
+                break;
+            default:
+                isCallerSystem = (callerApp != null) && callerApp.persistent;
+                break;
+        }
 
-            // Yell if the system is trying to send a non-protected broadcast.
-            // The vast majority of broadcasts sent from system callers should
-            // be protected to avoid security holes, so exceptions here should
-            // be incredibly rare.
-            if (!isProtectedBroadcast
-                    && !Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) {
-                // TODO: eventually switch over to hard throw
+        if (isCallerSystem) {
+            if (isProtectedBroadcast
+                    || Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)
+                    || Intent.ACTION_MEDIA_SCANNER_SCAN_FILE.equals(action)
+                    || AppWidgetManager.ACTION_APPWIDGET_CONFIGURE.equals(action)
+                    || AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)) {
+                // Broadcast is either protected, or it's a public action that
+                // we've relaxed, so it's fine for system internals to send.
+            } else {
+                // The vast majority of broadcasts sent from system internals
+                // should be protected to avoid security holes, so yell loudly
+                // to ensure we examine these cases.
                 Log.wtf(TAG, "Sending non-protected broadcast " + action
                         + " from system", new Throwable());
             }
 
-        } else if (callerApp == null || !callerApp.persistent) {
+        } else {
             if (isProtectedBroadcast) {
                 String msg = "Permission Denial: not allowed to send broadcast "
                         + action + " from pid="
                         + callingPid + ", uid=" + callingUid;
                 Slog.w(TAG, msg);
                 throw new SecurityException(msg);
-            } else if (AppWidgetManager.ACTION_APPWIDGET_CONFIGURE.equals(action)) {
+
+            } else if (AppWidgetManager.ACTION_APPWIDGET_CONFIGURE.equals(action)
+                    || AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)) {
                 // Special case for compatibility: we don't want apps to send this,
                 // but historically it has not been protected and apps may be using it
                 // to poke their own app widget.  So, instead of making it protected,
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index d215fc6..3da0f8d 100755
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -16,22 +16,21 @@
 
 package com.android.server.am;
 
-import static com.android.server.am.ActivityManagerDebugConfig.*;
+import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SAVED_STATE;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SWITCH;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_THUMBNAILS;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_STATES;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SWITCH;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_THUMBNAILS;
+import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
+import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.am.TaskRecord.INVALID_TASK_ID;
 
 import android.app.ActivityManager.TaskDescription;
-import android.app.PendingIntent;
-import android.os.PersistableBundle;
-import android.os.Trace;
-
-import com.android.internal.app.ResolverActivity;
-import com.android.internal.content.ReferrerIntent;
-import com.android.internal.util.XmlUtils;
-import com.android.server.AttributeCache;
-import com.android.server.am.ActivityStack.ActivityState;
-import com.android.server.am.ActivityStackSupervisor.ActivityContainer;
-
 import android.app.ActivityOptions;
+import android.app.PendingIntent;
 import android.app.ResultInfo;
 import android.content.ComponentName;
 import android.content.Intent;
@@ -45,9 +44,11 @@
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.Message;
+import android.os.PersistableBundle;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.SystemClock;
+import android.os.Trace;
 import android.os.UserHandle;
 import android.util.EventLog;
 import android.util.Log;
@@ -57,9 +58,12 @@
 import android.view.IApplicationToken;
 import android.view.WindowManager;
 
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlSerializer;
+import com.android.internal.app.ResolverActivity;
+import com.android.internal.content.ReferrerIntent;
+import com.android.internal.util.XmlUtils;
+import com.android.server.AttributeCache;
+import com.android.server.am.ActivityStack.ActivityState;
+import com.android.server.am.ActivityStackSupervisor.ActivityContainer;
 
 import java.io.File;
 import java.io.IOException;
@@ -69,6 +73,10 @@
 import java.util.HashSet;
 import java.util.Objects;
 
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
 /**
  * An entry in the history stack, representing an activity.
  */
@@ -398,6 +406,11 @@
         }
     }
 
+    boolean isFreeform() {
+        return task != null && task.stack != null
+                && task.stack.mStackId == FREEFORM_WORKSPACE_STACK_ID;
+    }
+
     static class Token extends IApplicationToken.Stub {
         private final WeakReference<ActivityRecord> weakActivity;
         private final ActivityManagerService mService;
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 52f32e8..59acccd 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -821,10 +821,9 @@
 
         if (hasVisibleBehindActivity()) {
             // Stop visible behind activity before going to sleep.
-            final ActivityRecord r = mActivityContainer.mActivityDisplay.mVisibleBehindActivity;
+            final ActivityRecord r = getVisibleBehindActivity();
             mStackSupervisor.mStoppingActivities.add(r);
-            if (DEBUG_STATES) Slog.v(TAG_STATES,
-                    "Sleep still waiting to stop visible behind " + r);
+            if (DEBUG_STATES) Slog.v(TAG_STATES, "Sleep still waiting to stop visible behind " + r);
             return true;
         }
 
@@ -1061,7 +1060,7 @@
             mHandler.removeMessages(STOP_TIMEOUT_MSG, r);
             r.stopped = true;
             r.state = ActivityState.STOPPED;
-            if (mActivityContainer.mActivityDisplay.mVisibleBehindActivity == r) {
+            if (getVisibleBehindActivity() == r) {
                 mStackSupervisor.requestVisibleBehindLocked(r, false);
             }
             if (r.finishing) {
@@ -1222,9 +1221,9 @@
 
         next.returningOptions = null;
 
-        if (mActivityContainer.mActivityDisplay.mVisibleBehindActivity == next) {
+        if (getVisibleBehindActivity() == next) {
             // When resuming an activity, require it to call requestVisibleBehind() again.
-            mActivityContainer.mActivityDisplay.setVisibleBehindActivity(null);
+            setVisibleBehindActivity(null);
         }
     }
 
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 2d5f76c..18bf1c3 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -2266,7 +2266,8 @@
             // Also put noDisplay activities in the source task. These by itself can
             // be placed in any task/stack, however it could launch other activities
             // like ResolverActivity, and we want those to stay in the original task.
-            if (r.isResolverActivity() || r.noDisplay) {
+            if ((r.isResolverActivity() || r.noDisplay) && sourceRecord != null
+                    && sourceRecord.isFreeform())  {
                 addingToTask = true;
             }
         }
@@ -5182,7 +5183,7 @@
 
         /** All of the stacks on this display. Order matters, topmost stack is in front of all other
          * stacks, bottommost behind. Accessed directly by ActivityManager package classes */
-        final ArrayList<ActivityStack> mStacks = new ArrayList<ActivityStack>();
+        final ArrayList<ActivityStack> mStacks = new ArrayList<>();
 
         ActivityRecord mVisibleBehindActivity;
 
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 62e78a4..5426b72 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -215,7 +215,8 @@
 
                 Intent intent = new Intent(Intent.ACTION_LOCKED_BOOT_COMPLETED, null);
                 intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
-                intent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT);
+                intent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT
+                        | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
                 mService.broadcastIntentLocked(null, null, intent, null, resultTo, 0, null, null,
                         new String[] { android.Manifest.permission.RECEIVE_BOOT_COMPLETED },
                         AppOpsManager.OP_NONE, null, true, false, MY_PID, SYSTEM_UID, userId);
@@ -245,6 +246,7 @@
                 mHandler.sendMessage(mHandler.obtainMessage(SYSTEM_USER_UNLOCK_MSG, userId, 0));
 
                 final Intent unlockedIntent = new Intent(Intent.ACTION_USER_UNLOCKED);
+                unlockedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
                 unlockedIntent.addFlags(
                         Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND);
                 mService.broadcastIntentLocked(null, null, unlockedIntent, null, null, 0, null,
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index bb07e9d..0bfbd7f 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -1248,6 +1248,13 @@
             return mRankingHelper.getTopicImportance(pkg, uid, topic);
         }
 
+        @Override
+        public void setAppImportance(String pkg, int uid, int importance) {
+            enforceSystemOrSystemUI("Caller not system or systemui");
+            mRankingHelper.setAppImportance(pkg, uid, importance);
+            savePolicyFile();
+        }
+
         /**
          * System-only API for getting a list of current (i.e. not cleared) notifications.
          *
diff --git a/services/core/java/com/android/server/notification/RankingConfig.java b/services/core/java/com/android/server/notification/RankingConfig.java
index acdd90a..a6c9b0d 100644
--- a/services/core/java/com/android/server/notification/RankingConfig.java
+++ b/services/core/java/com/android/server/notification/RankingConfig.java
@@ -35,4 +35,6 @@
     void setTopicImportance(String packageName, int uid, Notification.Topic topic, int importance);
 
     int getTopicImportance(String packageName, int uid, Notification.Topic topic);
+
+    void setAppImportance(String packageName, int uid, int importance);
 }
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index 5a31c6a..32c0ce2 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -251,6 +251,7 @@
             }
             out.startTag(null, TAG_PACKAGE);
             out.attribute(null, ATT_NAME, r.pkg);
+            out.attribute(null, ATT_IMPORTANCE, Integer.toString(r.importance));
 
             if (!forBackup) {
                 out.attribute(null, ATT_UID, Integer.toString(r.uid));
@@ -426,6 +427,20 @@
         updateConfig();
     }
 
+    /**
+     * Sets the default importance for all new topics that appear in the future, and resets
+     * the importance of all current topics.
+     */
+    @Override
+    public void setAppImportance(String pkgName, int uid, int importance) {
+        final Record r = getOrCreateRecord(pkgName, uid);
+        r.importance = importance;
+        for (Topic t :  r.topics.values()) {
+            t.importance = importance;
+        }
+        updateConfig();
+    }
+
     private Topic getOrCreateTopic(Record r, Notification.Topic topic) {
         if (topic == null) {
             topic = createDefaultTopic();
@@ -435,6 +450,7 @@
             return t;
         } else {
             t = new Topic(topic);
+            t.importance = r.importance;
             r.topics.put(topic.getId(), t);
             return t;
         }
@@ -477,6 +493,8 @@
                 pw.print(" (");
                 pw.print(r.uid == Record.UNKNOWN_UID ? "UNKNOWN_UID" : Integer.toString(r.uid));
                 pw.print(')');
+                pw.print(" importance=");
+                pw.print(Ranking.importanceToString(r.importance));
                 pw.println();
                 for (Topic t : r.topics.values()) {
                     pw.print(prefix);
@@ -532,6 +550,7 @@
 
         String pkg;
         int uid = UNKNOWN_UID;
+        int importance = DEFAULT_IMPORTANCE;
         Map<String, Topic> topics = new ArrayMap<>();
    }
 
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index fa0aa37..66d10b5 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -482,7 +482,6 @@
             throw new PackageManagerException(INSTALL_FAILED_CONTAINER_ERROR,
                     "Failed to resolve stage location", e);
         }
-        final boolean quickInstall = (params.installFlags & PackageManager.INSTALL_QUICK) != 0;
 
         // Verify that stage looks sane with respect to existing application.
         // This currently only ensures packageName, versionCode, and certificate
@@ -490,10 +489,7 @@
         validateInstallLocked();
 
         Preconditions.checkNotNull(mPackageName);
-        // TODO: fix b/25118622; don't bypass signature check
-        if (!quickInstall) {
-            Preconditions.checkNotNull(mSignatures);
-        }
+        Preconditions.checkNotNull(mSignatures);
         Preconditions.checkNotNull(mResolvedBaseFile);
 
         if (!mPermissionsAccepted) {
@@ -603,7 +599,6 @@
      * {@link PackageManagerService}.
      */
     private void validateInstallLocked() throws PackageManagerException {
-        final boolean quickInstall = (params.installFlags & PackageManager.INSTALL_QUICK) != 0;
         mPackageName = null;
         mVersionCode = -1;
         mSignatures = null;
@@ -627,9 +622,7 @@
 
             final ApkLite apk;
             try {
-                // TODO: fix b/25118622; always use PARSE_COLLECT_CERTIFICATES
-                final int parseFlags = quickInstall ? 0 : PackageParser.PARSE_COLLECT_CERTIFICATES;
-                apk = PackageParser.parseApkLite(file, parseFlags);
+                apk = PackageParser.parseApkLite(file, PackageParser.PARSE_COLLECT_CERTIFICATES);
             } catch (PackageParserException e) {
                 throw PackageManagerException.from(e);
             }
@@ -750,7 +743,6 @@
     }
 
     private void assertApkConsistent(String tag, ApkLite apk) throws PackageManagerException {
-        final boolean quickInstall = (params.installFlags & PackageManager.INSTALL_QUICK) != 0;
         if (!mPackageName.equals(apk.packageName)) {
             throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, tag + " package "
                     + apk.packageName + " inconsistent with " + mPackageName);
@@ -760,8 +752,7 @@
                     + " version code " + apk.versionCode + " inconsistent with "
                     + mVersionCode);
         }
-        // TODO: fix b/25118622; don't bypass signature check
-        if (!quickInstall && !Signature.areExactMatch(mSignatures, apk.signatures)) {
+        if (!Signature.areExactMatch(mSignatures, apk.signatures)) {
             throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
                     tag + " signatures are inconsistent");
         }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 42e8b01..dfb01eb 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -10426,10 +10426,6 @@
         if (!DEFAULT_VERIFY_ENABLE) {
             return false;
         }
-        // TODO: fix b/25118622; don't bypass verification
-        if (Build.IS_DEBUGGABLE && (installFlags & PackageManager.INSTALL_QUICK) != 0) {
-            return false;
-        }
         // Ephemeral apps don't get the full verification treatment
         if ((installFlags & PackageManager.INSTALL_EPHEMERAL) != 0) {
             if (DEBUG_EPHEMERAL) {
@@ -12792,7 +12788,6 @@
         final boolean forwardLocked = ((installFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0);
         final boolean onExternal = (((installFlags & PackageManager.INSTALL_EXTERNAL) != 0)
                 || (args.volumeUuid != null));
-        final boolean quickInstall = ((installFlags & PackageManager.INSTALL_QUICK) != 0);
         final boolean ephemeral = ((installFlags & PackageManager.INSTALL_EPHEMERAL) != 0);
         boolean replace = false;
         int scanFlags = SCAN_NEW_INSTALL | SCAN_UPDATE_SIGNATURE;
@@ -12818,7 +12813,6 @@
                 | PackageParser.PARSE_ENFORCE_CODE
                 | (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0)
                 | (onExternal ? PackageParser.PARSE_EXTERNAL_STORAGE : 0)
-                | (quickInstall ? PackageParser.PARSE_SKIP_VERIFICATION : 0)
                 | (ephemeral ? PackageParser.PARSE_IS_EPHEMERAL : 0);
         PackageParser pp = new PackageParser();
         pp.setSeparateProcesses(mSeparateProcesses);
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index f5da103..13f4826 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -526,6 +526,7 @@
         if (parentHandle != null) {
             intent = new Intent(Intent.ACTION_MANAGED_PROFILE_AVAILABILITY_CHANGED);
             intent.putExtra(Intent.EXTRA_USER, profileHandle);
+            intent.putExtra(Intent.EXTRA_USER_HANDLE, profileHandle.getIdentifier());
             intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
             intent.putExtras(extras);
             mContext.sendBroadcastAsUser(intent, parentHandle);
@@ -2073,6 +2074,7 @@
         managedProfileIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY |
                 Intent.FLAG_RECEIVER_FOREGROUND);
         managedProfileIntent.putExtra(Intent.EXTRA_USER, new UserHandle(removedUserId));
+        managedProfileIntent.putExtra(Intent.EXTRA_USER_HANDLE, removedUserId);
         mContext.sendBroadcastAsUser(managedProfileIntent, new UserHandle(parentUserId), null);
     }
 
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index 6a5183f..62d4f36 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -782,7 +782,7 @@
         SurfaceControl.openTransaction();
         try {
             for (int i = mService.mDisplayContents.size() - 1; i >= 0; i--) {
-                DisplayContent display = mService.mDisplayContents.get(i);
+                DisplayContent display = mService.mDisplayContents.valueAt(i);
                 final WindowList windows = mService.getWindowListLocked(display.getDisplayId());
                 for (int j = windows.size() - 1; j >= 0; j--) {
                     windows.get(j).maybeRemoveReplacedWindow();
diff --git a/services/core/java/com/android/server/wm/WindowLayersController.java b/services/core/java/com/android/server/wm/WindowLayersController.java
index fc7c448..4a77b22 100644
--- a/services/core/java/com/android/server/wm/WindowLayersController.java
+++ b/services/core/java/com/android/server/wm/WindowLayersController.java
@@ -116,7 +116,7 @@
                         + " anim layer: " + childWindow.mWinAnimator.mAnimLayer);
             }
         }
-        for (int i = mService.mInputMethodDialogs.size(); i >= 0; i--) {
+        for (int i = mService.mInputMethodDialogs.size() - 1; i >= 0; i--) {
             final WindowState dialog = mService.mInputMethodDialogs.get(i);
             dialog.mWinAnimator.mAnimLayer = dialog.mLayer + adj;
             if (DEBUG_LAYERS) Slog.v(TAG_WM, "IM win " + imw
diff --git a/services/print/java/com/android/server/print/PrintManagerService.java b/services/print/java/com/android/server/print/PrintManagerService.java
index 0a8c014..f18617e 100644
--- a/services/print/java/com/android/server/print/PrintManagerService.java
+++ b/services/print/java/com/android/server/print/PrintManagerService.java
@@ -77,8 +77,8 @@
     }
 
     @Override
-    public void onStartUser(int userHandle) {
-        mPrintManagerImpl.handleUserStarted(userHandle);
+    public void onUnlockUser(int userHandle) {
+        mPrintManagerImpl.handleUserUnlocked(userHandle);
     }
 
     @Override
@@ -473,14 +473,11 @@
                 public void onChange(boolean selfChange, Uri uri, int userId) {
                     if (enabledPrintServicesUri.equals(uri)) {
                         synchronized (mLock) {
-                            if (userId != UserHandle.USER_ALL) {
-                                UserState userState = getOrCreateUserStateLocked(userId);
-                                userState.updateIfNeededLocked();
-                            } else {
-                                final int userCount = mUserStates.size();
-                                for (int i = 0; i < userCount; i++) {
-                                    UserState userState = mUserStates.valueAt(i);
-                                    userState.updateIfNeededLocked();
+                            final int userCount = mUserStates.size();
+                            for (int i = 0; i < userCount; i++) {
+                                if (userId == UserHandle.USER_ALL
+                                        || userId == mUserStates.keyAt(i)) {
+                                    mUserStates.valueAt(i).updateIfNeededLocked();
                                 }
                             }
                         }
@@ -496,6 +493,7 @@
             PackageMonitor monitor = new PackageMonitor() {
                 @Override
                 public void onPackageModified(String packageName) {
+                    if (!mUserManager.isUserUnlocked(getChangingUserId())) return;
                     synchronized (mLock) {
                         // A background user/profile's print jobs are running but there is
                         // no UI shown. Hence, if the packages of such a user change we need
@@ -517,6 +515,7 @@
 
                 @Override
                 public void onPackageRemoved(String packageName, int uid) {
+                    if (!mUserManager.isUserUnlocked(getChangingUserId())) return;
                     synchronized (mLock) {
                         // A background user/profile's print jobs are running but there is
                         // no UI shown. Hence, if the packages of such a user change we need
@@ -544,6 +543,7 @@
                 @Override
                 public boolean onHandleForceStop(Intent intent, String[] stoppedPackages,
                         int uid, boolean doit) {
+                    if (!mUserManager.isUserUnlocked(getChangingUserId())) return false;
                     synchronized (mLock) {
                         // A background user/profile's print jobs are running but there is
                         // no UI shown. Hence, if the packages of such a user change we need
@@ -574,6 +574,8 @@
 
                 @Override
                 public void onPackageAdded(String packageName, int uid) {
+                    if (!mUserManager.isUserUnlocked(getChangingUserId())) return;
+
                     // A background user/profile's print jobs are running but there is
                     // no UI shown. Hence, if the packages of such a user change we need
                     // to handle it as the change may affect ongoing print jobs.
@@ -634,6 +636,11 @@
         }
 
         private UserState getOrCreateUserStateLocked(int userId) {
+            if (!mUserManager.isUserUnlocked(userId)) {
+                throw new IllegalStateException(
+                        "User " + userId + " must be unlocked for printing to be available");
+            }
+
             UserState userState = mUserStates.get(userId);
             if (userState == null) {
                 userState = new UserState(mContext, userId, mLock);
@@ -642,7 +649,7 @@
             return userState;
         }
 
-        private void handleUserStarted(final int userId) {
+        private void handleUserUnlocked(final int userId) {
             // This code will touch the remote print spooler which
             // must be called off the main thread, so post the work.
             BackgroundThread.getHandler().post(new Runnable() {
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 3b281e2..0b5aaa3 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -766,7 +766,7 @@
             IPhoneSubInfo info = getSubscriberInfo();
             if (info == null)
                 return null;
-            return info.getDeviceIdForPhone(slotId);
+            return info.getDeviceIdForPhone(slotId, mContext.getOpPackageName());
         } catch (RemoteException ex) {
             return null;
         } catch (NullPointerException ex) {
@@ -4865,4 +4865,4 @@
         }
         return null;
     }
-}
\ No newline at end of file
+}
diff --git a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
index ed85392..dc2b297 100644
--- a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
+++ b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
@@ -36,7 +36,7 @@
      * Retrieves the unique device ID of a phone for the device, e.g., IMEI
      * for GSM phones.
      */
-    String getDeviceIdForPhone(int phoneId);
+    String getDeviceIdForPhone(int phoneId, String callingPackage);
 
     /**
      * Retrieves the IMEI.
diff --git a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
index cf1a4aa..fecfdf9 100644
--- a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
+++ b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
@@ -23,6 +23,7 @@
 import android.content.ContentResolver;
 import android.content.Intent;
 import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
 import android.graphics.drawable.BitmapDrawable;
 import android.os.Bundle;
 import android.os.Vibrator;
@@ -180,6 +181,9 @@
 
         new Test("with topic GoodBye") {
             public void run() {
+                Notification.BigPictureStyle picture = new Notification.BigPictureStyle();
+                picture.bigPicture(BitmapFactory.decodeResource(getResources(),
+                        R.id.large_icon_pineapple2));
                 Notification n = new Notification.Builder(NotificationTestList.this)
                         .setSmallIcon(R.drawable.icon1)
                         .setWhen(mActivityCreateTime)
@@ -187,11 +191,29 @@
                         .setContentText("This is a notification!!!")
                         .setContentIntent(makeIntent2())
                         .setTopic(new Notification.Topic("bye", "Goodbye"))
+                        .setStyle(picture)
                         .build();
 
                 mNM.notify(9999, n);
             }
         },
+        new Test("with topic Bananas") {
+            public void run() {
+                Notification.BigTextStyle bigText = new Notification.BigTextStyle();
+                bigText.bigText("bananas are great\nso tasty\nyum\nyum\nyum\n");
+                Notification n = new Notification.Builder(NotificationTestList.this)
+                        .setSmallIcon(R.drawable.icon1)
+                        .setStyle(bigText)
+                        .setWhen(mActivityCreateTime)
+                        .setContentTitle("bananananana")
+                        .setContentText("This is a banana!!!")
+                        .setContentIntent(makeIntent2())
+                        .setTopic(new Notification.Topic("bananas", "Bananas"))
+                        .build();
+
+                mNM.notify(999, n);
+            }
+        },
 
         new Test("Whens") {
             public void run()