Merge "Add restrictedSwitchSummary attribute to restricted switch preferences." into nyc-dev
diff --git a/api/current.txt b/api/current.txt
index 535ab01..a04ecfb 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -29527,7 +29527,7 @@
     field public static final int MEASUREMENT_BLUETOOTH_TX_MS = 10022; // 0x2726
     field public static final int MEASUREMENT_BLUETOOTH_TX_PACKETS = 10059; // 0x274b
     field public static final int MEASUREMENT_BUTTON_USER_ACTIVITY_COUNT = 10046; // 0x273e
-    field public static final int MEASUREMENT_CPU_POWER_MAUS = 10064; // 0x2750
+    field public static final int MEASUREMENT_CPU_POWER_MAMS = 10064; // 0x2750
     field public static final int MEASUREMENT_MOBILE_IDLE_MS = 10024; // 0x2728
     field public static final int MEASUREMENT_MOBILE_POWER_MAMS = 10027; // 0x272b
     field public static final int MEASUREMENT_MOBILE_RX_BYTES = 10048; // 0x2740
@@ -29539,11 +29539,11 @@
     field public static final int MEASUREMENT_OTHER_USER_ACTIVITY_COUNT = 10045; // 0x273d
     field public static final int MEASUREMENT_REALTIME_BATTERY_MS = 10001; // 0x2711
     field public static final int MEASUREMENT_REALTIME_SCREEN_OFF_BATTERY_MS = 10003; // 0x2713
-    field public static final int MEASUREMENT_SYSTEM_CPU_TIME_US = 10063; // 0x274f
+    field public static final int MEASUREMENT_SYSTEM_CPU_TIME_MS = 10063; // 0x274f
     field public static final int MEASUREMENT_TOUCH_USER_ACTIVITY_COUNT = 10047; // 0x273f
     field public static final int MEASUREMENT_UPTIME_BATTERY_MS = 10002; // 0x2712
     field public static final int MEASUREMENT_UPTIME_SCREEN_OFF_BATTERY_MS = 10004; // 0x2714
-    field public static final int MEASUREMENT_USER_CPU_TIME_US = 10062; // 0x274e
+    field public static final int MEASUREMENT_USER_CPU_TIME_MS = 10062; // 0x274e
     field public static final int MEASUREMENT_WIFI_FULL_LOCK_MS = 10029; // 0x272d
     field public static final int MEASUREMENT_WIFI_IDLE_MS = 10016; // 0x2720
     field public static final int MEASUREMENT_WIFI_MULTICAST_MS = 10031; // 0x272f
diff --git a/api/system-current.txt b/api/system-current.txt
index 2f39ac0..dd2f18b 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -32024,7 +32024,7 @@
     field public static final int MEASUREMENT_BLUETOOTH_TX_MS = 10022; // 0x2726
     field public static final int MEASUREMENT_BLUETOOTH_TX_PACKETS = 10059; // 0x274b
     field public static final int MEASUREMENT_BUTTON_USER_ACTIVITY_COUNT = 10046; // 0x273e
-    field public static final int MEASUREMENT_CPU_POWER_MAUS = 10064; // 0x2750
+    field public static final int MEASUREMENT_CPU_POWER_MAMS = 10064; // 0x2750
     field public static final int MEASUREMENT_MOBILE_IDLE_MS = 10024; // 0x2728
     field public static final int MEASUREMENT_MOBILE_POWER_MAMS = 10027; // 0x272b
     field public static final int MEASUREMENT_MOBILE_RX_BYTES = 10048; // 0x2740
@@ -32036,11 +32036,11 @@
     field public static final int MEASUREMENT_OTHER_USER_ACTIVITY_COUNT = 10045; // 0x273d
     field public static final int MEASUREMENT_REALTIME_BATTERY_MS = 10001; // 0x2711
     field public static final int MEASUREMENT_REALTIME_SCREEN_OFF_BATTERY_MS = 10003; // 0x2713
-    field public static final int MEASUREMENT_SYSTEM_CPU_TIME_US = 10063; // 0x274f
+    field public static final int MEASUREMENT_SYSTEM_CPU_TIME_MS = 10063; // 0x274f
     field public static final int MEASUREMENT_TOUCH_USER_ACTIVITY_COUNT = 10047; // 0x273f
     field public static final int MEASUREMENT_UPTIME_BATTERY_MS = 10002; // 0x2712
     field public static final int MEASUREMENT_UPTIME_SCREEN_OFF_BATTERY_MS = 10004; // 0x2714
-    field public static final int MEASUREMENT_USER_CPU_TIME_US = 10062; // 0x274e
+    field public static final int MEASUREMENT_USER_CPU_TIME_MS = 10062; // 0x274e
     field public static final int MEASUREMENT_WIFI_FULL_LOCK_MS = 10029; // 0x272d
     field public static final int MEASUREMENT_WIFI_IDLE_MS = 10016; // 0x2720
     field public static final int MEASUREMENT_WIFI_MULTICAST_MS = 10031; // 0x272f
@@ -32920,6 +32920,7 @@
     method public abstract void onConnected();
     method public abstract void onDisconnected();
     method public final void updateRecommendations(java.util.List<android.printservice.recommendation.RecommendationInfo>);
+    field public static final java.lang.String SERVICE_INTERFACE = "android.printservice.recommendation.RecommendationService";
   }
 
 }
diff --git a/api/test-current.txt b/api/test-current.txt
index 2ccf37a..d056f7d 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -29596,7 +29596,7 @@
     field public static final int MEASUREMENT_BLUETOOTH_TX_MS = 10022; // 0x2726
     field public static final int MEASUREMENT_BLUETOOTH_TX_PACKETS = 10059; // 0x274b
     field public static final int MEASUREMENT_BUTTON_USER_ACTIVITY_COUNT = 10046; // 0x273e
-    field public static final int MEASUREMENT_CPU_POWER_MAUS = 10064; // 0x2750
+    field public static final int MEASUREMENT_CPU_POWER_MAMS = 10064; // 0x2750
     field public static final int MEASUREMENT_MOBILE_IDLE_MS = 10024; // 0x2728
     field public static final int MEASUREMENT_MOBILE_POWER_MAMS = 10027; // 0x272b
     field public static final int MEASUREMENT_MOBILE_RX_BYTES = 10048; // 0x2740
@@ -29608,11 +29608,11 @@
     field public static final int MEASUREMENT_OTHER_USER_ACTIVITY_COUNT = 10045; // 0x273d
     field public static final int MEASUREMENT_REALTIME_BATTERY_MS = 10001; // 0x2711
     field public static final int MEASUREMENT_REALTIME_SCREEN_OFF_BATTERY_MS = 10003; // 0x2713
-    field public static final int MEASUREMENT_SYSTEM_CPU_TIME_US = 10063; // 0x274f
+    field public static final int MEASUREMENT_SYSTEM_CPU_TIME_MS = 10063; // 0x274f
     field public static final int MEASUREMENT_TOUCH_USER_ACTIVITY_COUNT = 10047; // 0x273f
     field public static final int MEASUREMENT_UPTIME_BATTERY_MS = 10002; // 0x2712
     field public static final int MEASUREMENT_UPTIME_SCREEN_OFF_BATTERY_MS = 10004; // 0x2714
-    field public static final int MEASUREMENT_USER_CPU_TIME_US = 10062; // 0x274e
+    field public static final int MEASUREMENT_USER_CPU_TIME_MS = 10062; // 0x274e
     field public static final int MEASUREMENT_WIFI_FULL_LOCK_MS = 10029; // 0x272d
     field public static final int MEASUREMENT_WIFI_IDLE_MS = 10016; // 0x2720
     field public static final int MEASUREMENT_WIFI_MULTICAST_MS = 10031; // 0x272f
diff --git a/cmds/dpm/src/com/android/commands/dpm/Dpm.java b/cmds/dpm/src/com/android/commands/dpm/Dpm.java
index b83484d..31c7421 100644
--- a/cmds/dpm/src/com/android/commands/dpm/Dpm.java
+++ b/cmds/dpm/src/com/android/commands/dpm/Dpm.java
@@ -44,6 +44,7 @@
     private static final String COMMAND_SET_ACTIVE_ADMIN = "set-active-admin";
     private static final String COMMAND_SET_DEVICE_OWNER = "set-device-owner";
     private static final String COMMAND_SET_PROFILE_OWNER = "set-profile-owner";
+    private static final String COMMAND_REMOVE_ACTIVE_ADMIN = "remove-active-admin";
 
     private IDevicePolicyManager mDevicePolicyManager;
     private int mUserId = UserHandle.USER_SYSTEM;
@@ -60,6 +61,8 @@
                 "[ --name <NAME> ] <COMPONENT>\n" +
                 "usage: dpm set-profile-owner [ --user <USER_ID> | current ] [ --name <NAME> ] " +
                 "<COMPONENT>\n" +
+                "usage: dpm remove-active-admin [ --user <USER_ID> | current ] [ --name <NAME> ] " +
+                "<COMPONENT>\n" +
                 "\n" +
                 "dpm set-active-admin: Sets the given component as active admin" +
                 " for an existing user.\n" +
@@ -68,7 +71,11 @@
                 " package as device owner.\n" +
                 "\n" +
                 "dpm set-profile-owner: Sets the given component as active admin and profile" +
-                " owner for an existing user.\n");
+                " owner for an existing user.\n" +
+                "\n" +
+                "dpm remove-active-admin: Disables an active admin, the admin must have declared" +
+                " android:testOnly in the application in its manifest. This will also remove" +
+                " device and profile owners\n");
     }
 
     @Override
@@ -91,6 +98,9 @@
             case COMMAND_SET_PROFILE_OWNER:
                 runSetProfileOwner();
                 break;
+            case COMMAND_REMOVE_ACTIVE_ADMIN:
+                runRemoveActiveAdmin();
+                break;
             default:
                 throw new IllegalArgumentException ("unknown command '" + command + "'");
         }
@@ -152,6 +162,12 @@
         System.out.println("Active admin set to component " + mComponent.toShortString());
     }
 
+    private void runRemoveActiveAdmin() throws RemoteException {
+        parseArgs(/*canHaveName=*/ false);
+        mDevicePolicyManager.forceRemoveActiveAdmin(mComponent, mUserId);
+        System.out.println("Success: Admin removed " + mComponent);
+    }
+
     private void runSetProfileOwner() throws RemoteException {
         parseArgs(/*canHaveName=*/ true);
         mDevicePolicyManager.setActiveAdmin(mComponent, true /*refreshing*/, mUserId);
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java
index e788d27..8ff38bb 100644
--- a/core/java/android/animation/AnimatorSet.java
+++ b/core/java/android/animation/AnimatorSet.java
@@ -559,7 +559,8 @@
         boolean previouslyPaused = mPaused;
         super.pause();
         if (!previouslyPaused && mPaused) {
-            if (mDelayAnim != null) {
+            if (mDelayAnim.isStarted()) {
+                // If delay hasn't passed, pause the start delay animator.
                 mDelayAnim.pause();
             } else {
                 int size = mNodes.size();
@@ -578,7 +579,8 @@
         boolean previouslyPaused = mPaused;
         super.resume();
         if (previouslyPaused && !mPaused) {
-            if (mDelayAnim != null) {
+            if (mDelayAnim.isStarted()) {
+                // If start delay hasn't passed, resume the previously paused start delay animator
                 mDelayAnim.resume();
             } else {
                 int size = mNodes.size();
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index ee4c2f7..4b8d9ee 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -139,4 +139,9 @@
      * minimized state.
      */
     public abstract void notifyDockedStackMinimizedChanged(boolean minimized);
+
+    /**
+     * Kill foreground apps from the specified user.
+     */
+    public abstract void killForegroundAppsForUser(int userHandle);
 }
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 7a18df6..0ca2e14 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -6391,6 +6391,24 @@
         }
     }
 
+    /**
+     * @hide
+     * Remove a test admin synchronously without sending it a broadcast about being removed.
+     * If the admin is a profile owner or device owner it will still be removed.
+     *
+     * @param userHandle user id to remove the admin for.
+     * @param admin The administration compononent to remove.
+     * @throws SecurityException if the caller is not shell / root or the admin package
+     *         isn't a test application see {@link ApplicationInfo#FLAG_TEST_APP}.
+     */
+    public void forceRemoveActiveAdmin(ComponentName adminReceiver, int userHandle) {
+        try {
+            mService.forceRemoveActiveAdmin(adminReceiver, userHandle);
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
+        }
+    }
+
     private void throwIfParentInstance(String functionName) {
         if (mParentInstance) {
             throw new SecurityException(functionName + " cannot be called on the parent instance");
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index cba64c2..989e613 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -111,6 +111,7 @@
     boolean packageHasActiveAdmins(String packageName, int userHandle);
     void getRemoveWarning(in ComponentName policyReceiver, in RemoteCallback result, int userHandle);
     void removeActiveAdmin(in ComponentName policyReceiver, int userHandle);
+    void forceRemoveActiveAdmin(in ComponentName policyReceiver, int userHandle);
     boolean hasGrantedPolicy(in ComponentName policyReceiver, int usesPolicy, int userHandle);
 
     void setActivePasswordState(int quality, int length, int letters, int uppercase, int lowercase,
diff --git a/core/java/android/bluetooth/OobData.java b/core/java/android/bluetooth/OobData.java
index 70d47ee..8e659e0 100644
--- a/core/java/android/bluetooth/OobData.java
+++ b/core/java/android/bluetooth/OobData.java
@@ -22,7 +22,11 @@
 import android.util.Log;
 
 /**
- * Out Of Band Data for Bluetooth device.
+ * Out Of Band Data for Bluetooth device pairing.
+ *
+ * <p>This object represents optional data obtained from a remote device through
+ * an out-of-band channel (eg. NFC).
+ *
  * @hide
  */
 public class OobData implements Parcelable {
@@ -32,6 +36,11 @@
         return securityManagerTk;
     }
 
+    /**
+     * Sets the Temporary Key value to be used by the LE Security Manager during
+     * LE pairing. The value shall be 16 bytes. Please see Bluetooth CSSv6,
+     * Part A 1.8 for a detailed description.
+     */
     public void setSecurityManagerTk(byte[] securityManagerTk) {
         this.securityManagerTk = securityManagerTk;
     }
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 15cc17d..8349d3d 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -2446,6 +2446,15 @@
      * <p>This function will throw {@link SecurityException} if you do not
      * have permission to start the given service.
      *
+     * <p class="note"><strong>Note:</strong> Each call to startService()
+     * results in significant work done by the system to manage service
+     * lifecycle surrounding the processing of the intent, which can take
+     * multiple milliseconds of CPU time. Due to this cost, startService()
+     * should not be used for frequent intent delivery to a service, and only
+     * for scheduling significant work. Use {@link #bindService bound services}
+     * for high frequency calls.
+     * </p>
+     *
      * @param service Identifies the service to be started.  The Intent must be either
      *      fully explicit (supplying a component name) or specify a specific package
      *      name it is targetted to.  Additional values
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 4108f6d..bb8bca4 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -131,12 +131,6 @@
     /** File name in an APK for the Android manifest. */
     private static final String ANDROID_MANIFEST_FILENAME = "AndroidManifest.xml";
 
-    /**
-     * File name in an APK for bytecode.  There may be additional bytecode files
-     * but this one is always required for an APK that has code.
-     */
-    private static final String BYTECODE_FILENAME = "classes.dex";
-
     /** Path prefix for apps on expanded storage */
     private static final String MNT_EXPAND = "/mnt/expand/";
 
@@ -1137,13 +1131,11 @@
 
         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates");
         try {
-            collectCertificates(
-                    pkg, new File(pkg.baseCodePath), pkg.applicationInfo.flags, parseFlags);
+            collectCertificates(pkg, new File(pkg.baseCodePath), parseFlags);
 
             if (!ArrayUtils.isEmpty(pkg.splitCodePaths)) {
                 for (int i = 0; i < pkg.splitCodePaths.length; i++) {
-                    collectCertificates(
-                            pkg, new File(pkg.splitCodePaths[i]), pkg.splitFlags[i], parseFlags);
+                    collectCertificates(pkg, new File(pkg.splitCodePaths[i]), parseFlags);
                 }
             }
         } finally {
@@ -1151,10 +1143,8 @@
         }
     }
 
-    private static void collectCertificates(Package pkg, File apkFile, int apkFlags, int parseFlags)
+    private static void collectCertificates(Package pkg, File apkFile, int parseFlags)
             throws PackageParserException {
-        final boolean hasCode = (apkFlags & ApplicationInfo.FLAG_HAS_CODE) != 0;
-        final boolean requireCode = ((parseFlags & PARSE_ENFORCE_CODE) != 0) && hasCode;
         final String apkPath = apkFile.getAbsolutePath();
 
         // Try to verify the APK using APK Signature Scheme v2.
@@ -1202,7 +1192,6 @@
             }
         }
 
-        boolean codeFound = false;
         StrictJarFile jarFile = null;
         try {
             Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "strictJarFileCtor");
@@ -1226,10 +1215,6 @@
 
             // Optimization: early termination when APK already verified
             if (verified) {
-                if ((requireCode) && (jarFile.findEntry(BYTECODE_FILENAME) == null)) {
-                    throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                            "Package " + apkPath + " code is missing");
-                }
                 return;
             }
 
@@ -1249,19 +1234,11 @@
                     final String entryName = entry.getName();
                     if (entryName.startsWith("META-INF/")) continue;
                     if (entryName.equals(ANDROID_MANIFEST_FILENAME)) continue;
-                    if (entryName.equals(BYTECODE_FILENAME)) {
-                        codeFound = true;
-                    }
 
                     toVerify.add(entry);
                 }
             }
 
-            if (!codeFound && requireCode) {
-                throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                        "Package " + apkPath + " code is missing");
-            }
-
             // Verify that entries are signed consistently with the first entry
             // we encountered. Note that for splits, certificates may have
             // already been populated during an earlier parse of a base APK.
@@ -1349,7 +1326,7 @@
                 final Package tempPkg = new Package(null);
                 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates");
                 try {
-                    collectCertificates(tempPkg, apkFile, 0 /*apkFlags*/, 0 /*flags*/);
+                    collectCertificates(tempPkg, apkFile, 0 /*parseFlags*/);
                 } finally {
                     Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
                 }
diff --git a/core/java/android/net/INetworkPolicyListener.aidl b/core/java/android/net/INetworkPolicyListener.aidl
index 31dc965a..812f1fe 100644
--- a/core/java/android/net/INetworkPolicyListener.aidl
+++ b/core/java/android/net/INetworkPolicyListener.aidl
@@ -22,5 +22,6 @@
     void onUidRulesChanged(int uid, int uidRules);
     void onMeteredIfacesChanged(in String[] meteredIfaces);
     void onRestrictBackgroundChanged(boolean restrictBackground);
+    void onRestrictBackgroundWhitelistChanged(int uid, boolean whitelisted);
 
 }
diff --git a/core/java/android/os/health/UidHealthStats.java b/core/java/android/os/health/UidHealthStats.java
index c7d257f..337235a 100644
--- a/core/java/android/os/health/UidHealthStats.java
+++ b/core/java/android/os/health/UidHealthStats.java
@@ -261,16 +261,16 @@
     public static final int TIMER_MOBILE_RADIO_ACTIVE = HealthKeys.BASE_UID + 61;
 
     @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
-    public static final int MEASUREMENT_USER_CPU_TIME_US = HealthKeys.BASE_UID + 62;
+    public static final int MEASUREMENT_USER_CPU_TIME_MS = HealthKeys.BASE_UID + 62;
 
     @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
-    public static final int MEASUREMENT_SYSTEM_CPU_TIME_US = HealthKeys.BASE_UID + 63;
+    public static final int MEASUREMENT_SYSTEM_CPU_TIME_MS = HealthKeys.BASE_UID + 63;
 
     /**
      * An estimate of the number of milliamp-microsends used by this uid.
      */
     @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
-    public static final int MEASUREMENT_CPU_POWER_MAUS = HealthKeys.BASE_UID + 64;
+    public static final int MEASUREMENT_CPU_POWER_MAMS = HealthKeys.BASE_UID + 64;
 
     /**
      * @hide
diff --git a/core/java/android/printservice/recommendation/RecommendationService.java b/core/java/android/printservice/recommendation/RecommendationService.java
index b7ea512..733629a 100644
--- a/core/java/android/printservice/recommendation/RecommendationService.java
+++ b/core/java/android/printservice/recommendation/RecommendationService.java
@@ -27,7 +27,6 @@
 import android.os.Message;
 import android.os.RemoteException;
 import android.util.Log;
-import com.android.internal.annotations.GuardedBy;
 
 import java.util.List;
 
@@ -46,8 +45,6 @@
     /**
      * The {@link Intent} action that must be declared as handled by a service in its manifest for
      * the system to recognize it as a print service recommendation service.
-     *
-     * @hide
      */
     public static final String SERVICE_INTERFACE =
             "android.printservice.recommendation.RecommendationService";
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index ef50fdc..7da849a 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -102,13 +102,13 @@
     public @interface ScalingMode {}
     // From system/window.h
     /** @hide */
-    static final int SCALING_MODE_FREEZE = 0;
+    public static final int SCALING_MODE_FREEZE = 0;
     /** @hide */
-    static final int SCALING_MODE_SCALE_TO_WINDOW = 1;
+    public static final int SCALING_MODE_SCALE_TO_WINDOW = 1;
     /** @hide */
-    static final int SCALING_MODE_SCALE_CROP = 2;
+    public static final int SCALING_MODE_SCALE_CROP = 2;
     /** @hide */
-    static final int SCALING_MODE_NO_SCALE_CROP = 3;
+    public static final int SCALING_MODE_NO_SCALE_CROP = 3;
 
     /** @hide */
     @IntDef({ROTATION_0, ROTATION_90, ROTATION_180, ROTATION_270})
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index c30ede3..dc9014b 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -85,6 +85,8 @@
             IBinder displayToken, int mode);
     private static native void nativeDeferTransactionUntil(long nativeObject,
             IBinder handle, long frame);
+    private static native void nativeSetOverrideScalingMode(long nativeObject,
+            int scalingMode);
     private static native IBinder nativeGetHandle(long nativeObject);
 
 
@@ -376,6 +378,11 @@
         nativeDeferTransactionUntil(mNativeObject, handle, frame);
     }
 
+    public void setOverrideScalingMode(int scalingMode) {
+        checkNotReleased();
+        nativeSetOverrideScalingMode(mNativeObject, scalingMode);
+    }
+
     public IBinder getHandle() {
         return nativeGetHandle(mNativeObject);
     }
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index e9ca623..9e4f26f 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -2716,11 +2716,11 @@
                     mAttachInfo.mHardwareRenderer.setStopped(false);
                 }
 
-                mAttachInfo.mHardwareRenderer.draw(mView, mAttachInfo, this);
-
                 if (updated) {
                     requestDrawWindow();
                 }
+
+                mAttachInfo.mHardwareRenderer.draw(mView, mAttachInfo, this);
             } else {
                 // If we get here with a disabled & requested hardware renderer, something went
                 // wrong (an invalidate posted right before we destroyed the hardware surface
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 10afdb8..250d9b7 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -60,6 +60,7 @@
 import android.util.Xml;
 import android.view.Display;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.net.NetworkStatsFactory;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.FastPrintWriter;
@@ -1092,7 +1093,7 @@
         public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
             if (DEBUG) Log.i(TAG, "**** WRITING TIMER #" + mType + ": mTotalTime="
                     + computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs)));
-            out.writeInt(mCount);
+            out.writeInt(computeCurrentCountLocked());
             out.writeInt(mLoadedCount);
             out.writeInt(mUnpluggedCount);
             out.writeLong(computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs)));
@@ -1109,7 +1110,7 @@
                         + " old mUnpluggedCount=" + mUnpluggedCount);
             }
             mUnpluggedTime = computeRunTimeLocked(baseRealtime);
-            mUnpluggedCount = mCount;
+            mUnpluggedCount = computeCurrentCountLocked();
             if (DEBUG && mType < 0) {
                 Log.v(TAG, "unplug #" + mType
                         + ": new mUnpluggedTime=" + mUnpluggedTime
@@ -1192,7 +1193,7 @@
         public void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
             long runTime = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs));
             out.writeLong(runTime);
-            out.writeInt(mCount);
+            out.writeInt(computeCurrentCountLocked());
         }
 
         public void readSummaryFromParcelLocked(Parcel in) {
@@ -1249,7 +1250,8 @@
          */
         int mUpdateVersion;
 
-        SamplingTimer(Clocks clocks, TimeBase timeBase, Parcel in) {
+        @VisibleForTesting
+        public SamplingTimer(Clocks clocks, TimeBase timeBase, Parcel in) {
             super(clocks, 0, timeBase, in);
             mCurrentReportedCount = in.readInt();
             mUnpluggedReportedCount = in.readInt();
@@ -1259,7 +1261,8 @@
             mTimeBaseRunning = timeBase.isRunning();
         }
 
-        SamplingTimer(Clocks clocks, TimeBase timeBase, boolean trackReportedValues) {
+        @VisibleForTesting
+        public SamplingTimer(Clocks clocks, TimeBase timeBase, boolean trackReportedValues) {
             super(clocks, 0, timeBase);
             mTrackingReportedValues = trackReportedValues;
             mTimeBaseRunning = timeBase.isRunning();
diff --git a/core/java/com/android/internal/os/ProcessCpuTracker.java b/core/java/com/android/internal/os/ProcessCpuTracker.java
index d831902..b7e5718 100644
--- a/core/java/com/android/internal/os/ProcessCpuTracker.java
+++ b/core/java/com/android/internal/os/ProcessCpuTracker.java
@@ -34,9 +34,11 @@
 import java.io.FileInputStream;
 import java.io.PrintWriter;
 import java.io.StringWriter;
+import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
+import java.util.Date;
 import java.util.StringTokenizer;
 
 public class ProcessCpuTracker {
@@ -147,6 +149,9 @@
     private long mCurrentSampleRealTime;
     private long mLastSampleRealTime;
 
+    private long mCurrentSampleWallTime;
+    private long mLastSampleWallTime;
+
     private long mBaseUserTime;
     private long mBaseSystemTime;
     private long mBaseIoWaitTime;
@@ -305,6 +310,7 @@
 
         final long nowUptime = SystemClock.uptimeMillis();
         final long nowRealtime = SystemClock.elapsedRealtime();
+        final long nowWallTime = System.currentTimeMillis();
 
         final long[] sysCpu = mSystemCpuData;
         if (Process.readProcFile("/proc/stat", SYSTEM_CPU_FORMAT,
@@ -367,6 +373,8 @@
         mCurrentSampleTime = nowUptime;
         mLastSampleRealTime = mCurrentSampleRealTime;
         mCurrentSampleRealTime = nowRealtime;
+        mLastSampleWallTime = mCurrentSampleWallTime;
+        mCurrentSampleWallTime = nowWallTime;
 
         final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();
         try {
@@ -710,6 +718,8 @@
     }
 
     final public String printCurrentState(long now) {
+        final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
+
         buildWorkingProcs();
 
         StringWriter sw = new StringWriter();
@@ -727,6 +737,11 @@
             pw.print(mCurrentSampleTime-now);
             pw.print("ms later");
         }
+        pw.print(" (");
+        pw.print(sdf.format(new Date(mLastSampleWallTime)));
+        pw.print(" to ");
+        pw.print(sdf.format(new Date(mCurrentSampleWallTime)));
+        pw.print(")");
 
         long sampleTime = mCurrentSampleTime - mLastSampleTime;
         long sampleRealTime = mCurrentSampleRealTime - mLastSampleRealTime;
diff --git a/core/java/com/android/internal/policy/BackdropFrameRenderer.java b/core/java/com/android/internal/policy/BackdropFrameRenderer.java
index b1598e7..b781fd4 100644
--- a/core/java/com/android/internal/policy/BackdropFrameRenderer.java
+++ b/core/java/com/android/internal/policy/BackdropFrameRenderer.java
@@ -16,8 +16,6 @@
 
 package com.android.internal.policy;
 
-import static android.view.WindowCallbacks.RESIZE_MODE_FREEFORM;
-
 import android.graphics.Rect;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
@@ -102,9 +100,6 @@
         mOldSystemInsets.set(systemInsets);
         mOldStableInsets.set(stableInsets);
         mResizeMode = resizeMode;
-        synchronized (this) {
-            redrawLocked(initialBounds, fullscreen, mSystemInsets, mStableInsets);
-        }
 
         // Kick off our draw thread.
         start();
@@ -160,7 +155,7 @@
             mSystemInsets.set(systemInsets);
             mStableInsets.set(stableInsets);
             // Notify of a bounds change.
-            pingRenderLocked();
+            pingRenderLocked(false /* drawImmediate */);
         }
     }
 
@@ -172,7 +167,7 @@
             if (mRenderer != null) {
                 // Enforce a window redraw.
                 mOldTargetRect.set(0, 0, 0, 0);
-                pingRenderLocked();
+                pingRenderLocked(false /* drawImmediate */);
             }
         }
     }
@@ -197,7 +192,7 @@
                 mRenderer = null;
 
                 // Exit the renderer loop.
-                pingRenderLocked();
+                pingRenderLocked(false /* drawImmediate */);
             }
         }
     }
@@ -208,9 +203,6 @@
             Looper.prepare();
             synchronized (this) {
                 mChoreographer = Choreographer.getInstance();
-
-                // Draw at least once.
-                mChoreographer.postFrameCallback(this);
             }
             Looper.loop();
         } finally {
@@ -236,18 +228,22 @@
                 Looper.myLooper().quit();
                 return;
             }
-            mNewTargetRect.set(mTargetRect);
-            if (!mNewTargetRect.equals(mOldTargetRect)
-                    || mOldFullscreen != mFullscreen
-                    || !mStableInsets.equals(mOldStableInsets)
-                    || !mSystemInsets.equals(mOldSystemInsets)
-                    || mReportNextDraw) {
-                mOldFullscreen = mFullscreen;
-                mOldTargetRect.set(mNewTargetRect);
-                mOldSystemInsets.set(mSystemInsets);
-                mOldStableInsets.set(mStableInsets);
-                redrawLocked(mNewTargetRect, mFullscreen, mSystemInsets, mStableInsets);
-            }
+            doFrameUncheckedLocked();
+        }
+    }
+
+    private void doFrameUncheckedLocked() {
+        mNewTargetRect.set(mTargetRect);
+        if (!mNewTargetRect.equals(mOldTargetRect)
+                || mOldFullscreen != mFullscreen
+                || !mStableInsets.equals(mOldStableInsets)
+                || !mSystemInsets.equals(mOldSystemInsets)
+                || mReportNextDraw) {
+            mOldFullscreen = mFullscreen;
+            mOldTargetRect.set(mNewTargetRect);
+            mOldSystemInsets.set(mSystemInsets);
+            mOldStableInsets.set(mStableInsets);
+            redrawLocked(mNewTargetRect, mFullscreen, mSystemInsets, mStableInsets);
         }
     }
 
@@ -288,7 +284,7 @@
         synchronized (this) {
             mReportNextDraw = reportNextDraw;
             mOldTargetRect.set(0, 0, 0, 0);
-            pingRenderLocked();
+            pingRenderLocked(true /* drawImmediate */);
         }
     }
 
@@ -403,10 +399,14 @@
      * Sends a message to the renderer to wake up and perform the next action which can be
      * either the next rendering or the self destruction if mRenderer is null.
      * Note: This call must be synchronized.
+     *
+     * @param drawImmediate if we should draw immediately instead of scheduling a frame
      */
-    private void pingRenderLocked() {
-        if (mChoreographer != null) {
+    private void pingRenderLocked(boolean drawImmediate) {
+        if (mChoreographer != null && !drawImmediate) {
             mChoreographer.postFrameCallback(this);
+        } else {
+            doFrameUncheckedLocked();
         }
     }
 
diff --git a/core/java/com/android/internal/policy/DividerSnapAlgorithm.java b/core/java/com/android/internal/policy/DividerSnapAlgorithm.java
index 669e1ef..b8bc161 100644
--- a/core/java/com/android/internal/policy/DividerSnapAlgorithm.java
+++ b/core/java/com/android/internal/policy/DividerSnapAlgorithm.java
@@ -330,6 +330,14 @@
         return snapTarget;
     }
 
+    public boolean isFirstSplitTargetAvailable() {
+        return mFirstSplitTarget != mMiddleTarget;
+    }
+
+    public boolean isLastSplitTargetAvailable() {
+        return mLastSplitTarget != mMiddleTarget;
+    }
+
     /**
      * Cycles through all non-dismiss targets with a stepping of {@param increment}. It moves left
      * if {@param increment} is negative and moves right otherwise.
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index 994bdeb..3d05422 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -41,7 +41,6 @@
     void setImeWindowStatus(in IBinder token, int vis, int backDisposition,
             boolean showImeSwitcher);
     void expandSettingsPanel(String subPanel);
-    void setCurrentUser(int newUserId);
 
     // ---- Methods below are for use by the status bar policy services ----
     // You need the STATUS_BAR_SERVICE permission
@@ -63,48 +62,6 @@
             in NotificationVisibility[] noLongerVisibleKeys);
     void onNotificationExpansionChanged(in String key, in boolean userAction, in boolean expanded);
     void setSystemUiVisibility(int vis, int mask, String cause);
-    void setWindowState(int window, int state);
-
-    void showRecentApps(boolean triggeredFromAltTab, boolean fromHome);
-    void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey);
-    void toggleRecentApps();
-    void preloadRecentApps();
-    void cancelPreloadRecentApps();
-
-    void toggleKeyboardShortcutsMenu(int deviceId);
-
-    /**
-     * Notifies the status bar that an app transition is pending to delay applying some flags with
-     * visual impact until {@link #appTransitionReady} is called.
-     */
-    void appTransitionPending();
-
-    /**
-     * Notifies the status bar that a pending app transition has been cancelled.
-     */
-    void appTransitionCancelled();
-
-    /**
-     * Notifies the status bar that an app transition is now being executed.
-     *
-     * @param statusBarAnimationsStartTime the desired start time for all visual animations in the
-     *        status bar caused by this app transition in uptime millis
-     * @param statusBarAnimationsDuration the duration for all visual animations in the status
-     *        bar caused by this app transition in millis
-     */
-    void appTransitionStarting(long statusBarAnimationsStartTime, long statusBarAnimationsDuration);
-
-    void startAssist(in Bundle args);
-
-    /**
-     * Request picture-in-picture.
-     *
-     * <p>
-     * This is called when an user presses picture-in-picture key or equivalent.
-     * TV device may start picture-in-picture from foreground activity if there's none.
-     * Picture-in-picture overlay menu will be shown instead otherwise.
-     */
-    void requestTvPictureInPicture();
 
     void addTile(in ComponentName tile);
     void remTile(in ComponentName tile);
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index d8233a0..0590134 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -597,6 +597,13 @@
     ctrl->deferTransactionUntil(handle, frameNumber);
 }
 
+static void nativeSetOverrideScalingMode(JNIEnv* env, jclass clazz, jlong nativeObject,
+        jint scalingMode) {
+    auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
+
+    ctrl->setOverrideScalingMode(scalingMode);
+}
+
 static jobject nativeGetHandle(JNIEnv* env, jclass clazz, jlong nativeObject) {
     auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
 
@@ -676,6 +683,8 @@
             (void*)nativeSetDisplayPowerMode },
     {"nativeDeferTransactionUntil", "(JLandroid/os/IBinder;J)V",
             (void*)nativeDeferTransactionUntil },
+    {"nativeSetOverrideScalingMode", "(JI)V",
+            (void*)nativeSetOverrideScalingMode },
     {"nativeGetHandle", "(J)Landroid/os/IBinder;",
             (void*)nativeGetHandle }
 };
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsSamplingTimerTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsSamplingTimerTest.java
new file mode 100644
index 0000000..51d41a4
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsSamplingTimerTest.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.android.internal.os;
+
+import android.os.BatteryStats;
+import android.os.Parcel;
+import android.support.test.filters.SmallTest;
+
+import junit.framework.TestCase;
+
+public class BatteryStatsSamplingTimerTest extends TestCase {
+
+    @SmallTest
+    public void testSampleTimerSummaryParceling() throws Exception {
+        final MockClocks clocks = new MockClocks();
+        clocks.realtime = 0;
+        clocks.uptime = 0;
+
+        final BatteryStatsImpl.TimeBase timeBase = new BatteryStatsImpl.TimeBase();
+        timeBase.init(clocks.uptimeMillis(), clocks.elapsedRealtime());
+
+        BatteryStatsImpl.SamplingTimer timer = new BatteryStatsImpl.SamplingTimer(clocks, timeBase,
+                true);
+
+        // Start running on battery.
+        timeBase.setRunning(true, clocks.uptimeMillis(), clocks.elapsedRealtime());
+
+        // The first update on battery consumes the values as a way of starting cleanly.
+        timer.addCurrentReportedTotalTime(10);
+        timer.addCurrentReportedCount(1);
+
+        timer.addCurrentReportedTotalTime(10);
+        timer.addCurrentReportedCount(1);
+
+        clocks.realtime = 20;
+        clocks.uptime = 20;
+
+        assertEquals(10, timer.getTotalTimeLocked(clocks.elapsedRealtime(),
+                BatteryStats.STATS_SINCE_CHARGED));
+        assertEquals(1, timer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
+
+        // Grab a summary parcel while on battery.
+        final Parcel onBatterySummaryParcel = Parcel.obtain();
+        timer.writeSummaryFromParcelLocked(onBatterySummaryParcel, clocks.elapsedRealtime() * 1000);
+        onBatterySummaryParcel.setDataPosition(0);
+
+        // Stop running on battery.
+        timeBase.setRunning(false, clocks.uptimeMillis(), clocks.elapsedRealtime());
+
+        assertEquals(10, timer.getTotalTimeLocked(clocks.elapsedRealtime(),
+                BatteryStats.STATS_SINCE_CHARGED));
+        assertEquals(1, timer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
+
+        // Grab a summary parcel while not on battery.
+        final Parcel offBatterySummaryParcel = Parcel.obtain();
+        timer.writeSummaryFromParcelLocked(offBatterySummaryParcel,
+                clocks.elapsedRealtime() * 1000);
+        offBatterySummaryParcel.setDataPosition(0);
+
+        // Read the on battery summary from the parcel.
+        BatteryStatsImpl.SamplingTimer unparceledTimer = new BatteryStatsImpl.SamplingTimer(
+                clocks, timeBase, true);
+        unparceledTimer.readSummaryFromParcelLocked(onBatterySummaryParcel);
+
+        assertEquals(10, unparceledTimer.getTotalTimeLocked(0, BatteryStats.STATS_SINCE_CHARGED));
+        assertEquals(1, unparceledTimer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
+
+        // Read the off battery summary from the parcel.
+        unparceledTimer = new BatteryStatsImpl.SamplingTimer(clocks, timeBase, true);
+        unparceledTimer.readSummaryFromParcelLocked(offBatterySummaryParcel);
+
+        assertEquals(10, unparceledTimer.getTotalTimeLocked(0, BatteryStats.STATS_SINCE_CHARGED));
+        assertEquals(1, unparceledTimer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
+    }
+}
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsServTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsServTest.java
index 1c3cd38..5fd8225 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsServTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsServTest.java
@@ -16,20 +16,13 @@
 
 package com.android.internal.os;
 
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.util.ArrayList;
-
 import android.os.BatteryStats;
 import android.os.Parcel;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.util.Log;
+import android.support.test.filters.SmallTest;
 
 import junit.framework.Assert;
 import junit.framework.TestCase;
 
-import com.android.internal.os.BatteryStatsImpl;
-
 /**
  * Provides test cases for android.os.BatteryStats.
  */
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java
index 05aa53c..78bcbbc 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java
@@ -5,6 +5,7 @@
 
 @RunWith(Suite.class)
 @Suite.SuiteClasses({
+        BatteryStatsSamplingTimerTest.class,
         BatteryStatsServTest.class,
         BatteryStatsTimeBaseTest.class,
         BatteryStatsTimerTest.class,
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimeBaseTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimeBaseTest.java
index ab92f15..3190d9e 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimeBaseTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimeBaseTest.java
@@ -18,11 +18,10 @@
 
 import java.io.PrintWriter;
 import java.io.StringWriter;
-import java.util.ArrayList;
 
 import android.os.BatteryStats;
 import android.os.Parcel;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.support.test.filters.SmallTest;
 import android.util.Log;
 
 import junit.framework.Assert;
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimerTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimerTest.java
index 3e17fcb..98d0f7f 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimerTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimerTest.java
@@ -18,8 +18,7 @@
 
 import android.os.BatteryStats;
 import android.os.Parcel;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.util.Log;
+import android.support.test.filters.SmallTest;
 import android.util.StringBuilderPrinter;
 
 import junit.framework.Assert;
@@ -148,7 +147,7 @@
         timer.onTimeStarted(10, 20, 50);
         Assert.assertEquals(50, timer.lastComputeRunTimeRealtime);
         Assert.assertEquals(4, timer.getUnpluggedTime());
-        Assert.assertEquals(0, timer.getUnpluggedCount());
+        Assert.assertEquals(3000, timer.getUnpluggedCount());
 
         // Test that stopping the timer updates mTotalTime and mCount
         timer.nextComputeRunTime = 17;
@@ -168,15 +167,16 @@
         // Test write then read
         TestTimer timer1 = new TestTimer(clocks, 0, timeBase);
         timer1.setCount(1);
-        timer1.setLoadedCount(2);
-        timer1.setLastCount(3);
-        timer1.setUnpluggedCount(4);
+        timer1.setLoadedCount(3);
+        timer1.setLastCount(4);
+        timer1.setUnpluggedCount(5);
         timer1.setTotalTime(9223372036854775807L);
         timer1.setLoadedTime(9223372036854775806L);
         timer1.setLastTime(9223372036854775805L);
         timer1.setUnpluggedTime(9223372036854775804L);
         timer1.setTimeBeforeMark(9223372036854775803L);
         timer1.nextComputeRunTime = 201;
+        timer1.nextComputeCurrentCount = 2;
 
         Parcel parcel = Parcel.obtain();
         Timer.writeTimerToParcel(parcel, timer1, 77);
@@ -185,10 +185,10 @@
         Assert.assertTrue("parcel null object", parcel.readInt() != 0);
 
         TestTimer timer2 = new TestTimer(clocks, 0, timeBase, parcel);
-        Assert.assertEquals(1, timer2.getCount());
-        Assert.assertEquals(2, timer2.getLoadedCount());
+        Assert.assertEquals(2, timer2.getCount()); // from computeTotalCountLocked()
+        Assert.assertEquals(3, timer2.getLoadedCount());
         Assert.assertEquals(0, timer2.getLastCount()); // NOT saved
-        Assert.assertEquals(4, timer2.getUnpluggedCount());
+        Assert.assertEquals(5, timer2.getUnpluggedCount());
         Assert.assertEquals(201, timer2.getTotalTime()); // from computeRunTimeLocked()
         Assert.assertEquals(9223372036854775806L, timer2.getLoadedTime());
         Assert.assertEquals(0, timer2.getLastTime()); // NOT saved
@@ -309,6 +309,7 @@
 
         Parcel parcel = Parcel.obtain();
         timer1.nextComputeRunTime = 9223372036854775800L;
+        timer1.nextComputeCurrentCount = 1;
         timer1.writeSummaryFromParcelLocked(parcel, 201);
         Assert.assertEquals(40, timer1.lastComputeRunTimeRealtime);
 
diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
index 35385eb..6762bea 100644
--- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
@@ -310,6 +310,15 @@
 
     @Override
     public boolean setVisible(boolean visible, boolean restart) {
+        if (mAnimatorSet.isInfinite() && mAnimatorSet.isStarted()) {
+            if (visible) {
+                // Resume the infinite animation when the drawable becomes visible again.
+                mAnimatorSet.resume();
+            } else {
+                // Pause the infinite animation once the drawable is no longer visible.
+                mAnimatorSet.pause();
+            }
+        }
         mAnimatedVectorState.mVectorDrawable.setVisible(visible, restart);
         return super.setVisible(visible, restart);
     }
@@ -815,6 +824,9 @@
         void onDraw(Canvas canvas);
         boolean isStarted();
         boolean isRunning();
+        boolean isInfinite();
+        void pause();
+        void resume();
     }
 
     private static class VectorDrawableAnimatorUI implements VectorDrawableAnimator {
@@ -825,6 +837,7 @@
         // Caching the listener in the case when listener operation is called before the mSet is
         // setup by init().
         private ArrayList<AnimatorListener> mListenerArray = null;
+        private boolean mIsInfinite = false;
 
         VectorDrawableAnimatorUI(@NonNull AnimatedVectorDrawable drawable) {
             mDrawable = drawable;
@@ -840,6 +853,7 @@
             // Keep a deep copy of the set, such that set can be still be constantly representing
             // the static content from XML file.
             mSet = set.clone();
+            mIsInfinite = mSet.getTotalDuration() == Animator.DURATION_INFINITE;
 
             // If there are listeners added before calling init(), now they should be setup.
             if (mListenerArray != null && !mListenerArray.isEmpty()) {
@@ -934,6 +948,27 @@
             return mSet != null && mSet.isRunning();
         }
 
+        @Override
+        public boolean isInfinite() {
+            return mIsInfinite;
+        }
+
+        @Override
+        public void pause() {
+            if (mSet == null) {
+                return;
+            }
+            mSet.pause();
+        }
+
+        @Override
+        public void resume() {
+            if (mSet == null) {
+                return;
+            }
+            mSet.resume();
+        }
+
         private void invalidateOwningView() {
             mDrawable.invalidateSelf();
         }
@@ -956,6 +991,7 @@
         private boolean mStarted = false;
         private boolean mInitialized = false;
         private boolean mIsReversible = false;
+        private boolean mIsInfinite = false;
         // This needs to be set before parsing starts.
         private boolean mShouldIgnoreInvalidAnim;
         // TODO: Consider using NativeAllocationRegistery to track native allocation
@@ -983,6 +1019,7 @@
             mShouldIgnoreInvalidAnim = shouldIgnoreInvalidAnimation();
             parseAnimatorSet(set, 0);
             mInitialized = true;
+            mIsInfinite = set.getTotalDuration() == Animator.DURATION_INFINITE;
 
             // Check reversible.
             mIsReversible = true;
@@ -1408,6 +1445,21 @@
             }
         }
 
+        @Override
+        public boolean isInfinite() {
+            return mIsInfinite;
+        }
+
+        @Override
+        public void pause() {
+            // TODO: Implement pause for Animator On RT.
+        }
+
+        @Override
+        public void resume() {
+            // TODO: Implement resume for Animator On RT.
+        }
+
         private void onAnimationEnd(int listenerId) {
             if (listenerId != mLastListenerId) {
                 return;
diff --git a/media/jni/android_mtp_MtpDatabase.cpp b/media/jni/android_mtp_MtpDatabase.cpp
index d6bf9ad..7217832 100644
--- a/media/jni/android_mtp_MtpDatabase.cpp
+++ b/media/jni/android_mtp_MtpDatabase.cpp
@@ -933,7 +933,7 @@
                 }
 
                 if (image_data.thumbnail.length == 0
-                        || image_data.thumbnail.format == ::piex::Image::kJpegCompressed) {
+                        || image_data.thumbnail.format != ::piex::Image::kJpegCompressed) {
                     // No thumbnail or non jpeg thumbnail.
                     break;
                 }
diff --git a/packages/DocumentsUI/res/values/strings.xml b/packages/DocumentsUI/res/values/strings.xml
index be21b55..e67cc8a 100644
--- a/packages/DocumentsUI/res/values/strings.xml
+++ b/packages/DocumentsUI/res/values/strings.xml
@@ -247,4 +247,9 @@
         <item quantity="one">Delete <xliff:g id="count" example="1">%1$d</xliff:g> item?</item>
         <item quantity="other">Delete <xliff:g id="count" example="3">%1$d</xliff:g> items?</item>
     </plurals>
+    <!-- Snackbar shown to users who wanted to select more than 1000 items (files or directories). -->
+    <string name="too_many_selected">Sorry, you can only select up to 1000 items at a time</string>
+    <!-- Snackbar shown to users who wanted to select all, but there were too many items (files or directories).
+         Only the first 1000 items are selected in such case. -->
+    <string name="too_many_in_select_all">Could only select 1000 items</string>
 </resources>
diff --git a/packages/DocumentsUI/src/com/android/documentsui/QuickViewIntentBuilder.java b/packages/DocumentsUI/src/com/android/documentsui/QuickViewIntentBuilder.java
index babde99..c78face 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/QuickViewIntentBuilder.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/QuickViewIntentBuilder.java
@@ -17,6 +17,7 @@
 package com.android.documentsui;
 
 import static com.android.documentsui.Shared.DEBUG;
+import static com.android.documentsui.Shared.MAX_DOCS_IN_INTENT;
 import static com.android.documentsui.model.DocumentInfo.getCursorString;
 
 import android.content.ClipData;
@@ -46,7 +47,6 @@
 final class QuickViewIntentBuilder {
 
     private static final String TAG = "QuickViewIntentBuilder";
-    private static final int MAX_CLIP_ITEMS = 1000;
 
     private final DocumentInfo mDocument;
     private final Model mModel;
@@ -165,11 +165,11 @@
         int firstSibling;
         int lastSibling;
         if (documentLocation < uris.size() / 2) {
-            firstSibling = Math.max(0, documentLocation - MAX_CLIP_ITEMS / 2);
-            lastSibling = Math.min(uris.size() - 1, firstSibling + MAX_CLIP_ITEMS - 1);
+            firstSibling = Math.max(0, documentLocation - MAX_DOCS_IN_INTENT / 2);
+            lastSibling = Math.min(uris.size() - 1, firstSibling + MAX_DOCS_IN_INTENT - 1);
         } else {
-            lastSibling = Math.min(uris.size() - 1, documentLocation + MAX_CLIP_ITEMS / 2);
-            firstSibling = Math.max(0, lastSibling - MAX_CLIP_ITEMS + 1);
+            lastSibling = Math.min(uris.size() - 1, documentLocation + MAX_DOCS_IN_INTENT / 2);
+            firstSibling = Math.max(0, lastSibling - MAX_DOCS_IN_INTENT + 1);
         }
 
         if (DEBUG) Log.d(TAG, "Copmuted siblings from index: " + firstSibling
diff --git a/packages/DocumentsUI/src/com/android/documentsui/Shared.java b/packages/DocumentsUI/src/com/android/documentsui/Shared.java
index 1ba836a..07c3cdbc 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/Shared.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/Shared.java
@@ -104,6 +104,11 @@
      */
     public static final String EXTRA_BENCHMARK = "com.android.documentsui.benchmark";
 
+    /**
+     * Maximum number of items in a Binder transaction packet.
+     */
+    public static final int MAX_DOCS_IN_INTENT = 1000;
+
     private static final Collator sCollator;
 
     static {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
index 8c073c9c..297fbc7 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
@@ -17,6 +17,7 @@
 package com.android.documentsui.dirlist;
 
 import static com.android.documentsui.Shared.DEBUG;
+import static com.android.documentsui.Shared.MAX_DOCS_IN_INTENT;
 import static com.android.documentsui.State.MODE_GRID;
 import static com.android.documentsui.State.MODE_LIST;
 import static com.android.documentsui.State.SORT_ORDER_UNKNOWN;
@@ -108,9 +109,11 @@
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Objects;
+import java.util.Set;
 
 /**
  * Display the documents inside a single directory.
@@ -475,8 +478,18 @@
 
                 final String docMimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE);
                 final int docFlags = getCursorInt(cursor, Document.COLUMN_FLAGS);
+                if (!mTuner.canSelectType(docMimeType, docFlags)) {
+                    return false;
+                }
 
-                return mTuner.canSelectType(docMimeType, docFlags);
+                if (mSelected.size() >= MAX_DOCS_IN_INTENT) {
+                    Snackbars.makeSnackbar(
+                            getActivity(),
+                            R.string.too_many_selected,
+                            Snackbar.LENGTH_SHORT)
+                            .show();
+                    return false;
+                }
             }
             return true;
         }
@@ -1108,9 +1121,17 @@
     public void selectAllFiles() {
         Metrics.logUserAction(getContext(), Metrics.USER_ACTION_SELECT_ALL);
 
-        // Exclude disabled files
-        List<String> enabled = new ArrayList<String>();
-        for (String id : mAdapter.getModelIds()) {
+        // Exclude disabled files.
+        Set<String> enabled = new HashSet<String>();
+        List<String> modelIds = mAdapter.getModelIds();
+
+        // Get the current selection.
+        String[] alreadySelected = mSelectionManager.getSelection().getAll();
+        for (String id : alreadySelected) {
+           enabled.add(id);
+        }
+
+        for (String id : modelIds) {
             Cursor cursor = getModel().getItem(id);
             if (cursor == null) {
                 Log.w(TAG, "Skipping selection. Can't obtain cursor for modeId: " + id);
@@ -1118,7 +1139,15 @@
             }
             String docMimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE);
             int docFlags = getCursorInt(cursor, Document.COLUMN_FLAGS);
-            if (isDocumentEnabled(docMimeType, docFlags)) {
+            if (mTuner.canSelectType(docMimeType, docFlags)) {
+                if (enabled.size() >= MAX_DOCS_IN_INTENT) {
+                    Snackbars.makeSnackbar(
+                        getActivity(),
+                        R.string.too_many_in_select_all,
+                        Snackbar.LENGTH_SHORT)
+                        .show();
+                    break;
+                }
                 enabled.add(id);
             }
         }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java
index e3eae33..ecdbe63 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java
@@ -154,7 +154,8 @@
             MenuItem rename = menu.findItem(R.id.menu_rename);
             MenuItem selectAll = menu.findItem(R.id.menu_select_all);
 
-            open.setVisible(true);
+            open.setVisible(mState.action == ACTION_GET_CONTENT ||
+                    mState.action == ACTION_OPEN);
             share.setVisible(false);
             delete.setVisible(false);
             rename.setVisible(false);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java
index 35d8988..8852985 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java
@@ -154,6 +154,10 @@
                         // Update the selection to remove any disappeared IDs.
                         mSelection.cancelProvisionalSelection();
                         mSelection.intersect(mModelIds);
+
+                        if (mBandManager != null && mBandManager.isActive()) {
+                            mBandManager.endBandSelect();
+                        }
                     }
 
                     @Override
@@ -940,6 +944,10 @@
          * Layout items are excluded from the GridModel.
          */
         boolean isLayoutItem(int adapterPosition);
+        /**
+         * Items may be in the adapter, but without an attached view.
+         */
+        boolean hasView(int adapterPosition);
     }
 
     /** Recycler view facade implementation backed by good ol' RecyclerView. */
@@ -1061,6 +1069,11 @@
                     return true;
             }
         }
+
+        @Override
+        public boolean hasView(int pos) {
+            return mView.findViewHolderForAdapterPosition(pos) != null;
+        }
     }
 
     public interface Callback {
@@ -1473,10 +1486,14 @@
          *     y-value.
          */
         void startSelection(Point relativeOrigin) {
+            recordVisibleChildren();
+            if (isEmpty()) {
+                // The selection band logic works only if there is at least one visible child.
+                return;
+            }
+
             mIsActive = true;
             mPointer = mHelper.createAbsolutePoint(relativeOrigin);
-
-            recordVisibleChildren();
             mRelativeOrigin = new RelativePoint(mPointer);
             mRelativePointer = new RelativePoint(mPointer);
             computeCurrentSelection();
@@ -1530,7 +1547,11 @@
         private void recordVisibleChildren() {
             for (int i = 0; i < mHelper.getVisibleChildCount(); i++) {
                 int adapterPosition = mHelper.getAdapterPositionAt(i);
-                if (!mHelper.isLayoutItem(adapterPosition) &&
+                // Sometimes the view is not attached, as we notify the multi selection manager
+                // synchronously, while views are attached asynchronously. As a result items which
+                // are in the adapter may not actually have a corresponding view (yet).
+                if (mHelper.hasView(adapterPosition) &&
+                        !mHelper.isLayoutItem(adapterPosition) &&
                         !mKnownPositions.get(adapterPosition)) {
                     mKnownPositions.put(adapterPosition, true);
                     recordItemData(mHelper.getAbsoluteRectForChildViewAt(i), adapterPosition);
@@ -1539,6 +1560,13 @@
         }
 
         /**
+         * Checks if there are any recorded children.
+         */
+        private boolean isEmpty() {
+            return mColumnBounds.size() == 0 || mRowBounds.size() == 0;
+        }
+
+        /**
          * Updates the limits lists and column map with the given item metadata.
          * @param absoluteChildRect The absolute rectangle for the child view being processed.
          * @param adapterPosition The position of the child view being processed.
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/MultiSelectManager_GridModelTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/MultiSelectManager_GridModelTest.java
index cc119fe..e401de1 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/MultiSelectManager_GridModelTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/MultiSelectManager_GridModelTest.java
@@ -448,6 +448,11 @@
             return false;
         }
 
+        @Override
+        public boolean hasView(int adapterPosition) {
+            return true;
+        }
+
         public static final class Item {
             public String name;
             public Rect rect;
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/TestSelectionEnvironment.java b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/TestSelectionEnvironment.java
index 56e54a6..f564769 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/TestSelectionEnvironment.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/TestSelectionEnvironment.java
@@ -100,4 +100,9 @@
     public boolean isLayoutItem(int adapterPosition) {
         return false;
     }
+
+    @Override
+    public boolean hasView(int adapterPosition) {
+        return true;
+    }
 }
diff --git a/packages/PrintServiceRecommendationService/Android.mk b/packages/PrintRecommendationService/Android.mk
similarity index 100%
rename from packages/PrintServiceRecommendationService/Android.mk
rename to packages/PrintRecommendationService/Android.mk
diff --git a/packages/PrintServiceRecommendationService/AndroidManifest.xml b/packages/PrintRecommendationService/AndroidManifest.xml
similarity index 100%
rename from packages/PrintServiceRecommendationService/AndroidManifest.xml
rename to packages/PrintRecommendationService/AndroidManifest.xml
diff --git a/packages/PrintRecommendationService/CleanSpec.mk b/packages/PrintRecommendationService/CleanSpec.mk
new file mode 100644
index 0000000..c087cb8
--- /dev/null
+++ b/packages/PrintRecommendationService/CleanSpec.mk
@@ -0,0 +1,49 @@
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# If you don't need to do a full clean build but would like to touch
+# a file or delete some intermediate files, add a clean step to the end
+# of the list.  These steps will only be run once, if they haven't been
+# run before.
+#
+# E.g.:
+#     $(call add-clean-step, touch -c external/sqlite/sqlite3.h)
+#     $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates)
+#
+# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with
+# files that are missing or have been moved.
+#
+# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory.
+# Use $(OUT_DIR) to refer to the "out" directory.
+#
+# If you need to re-do something that's already mentioned, just copy
+# the command and add it to the bottom of the list.  E.g., if a change
+# that you made last week required touching a file and a change you
+# made today requires touching the same file, just copy the old
+# touch step and add it to the end of the list.
+#
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
+
+# For example:
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates)
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates)
+#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
+#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
+
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
diff --git a/packages/PrintServiceRecommendationService/MODULE_LICENSE_APACHE2 b/packages/PrintRecommendationService/MODULE_LICENSE_APACHE2
similarity index 100%
rename from packages/PrintServiceRecommendationService/MODULE_LICENSE_APACHE2
rename to packages/PrintRecommendationService/MODULE_LICENSE_APACHE2
diff --git a/packages/PrintServiceRecommendationService/NOTICE b/packages/PrintRecommendationService/NOTICE
similarity index 100%
rename from packages/PrintServiceRecommendationService/NOTICE
rename to packages/PrintRecommendationService/NOTICE
diff --git a/packages/PrintServiceRecommendationService/res/values/donottranslate.xml b/packages/PrintRecommendationService/res/values/donottranslate.xml
similarity index 100%
rename from packages/PrintServiceRecommendationService/res/values/donottranslate.xml
rename to packages/PrintRecommendationService/res/values/donottranslate.xml
diff --git a/packages/PrintServiceRecommendationService/res/values/strings.xml b/packages/PrintRecommendationService/res/values/strings.xml
similarity index 100%
rename from packages/PrintServiceRecommendationService/res/values/strings.xml
rename to packages/PrintRecommendationService/res/values/strings.xml
diff --git a/packages/PrintServiceRecommendationService/res/xml/vendorconfigs.xml b/packages/PrintRecommendationService/res/xml/vendorconfigs.xml
similarity index 100%
rename from packages/PrintServiceRecommendationService/res/xml/vendorconfigs.xml
rename to packages/PrintRecommendationService/res/xml/vendorconfigs.xml
diff --git a/packages/PrintServiceRecommendationService/src/com/android/printservice/recommendation/PrintServicePlugin.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/PrintServicePlugin.java
similarity index 100%
rename from packages/PrintServiceRecommendationService/src/com/android/printservice/recommendation/PrintServicePlugin.java
rename to packages/PrintRecommendationService/src/com/android/printservice/recommendation/PrintServicePlugin.java
diff --git a/packages/PrintServiceRecommendationService/src/com/android/printservice/recommendation/RecommendationServiceImpl.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/RecommendationServiceImpl.java
similarity index 100%
rename from packages/PrintServiceRecommendationService/src/com/android/printservice/recommendation/RecommendationServiceImpl.java
rename to packages/PrintRecommendationService/src/com/android/printservice/recommendation/RecommendationServiceImpl.java
diff --git a/packages/PrintServiceRecommendationService/src/com/android/printservice/recommendation/RemotePrintServicePlugin.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/RemotePrintServicePlugin.java
similarity index 100%
rename from packages/PrintServiceRecommendationService/src/com/android/printservice/recommendation/RemotePrintServicePlugin.java
rename to packages/PrintRecommendationService/src/com/android/printservice/recommendation/RemotePrintServicePlugin.java
diff --git a/packages/PrintServiceRecommendationService/src/com/android/printservice/recommendation/plugin/mdnsFilter/MDNSFilterPlugin.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/mdnsFilter/MDNSFilterPlugin.java
similarity index 100%
rename from packages/PrintServiceRecommendationService/src/com/android/printservice/recommendation/plugin/mdnsFilter/MDNSFilterPlugin.java
rename to packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/mdnsFilter/MDNSFilterPlugin.java
diff --git a/packages/PrintServiceRecommendationService/src/com/android/printservice/recommendation/plugin/mdnsFilter/VendorConfig.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/mdnsFilter/VendorConfig.java
similarity index 100%
rename from packages/PrintServiceRecommendationService/src/com/android/printservice/recommendation/plugin/mdnsFilter/VendorConfig.java
rename to packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/mdnsFilter/VendorConfig.java
diff --git a/packages/PrintServiceRecommendationService/src/com/android/printservice/recommendation/util/MDNSUtils.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/util/MDNSUtils.java
similarity index 100%
rename from packages/PrintServiceRecommendationService/src/com/android/printservice/recommendation/util/MDNSUtils.java
rename to packages/PrintRecommendationService/src/com/android/printservice/recommendation/util/MDNSUtils.java
diff --git a/packages/PrintServiceRecommendationService/src/com/android/printservice/recommendation/util/NsdResolveQueue.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/util/NsdResolveQueue.java
similarity index 100%
rename from packages/PrintServiceRecommendationService/src/com/android/printservice/recommendation/util/NsdResolveQueue.java
rename to packages/PrintRecommendationService/src/com/android/printservice/recommendation/util/NsdResolveQueue.java
diff --git a/packages/SettingsLib/res/layout/drawer_category.xml b/packages/SettingsLib/res/layout/drawer_category.xml
index b7b50d0..582821b 100644
--- a/packages/SettingsLib/res/layout/drawer_category.xml
+++ b/packages/SettingsLib/res/layout/drawer_category.xml
@@ -28,7 +28,8 @@
     <TextView
         android:id="@android:id/title"
         android:layout_width="match_parent"
-        android:layout_height="48dp"
+        android:layout_height="wrap_content"
+        android:minHeight="48dp"
         android:paddingTop="16dp"
         android:paddingBottom="16dp"
         android:paddingStart="16dp"
diff --git a/packages/SettingsLib/res/layout/drawer_item.xml b/packages/SettingsLib/res/layout/drawer_item.xml
index 4b53049..e1f1ae5 100644
--- a/packages/SettingsLib/res/layout/drawer_item.xml
+++ b/packages/SettingsLib/res/layout/drawer_item.xml
@@ -17,7 +17,8 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/tile_item"
     android:layout_width="match_parent"
-    android:layout_height="48dp"
+    android:layout_height="wrap_content"
+    android:minHeight="48dp"
     android:orientation="horizontal" >
 
     <ImageView
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java
index ea56f50..1ad710a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java
@@ -110,9 +110,9 @@
                 if (isDisabledByAdmin()) {
                     additionalSummaryView.setText(mRestrictedSwitchSummary);
                     additionalSummaryView.setVisibility(View.VISIBLE);
+                } else {
+                    additionalSummaryView.setVisibility(View.GONE);
                 }
-            } else {
-                additionalSummaryView.setVisibility(View.GONE);
             }
         } else {
             final TextView summaryView = (TextView) holder.findViewById(android.R.id.summary);
@@ -121,9 +121,9 @@
                     summaryView.setText(mRestrictedSwitchSummary);
                     summaryView.setVisibility(View.VISIBLE);
                 }
+                // No need to change the visibility to GONE in the else case here since Preference
+                // class would have already changed it if there is no summary to display.
             }
-            // No need to change the visibility to GONE in the else case here since Preference class
-            // would have already changed it if there is no summary to display.
         }
     }
 
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index b557dc4..4e9b59f 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -111,6 +111,8 @@
     <uses-permission android:name="android.permission.VIBRATE" />
     <uses-permission android:name="android.permission.MANAGE_ACTIVITY_STACKS" />
     <uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
+    <!-- Permission needed to rename bugreport notifications (so they're not shown as Shell) -->
+    <uses-permission android:name="android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME" />
 
     <application android:label="@string/app_label"
                  android:defaultToDeviceProtectedStorage="true"
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index 346ae20..ec39998 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -62,6 +62,7 @@
 import android.content.res.Configuration;
 import android.net.Uri;
 import android.os.AsyncTask;
+import android.os.Bundle;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.IBinder;
@@ -204,6 +205,8 @@
      */
     private boolean mTakingScreenshot;
 
+    private static final Bundle sNotificationBundle = new Bundle();
+
     @Override
     public void onCreate() {
         mContext = getApplicationContext();
@@ -979,7 +982,13 @@
     }
 
     private static Notification.Builder newBaseNotification(Context context) {
+        if (sNotificationBundle.isEmpty()) {
+            // Rename notifcations from "Shell" to "Android System"
+            sNotificationBundle.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME,
+                    context.getString(com.android.internal.R.string.android_system_label));
+        }
         return new Notification.Builder(context)
+                .addExtras(sNotificationBundle)
                 .setCategory(Notification.CATEGORY_SYSTEM)
                 .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
                 .setLocalOnly(true)
diff --git a/packages/SystemUI/res/layout/qs_detail.xml b/packages/SystemUI/res/layout/qs_detail.xml
index af2a285..32839d8 100644
--- a/packages/SystemUI/res/layout/qs_detail.xml
+++ b/packages/SystemUI/res/layout/qs_detail.xml
@@ -44,11 +44,15 @@
         android:layout_height="wrap_content"
         />
 
-    <FrameLayout
+    <ScrollView
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1">
+        <FrameLayout
             android:id="@android:id/content"
             android:layout_width="match_parent"
-            android:layout_height="0dp"
-            android:layout_weight="1" />
+            android:layout_height="wrap_content" />
+    </ScrollView>
 
     <include layout="@layout/qs_detail_buttons" />
 
diff --git a/packages/SystemUI/res/values-sw410dp/config.xml b/packages/SystemUI/res/values-sw410dp/config.xml
index 08b2f88..049a535 100644
--- a/packages/SystemUI/res/values-sw410dp/config.xml
+++ b/packages/SystemUI/res/values-sw410dp/config.xml
@@ -21,4 +21,6 @@
      for different hardware and product builds. -->
 <resources>
     <integer name="quick_settings_num_rows">2</integer>
+
+    <bool name="quick_settings_show_date">true</bool>
 </resources>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index c54db37..ef84c76 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -268,5 +268,7 @@
     <!-- Nav bar button default ordering/layout -->
     <string name="config_navBarLayout" translatable="false">space,back;home;recent,menu_ime</string>
 
+    <bool name="quick_settings_show_date">false</bool>
+
 </resources>
 
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
index 9697ea6..94d79f2 100644
--- a/packages/SystemUI/res/values/ids.xml
+++ b/packages/SystemUI/res/values/ids.xml
@@ -63,9 +63,10 @@
     <item type="id" name="is_clicked_heads_up_tag" />
 
     <!-- Accessibility actions for the docked stack divider -->
-    <item type="id" name="action_move_left" />
-    <item type="id" name="action_move_right" />
-    <item type="id" name="action_move_up" />
-    <item type="id" name="action_move_down" />
+    <item type="id" name="action_move_tl_full" />
+    <item type="id" name="action_move_tl_70" />
+    <item type="id" name="action_move_tl_50" />
+    <item type="id" name="action_move_tl_30" />
+    <item type="id" name="action_move_rb_full" />
 </resources>
 
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index a03aa28..ea55ac2 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -605,7 +605,7 @@
     <string name="dessert_case">Dessert Case</string>
 
     <!-- Name of the launcher shortcut icon that allows dreams to be started immediately [CHAR LIMIT=20] -->
-    <string name="start_dreams">Daydream</string>
+    <string name="start_dreams">Screen saver</string>
 
     <!-- Textual description of Ethernet connections -->
     <string name="ethernet_label">Ethernet</string>
@@ -1580,17 +1580,27 @@
     <!-- Accessibility label for the divider that separates the windows in split-screen mode [CHAR LIMIT=NONE] -->
     <string name="accessibility_divider">Split-screen divider</string>
 
-    <!-- Accessibility action for moving down the docked stack divider [CHAR LIMIT=NONE] -->
-    <string name="accessibility_action_divider_move_down">Move down</string>
+    <!-- Accessibility action for moving docked stack divider to make the left screen full screen [CHAR LIMIT=NONE] -->
+    <string name="accessibility_action_divider_left_full">Left full screen</string>
+    <!-- Accessibility action for moving docked stack divider to make the left screen 70% [CHAR LIMIT=NONE] -->
+    <string name="accessibility_action_divider_left_70">Left 70%</string>
+    <!-- Accessibility action for moving docked stack divider to make the left screen 50% [CHAR LIMIT=NONE] -->
+    <string name="accessibility_action_divider_left_50">Left 50%</string>
+    <!-- Accessibility action for moving docked stack divider to make the left screen 30% [CHAR LIMIT=NONE] -->
+    <string name="accessibility_action_divider_left_30">Left 30%</string>
+    <!-- Accessibility action for moving docked stack divider to make the right screen full screen [CHAR LIMIT=NONE] -->
+    <string name="accessibility_action_divider_right_full">Right full screen</string>
 
-    <!-- Accessibility action for moving down the docked stack divider [CHAR LIMIT=NONE] -->
-    <string name="accessibility_action_divider_move_up">Move up</string>
-
-    <!-- Accessibility action for moving down the docked stack divider [CHAR LIMIT=NONE] -->
-    <string name="accessibility_action_divider_move_left">Move left</string>
-
-    <!-- Accessibility action for moving down the docked stack divider [CHAR LIMIT=NONE] -->
-    <string name="accessibility_action_divider_move_right">Move right</string>
+    <!-- Accessibility action for moving docked stack divider to make the top screen full screen [CHAR LIMIT=NONE] -->
+    <string name="accessibility_action_divider_top_full">Top full screen</string>
+    <!-- Accessibility action for moving docked stack divider to make the top screen 70% [CHAR LIMIT=NONE] -->
+    <string name="accessibility_action_divider_top_70">Top 70%</string>
+    <!-- Accessibility action for moving docked stack divider to make the top screen 50% [CHAR LIMIT=NONE] -->
+    <string name="accessibility_action_divider_top_50">Top 50%</string>
+    <!-- Accessibility action for moving docked stack divider to make the top screen 30% [CHAR LIMIT=NONE] -->
+    <string name="accessibility_action_divider_top_30">Top 30%</string>
+    <!-- Accessibility action for moving docked stack divider to make the bottom screen full screen [CHAR LIMIT=NONE] -->
+    <string name="accessibility_action_divider_bottom_full">Bottom full screen</string>
 
     <!-- Accessibility description of a QS tile while editing positions [CHAR LIMIT=NONE] -->
     <string name="accessibility_qs_edit_tile_label">Position <xliff:g id="position" example="2">%1$d</xliff:g>, <xliff:g id="tile_name" example="Wi-Fi">%2$s</xliff:g>. Double tap to edit.</string>
diff --git a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
index d12ab29..cecbfcb 100644
--- a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
@@ -317,8 +317,8 @@
                     mResizedView = null;
                     mWatchingForPull = false;
                 }
-                mInitialTouchY = ev.getY();
-                mInitialTouchX = ev.getX();
+                mInitialTouchY = ev.getRawY();
+                mInitialTouchX = ev.getRawX();
                 break;
 
             case MotionEvent.ACTION_CANCEL:
@@ -412,8 +412,8 @@
                 mWatchingForPull = mScrollAdapter != null &&
                         isInside(mScrollAdapter.getHostView(), x, y);
                 mResizedView = findView(x, y);
-                mInitialTouchX = ev.getX();
-                mInitialTouchY = ev.getY();
+                mInitialTouchX = ev.getRawX();
+                mInitialTouchY = ev.getRawY();
                 break;
             case MotionEvent.ACTION_MOVE: {
                 if (mWatchingForPull) {
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index 1306284..c72f5d2 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -29,6 +29,7 @@
 import android.graphics.RectF;
 import android.graphics.Region.Op;
 import android.opengl.GLUtils;
+import android.os.AsyncTask;
 import android.os.SystemProperties;
 import android.renderscript.Matrix4f;
 import android.service.wallpaper.WallpaperService;
@@ -155,6 +156,8 @@
 
         private int mLastRequestedWidth = -1;
         private int mLastRequestedHeight = -1;
+        private AsyncTask<Void, Void, Bitmap> mLoader;
+        private boolean mNeedsDrawAfterLoadingWallpaper;
 
         public DrawableEngine() {
             super();
@@ -184,10 +187,9 @@
             super.onCreate(surfaceHolder);
 
             mDefaultDisplay = getSystemService(WindowManager.class).getDefaultDisplay();
-
-            updateSurfaceSize(surfaceHolder, getDefaultDisplayInfo());
-
             setOffsetNotificationsEnabled(false);
+
+            updateSurfaceSize(surfaceHolder, getDefaultDisplayInfo(), false /* forDraw */);
         }
 
         @Override
@@ -197,17 +199,19 @@
             mWallpaperManager.forgetLoadedWallpaper();
         }
 
-        void updateSurfaceSize(SurfaceHolder surfaceHolder, DisplayInfo displayInfo) {
+        boolean updateSurfaceSize(SurfaceHolder surfaceHolder, DisplayInfo displayInfo,
+                boolean forDraw) {
+            boolean hasWallpaper = true;
+
             // Load background image dimensions, if we haven't saved them yet
             if (mBackgroundWidth <= 0 || mBackgroundHeight <= 0) {
                 // Need to load the image to get dimensions
                 mWallpaperManager.forgetLoadedWallpaper();
-                updateWallpaperLocked();
-                if (mBackgroundWidth <= 0 || mBackgroundHeight <= 0) {
-                    // Default to the display size if we can't find the dimensions
-                    mBackgroundWidth = displayInfo.logicalWidth;
-                    mBackgroundHeight = displayInfo.logicalHeight;
+                loadWallpaper(forDraw);
+                if (DEBUG) {
+                    Log.d(TAG, "Reloading, redoing updateSurfaceSize later.");
                 }
+                hasWallpaper = false;
             }
 
             // Force the wallpaper to cover the screen in both dimensions
@@ -224,6 +228,7 @@
             } else {
                 surfaceHolder.setSizeFromLayout();
             }
+            return hasWallpaper;
         }
 
         @Override
@@ -299,6 +304,7 @@
             }
             super.onSurfaceRedrawNeeded(holder);
 
+            mLastSurfaceHeight = mLastSurfaceWidth = -1;
             drawFrame();
         }
 
@@ -317,7 +323,9 @@
                 // should change
                 if (newRotation != mLastRotation) {
                     // Update surface size (if necessary)
-                    updateSurfaceSize(getSurfaceHolder(), displayInfo);
+                    if (!updateSurfaceSize(getSurfaceHolder(), displayInfo, true /* forDraw */)) {
+                        return; // had to reload wallpaper, will retry later
+                    }
                     mRotationAtLastSurfaceSizeUpdate = newRotation;
                     mDisplayWidthAtLastSurfaceSizeUpdate = displayInfo.logicalWidth;
                     mDisplayHeightAtLastSurfaceSizeUpdate = displayInfo.logicalHeight;
@@ -339,8 +347,8 @@
                 }
                 mLastRotation = newRotation;
 
-                // Load bitmap if it is not yet loaded or if it was loaded at a different size
-                if (mBackground == null || surfaceDimensionsChanged) {
+                // Load bitmap if it is not yet loaded
+                if (mBackground == null) {
                     if (DEBUG) {
                         Log.d(TAG, "Reloading bitmap: mBackground, bgw, bgh, dw, dh = " +
                                 mBackground + ", " +
@@ -349,20 +357,11 @@
                                 dw + ", " + dh);
                     }
                     mWallpaperManager.forgetLoadedWallpaper();
-                    updateWallpaperLocked();
-                    if (mBackground == null) {
-                        if (DEBUG) {
-                            Log.d(TAG, "Unable to load bitmap");
-                        }
-                        return;
-                    }
+                    loadWallpaper(true /* needDraw */);
                     if (DEBUG) {
-                        if (dw != mBackground.getWidth() || dh != mBackground.getHeight()) {
-                            Log.d(TAG, "Surface != bitmap dimensions: surface w/h, bitmap w/h: " +
-                                    dw + ", " + dh + ", " + mBackground.getWidth() + ", " +
-                                    mBackground.getHeight());
-                        }
+                        Log.d(TAG, "Reloading, resuming draw later");
                     }
+                    return;
                 }
 
                 // Center the scaled image
@@ -422,36 +421,77 @@
             }
         }
 
-        private void updateWallpaperLocked() {
-            Throwable exception = null;
-            try {
-                mBackground = null;
-                mBackgroundWidth = -1;
-                mBackgroundHeight = -1;
-                mBackground = mWallpaperManager.getBitmap();
-                mBackgroundWidth = mBackground.getWidth();
-                mBackgroundHeight = mBackground.getHeight();
-            } catch (RuntimeException e) {
-                exception = e;
-            } catch (OutOfMemoryError e) {
-                exception = e;
-            }
-
-            if (exception != null) {
-                mBackground = null;
-                mBackgroundWidth = -1;
-                mBackgroundHeight = -1;
-                // Note that if we do fail at this, and the default wallpaper can't
-                // be loaded, we will go into a cycle.  Don't do a build where the
-                // default wallpaper can't be loaded.
-                Log.w(TAG, "Unable to load wallpaper!", exception);
-                try {
-                    mWallpaperManager.clear();
-                } catch (IOException ex) {
-                    // now we're really screwed.
-                    Log.w(TAG, "Unable reset to default wallpaper!", ex);
+        /**
+         * Loads the wallpaper on background thread and schedules updating the surface frame,
+         * and if {@param needsDraw} is set also draws a frame.
+         *
+         * If loading is already in-flight, subsequent loads are ignored (but needDraw is or-ed to
+         * the active request).
+         */
+        private void loadWallpaper(boolean needsDraw) {
+            mNeedsDrawAfterLoadingWallpaper |= needsDraw;
+            if (mLoader != null) {
+                if (DEBUG) {
+                    Log.d(TAG, "Skipping loadWallpaper, already in flight ");
                 }
+                return;
             }
+            mLoader = new AsyncTask<Void, Void, Bitmap>() {
+                @Override
+                protected Bitmap doInBackground(Void... params) {
+                    Throwable exception;
+                    try {
+                        return mWallpaperManager.getBitmap();
+                    } catch (RuntimeException | OutOfMemoryError e) {
+                        exception = e;
+                    }
+
+                    if (exception != null) {
+                        // Note that if we do fail at this, and the default wallpaper can't
+                        // be loaded, we will go into a cycle.  Don't do a build where the
+                        // default wallpaper can't be loaded.
+                        Log.w(TAG, "Unable to load wallpaper!", exception);
+                        try {
+                            mWallpaperManager.clear();
+                        } catch (IOException ex) {
+                            // now we're really screwed.
+                            Log.w(TAG, "Unable reset to default wallpaper!", ex);
+                        }
+
+                        try {
+                            return mWallpaperManager.getBitmap();
+                        } catch (RuntimeException | OutOfMemoryError e) {
+                            Log.w(TAG, "Unable to load default wallpaper!", e);
+                        }
+                    }
+                    return null;
+                }
+
+                @Override
+                protected void onPostExecute(Bitmap b) {
+                    mBackground = null;
+                    mBackgroundWidth = -1;
+                    mBackgroundHeight = -1;
+
+                    if (b != null) {
+                        mBackground = b;
+                        mBackgroundWidth = mBackground.getWidth();
+                        mBackgroundHeight = mBackground.getHeight();
+                    }
+
+                    if (DEBUG) {
+                        Log.d(TAG, "Wallpaper loaded: " + mBackground);
+                    }
+                    updateSurfaceSize(getSurfaceHolder(), getDefaultDisplayInfo(),
+                            false /* forDraw */);
+                    if (mNeedsDrawAfterLoadingWallpaper) {
+                        drawFrame();
+                    }
+
+                    mLoader = null;
+                    mNeedsDrawAfterLoadingWallpaper = false;
+                }
+            }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
         }
 
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/RecentsComponent.java b/packages/SystemUI/src/com/android/systemui/RecentsComponent.java
index eaafafa..94b2fdb 100644
--- a/packages/SystemUI/src/com/android/systemui/RecentsComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/RecentsComponent.java
@@ -21,9 +21,9 @@
 import android.view.View;
 
 public interface RecentsComponent {
-    void showRecents(boolean triggeredFromAltTab, boolean fromHome, View statusBarView);
+    void showRecents(boolean triggeredFromAltTab, boolean fromHome);
     void hideRecents(boolean triggeredFromAltTab, boolean triggeredFromHomeKey);
-    void toggleRecents(Display display, int layoutDirection, View statusBarView);
+    void toggleRecents(Display display);
     void preloadRecents();
     void cancelPreloadingRecents();
     void showNextAffiliatedTask();
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUISecondaryUserService.java b/packages/SystemUI/src/com/android/systemui/SystemUISecondaryUserService.java
index f619bfb..c8a2e17 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUISecondaryUserService.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUISecondaryUserService.java
@@ -16,11 +16,9 @@
 
 package com.android.systemui;
 
-import android.app.ActivityManager;
 import android.app.Service;
 import android.content.Intent;
 import android.os.IBinder;
-import android.os.Process;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -43,15 +41,19 @@
         SystemUI[] services = ((SystemUIApplication) getApplication()).getServices();
         if (args == null || args.length == 0) {
             for (SystemUI ui: services) {
-                pw.println("dumping service: " + ui.getClass().getName());
-                ui.dump(fd, pw, args);
+                if (ui != null) {
+                    pw.println("dumping service: " + ui.getClass().getName());
+                    ui.dump(fd, pw, args);
+                }
             }
         } else {
             String svc = args[0];
             for (SystemUI ui: services) {
-                String name = ui.getClass().getName();
-                if (name.endsWith(svc)) {
-                    ui.dump(fd, pw, args);
+                if (ui != null) {
+                    String name = ui.getClass().getName();
+                    if (name.endsWith(svc)) {
+                        ui.dump(fd, pw, args);
+                    }
                 }
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
index 0798590..1ac5992 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
@@ -27,6 +27,7 @@
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.view.MotionEvent;
+import android.view.accessibility.AccessibilityManager;
 
 import com.android.systemui.analytics.DataCollector;
 import com.android.systemui.statusbar.StatusBarState;
@@ -60,6 +61,7 @@
     private final SensorManager mSensorManager;
     private final DataCollector mDataCollector;
     private final HumanInteractionClassifier mHumanInteractionClassifier;
+    private final AccessibilityManager mAccessibilityManager;
 
     private static FalsingManager sInstance = null;
 
@@ -78,7 +80,8 @@
 
     private FalsingManager(Context context) {
         mContext = context;
-        mSensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);
+        mSensorManager = mContext.getSystemService(SensorManager.class);
+        mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
         mDataCollector = DataCollector.getInstance(mContext);
         mHumanInteractionClassifier = HumanInteractionClassifier.getInstance(mContext);
         mScreenOn = context.getSystemService(PowerManager.class).isInteractive();
@@ -177,6 +180,11 @@
                         .toString());
             }
         }
+        if (mAccessibilityManager.isTouchExplorationEnabled()) {
+            // Touch exploration triggers false positives in the classifier and
+            // already sufficiently prevents false unlocks.
+            return false;
+        }
         return mHumanInteractionClassifier.isFalseTouch();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 1149c59..74f1b80 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -70,6 +70,7 @@
 
     private QSCustomizer mCustomizePanel;
     private Record mDetailRecord;
+    private boolean mTriggeredExpand;
 
     public QSPanel(Context context) {
         this(context, null);
@@ -384,8 +385,16 @@
     }
 
     protected void handleShowDetail(Record r, boolean show) {
-        if (show && !mExpanded) {
-            mHost.animateExpandQS();
+        if (show) {
+            if (!mExpanded) {
+                mTriggeredExpand = true;
+                mHost.animateToggleQSExpansion();
+            } else {
+                mTriggeredExpand = false;
+            }
+        } else if (mTriggeredExpand) {
+            mHost.animateToggleQSExpansion();
+            mTriggeredExpand = false;
         }
         if (r instanceof TileRecord) {
             handleShowDetailTile((TileRecord) r, show);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
index 3e32905..7692598 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
@@ -389,7 +389,7 @@
         void startRunnableDismissingKeyguard(Runnable runnable);
         void warn(String message, Throwable t);
         void collapsePanels();
-        void animateExpandQS();
+        void animateToggleQSExpansion();
         void openPanels();
         Looper getLooper();
         Context getContext();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
index faa5283..41b49d8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
@@ -279,6 +279,7 @@
 
     private void selectPosition(int position, View v) {
         // Remove the placeholder.
+        notifyItemRemoved(mEditIndex);
         mTiles.remove(mEditIndex--);
         mAccessibilityMoving = false;
         move(mAccessibilityFromIndex, position, v);
@@ -323,7 +324,7 @@
     }
 
     private boolean move(int from, int to, View v) {
-        if (to >= mEditIndex) {
+        if (to > mEditIndex) {
             if (from >= mEditIndex) {
                 return false;
             }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
index d04a2fc..9bc85c8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
@@ -144,14 +144,18 @@
                 String packageName = info.serviceInfo.packageName;
                 ComponentName componentName = new ComponentName(packageName, info.serviceInfo.name);
                 String spec = CustomTile.toSpec(componentName);
+                if (info.serviceInfo.icon == 0) {
+                    continue;
+                }
                 Drawable icon = info.serviceInfo.loadIcon(pm);
                 if (!permission.BIND_QUICK_SETTINGS_TILE.equals(info.serviceInfo.permission)) {
                     continue;
                 }
-                if (icon != null) {
-                    icon.mutate();
-                    icon.setTint(mContext.getColor(android.R.color.white));
+                if (icon == null) {
+                    continue;
                 }
+                icon.mutate();
+                icon.setTint(mContext.getColor(android.R.color.white));
                 CharSequence label = info.serviceInfo.loadLabel(pm);
                 final CharSequence appLabel = info.serviceInfo.applicationInfo.loadLabel(pm);
                 addTile(spec, icon, label != null ? label.toString() : "null", appLabel, mContext);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
index 6b20681..54dd015 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
@@ -36,7 +36,6 @@
 import android.view.IWindowManager;
 import android.view.WindowManager;
 import android.view.WindowManagerGlobal;
-
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
@@ -59,6 +58,7 @@
     private final IQSTileService mService;
     private final TileServiceManager mServiceManager;
     private final int mUser;
+    private final android.graphics.drawable.Icon mDefaultIcon;
 
     private boolean mListening;
     private boolean mBound;
@@ -73,15 +73,19 @@
         mService = mServiceManager.getTileService();
         mTile = new Tile(mComponent);
         mUser = ActivityManager.getCurrentUser();
+        android.graphics.drawable.Icon defaultIcon;
         try {
             PackageManager pm = mContext.getPackageManager();
             ServiceInfo info = pm.getServiceInfo(mComponent,
                     PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE);
-            mTile.setIcon(android.graphics.drawable.Icon
-                    .createWithResource(mComponent.getPackageName(), info.icon));
+            defaultIcon = info.icon != 0 ? android.graphics.drawable.Icon
+                    .createWithResource(mComponent.getPackageName(), info.icon) : null;
+            mTile.setIcon(defaultIcon);
             mTile.setLabel(info.loadLabel(pm));
         } catch (Exception e) {
+            defaultIcon = null;
         }
+        mDefaultIcon = defaultIcon;
         try {
             mService.setQSTile(mTile);
         } catch (RemoteException e) {
@@ -91,13 +95,7 @@
 
     @Override
     public boolean isAvailable() {
-        try {
-            ServiceInfo info = mContext.getPackageManager().getServiceInfo(mComponent,
-                    PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE);
-            return true;
-        } catch (Exception e) {
-            return false;
-        }
+        return mDefaultIcon != null;
     }
 
     public int getUser() {
@@ -227,11 +225,18 @@
 
     @Override
     protected void handleUpdateState(State state, Object arg) {
-        Drawable drawable = mTile.getIcon().loadDrawable(mContext);
         int tileState = mTile.getState();
         if (mServiceManager.hasPendingBind()) {
             tileState = Tile.STATE_UNAVAILABLE;
         }
+        Drawable drawable;
+        try {
+            drawable = mTile.getIcon().loadDrawable(mContext);
+        } catch (Exception e) {
+            Log.w(TAG, "Invalid icon, forcing into unavailable state");
+            tileState = Tile.STATE_UNAVAILABLE;
+            drawable = mDefaultIcon.loadDrawable(mContext);
+        }
         int color = mContext.getColor(getColor(tileState));
         drawable.setTint(color);
         state.icon = new DrawableIcon(drawable);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
index 5a26a4a..5903218 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
@@ -148,13 +148,20 @@
         if (DEBUG) Log.d(TAG, "onServiceConnected " + name);
         // Got a connection, set the binding count to 0.
         mBindTryCount = 0;
-        mWrapper = new QSTileServiceWrapper(Stub.asInterface(service));
+        final QSTileServiceWrapper wrapper = new QSTileServiceWrapper(Stub.asInterface(service));
         try {
             service.linkToDeath(this, 0);
         } catch (RemoteException e) {
         }
-        setQSService(mService);
-        setQSTile(mTile);
+        if (!wrapper.setQSService(mService)) {
+            handleDeath();
+            return;
+        }
+        if (!wrapper.setQSTile(mTile)) {
+            handleDeath();
+            return;
+        }
+        mWrapper = wrapper;
         handlePendingMessages();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/IRecentsNonSystemUserCallbacks.aidl b/packages/SystemUI/src/com/android/systemui/recents/IRecentsNonSystemUserCallbacks.aidl
index 7ce9384..9403664 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/IRecentsNonSystemUserCallbacks.aidl
+++ b/packages/SystemUI/src/com/android/systemui/recents/IRecentsNonSystemUserCallbacks.aidl
@@ -27,9 +27,9 @@
     void preloadRecents();
     void cancelPreloadingRecents();
     void showRecents(boolean triggeredFromAltTab, boolean draggingInRecents, boolean animate,
-            boolean reloadTasks, boolean fromHome);
+            boolean reloadTasks, boolean fromHome, int recentsGrowTarget);
     void hideRecents(boolean triggeredFromAltTab, boolean triggeredFromHomeKey);
-    void toggleRecents();
+    void toggleRecents(int recentsGrowTarget);
     void onConfigurationChanged();
     void dockTopTask(int topTaskId, int dragMode, int stackCreateMode,
             in Rect initialBounds);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
index bb709c5..630cb66 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
@@ -37,9 +37,7 @@
 import android.provider.Settings;
 import android.util.EventLog;
 import android.util.Log;
-import android.util.MutableBoolean;
 import android.view.Display;
-import android.view.View;
 import android.widget.Toast;
 
 import com.android.internal.logging.MetricsLogger;
@@ -59,6 +57,7 @@
 import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.recents.model.RecentsTaskLoader;
 import com.android.systemui.recents.tv.RecentsTvImpl;
+import com.android.systemui.stackdivider.Divider;
 
 import java.util.ArrayList;
 
@@ -75,6 +74,7 @@
 
     public final static int EVENT_BUS_PRIORITY = 1;
     public final static int BIND_TO_SYSTEM_USER_RETRY_DELAY = 5000;
+    public final static int RECENTS_GROW_TARGET_INVALID = -1;
 
     // Purely for experimentation
     private final static String RECENTS_OVERRIDE_SYSPROP_KEY = "persist.recents_override_pkg";
@@ -238,7 +238,7 @@
      * Shows the Recents.
      */
     @Override
-    public void showRecents(boolean triggeredFromAltTab, boolean fromHome, View statusBarView) {
+    public void showRecents(boolean triggeredFromAltTab, boolean fromHome) {
         // Ensure the device has been provisioned before allowing the user to interact with
         // recents
         if (!isUserSetup()) {
@@ -249,10 +249,12 @@
             return;
         }
 
+        int recentsGrowTarget = getComponent(Divider.class).getView().growsRecents();
+
         int currentUser = sSystemServicesProxy.getCurrentUser();
         if (sSystemServicesProxy.isSystemUser(currentUser)) {
             mImpl.showRecents(triggeredFromAltTab, false /* draggingInRecents */,
-                    true /* animate */, false /* reloadTasks */, fromHome);
+                    true /* animate */, false /* reloadTasks */, fromHome, recentsGrowTarget);
         } else {
             if (mSystemToUserCallbacks != null) {
                 IRecentsNonSystemUserCallbacks callbacks =
@@ -260,7 +262,8 @@
                 if (callbacks != null) {
                     try {
                         callbacks.showRecents(triggeredFromAltTab, false /* draggingInRecents */,
-                                true /* animate */, false /* reloadTasks */, fromHome);
+                                true /* animate */, false /* reloadTasks */, fromHome,
+                                recentsGrowTarget);
                     } catch (RemoteException e) {
                         Log.e(TAG, "Callback failed", e);
                     }
@@ -310,7 +313,7 @@
      * Toggles the Recents activity.
      */
     @Override
-    public void toggleRecents(Display display, int layoutDirection, View statusBarView) {
+    public void toggleRecents(Display display) {
         // Ensure the device has been provisioned before allowing the user to interact with
         // recents
         if (!isUserSetup()) {
@@ -321,16 +324,18 @@
             return;
         }
 
+        int growTarget = getComponent(Divider.class).getView().growsRecents();
+
         int currentUser = sSystemServicesProxy.getCurrentUser();
         if (sSystemServicesProxy.isSystemUser(currentUser)) {
-            mImpl.toggleRecents();
+            mImpl.toggleRecents(growTarget);
         } else {
             if (mSystemToUserCallbacks != null) {
                 IRecentsNonSystemUserCallbacks callbacks =
                         mSystemToUserCallbacks.getNonSystemUserRecentsForUser(currentUser);
                 if (callbacks != null) {
                     try {
-                        callbacks.toggleRecents();
+                        callbacks.toggleRecents(growTarget);
                     } catch (RemoteException e) {
                         Log.e(TAG, "Callback failed", e);
                     }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index 3ecada9..f961390 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -38,8 +38,10 @@
 import android.view.AppTransitionAnimationSpec;
 import android.view.LayoutInflater;
 import android.view.ViewConfiguration;
+import android.view.WindowManager;
 
 import com.android.internal.logging.MetricsLogger;
+import com.android.internal.policy.DockedDividerUtils;
 import com.android.systemui.R;
 import com.android.systemui.SystemUIApplication;
 import com.android.systemui.recents.events.EventBus;
@@ -68,6 +70,7 @@
 import com.android.systemui.recents.views.TaskStackViewScroller;
 import com.android.systemui.recents.views.TaskViewHeader;
 import com.android.systemui.recents.views.TaskViewTransform;
+import com.android.systemui.stackdivider.DividerView;
 import com.android.systemui.statusbar.BaseStatusBar;
 import com.android.systemui.statusbar.phone.NavigationBarGestureHelper;
 import com.android.systemui.statusbar.phone.PhoneStatusBar;
@@ -156,7 +159,8 @@
             // When this fires, then the user has not released alt-tab for at least
             // FAST_ALT_TAB_DELAY_MS milliseconds
             showRecents(mTriggeredFromAltTab, false /* draggingInRecents */, true /* animate */,
-                    false /* reloadTasks */, false /* fromHome */);
+                    false /* reloadTasks */, false /* fromHome */,
+                    DividerView.INVALID_RECENTS_GROW_TARGET);
         }
     });
 
@@ -230,7 +234,8 @@
     }
 
     public void showRecents(boolean triggeredFromAltTab, boolean draggingInRecents,
-            boolean animate, boolean launchedWhileDockingTask, boolean fromHome) {
+            boolean animate, boolean launchedWhileDockingTask, boolean fromHome,
+            int growTarget) {
         mTriggeredFromAltTab = triggeredFromAltTab;
         mDraggingInRecents = draggingInRecents;
         mLaunchedWhileDocking = launchedWhileDockingTask;
@@ -260,7 +265,7 @@
             ActivityManager.RunningTaskInfo topTask = ssp.getTopMostTask();
             MutableBoolean isTopTaskHome = new MutableBoolean(true);
             if (topTask == null || !ssp.isRecentsTopMost(topTask, isTopTaskHome)) {
-                startRecentsActivity(topTask, isTopTaskHome.value || fromHome, animate);
+                startRecentsActivity(topTask, isTopTaskHome.value || fromHome, animate, growTarget);
             }
         } catch (ActivityNotFoundException e) {
             Log.e(TAG, "Failed to launch RecentsActivity", e);
@@ -284,7 +289,7 @@
                 triggeredFromHomeKey));
     }
 
-    public void toggleRecents() {
+    public void toggleRecents(int growTarget) {
         // Skip this toggle if we are already waiting to trigger recents via alt-tab
         if (mFastAltTabTrigger.isDozing()) {
             return;
@@ -338,7 +343,7 @@
                 }
 
                 // Otherwise, start the recents activity
-                startRecentsActivity(topTask, isTopTaskHome.value, true /* animate */);
+                startRecentsActivity(topTask, isTopTaskHome.value, true /* animate */, growTarget);
 
                 // Only close the other system windows if we are actually showing recents
                 ssp.sendCloseSystemWindows(BaseStatusBar.SYSTEM_DIALOG_REASON_RECENT_APPS);
@@ -369,7 +374,7 @@
                 // At this point, we don't know anything about the stack state.  So only calculate
                 // the dimensions of the thumbnail that we need for the transition into Recents, but
                 // do not draw it until we construct the activity options when we start Recents
-                updateHeaderBarLayout(stack);
+                updateHeaderBarLayout(stack, null /* window rect override*/);
             }
         }
     }
@@ -535,7 +540,8 @@
                     dragMode == NavigationBarGestureHelper.DRAG_MODE_RECENTS,
                     false /* animate */,
                     true /* launchedWhileDockingTask*/,
-                    false /* fromHome */);
+                    false /* fromHome */,
+                    DividerView.INVALID_RECENTS_GROW_TARGET);
         }
     }
 
@@ -574,12 +580,17 @@
      * since the last call, it will attempt to re-measure and layout the header bar to the new size.
      *
      * @param stack the stack to initialize the stack layout with
+     * @param windowRectOverride the rectangle to use when calculating the stack state which can
+     *                           be different from the current window rect if recents is resizing
+     *                           while being launched
      */
-    private void updateHeaderBarLayout(TaskStack stack) {
+    private void updateHeaderBarLayout(TaskStack stack, Rect windowRectOverride) {
         SystemServicesProxy ssp = Recents.getSystemServices();
         Rect systemInsets = new Rect();
         ssp.getStableInsets(systemInsets);
-        Rect windowRect = ssp.getWindowRect();
+        Rect windowRect = windowRectOverride != null
+                ? new Rect(windowRectOverride)
+                : ssp.getWindowRect();
         // When docked, the nav bar insets are consumed and the activity is measured without insets.
         // However, the window bounds include the insets, so we need to subtract them here to make
         // them identical.
@@ -682,7 +693,8 @@
      * Creates the activity options for an app->recents transition.
      */
     private ActivityOptions getThumbnailTransitionActivityOptions(
-            ActivityManager.RunningTaskInfo topTask, TaskStackView stackView) {
+            ActivityManager.RunningTaskInfo topTask, TaskStackView stackView,
+            Rect windowOverrideRect) {
         if (topTask.stackId == FREEFORM_WORKSPACE_STACK_ID) {
             ArrayList<AppTransitionAnimationSpec> specs = new ArrayList<>();
             ArrayList<Task> tasks = stackView.getStack().getStackTasks();
@@ -696,7 +708,8 @@
                 Task task = tasks.get(i);
                 if (task.isFreeformTask()) {
                     mTmpTransform = stackLayout.getStackTransformScreenCoordinates(task,
-                                    stackScroller.getStackScroll(), mTmpTransform, null);
+                            stackScroller.getStackScroll(), mTmpTransform, null,
+                            windowOverrideRect);
                     Bitmap thumbnail = drawThumbnailTransitionBitmap(task, mTmpTransform,
                             mThumbTransitionBitmapCache);
                     Rect toTaskRect = new Rect();
@@ -711,7 +724,8 @@
         } else {
             // Update the destination rect
             Task toTask = new Task();
-            TaskViewTransform toTransform = getThumbnailTransitionTransform(stackView, toTask);
+            TaskViewTransform toTransform = getThumbnailTransitionTransform(stackView, toTask,
+                    windowOverrideRect);
             Bitmap thumbnail = drawThumbnailTransitionBitmap(toTask, toTransform,
                     mThumbTransitionBitmapCache);
             if (thumbnail != null) {
@@ -729,7 +743,7 @@
      * Returns the transition rect for the given task id.
      */
     private TaskViewTransform getThumbnailTransitionTransform(TaskStackView stackView,
-            Task runningTaskOut) {
+            Task runningTaskOut, Rect windowOverrideRect) {
         // Find the running task in the TaskStack
         TaskStack stack = stackView.getStack();
         Task launchTask = stack.getLaunchTarget();
@@ -745,7 +759,7 @@
         stackView.updateLayoutAlgorithm(true /* boundScroll */);
         stackView.updateToInitialState();
         stackView.getStackAlgorithm().getStackTransformScreenCoordinates(launchTask,
-                stackView.getScroller().getStackScroll(), mTmpTransform, null);
+                stackView.getScroller().getStackScroll(), mTmpTransform, null, windowOverrideRect);
         return mTmpTransform;
     }
 
@@ -788,7 +802,7 @@
      * Shows the recents activity
      */
     protected void startRecentsActivity(ActivityManager.RunningTaskInfo topTask,
-            boolean isTopTaskHome, boolean animate) {
+            boolean isTopTaskHome, boolean animate, int growTarget) {
         RecentsTaskLoader loader = Recents.getTaskLoader();
         RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
 
@@ -820,7 +834,8 @@
         preloadIcon(topTask);
 
         // Update the header bar if necessary
-        updateHeaderBarLayout(stack);
+        Rect windowOverrideRect = getWindowRectOverride(growTarget);
+        updateHeaderBarLayout(stack, windowOverrideRect);
 
         // Prepare the dummy stack for the transition
         TaskStackLayoutAlgorithm.VisibilityReport stackVr =
@@ -838,7 +853,8 @@
         ActivityOptions opts;
         if (useThumbnailTransition) {
             // Try starting with a thumbnail transition
-            opts = getThumbnailTransitionActivityOptions(topTask, mDummyStackView);
+            opts = getThumbnailTransitionActivityOptions(topTask, mDummyStackView,
+                    windowOverrideRect);
         } else {
             // If there is no thumbnail transition, but is launching from home into recents, then
             // use a quick home transition
@@ -850,6 +866,18 @@
         mLastToggleTime = SystemClock.elapsedRealtime();
     }
 
+    private Rect getWindowRectOverride(int growTarget) {
+        if (growTarget == DividerView.INVALID_RECENTS_GROW_TARGET) {
+            return null;
+        }
+        Rect result = new Rect();
+        Rect displayRect = Recents.getSystemServices().getDisplayRect();
+        DockedDividerUtils.calculateBoundsForPosition(growTarget, WindowManager.DOCKED_BOTTOM,
+                result, displayRect.width(), displayRect.height(),
+                Recents.getSystemServices().getDockedDividerSize(mContext));
+        return result;
+    }
+
     /**
      * Starts the recents activity.
      */
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImplProxy.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImplProxy.java
index 257bda2..defc6ed 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImplProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImplProxy.java
@@ -57,13 +57,15 @@
 
     @Override
     public void showRecents(boolean triggeredFromAltTab, boolean draggingInRecents, boolean animate,
-            boolean reloadTasks, boolean fromHome) throws RemoteException {
+            boolean reloadTasks, boolean fromHome, int growTarget)
+            throws RemoteException {
         SomeArgs args = SomeArgs.obtain();
         args.argi1 = triggeredFromAltTab ? 1 : 0;
         args.argi2 = draggingInRecents ? 1 : 0;
         args.argi3 = animate ? 1 : 0;
         args.argi4 = reloadTasks ? 1 : 0;
         args.argi5 = fromHome ? 1 : 0;
+        args.argi6 = growTarget;
         mHandler.sendMessage(mHandler.obtainMessage(MSG_SHOW_RECENTS, args));
     }
 
@@ -75,8 +77,8 @@
     }
 
     @Override
-    public void toggleRecents() throws RemoteException {
-        mHandler.sendEmptyMessage(MSG_TOGGLE_RECENTS);
+    public void toggleRecents(int growTarget) throws RemoteException {
+        mHandler.sendMessage(mHandler.obtainMessage(MSG_TOGGLE_RECENTS, growTarget));
     }
 
     @Override
@@ -119,13 +121,13 @@
                 case MSG_SHOW_RECENTS:
                     SomeArgs args = (SomeArgs) msg.obj;
                     mImpl.showRecents(args.argi1 != 0, args.argi2 != 0, args.argi3 != 0,
-                            args.argi4 != 0, args.argi5 != 0);
+                            args.argi4 != 0, args.argi5 != 0, args.argi6);
                     break;
                 case MSG_HIDE_RECENTS:
                     mImpl.hideRecents(msg.arg1 != 0, msg.arg2 != 0);
                     break;
                 case MSG_TOGGLE_RECENTS:
-                    mImpl.toggleRecents();
+                    mImpl.toggleRecents(msg.arg1);
                     break;
                 case MSG_ON_CONFIGURATION_CHANGED:
                     mImpl.onConfigurationChanged();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/RecentsGrowingEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/RecentsGrowingEvent.java
new file mode 100644
index 0000000..d9b0027
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/ui/RecentsGrowingEvent.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.recents.events.ui;
+
+import com.android.systemui.recents.events.EventBus;
+
+/**
+ * Sent when recents is about to grow in multi-window mode when entering recents.
+ */
+public class RecentsGrowingEvent extends EventBus.Event {
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvImpl.java b/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvImpl.java
index dc0d1f1..18b9263 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvImpl.java
@@ -49,7 +49,7 @@
 
     @Override
     protected void startRecentsActivity(ActivityManager.RunningTaskInfo topTask,
-            boolean isTopTaskHome, boolean animate) {
+            boolean isTopTaskHome, boolean animate, int growTarget) {
         RecentsTaskLoader loader = Recents.getTaskLoader();
 
         // In the case where alt-tab is triggered, we never get a preloadRecents() call, so we
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 04f10ef8..1238c63 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
@@ -302,7 +302,8 @@
                 specs.add(composeOffscreenAnimationSpec(task, offscreenTaskRect));
             } else {
                 mTmpTransform.fillIn(taskView);
-                stackLayout.transformToScreenCoordinates(mTmpTransform);
+                stackLayout.transformToScreenCoordinates(mTmpTransform,
+                        null /* windowOverrideRect */);
                 specs.add(composeAnimationSpec(stackView, taskView, mTmpTransform,
                         true /* addHeaderBitmap */));
             }
@@ -324,7 +325,8 @@
                     specs.add(composeOffscreenAnimationSpec(t, offscreenTaskRect));
                 } else {
                     mTmpTransform.fillIn(taskView);
-                    stackLayout.transformToScreenCoordinates(mTmpTransform);
+                    stackLayout.transformToScreenCoordinates(mTmpTransform,
+                            null /* windowOverrideRect */);
                     specs.add(composeAnimationSpec(stackView, tv, mTmpTransform,
                             true /* addHeaderBitmap */));
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
index 774e4e9..0022d66 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
@@ -830,18 +830,23 @@
      * Like {@link #getStackTransform}, but in screen coordinates
      */
     public TaskViewTransform getStackTransformScreenCoordinates(Task task, float stackScroll,
-            TaskViewTransform transformOut, TaskViewTransform frontTransform) {
+            TaskViewTransform transformOut, TaskViewTransform frontTransform,
+            Rect windowOverrideRect) {
         TaskViewTransform transform = getStackTransform(task, stackScroll, mFocusState,
                 transformOut, frontTransform, true /* forceUpdate */,
                 false /* ignoreTaskOverrides */);
-        return transformToScreenCoordinates(transform);
+        return transformToScreenCoordinates(transform, windowOverrideRect);
     }
 
     /**
-     * Transforms the given {@param transformOut} to the screen coordinates.
+     * Transforms the given {@param transformOut} to the screen coordinates, overriding the current
+     * window rectangle with {@param windowOverrideRect} if non-null.
      */
-    public TaskViewTransform transformToScreenCoordinates(TaskViewTransform transformOut) {
-        Rect windowRect = Recents.getSystemServices().getWindowRect();
+    public TaskViewTransform transformToScreenCoordinates(TaskViewTransform transformOut,
+            Rect windowOverrideRect) {
+        Rect windowRect = windowOverrideRect != null
+                ? windowOverrideRect
+                : Recents.getSystemServices().getWindowRect();
         transformOut.rect.offset(windowRect.left, windowRect.top);
         return transformOut;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index 6176d99..610b4e1 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -72,6 +72,7 @@
 import com.android.systemui.recents.events.ui.DeleteTaskDataEvent;
 import com.android.systemui.recents.events.ui.DismissAllTaskViewsEvent;
 import com.android.systemui.recents.events.ui.DismissTaskViewEvent;
+import com.android.systemui.recents.events.ui.RecentsGrowingEvent;
 import com.android.systemui.recents.events.ui.TaskViewDismissedEvent;
 import com.android.systemui.recents.events.ui.UpdateFreeformTaskViewVisibilityEvent;
 import com.android.systemui.recents.events.ui.UserInteractionEvent;
@@ -189,6 +190,9 @@
     private TaskViewTransform mTmpTransform = new TaskViewTransform();
     private ArrayList<TaskViewTransform> mTmpTaskTransforms = new ArrayList<>();
     private int[] mTmpIntPair = new int[2];
+    private boolean mResetToInitialStateWhenResized;
+    private int mLastWidth;
+    private int mLastHeight;
 
     // A convenience update listener to request updating clipping of tasks
     private ValueAnimator.AnimatorUpdateListener mRequestUpdateClippingListener =
@@ -1164,9 +1168,13 @@
 
         // If this is the first layout, then scroll to the front of the stack, then update the
         // TaskViews with the stack so that we can lay them out
-        if (mAwaitingFirstLayout || mInitialState != INITIAL_STATE_UPDATE_NONE) {
-            if (mInitialState != INITIAL_STATE_UPDATE_LAYOUT_ONLY) {
+        boolean resetToInitialState = (width != mLastWidth || height != mLastHeight)
+                && mResetToInitialStateWhenResized;
+        if (mAwaitingFirstLayout || mInitialState != INITIAL_STATE_UPDATE_NONE
+                || resetToInitialState) {
+            if (mInitialState != INITIAL_STATE_UPDATE_LAYOUT_ONLY || resetToInitialState) {
                 updateToInitialState();
+                mResetToInitialStateWhenResized = false;
             }
             if (!mAwaitingFirstLayout) {
                 mInitialState = INITIAL_STATE_UPDATE_NONE;
@@ -1186,6 +1194,8 @@
         }
 
         setMeasuredDimension(width, height);
+        mLastWidth = width;
+        mLastHeight = height;
         mInMeasureLayout = false;
     }
 
@@ -1765,6 +1775,7 @@
                 mTmpTransform, null);
         mTmpTransform.scale = finalScale;
         mTmpTransform.translationZ = mLayoutAlgorithm.mMaxTranslationZ + 1;
+        mTmpTransform.dimAlpha = 0f;
         updateTaskViewToTransform(event.taskView, mTmpTransform,
                 new AnimationProps(DRAG_SCALE_DURATION, Interpolators.FAST_OUT_SLOW_IN));
     }
@@ -1972,6 +1983,10 @@
         }
     }
 
+    public final void onBusEvent(RecentsGrowingEvent event) {
+        mResetToInitialStateWhenResized = true;
+    }
+
     public void reloadOnConfigurationChange() {
         mStableLayoutAlgorithm.reloadOnConfigurationChange(getContext());
         mLayoutAlgorithm.reloadOnConfigurationChange(getContext());
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index 67c4008..44a167b 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -32,6 +32,7 @@
 import android.hardware.display.DisplayManager;
 import android.os.Bundle;
 import android.util.AttributeSet;
+import android.util.MutableInt;
 import android.view.Display;
 import android.view.DisplayInfo;
 import android.view.GestureDetector;
@@ -66,6 +67,7 @@
 import com.android.systemui.recents.events.activity.RecentsActivityStartingEvent;
 import com.android.systemui.recents.events.activity.UndockingTaskEvent;
 import com.android.systemui.recents.events.ui.RecentsDrawnEvent;
+import com.android.systemui.recents.events.ui.RecentsGrowingEvent;
 import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.stackdivider.events.StartedDragingEvent;
 import com.android.systemui.stackdivider.events.StoppedDragingEvent;
@@ -81,6 +83,8 @@
     static final long TOUCH_ANIMATION_DURATION = 150;
     static final long TOUCH_RELEASE_ANIMATION_DURATION = 200;
 
+    public static final int INVALID_RECENTS_GROW_TARGET = -1;
+
     private static final int LOG_VALUE_RESIZE_50_50 = 0;
     private static final int LOG_VALUE_RESIZE_DOCKED_SMALLER = 1;
     private static final int LOG_VALUE_RESIZE_DOCKED_LARGER = 2;
@@ -88,7 +92,6 @@
     private static final int LOG_VALUE_UNDOCK_MAX_DOCKED = 0;
     private static final int LOG_VALUE_UNDOCK_MAX_OTHER = 1;
 
-
     private static final int TASK_POSITION_SAME = Integer.MAX_VALUE;
     private static final boolean SWAPPING_ENABLED = false;
 
@@ -154,31 +157,62 @@
         public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
             super.onInitializeAccessibilityNodeInfo(host, info);
             if (isHorizontalDivision()) {
-                info.addAction(new AccessibilityAction(R.id.action_move_up,
-                        mContext.getString(R.string.accessibility_action_divider_move_up)));
-                info.addAction(new AccessibilityAction(R.id.action_move_down,
-                        mContext.getString(R.string.accessibility_action_divider_move_down)));
+                info.addAction(new AccessibilityAction(R.id.action_move_tl_full,
+                        mContext.getString(R.string.accessibility_action_divider_top_full)));
+                if (mSnapAlgorithm.isFirstSplitTargetAvailable()) {
+                    info.addAction(new AccessibilityAction(R.id.action_move_tl_70,
+                            mContext.getString(R.string.accessibility_action_divider_top_70)));
+                }
+                info.addAction(new AccessibilityAction(R.id.action_move_tl_50,
+                        mContext.getString(R.string.accessibility_action_divider_top_50)));
+                if (mSnapAlgorithm.isLastSplitTargetAvailable()) {
+                    info.addAction(new AccessibilityAction(R.id.action_move_tl_30,
+                            mContext.getString(R.string.accessibility_action_divider_top_30)));
+                }
+                info.addAction(new AccessibilityAction(R.id.action_move_rb_full,
+                        mContext.getString(R.string.accessibility_action_divider_bottom_full)));
             } else {
-                info.addAction(new AccessibilityAction(R.id.action_move_left,
-                        mContext.getString(R.string.accessibility_action_divider_move_left)));
-                info.addAction(new AccessibilityAction(R.id.action_move_right,
-                        mContext.getString(R.string.accessibility_action_divider_move_right)));
+                info.addAction(new AccessibilityAction(R.id.action_move_tl_full,
+                        mContext.getString(R.string.accessibility_action_divider_left_full)));
+                if (mSnapAlgorithm.isFirstSplitTargetAvailable()) {
+                    info.addAction(new AccessibilityAction(R.id.action_move_tl_70,
+                            mContext.getString(R.string.accessibility_action_divider_left_70)));
+                }
+                info.addAction(new AccessibilityAction(R.id.action_move_tl_50,
+                        mContext.getString(R.string.accessibility_action_divider_left_50)));
+                if (mSnapAlgorithm.isLastSplitTargetAvailable()) {
+                    info.addAction(new AccessibilityAction(R.id.action_move_tl_30,
+                            mContext.getString(R.string.accessibility_action_divider_left_30)));
+                }
+                info.addAction(new AccessibilityAction(R.id.action_move_rb_full,
+                        mContext.getString(R.string.accessibility_action_divider_right_full)));
             }
         }
 
         @Override
         public boolean performAccessibilityAction(View host, int action, Bundle args) {
-            if (action == R.id.action_move_up || action == R.id.action_move_down
-                    || action == R.id.action_move_left || action == R.id.action_move_right) {
-                int position = getCurrentPosition();
-                SnapTarget currentTarget = mSnapAlgorithm.calculateSnapTarget(
-                        position, 0 /* velocity */);
-                SnapTarget nextTarget =
-                        action == R.id.action_move_up || action == R.id.action_move_left
-                                ? mSnapAlgorithm.getPreviousTarget(currentTarget)
-                                : mSnapAlgorithm.getNextTarget(currentTarget);
+            int currentPosition = getCurrentPosition();
+            SnapTarget nextTarget = null;
+            switch (action) {
+                case R.id.action_move_tl_full:
+                    nextTarget = mSnapAlgorithm.getDismissEndTarget();
+                    break;
+                case R.id.action_move_tl_70:
+                    nextTarget = mSnapAlgorithm.getLastSplitTarget();
+                    break;
+                case R.id.action_move_tl_50:
+                    nextTarget = mSnapAlgorithm.getMiddleTarget();
+                    break;
+                case R.id.action_move_tl_30:
+                    nextTarget = mSnapAlgorithm.getFirstSplitTarget();
+                    break;
+                case R.id.action_move_rb_full:
+                    nextTarget = mSnapAlgorithm.getDismissStartTarget();
+                    break;
+            }
+            if (nextTarget != null) {
                 startDragging(true /* animate */, false /* touching */);
-                stopDragging(getCurrentPosition(), nextTarget, 250, Interpolators.FAST_OUT_SLOW_IN);
+                stopDragging(currentPosition, nextTarget, 250, Interpolators.FAST_OUT_SLOW_IN);
                 return true;
             }
             return super.performAccessibilityAction(host, action, args);
@@ -997,6 +1031,24 @@
                 mBackground.getRight(), mBackground.getBottom(), Op.UNION);
     }
 
+    /**
+     * Checks whether recents will grow when invoked. This happens in multi-window when recents is
+     * very small. When invoking recents, we shrink the docked stack so recents has more space.
+     *
+     * @return the position of the divider when recents grows, or
+     *         {@link #INVALID_RECENTS_GROW_TARGET} if recents won't grow
+     */
+    public int growsRecents() {
+        boolean result = mGrowRecents
+                && mWindowManagerProxy.getDockSide() == WindowManager.DOCKED_TOP
+                && getCurrentPosition() == getSnapAlgorithm().getLastSplitTarget().position;
+        if (result) {
+            return getSnapAlgorithm().getMiddleTarget().position;
+        } else {
+            return INVALID_RECENTS_GROW_TARGET;
+        }
+    }
+
     public final void onBusEvent(RecentsActivityStartingEvent recentsActivityStartingEvent) {
         if (mGrowRecents && getWindowManagerProxy().getDockSide() == WindowManager.DOCKED_TOP
                 && getCurrentPosition() == getSnapAlgorithm().getLastSplitTarget().position) {
@@ -1036,7 +1088,8 @@
         if (mGrowAfterRecentsDrawn) {
             mGrowAfterRecentsDrawn = false;
             updateDockSide();
-            stopDragging(getCurrentPosition(), mSnapAlgorithm.getMiddleTarget(), 250,
+            EventBus.getDefault().send(new RecentsGrowingEvent());
+            stopDragging(getCurrentPosition(), mSnapAlgorithm.getMiddleTarget(), 336,
                     Interpolators.FAST_OUT_SLOW_IN);
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivity.java b/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivity.java
index 177296b..18834ed 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivity.java
@@ -18,6 +18,7 @@
 
 import android.annotation.Nullable;
 import android.app.Activity;
+import android.app.ActivityManager;
 import android.os.Bundle;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
@@ -75,4 +76,9 @@
         finish();
         return true;
     }
+
+    @Override
+    public void setTaskDescription(ActivityManager.TaskDescription taskDescription) {
+        // Do nothing
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index cb1128b..2d5b6d4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -1318,7 +1318,7 @@
     protected void showRecents(boolean triggeredFromAltTab, boolean fromHome) {
         if (mRecents != null) {
             sendCloseSystemWindows(SYSTEM_DIALOG_REASON_RECENT_APPS);
-            mRecents.showRecents(triggeredFromAltTab, fromHome, getStatusBarView());
+            mRecents.showRecents(triggeredFromAltTab, fromHome);
         }
     }
 
@@ -1330,7 +1330,7 @@
 
     protected void toggleRecents() {
         if (mRecents != null) {
-            mRecents.toggleRecents(mDisplay, mLayoutDirection, getStatusBarView());
+            mRecents.toggleRecents(mDisplay);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/FakeShadowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/FakeShadowView.java
index 32c26ba..0c1891e1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/FakeShadowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/FakeShadowView.java
@@ -25,6 +25,7 @@
 import android.view.ViewOutlineProvider;
 import android.widget.LinearLayout;
 
+import com.android.systemui.R;
 import com.android.systemui.statusbar.AlphaOptimizedFrameLayout;
 
 /**
@@ -32,6 +33,7 @@
  */
 public class FakeShadowView extends AlphaOptimizedFrameLayout {
     public static final float SHADOW_SIBLING_TRESHOLD = 0.1f;
+    private final int mShadowMinHeight;
 
     private View mFakeShadow;
     private float mOutlineAlpha;
@@ -64,6 +66,8 @@
             }
         });
         addView(mFakeShadow);
+        mShadowMinHeight = Math.max(1, context.getResources()
+                .getDimensionPixelSize(R.dimen.notification_divider_height));
     }
 
     public void setFakeShadowTranslationZ(float fakeShadowTranslationZ, float outlineAlpha,
@@ -72,6 +76,7 @@
             mFakeShadow.setVisibility(INVISIBLE);
         } else {
             mFakeShadow.setVisibility(VISIBLE);
+            fakeShadowTranslationZ = Math.max(mShadowMinHeight, fakeShadowTranslationZ);
             mFakeShadow.setTranslationZ(fakeShadowTranslationZ);
             mFakeShadow.setTranslationX(outlineTranslation);
             mFakeShadow.setTranslationY(shadowYEnd - mFakeShadow.getHeight());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
index 915b565..1a9a40b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
@@ -43,9 +43,9 @@
     private static final int HINT_CIRCLE_OPEN_DURATION = 500;
 
     private final Context mContext;
+    private final Callback mCallback;
 
     private FlingAnimationUtils mFlingAnimationUtils;
-    private Callback mCallback;
     private VelocityTracker mVelocityTracker;
     private boolean mSwipingInProgress;
     private float mInitialTouchX;
@@ -318,12 +318,11 @@
         float vel = getCurrentVelocity(lastX, lastY);
 
         // We snap back if the current translation is not far enough
-        boolean snapBack;
-        if (mFalsingManager.isFalseTouch()) {
-            snapBack = mFalsingManager.isFalseTouch();
-        } else {
-            snapBack = isBelowFalsingThreshold();
+        boolean snapBack = false;
+        if (mCallback.needsAntiFalsing()) {
+            snapBack = snapBack || mFalsingManager.isFalseTouch();
         }
+        snapBack = snapBack || isBelowFalsingThreshold();
 
         // or if the velocity is in the opposite direction.
         boolean velIsInWrongDirection = vel * mTranslation < 0;
@@ -582,5 +581,7 @@
          * @return The factor the minimum swipe amount should be multiplied with.
          */
         float getAffordanceFalsingFactor();
+
+        boolean needsAntiFalsing();
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
index 92f3585..ef19d95 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.statusbar.phone;
 
+import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.IWallpaperManager;
 import android.app.IWallpaperManagerCallback;
@@ -26,8 +27,9 @@
 import android.graphics.BitmapFactory;
 import android.graphics.Rect;
 import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
 import android.graphics.drawable.DrawableWrapper;
-import android.os.Bundle;
+import android.os.AsyncTask;
 import android.os.Handler;
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
@@ -46,9 +48,7 @@
 
     private static final String TAG = "LockscreenWallpaper";
 
-    private final Context mContext;
     private final PhoneStatusBar mBar;
-    private final IWallpaperManager mService;
     private final WallpaperManager mWallpaperManager;
     private final Handler mH;
 
@@ -58,69 +58,75 @@
     // The user selected in the UI, or null if no user is selected or UI doesn't support selecting
     // users.
     private UserHandle mSelectedUser;
+    private AsyncTask<Void, Void, LoaderResult> mLoader;
 
     public LockscreenWallpaper(Context ctx, PhoneStatusBar bar, Handler h) {
-        mContext = ctx;
         mBar = bar;
         mH = h;
-        mService = IWallpaperManager.Stub.asInterface(
-                ServiceManager.getService(Context.WALLPAPER_SERVICE));
         mWallpaperManager = (WallpaperManager) ctx.getSystemService(Context.WALLPAPER_SERVICE);
         mCurrentUserId = ActivityManager.getCurrentUser();
 
+        IWallpaperManager service = IWallpaperManager.Stub.asInterface(
+                ServiceManager.getService(Context.WALLPAPER_SERVICE));
         try {
-            mService.setLockWallpaperCallback(this);
+            service.setLockWallpaperCallback(this);
         } catch (RemoteException e) {
             Log.e(TAG, "System dead?" + e);
         }
     }
 
     public Bitmap getBitmap() {
-        try {
-            if (mCached) {
-                return mCache;
-            }
-            if (!mService.isWallpaperSupported(mContext.getOpPackageName())) {
-                mCached = true;
-                mCache = null;
-                return null;
-            }
-            // Prefer the selected user (when specified) over the current user for the FLAG_SET_LOCK
-            // wallpaper.
-            final int lockWallpaperUserId =
-                    mSelectedUser != null ? mSelectedUser.getIdentifier() : mCurrentUserId;
-            ParcelFileDescriptor fd = mService.getWallpaper(null, WallpaperManager.FLAG_LOCK,
-                    new Bundle(), lockWallpaperUserId);
-            if (fd != null) {
-                try {
-                    BitmapFactory.Options options = new BitmapFactory.Options();
-                    mCache = BitmapFactory.decodeFileDescriptor(
-                            fd.getFileDescriptor(), null, options);
-                    mCached = true;
-                    return mCache;
-                } catch (OutOfMemoryError e) {
-                    Log.w(TAG, "Can't decode file", e);
-                    return null;
-                } finally {
-                    IoUtils.closeQuietly(fd);
-                }
-            } else {
-                mCached = true;
-                if (mSelectedUser != null && mSelectedUser.getIdentifier() != mCurrentUserId) {
-                    // When selected user is different from the current user, show the selected
-                    // user's static wallpaper.
-                    mCache = mWallpaperManager.getBitmapAsUser(mSelectedUser.getIdentifier());
-                } else {
-                    // When there is no selected user, or it's same as the current user, show the
-                    // system (possibly dynamic) wallpaper for the selected user.
-                    mCache = null;
-                }
-                return mCache;
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "System dead?" + e);
+        if (mCached) {
+            return mCache;
+        }
+        if (!mWallpaperManager.isWallpaperSupported()) {
+            mCached = true;
+            mCache = null;
             return null;
         }
+
+        LoaderResult result = loadBitmap(mCurrentUserId, mSelectedUser);
+        if (result.success) {
+            mCached = true;
+            mCache = result.bitmap;
+        }
+        return mCache;
+    }
+
+    public LoaderResult loadBitmap(int currentUserId, UserHandle selectedUser) {
+        // May be called on any thread - only use thread safe operations.
+
+        // Prefer the selected user (when specified) over the current user for the FLAG_SET_LOCK
+        // wallpaper.
+        final int lockWallpaperUserId =
+                selectedUser != null ? selectedUser.getIdentifier() : currentUserId;
+        ParcelFileDescriptor fd = mWallpaperManager.getWallpaperFile(
+                WallpaperManager.FLAG_LOCK, lockWallpaperUserId);
+
+        if (fd != null) {
+            try {
+                BitmapFactory.Options options = new BitmapFactory.Options();
+                return LoaderResult.success(BitmapFactory.decodeFileDescriptor(
+                        fd.getFileDescriptor(), null, options));
+            } catch (OutOfMemoryError e) {
+                Log.w(TAG, "Can't decode file", e);
+                return LoaderResult.fail();
+            } finally {
+                IoUtils.closeQuietly(fd);
+            }
+        } else {
+            if (selectedUser != null && selectedUser.getIdentifier() != currentUserId) {
+                // When selected user is different from the current user, show the selected
+                // user's static wallpaper.
+                return LoaderResult.success(
+                        mWallpaperManager.getBitmapAsUser(selectedUser.getIdentifier()));
+
+            } else {
+                // When there is no selected user, or it's same as the current user, show the
+                // system (possibly dynamic) wallpaper for the selected user.
+                return LoaderResult.success(null);
+            }
+        }
     }
 
     public void setCurrentUser(int user) {
@@ -135,14 +141,16 @@
             return;
         }
         mSelectedUser = selectedUser;
-
-        mH.removeCallbacks(this);
-        mH.post(this);
+        postUpdateWallpaper();
     }
 
     @Override
     public void onWallpaperChanged() {
         // Called on Binder thread.
+        postUpdateWallpaper();
+    }
+
+    private void postUpdateWallpaper() {
         mH.removeCallbacks(this);
         mH.post(this);
     }
@@ -150,10 +158,52 @@
     @Override
     public void run() {
         // Called in response to onWallpaperChanged on the main thread.
-        mCached = false;
-        mCache = null;
-        getBitmap();
-        mBar.updateMediaMetaData(true /* metaDataChanged */, true /* allowEnterAnimation */);
+
+        if (mLoader != null) {
+            mLoader.cancel(false /* interrupt */);
+        }
+
+        final int currentUser = mCurrentUserId;
+        final UserHandle selectedUser = mSelectedUser;
+        mLoader = new AsyncTask<Void, Void, LoaderResult>() {
+            @Override
+            protected LoaderResult doInBackground(Void... params) {
+                return loadBitmap(currentUser, selectedUser);
+            }
+
+            @Override
+            protected void onPostExecute(LoaderResult result) {
+                super.onPostExecute(result);
+                if (isCancelled()) {
+                    return;
+                }
+                if (result.success) {
+                    mCached = true;
+                    mCache = result.bitmap;
+                    mBar.updateMediaMetaData(
+                            true /* metaDataChanged */, true /* allowEnterAnimation */);
+                }
+                mLoader = null;
+            }
+        }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+    }
+
+    private static class LoaderResult {
+        public final boolean success;
+        public final Bitmap bitmap;
+
+        LoaderResult(boolean success, Bitmap bitmap) {
+            this.success = success;
+            this.bitmap = bitmap;
+        }
+
+        static LoaderResult success(Bitmap b) {
+            return new LoaderResult(true, b);
+        }
+
+        static LoaderResult fail() {
+            return new LoaderResult(false, null);
+        }
     }
 
     /**
@@ -161,12 +211,16 @@
      */
     public static class WallpaperDrawable extends DrawableWrapper {
 
-        private Bitmap mBackground;
-        private Rect mTmpRect = new Rect();
+        private final ConstantState mState;
+        private final Rect mTmpRect = new Rect();
 
         public WallpaperDrawable(Resources r, Bitmap b) {
-            super(new BitmapDrawable(r, b));
-            mBackground = b;
+            this(r, new ConstantState(b));
+        }
+
+        private WallpaperDrawable(Resources r, ConstantState state) {
+            super(new BitmapDrawable(r, state.mBackground));
+            mState = state;
         }
 
         @Override
@@ -183,8 +237,8 @@
         protected void onBoundsChange(Rect bounds) {
             int vwidth = getBounds().width();
             int vheight = getBounds().height();
-            int dwidth = mBackground.getWidth();
-            int dheight = mBackground.getHeight();
+            int dwidth = mState.mBackground.getWidth();
+            int dheight = mState.mBackground.getHeight();
             float scale;
             float dx = 0, dy = 0;
 
@@ -207,5 +261,35 @@
 
             super.onBoundsChange(mTmpRect);
         }
+
+        @Override
+        public ConstantState getConstantState() {
+            return mState;
+        }
+
+        static class ConstantState extends Drawable.ConstantState {
+
+            private final Bitmap mBackground;
+
+            ConstantState(Bitmap background) {
+                mBackground = background;
+            }
+
+            @Override
+            public Drawable newDrawable() {
+                return newDrawable(null);
+            }
+
+            @Override
+            public Drawable newDrawable(@Nullable Resources res) {
+                return new WallpaperDrawable(res, this);
+            }
+
+            @Override
+            public int getChangingConfigurations() {
+                // DrawableWrapper already handles this for us.
+                return 0;
+            }
+        }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 62c0fa9..48cf631 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -701,7 +701,7 @@
     }
 
     private boolean isFalseTouch() {
-        if (mStatusBarState != StatusBarState.KEYGUARD) {
+        if (!needsAntiFalsing()) {
             return false;
         }
         if (mFalsingManager.isClassiferEnabled()) {
@@ -1941,6 +1941,11 @@
     }
 
     @Override
+    public boolean needsAntiFalsing() {
+        return mStatusBarState == StatusBarState.KEYGUARD;
+    }
+
+    @Override
     protected float getPeekHeight() {
         if (mNotificationStackScroller.getNotGoneChildCount() > 0) {
             return mNotificationStackScroller.getPeekHeight();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index d3f3b2d..712f814 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -2021,7 +2021,8 @@
             if (metaDataChanged) {
                 if (mBackdropBack.getDrawable() != null) {
                     Drawable drawable =
-                            mBackdropBack.getDrawable().getConstantState().newDrawable().mutate();
+                            mBackdropBack.getDrawable().getConstantState()
+                                    .newDrawable(mBackdropFront.getResources()).mutate();
                     mBackdropFront.setImageDrawable(drawable);
                     if (mScrimSrcModeEnabled) {
                         mBackdropFront.getDrawable().mutate().setXfermode(mSrcOverXferMode);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
index 82496ac..493b23f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
@@ -209,7 +209,7 @@
         // already logged
     }
 
-    public void animateExpandQS() {
+    public void animateToggleQSExpansion() {
         // TODO: Better path to animated panel expansion.
         mHeader.performClick();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
index 2b03dfb..b8e069d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
@@ -106,6 +106,8 @@
         mDateTimeGroup = (ViewGroup) findViewById(R.id.date_time_group);
         mDateTimeGroup.setPivotX(0);
         mDateTimeGroup.setPivotY(0);
+        boolean showDate = getResources().getBoolean(R.bool.quick_settings_show_date);
+        findViewById(R.id.date).setVisibility(showDate ? View.VISIBLE : View.GONE);
 
         mExpandIndicator = (ExpandableIndicator) findViewById(R.id.expand_indicator);
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverController.java
index c4c64e7..e6e189f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverController.java
@@ -89,6 +89,10 @@
                 }
             });
         }
+
+        @Override
+        public void onRestrictBackgroundWhitelistChanged(int uid, boolean whitelisted) {
+        }
     };
 
     public interface Listener {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index 40eb71d..40dacd3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -791,7 +791,7 @@
 
     private SubscriptionInfo addSignalController(int id, int simSlotIndex) {
         SubscriptionInfo info = new SubscriptionInfo(id, "", simSlotIndex, "", "", 0, 0, "", 0,
-                null, 0, 0, "");
+                null, 0, 0, "", SubscriptionManager.SIM_PROVISIONED);
         mMobileSignalControllers.put(id, new MobileSignalController(mContext,
                 mConfig, mHasMobileDataFeature, mPhone, mCallbackHandler, this, info,
                 mSubDefaults, mReceiverHandler.getLooper()));
diff --git a/rs/java/android/renderscript/Element.java b/rs/java/android/renderscript/Element.java
index 50226ac..9d2f750 100644
--- a/rs/java/android/renderscript/Element.java
+++ b/rs/java/android/renderscript/Element.java
@@ -311,8 +311,12 @@
      * @return Element
      */
     public static Element BOOLEAN(RenderScript rs) {
-        if(rs.mElement_BOOLEAN == null) {
-            rs.mElement_BOOLEAN = createUser(rs, DataType.BOOLEAN);
+        if (rs.mElement_BOOLEAN == null) {
+            synchronized (rs) {
+                if (rs.mElement_BOOLEAN == null) {
+                    rs.mElement_BOOLEAN = createUser(rs, DataType.BOOLEAN);
+                }
+            }
         }
         return rs.mElement_BOOLEAN;
     }
@@ -325,8 +329,12 @@
      * @return Element
      */
     public static Element U8(RenderScript rs) {
-        if(rs.mElement_U8 == null) {
-            rs.mElement_U8 = createUser(rs, DataType.UNSIGNED_8);
+        if (rs.mElement_U8 == null) {
+            synchronized (rs) {
+                if (rs.mElement_U8 == null) {
+                    rs.mElement_U8 = createUser(rs, DataType.UNSIGNED_8);
+                }
+            }
         }
         return rs.mElement_U8;
     }
@@ -339,436 +347,683 @@
      * @return Element
      */
     public static Element I8(RenderScript rs) {
-        if(rs.mElement_I8 == null) {
-            rs.mElement_I8 = createUser(rs, DataType.SIGNED_8);
+        if (rs.mElement_I8 == null) {
+            synchronized (rs) {
+                if (rs.mElement_I8 == null) {
+                    rs.mElement_I8 = createUser(rs, DataType.SIGNED_8);
+                }
+            }
         }
         return rs.mElement_I8;
     }
 
     public static Element U16(RenderScript rs) {
-        if(rs.mElement_U16 == null) {
-            rs.mElement_U16 = createUser(rs, DataType.UNSIGNED_16);
+        if (rs.mElement_U16 == null) {
+            synchronized (rs) {
+                if (rs.mElement_U16 == null) {
+                    rs.mElement_U16 = createUser(rs, DataType.UNSIGNED_16);
+                }
+            }
         }
         return rs.mElement_U16;
     }
 
     public static Element I16(RenderScript rs) {
-        if(rs.mElement_I16 == null) {
-            rs.mElement_I16 = createUser(rs, DataType.SIGNED_16);
+        if (rs.mElement_I16 == null) {
+            synchronized (rs) {
+                if (rs.mElement_I16 == null) {
+                    rs.mElement_I16 = createUser(rs, DataType.SIGNED_16);
+                }
+            }
         }
         return rs.mElement_I16;
     }
 
     public static Element U32(RenderScript rs) {
-        if(rs.mElement_U32 == null) {
-            rs.mElement_U32 = createUser(rs, DataType.UNSIGNED_32);
+        if (rs.mElement_U32 == null) {
+            synchronized (rs) {
+                if (rs.mElement_U32 == null) {
+                    rs.mElement_U32 = createUser(rs, DataType.UNSIGNED_32);
+                }
+            }
         }
         return rs.mElement_U32;
     }
 
     public static Element I32(RenderScript rs) {
-        if(rs.mElement_I32 == null) {
-            rs.mElement_I32 = createUser(rs, DataType.SIGNED_32);
+        if (rs.mElement_I32 == null) {
+            synchronized (rs) {
+                if (rs.mElement_I32 == null) {
+                    rs.mElement_I32 = createUser(rs, DataType.SIGNED_32);
+                }
+            }
         }
         return rs.mElement_I32;
     }
 
     public static Element U64(RenderScript rs) {
-        if(rs.mElement_U64 == null) {
-            rs.mElement_U64 = createUser(rs, DataType.UNSIGNED_64);
+        if (rs.mElement_U64 == null) {
+            synchronized (rs) {
+                if (rs.mElement_U64 == null) {
+                    rs.mElement_U64 = createUser(rs, DataType.UNSIGNED_64);
+                }
+            }
         }
         return rs.mElement_U64;
     }
 
     public static Element I64(RenderScript rs) {
-        if(rs.mElement_I64 == null) {
-            rs.mElement_I64 = createUser(rs, DataType.SIGNED_64);
+        if (rs.mElement_I64 == null) {
+            synchronized (rs) {
+                if (rs.mElement_I64 == null) {
+                    rs.mElement_I64 = createUser(rs, DataType.SIGNED_64);
+                }
+            }
         }
         return rs.mElement_I64;
     }
 
     public static Element F16(RenderScript rs) {
-        if(rs.mElement_F16 == null) {
-            rs.mElement_F16 = createUser(rs, DataType.FLOAT_16);
+        if (rs.mElement_F16 == null) {
+            synchronized (rs) {
+                if (rs.mElement_F16 == null) {
+                    rs.mElement_F16 = createUser(rs, DataType.FLOAT_16);
+                }
+            }
         }
         return rs.mElement_F16;
     }
 
     public static Element F32(RenderScript rs) {
-        if(rs.mElement_F32 == null) {
-            rs.mElement_F32 = createUser(rs, DataType.FLOAT_32);
+        if (rs.mElement_F32 == null) {
+            synchronized (rs) {
+                if (rs.mElement_F32 == null) {
+                    rs.mElement_F32 = createUser(rs, DataType.FLOAT_32);
+                }
+            }
         }
         return rs.mElement_F32;
     }
 
     public static Element F64(RenderScript rs) {
-        if(rs.mElement_F64 == null) {
-            rs.mElement_F64 = createUser(rs, DataType.FLOAT_64);
+        if (rs.mElement_F64 == null) {
+            synchronized (rs) {
+                if (rs.mElement_F64 == null) {
+                    rs.mElement_F64 = createUser(rs, DataType.FLOAT_64);
+                }
+            }
         }
         return rs.mElement_F64;
     }
 
     public static Element ELEMENT(RenderScript rs) {
-        if(rs.mElement_ELEMENT == null) {
-            rs.mElement_ELEMENT = createUser(rs, DataType.RS_ELEMENT);
+        if (rs.mElement_ELEMENT == null) {
+            synchronized (rs) {
+                if (rs.mElement_ELEMENT == null) {
+                    rs.mElement_ELEMENT = createUser(rs, DataType.RS_ELEMENT);
+                }
+            }
         }
         return rs.mElement_ELEMENT;
     }
 
     public static Element TYPE(RenderScript rs) {
-        if(rs.mElement_TYPE == null) {
-            rs.mElement_TYPE = createUser(rs, DataType.RS_TYPE);
+        if (rs.mElement_TYPE == null) {
+            synchronized (rs) {
+                if (rs.mElement_TYPE == null) {
+                    rs.mElement_TYPE = createUser(rs, DataType.RS_TYPE);
+                }
+            }
         }
         return rs.mElement_TYPE;
     }
 
     public static Element ALLOCATION(RenderScript rs) {
-        if(rs.mElement_ALLOCATION == null) {
-            rs.mElement_ALLOCATION = createUser(rs, DataType.RS_ALLOCATION);
+        if (rs.mElement_ALLOCATION == null) {
+            synchronized (rs) {
+                if (rs.mElement_ALLOCATION == null) {
+                    rs.mElement_ALLOCATION = createUser(rs, DataType.RS_ALLOCATION);
+                }
+            }
         }
         return rs.mElement_ALLOCATION;
     }
 
     public static Element SAMPLER(RenderScript rs) {
-        if(rs.mElement_SAMPLER == null) {
-            rs.mElement_SAMPLER = createUser(rs, DataType.RS_SAMPLER);
+        if (rs.mElement_SAMPLER == null) {
+            synchronized (rs) {
+                if (rs.mElement_SAMPLER == null) {
+                    rs.mElement_SAMPLER = createUser(rs, DataType.RS_SAMPLER);
+                }
+            }
         }
         return rs.mElement_SAMPLER;
     }
 
     public static Element SCRIPT(RenderScript rs) {
-        if(rs.mElement_SCRIPT == null) {
-            rs.mElement_SCRIPT = createUser(rs, DataType.RS_SCRIPT);
+        if (rs.mElement_SCRIPT == null) {
+            synchronized (rs) {
+                if (rs.mElement_SCRIPT == null) {
+                    rs.mElement_SCRIPT = createUser(rs, DataType.RS_SCRIPT);
+                }
+            }
         }
         return rs.mElement_SCRIPT;
     }
 
     public static Element MESH(RenderScript rs) {
-        if(rs.mElement_MESH == null) {
-            rs.mElement_MESH = createUser(rs, DataType.RS_MESH);
+        if (rs.mElement_MESH == null) {
+            synchronized (rs) {
+                if (rs.mElement_MESH == null) {
+                    rs.mElement_MESH = createUser(rs, DataType.RS_MESH);
+                }
+            }
         }
         return rs.mElement_MESH;
     }
 
     public static Element PROGRAM_FRAGMENT(RenderScript rs) {
-        if(rs.mElement_PROGRAM_FRAGMENT == null) {
-            rs.mElement_PROGRAM_FRAGMENT = createUser(rs, DataType.RS_PROGRAM_FRAGMENT);
+        if (rs.mElement_PROGRAM_FRAGMENT == null) {
+            synchronized (rs) {
+                if (rs.mElement_PROGRAM_FRAGMENT == null) {
+                    rs.mElement_PROGRAM_FRAGMENT = createUser(rs, DataType.RS_PROGRAM_FRAGMENT);
+                }
+            }
         }
         return rs.mElement_PROGRAM_FRAGMENT;
     }
 
     public static Element PROGRAM_VERTEX(RenderScript rs) {
-        if(rs.mElement_PROGRAM_VERTEX == null) {
-            rs.mElement_PROGRAM_VERTEX = createUser(rs, DataType.RS_PROGRAM_VERTEX);
+        if (rs.mElement_PROGRAM_VERTEX == null) {
+            synchronized (rs) {
+                if (rs.mElement_PROGRAM_VERTEX == null) {
+                    rs.mElement_PROGRAM_VERTEX = createUser(rs, DataType.RS_PROGRAM_VERTEX);
+                }
+            }
         }
         return rs.mElement_PROGRAM_VERTEX;
     }
 
     public static Element PROGRAM_RASTER(RenderScript rs) {
-        if(rs.mElement_PROGRAM_RASTER == null) {
-            rs.mElement_PROGRAM_RASTER = createUser(rs, DataType.RS_PROGRAM_RASTER);
+        if (rs.mElement_PROGRAM_RASTER == null) {
+            synchronized (rs) {
+                if (rs.mElement_PROGRAM_RASTER == null) {
+                    rs.mElement_PROGRAM_RASTER = createUser(rs, DataType.RS_PROGRAM_RASTER);
+                }
+            }
         }
         return rs.mElement_PROGRAM_RASTER;
     }
 
     public static Element PROGRAM_STORE(RenderScript rs) {
-        if(rs.mElement_PROGRAM_STORE == null) {
-            rs.mElement_PROGRAM_STORE = createUser(rs, DataType.RS_PROGRAM_STORE);
+        if (rs.mElement_PROGRAM_STORE == null) {
+            synchronized (rs) {
+                if (rs.mElement_PROGRAM_STORE == null) {
+                    rs.mElement_PROGRAM_STORE = createUser(rs, DataType.RS_PROGRAM_STORE);
+                }
+            }
         }
         return rs.mElement_PROGRAM_STORE;
     }
 
     public static Element FONT(RenderScript rs) {
-        if(rs.mElement_FONT == null) {
-            rs.mElement_FONT = createUser(rs, DataType.RS_FONT);
+        if (rs.mElement_FONT == null) {
+            synchronized (rs) {
+                if (rs.mElement_FONT == null) {
+                    rs.mElement_FONT = createUser(rs, DataType.RS_FONT);
+                }
+            }
         }
         return rs.mElement_FONT;
     }
 
-
     public static Element A_8(RenderScript rs) {
-        if(rs.mElement_A_8 == null) {
-            rs.mElement_A_8 = createPixel(rs, DataType.UNSIGNED_8, DataKind.PIXEL_A);
+        if (rs.mElement_A_8 == null) {
+            synchronized (rs) {
+                if (rs.mElement_A_8 == null) {
+                    rs.mElement_A_8 = createPixel(rs, DataType.UNSIGNED_8, DataKind.PIXEL_A);
+                }
+            }
         }
         return rs.mElement_A_8;
     }
 
     public static Element RGB_565(RenderScript rs) {
-        if(rs.mElement_RGB_565 == null) {
-            rs.mElement_RGB_565 = createPixel(rs, DataType.UNSIGNED_5_6_5, DataKind.PIXEL_RGB);
+        if (rs.mElement_RGB_565 == null) {
+            synchronized (rs) {
+                if (rs.mElement_RGB_565 == null) {
+                    rs.mElement_RGB_565 = createPixel(rs, DataType.UNSIGNED_5_6_5, DataKind.PIXEL_RGB);
+                }
+            }
         }
         return rs.mElement_RGB_565;
     }
 
     public static Element RGB_888(RenderScript rs) {
-        if(rs.mElement_RGB_888 == null) {
-            rs.mElement_RGB_888 = createPixel(rs, DataType.UNSIGNED_8, DataKind.PIXEL_RGB);
+        if (rs.mElement_RGB_888 == null) {
+            synchronized (rs) {
+                if (rs.mElement_RGB_888 == null) {
+                    rs.mElement_RGB_888 = createPixel(rs, DataType.UNSIGNED_8, DataKind.PIXEL_RGB);
+                }
+            }
         }
         return rs.mElement_RGB_888;
     }
 
     public static Element RGBA_5551(RenderScript rs) {
-        if(rs.mElement_RGBA_5551 == null) {
-            rs.mElement_RGBA_5551 = createPixel(rs, DataType.UNSIGNED_5_5_5_1, DataKind.PIXEL_RGBA);
+        if (rs.mElement_RGBA_5551 == null) {
+            synchronized (rs) {
+                if (rs.mElement_RGBA_5551 == null) {
+                    rs.mElement_RGBA_5551 = createPixel(rs, DataType.UNSIGNED_5_5_5_1, DataKind.PIXEL_RGBA);
+                }
+            }
         }
         return rs.mElement_RGBA_5551;
     }
 
     public static Element RGBA_4444(RenderScript rs) {
-        if(rs.mElement_RGBA_4444 == null) {
-            rs.mElement_RGBA_4444 = createPixel(rs, DataType.UNSIGNED_4_4_4_4, DataKind.PIXEL_RGBA);
+        if (rs.mElement_RGBA_4444 == null) {
+            synchronized (rs) {
+                if (rs.mElement_RGBA_4444 == null) {
+                    rs.mElement_RGBA_4444 = createPixel(rs, DataType.UNSIGNED_4_4_4_4, DataKind.PIXEL_RGBA);
+                }
+            }
         }
         return rs.mElement_RGBA_4444;
     }
 
     public static Element RGBA_8888(RenderScript rs) {
-        if(rs.mElement_RGBA_8888 == null) {
-            rs.mElement_RGBA_8888 = createPixel(rs, DataType.UNSIGNED_8, DataKind.PIXEL_RGBA);
+        if (rs.mElement_RGBA_8888 == null) {
+            synchronized (rs) {
+                if (rs.mElement_RGBA_8888 == null) {
+                    rs.mElement_RGBA_8888 = createPixel(rs, DataType.UNSIGNED_8, DataKind.PIXEL_RGBA);
+                }
+            }
         }
         return rs.mElement_RGBA_8888;
     }
 
     public static Element F16_2(RenderScript rs) {
-        if(rs.mElement_HALF_2 == null) {
-            rs.mElement_HALF_2 = createVector(rs, DataType.FLOAT_16, 2);
+        if (rs.mElement_HALF_2 == null) {
+            synchronized (rs) {
+                if (rs.mElement_HALF_2 == null) {
+                    rs.mElement_HALF_2 = createVector(rs, DataType.FLOAT_16, 2);
+                }
+            }
         }
         return rs.mElement_HALF_2;
     }
 
     public static Element F16_3(RenderScript rs) {
-        if(rs.mElement_HALF_3 == null) {
-            rs.mElement_HALF_3 = createVector(rs, DataType.FLOAT_16, 3);
+        if (rs.mElement_HALF_3 == null) {
+            synchronized (rs) {
+                if (rs.mElement_HALF_3 == null) {
+                    rs.mElement_HALF_3 = createVector(rs, DataType.FLOAT_16, 3);
+                }
+            }
         }
         return rs.mElement_HALF_3;
     }
 
     public static Element F16_4(RenderScript rs) {
-        if(rs.mElement_HALF_4 == null) {
-            rs.mElement_HALF_4 = createVector(rs, DataType.FLOAT_16, 4);
+        if (rs.mElement_HALF_4 == null) {
+            synchronized (rs) {
+                if (rs.mElement_HALF_4 == null) {
+                    rs.mElement_HALF_4 = createVector(rs, DataType.FLOAT_16, 4);
+                }
+            }
         }
         return rs.mElement_HALF_4;
     }
 
     public static Element F32_2(RenderScript rs) {
-        if(rs.mElement_FLOAT_2 == null) {
-            rs.mElement_FLOAT_2 = createVector(rs, DataType.FLOAT_32, 2);
+        if (rs.mElement_FLOAT_2 == null) {
+            synchronized (rs) {
+                if (rs.mElement_FLOAT_2 == null) {
+                    rs.mElement_FLOAT_2 = createVector(rs, DataType.FLOAT_32, 2);
+                }
+            }
         }
         return rs.mElement_FLOAT_2;
     }
 
     public static Element F32_3(RenderScript rs) {
-        if(rs.mElement_FLOAT_3 == null) {
-            rs.mElement_FLOAT_3 = createVector(rs, DataType.FLOAT_32, 3);
+        if (rs.mElement_FLOAT_3 == null) {
+            synchronized (rs) {
+                if (rs.mElement_FLOAT_3 == null) {
+                    rs.mElement_FLOAT_3 = createVector(rs, DataType.FLOAT_32, 3);
+                }
+            }
         }
         return rs.mElement_FLOAT_3;
     }
 
     public static Element F32_4(RenderScript rs) {
-        if(rs.mElement_FLOAT_4 == null) {
-            rs.mElement_FLOAT_4 = createVector(rs, DataType.FLOAT_32, 4);
+        if (rs.mElement_FLOAT_4 == null) {
+            synchronized (rs) {
+                if (rs.mElement_FLOAT_4 == null) {
+                    rs.mElement_FLOAT_4 = createVector(rs, DataType.FLOAT_32, 4);
+                }
+            }
         }
         return rs.mElement_FLOAT_4;
     }
 
     public static Element F64_2(RenderScript rs) {
-        if(rs.mElement_DOUBLE_2 == null) {
-            rs.mElement_DOUBLE_2 = createVector(rs, DataType.FLOAT_64, 2);
+        if (rs.mElement_DOUBLE_2 == null) {
+            synchronized (rs) {
+                if (rs.mElement_DOUBLE_2 == null) {
+                    rs.mElement_DOUBLE_2 = createVector(rs, DataType.FLOAT_64, 2);
+                }
+            }
         }
         return rs.mElement_DOUBLE_2;
     }
 
     public static Element F64_3(RenderScript rs) {
-        if(rs.mElement_DOUBLE_3 == null) {
-            rs.mElement_DOUBLE_3 = createVector(rs, DataType.FLOAT_64, 3);
+        if (rs.mElement_DOUBLE_3 == null) {
+            synchronized (rs) {
+                if (rs.mElement_DOUBLE_3 == null) {
+                    rs.mElement_DOUBLE_3 = createVector(rs, DataType.FLOAT_64, 3);
+                }
+            }
         }
         return rs.mElement_DOUBLE_3;
     }
 
     public static Element F64_4(RenderScript rs) {
-        if(rs.mElement_DOUBLE_4 == null) {
-            rs.mElement_DOUBLE_4 = createVector(rs, DataType.FLOAT_64, 4);
+        if (rs.mElement_DOUBLE_4 == null) {
+            synchronized (rs) {
+                if (rs.mElement_DOUBLE_4 == null) {
+                    rs.mElement_DOUBLE_4 = createVector(rs, DataType.FLOAT_64, 4);
+                }
+            }
         }
         return rs.mElement_DOUBLE_4;
     }
 
     public static Element U8_2(RenderScript rs) {
-        if(rs.mElement_UCHAR_2 == null) {
-            rs.mElement_UCHAR_2 = createVector(rs, DataType.UNSIGNED_8, 2);
+        if (rs.mElement_UCHAR_2 == null) {
+            synchronized (rs) {
+                if (rs.mElement_UCHAR_2 == null) {
+                    rs.mElement_UCHAR_2 = createVector(rs, DataType.UNSIGNED_8, 2);
+                }
+            }
         }
         return rs.mElement_UCHAR_2;
     }
 
     public static Element U8_3(RenderScript rs) {
-        if(rs.mElement_UCHAR_3 == null) {
-            rs.mElement_UCHAR_3 = createVector(rs, DataType.UNSIGNED_8, 3);
+        if (rs.mElement_UCHAR_3 == null) {
+            synchronized (rs) {
+                if (rs.mElement_UCHAR_3 == null) {
+                    rs.mElement_UCHAR_3 = createVector(rs, DataType.UNSIGNED_8, 3);
+                }
+            }
         }
         return rs.mElement_UCHAR_3;
     }
 
     public static Element U8_4(RenderScript rs) {
-        if(rs.mElement_UCHAR_4 == null) {
-            rs.mElement_UCHAR_4 = createVector(rs, DataType.UNSIGNED_8, 4);
+        if (rs.mElement_UCHAR_4 == null) {
+            synchronized (rs) {
+                if (rs.mElement_UCHAR_4 == null) {
+                    rs.mElement_UCHAR_4 = createVector(rs, DataType.UNSIGNED_8, 4);
+                }
+            }
         }
         return rs.mElement_UCHAR_4;
     }
 
     public static Element I8_2(RenderScript rs) {
-        if(rs.mElement_CHAR_2 == null) {
-            rs.mElement_CHAR_2 = createVector(rs, DataType.SIGNED_8, 2);
+        if (rs.mElement_CHAR_2 == null) {
+            synchronized (rs) {
+                if (rs.mElement_CHAR_2 == null) {
+                    rs.mElement_CHAR_2 = createVector(rs, DataType.SIGNED_8, 2);
+                }
+            }
         }
         return rs.mElement_CHAR_2;
     }
 
     public static Element I8_3(RenderScript rs) {
-        if(rs.mElement_CHAR_3 == null) {
-            rs.mElement_CHAR_3 = createVector(rs, DataType.SIGNED_8, 3);
+        if (rs.mElement_CHAR_3 == null) {
+            synchronized (rs) {
+                if (rs.mElement_CHAR_3 == null) {
+                    rs.mElement_CHAR_3 = createVector(rs, DataType.SIGNED_8, 3);
+                }
+            }
         }
         return rs.mElement_CHAR_3;
     }
 
     public static Element I8_4(RenderScript rs) {
-        if(rs.mElement_CHAR_4 == null) {
-            rs.mElement_CHAR_4 = createVector(rs, DataType.SIGNED_8, 4);
+        if (rs.mElement_CHAR_4 == null) {
+            synchronized (rs) {
+                if (rs.mElement_CHAR_4 == null) {
+                    rs.mElement_CHAR_4 = createVector(rs, DataType.SIGNED_8, 4);
+                }
+            }
         }
         return rs.mElement_CHAR_4;
     }
 
     public static Element U16_2(RenderScript rs) {
-        if(rs.mElement_USHORT_2 == null) {
-            rs.mElement_USHORT_2 = createVector(rs, DataType.UNSIGNED_16, 2);
+        if (rs.mElement_USHORT_2 == null) {
+            synchronized (rs) {
+                if (rs.mElement_USHORT_2 == null) {
+                    rs.mElement_USHORT_2 = createVector(rs, DataType.UNSIGNED_16, 2);
+                }
+            }
         }
         return rs.mElement_USHORT_2;
     }
 
     public static Element U16_3(RenderScript rs) {
-        if(rs.mElement_USHORT_3 == null) {
-            rs.mElement_USHORT_3 = createVector(rs, DataType.UNSIGNED_16, 3);
+        if (rs.mElement_USHORT_3 == null) {
+            synchronized (rs) {
+                if (rs.mElement_USHORT_3 == null) {
+                    rs.mElement_USHORT_3 = createVector(rs, DataType.UNSIGNED_16, 3);
+                }
+            }
         }
         return rs.mElement_USHORT_3;
     }
 
     public static Element U16_4(RenderScript rs) {
-        if(rs.mElement_USHORT_4 == null) {
-            rs.mElement_USHORT_4 = createVector(rs, DataType.UNSIGNED_16, 4);
+        if (rs.mElement_USHORT_4 == null) {
+            synchronized (rs) {
+                if (rs.mElement_USHORT_4 == null) {
+                    rs.mElement_USHORT_4 = createVector(rs, DataType.UNSIGNED_16, 4);
+                }
+            }
         }
         return rs.mElement_USHORT_4;
     }
 
     public static Element I16_2(RenderScript rs) {
-        if(rs.mElement_SHORT_2 == null) {
-            rs.mElement_SHORT_2 = createVector(rs, DataType.SIGNED_16, 2);
+        if (rs.mElement_SHORT_2 == null) {
+            synchronized (rs) {
+                if (rs.mElement_SHORT_2 == null) {
+                    rs.mElement_SHORT_2 = createVector(rs, DataType.SIGNED_16, 2);
+                }
+            }
         }
         return rs.mElement_SHORT_2;
     }
 
     public static Element I16_3(RenderScript rs) {
-        if(rs.mElement_SHORT_3 == null) {
-            rs.mElement_SHORT_3 = createVector(rs, DataType.SIGNED_16, 3);
+        if (rs.mElement_SHORT_3 == null) {
+            synchronized (rs) {
+                if (rs.mElement_SHORT_3 == null) {
+                    rs.mElement_SHORT_3 = createVector(rs, DataType.SIGNED_16, 3);
+                }
+            }
         }
         return rs.mElement_SHORT_3;
     }
 
     public static Element I16_4(RenderScript rs) {
-        if(rs.mElement_SHORT_4 == null) {
-            rs.mElement_SHORT_4 = createVector(rs, DataType.SIGNED_16, 4);
+        if (rs.mElement_SHORT_4 == null) {
+            synchronized (rs) {
+                if (rs.mElement_SHORT_4 == null) {
+                    rs.mElement_SHORT_4 = createVector(rs, DataType.SIGNED_16, 4);
+                }
+            }
         }
         return rs.mElement_SHORT_4;
     }
 
     public static Element U32_2(RenderScript rs) {
-        if(rs.mElement_UINT_2 == null) {
-            rs.mElement_UINT_2 = createVector(rs, DataType.UNSIGNED_32, 2);
+        if (rs.mElement_UINT_2 == null) {
+            synchronized (rs) {
+                if (rs.mElement_UINT_2 == null) {
+                    rs.mElement_UINT_2 = createVector(rs, DataType.UNSIGNED_32, 2);
+                }
+            }
         }
         return rs.mElement_UINT_2;
     }
 
     public static Element U32_3(RenderScript rs) {
-        if(rs.mElement_UINT_3 == null) {
-            rs.mElement_UINT_3 = createVector(rs, DataType.UNSIGNED_32, 3);
+        if (rs.mElement_UINT_3 == null) {
+            synchronized (rs) {
+                if (rs.mElement_UINT_3 == null) {
+                    rs.mElement_UINT_3 = createVector(rs, DataType.UNSIGNED_32, 3);
+                }
+            }
         }
         return rs.mElement_UINT_3;
     }
 
     public static Element U32_4(RenderScript rs) {
-        if(rs.mElement_UINT_4 == null) {
-            rs.mElement_UINT_4 = createVector(rs, DataType.UNSIGNED_32, 4);
+        if (rs.mElement_UINT_4 == null) {
+            synchronized (rs) {
+                if (rs.mElement_UINT_4 == null) {
+                    rs.mElement_UINT_4 = createVector(rs, DataType.UNSIGNED_32, 4);
+                }
+            }
         }
         return rs.mElement_UINT_4;
     }
 
     public static Element I32_2(RenderScript rs) {
-        if(rs.mElement_INT_2 == null) {
-            rs.mElement_INT_2 = createVector(rs, DataType.SIGNED_32, 2);
+        if (rs.mElement_INT_2 == null) {
+            synchronized (rs) {
+                if (rs.mElement_INT_2 == null) {
+                    rs.mElement_INT_2 = createVector(rs, DataType.SIGNED_32, 2);
+                }
+            }
         }
         return rs.mElement_INT_2;
     }
 
     public static Element I32_3(RenderScript rs) {
-        if(rs.mElement_INT_3 == null) {
-            rs.mElement_INT_3 = createVector(rs, DataType.SIGNED_32, 3);
+        if (rs.mElement_INT_3 == null) {
+            synchronized (rs) {
+                if (rs.mElement_INT_3 == null) {
+                    rs.mElement_INT_3 = createVector(rs, DataType.SIGNED_32, 3);
+                }
+            }
         }
         return rs.mElement_INT_3;
     }
 
     public static Element I32_4(RenderScript rs) {
-        if(rs.mElement_INT_4 == null) {
-            rs.mElement_INT_4 = createVector(rs, DataType.SIGNED_32, 4);
+        if (rs.mElement_INT_4 == null) {
+            synchronized (rs) {
+                if (rs.mElement_INT_4 == null) {
+                    rs.mElement_INT_4 = createVector(rs, DataType.SIGNED_32, 4);
+                }
+            }
         }
         return rs.mElement_INT_4;
     }
 
     public static Element U64_2(RenderScript rs) {
-        if(rs.mElement_ULONG_2 == null) {
-            rs.mElement_ULONG_2 = createVector(rs, DataType.UNSIGNED_64, 2);
+        if (rs.mElement_ULONG_2 == null) {
+            synchronized (rs) {
+                if (rs.mElement_ULONG_2 == null) {
+                    rs.mElement_ULONG_2 = createVector(rs, DataType.UNSIGNED_64, 2);
+                }
+            }
         }
         return rs.mElement_ULONG_2;
     }
 
     public static Element U64_3(RenderScript rs) {
-        if(rs.mElement_ULONG_3 == null) {
-            rs.mElement_ULONG_3 = createVector(rs, DataType.UNSIGNED_64, 3);
+        if (rs.mElement_ULONG_3 == null) {
+            synchronized (rs) {
+                if (rs.mElement_ULONG_3 == null) {
+                    rs.mElement_ULONG_3 = createVector(rs, DataType.UNSIGNED_64, 3);
+                }
+            }
         }
         return rs.mElement_ULONG_3;
     }
 
     public static Element U64_4(RenderScript rs) {
-        if(rs.mElement_ULONG_4 == null) {
-            rs.mElement_ULONG_4 = createVector(rs, DataType.UNSIGNED_64, 4);
+        if (rs.mElement_ULONG_4 == null) {
+            synchronized (rs) {
+                if (rs.mElement_ULONG_4 == null) {
+                    rs.mElement_ULONG_4 = createVector(rs, DataType.UNSIGNED_64, 4);
+                }
+            }
         }
         return rs.mElement_ULONG_4;
     }
 
     public static Element I64_2(RenderScript rs) {
-        if(rs.mElement_LONG_2 == null) {
-            rs.mElement_LONG_2 = createVector(rs, DataType.SIGNED_64, 2);
+        if (rs.mElement_LONG_2 == null) {
+            synchronized (rs) {
+                if (rs.mElement_LONG_2 == null) {
+                    rs.mElement_LONG_2 = createVector(rs, DataType.SIGNED_64, 2);
+                }
+            }
         }
         return rs.mElement_LONG_2;
     }
 
     public static Element I64_3(RenderScript rs) {
-        if(rs.mElement_LONG_3 == null) {
-            rs.mElement_LONG_3 = createVector(rs, DataType.SIGNED_64, 3);
+        if (rs.mElement_LONG_3 == null) {
+            synchronized (rs) {
+                if (rs.mElement_LONG_3 == null) {
+                    rs.mElement_LONG_3 = createVector(rs, DataType.SIGNED_64, 3);
+                }
+            }
         }
         return rs.mElement_LONG_3;
     }
 
     public static Element I64_4(RenderScript rs) {
-        if(rs.mElement_LONG_4 == null) {
-            rs.mElement_LONG_4 = createVector(rs, DataType.SIGNED_64, 4);
+        if (rs.mElement_LONG_4 == null) {
+            synchronized (rs) {
+                if (rs.mElement_LONG_4 == null) {
+                    rs.mElement_LONG_4 = createVector(rs, DataType.SIGNED_64, 4);
+                }
+            }
         }
         return rs.mElement_LONG_4;
     }
 
     public static Element YUV(RenderScript rs) {
         if (rs.mElement_YUV == null) {
-            rs.mElement_YUV = createPixel(rs, DataType.UNSIGNED_8, DataKind.PIXEL_YUV);
+            synchronized (rs) {
+                if (rs.mElement_YUV == null) {
+                    rs.mElement_YUV = createPixel(rs, DataType.UNSIGNED_8, DataKind.PIXEL_YUV);
+                }
+            }
         }
         return rs.mElement_YUV;
     }
 
     public static Element MATRIX_4X4(RenderScript rs) {
-        if(rs.mElement_MATRIX_4X4 == null) {
-            rs.mElement_MATRIX_4X4 = createUser(rs, DataType.MATRIX_4X4);
+        if (rs.mElement_MATRIX_4X4 == null) {
+            synchronized (rs) {
+                if (rs.mElement_MATRIX_4X4 == null) {
+                    rs.mElement_MATRIX_4X4 = createUser(rs, DataType.MATRIX_4X4);
+                }
+            }
         }
         return rs.mElement_MATRIX_4X4;
     }
@@ -780,15 +1035,23 @@
     }
 
     public static Element MATRIX_3X3(RenderScript rs) {
-        if(rs.mElement_MATRIX_3X3 == null) {
-            rs.mElement_MATRIX_3X3 = createUser(rs, DataType.MATRIX_3X3);
+        if (rs.mElement_MATRIX_3X3 == null) {
+            synchronized (rs) {
+                if (rs.mElement_MATRIX_3X3 == null) {
+                    rs.mElement_MATRIX_3X3 = createUser(rs, DataType.MATRIX_3X3);
+                }
+            }
         }
         return rs.mElement_MATRIX_3X3;
     }
 
     public static Element MATRIX_2X2(RenderScript rs) {
-        if(rs.mElement_MATRIX_2X2 == null) {
-            rs.mElement_MATRIX_2X2 = createUser(rs, DataType.MATRIX_2X2);
+        if (rs.mElement_MATRIX_2X2 == null) {
+            synchronized (rs) {
+                if (rs.mElement_MATRIX_2X2 == null) {
+                    rs.mElement_MATRIX_2X2 = createUser(rs, DataType.MATRIX_2X2);
+                }
+            }
         }
         return rs.mElement_MATRIX_2X2;
     }
diff --git a/rs/java/android/renderscript/RenderScript.java b/rs/java/android/renderscript/RenderScript.java
index 2650e5a..3d1370a 100644
--- a/rs/java/android/renderscript/RenderScript.java
+++ b/rs/java/android/renderscript/RenderScript.java
@@ -1037,97 +1037,97 @@
     @SuppressWarnings({"FieldCanBeLocal"})
     MessageThread mMessageThread;
 
-    Element mElement_U8;
-    Element mElement_I8;
-    Element mElement_U16;
-    Element mElement_I16;
-    Element mElement_U32;
-    Element mElement_I32;
-    Element mElement_U64;
-    Element mElement_I64;
-    Element mElement_F16;
-    Element mElement_F32;
-    Element mElement_F64;
-    Element mElement_BOOLEAN;
+    volatile Element mElement_U8;
+    volatile Element mElement_I8;
+    volatile Element mElement_U16;
+    volatile Element mElement_I16;
+    volatile Element mElement_U32;
+    volatile Element mElement_I32;
+    volatile Element mElement_U64;
+    volatile Element mElement_I64;
+    volatile Element mElement_F16;
+    volatile Element mElement_F32;
+    volatile Element mElement_F64;
+    volatile Element mElement_BOOLEAN;
 
-    Element mElement_ELEMENT;
-    Element mElement_TYPE;
-    Element mElement_ALLOCATION;
-    Element mElement_SAMPLER;
-    Element mElement_SCRIPT;
-    Element mElement_MESH;
-    Element mElement_PROGRAM_FRAGMENT;
-    Element mElement_PROGRAM_VERTEX;
-    Element mElement_PROGRAM_RASTER;
-    Element mElement_PROGRAM_STORE;
-    Element mElement_FONT;
+    volatile Element mElement_ELEMENT;
+    volatile Element mElement_TYPE;
+    volatile Element mElement_ALLOCATION;
+    volatile Element mElement_SAMPLER;
+    volatile Element mElement_SCRIPT;
+    volatile Element mElement_MESH;
+    volatile Element mElement_PROGRAM_FRAGMENT;
+    volatile Element mElement_PROGRAM_VERTEX;
+    volatile Element mElement_PROGRAM_RASTER;
+    volatile Element mElement_PROGRAM_STORE;
+    volatile Element mElement_FONT;
 
-    Element mElement_A_8;
-    Element mElement_RGB_565;
-    Element mElement_RGB_888;
-    Element mElement_RGBA_5551;
-    Element mElement_RGBA_4444;
-    Element mElement_RGBA_8888;
+    volatile Element mElement_A_8;
+    volatile Element mElement_RGB_565;
+    volatile Element mElement_RGB_888;
+    volatile Element mElement_RGBA_5551;
+    volatile Element mElement_RGBA_4444;
+    volatile Element mElement_RGBA_8888;
 
-    Element mElement_HALF_2;
-    Element mElement_HALF_3;
-    Element mElement_HALF_4;
+    volatile Element mElement_HALF_2;
+    volatile Element mElement_HALF_3;
+    volatile Element mElement_HALF_4;
 
-    Element mElement_FLOAT_2;
-    Element mElement_FLOAT_3;
-    Element mElement_FLOAT_4;
+    volatile Element mElement_FLOAT_2;
+    volatile Element mElement_FLOAT_3;
+    volatile Element mElement_FLOAT_4;
 
-    Element mElement_DOUBLE_2;
-    Element mElement_DOUBLE_3;
-    Element mElement_DOUBLE_4;
+    volatile Element mElement_DOUBLE_2;
+    volatile Element mElement_DOUBLE_3;
+    volatile Element mElement_DOUBLE_4;
 
-    Element mElement_UCHAR_2;
-    Element mElement_UCHAR_3;
-    Element mElement_UCHAR_4;
+    volatile Element mElement_UCHAR_2;
+    volatile Element mElement_UCHAR_3;
+    volatile Element mElement_UCHAR_4;
 
-    Element mElement_CHAR_2;
-    Element mElement_CHAR_3;
-    Element mElement_CHAR_4;
+    volatile Element mElement_CHAR_2;
+    volatile Element mElement_CHAR_3;
+    volatile Element mElement_CHAR_4;
 
-    Element mElement_USHORT_2;
-    Element mElement_USHORT_3;
-    Element mElement_USHORT_4;
+    volatile Element mElement_USHORT_2;
+    volatile Element mElement_USHORT_3;
+    volatile Element mElement_USHORT_4;
 
-    Element mElement_SHORT_2;
-    Element mElement_SHORT_3;
-    Element mElement_SHORT_4;
+    volatile Element mElement_SHORT_2;
+    volatile Element mElement_SHORT_3;
+    volatile Element mElement_SHORT_4;
 
-    Element mElement_UINT_2;
-    Element mElement_UINT_3;
-    Element mElement_UINT_4;
+    volatile Element mElement_UINT_2;
+    volatile Element mElement_UINT_3;
+    volatile Element mElement_UINT_4;
 
-    Element mElement_INT_2;
-    Element mElement_INT_3;
-    Element mElement_INT_4;
+    volatile Element mElement_INT_2;
+    volatile Element mElement_INT_3;
+    volatile Element mElement_INT_4;
 
-    Element mElement_ULONG_2;
-    Element mElement_ULONG_3;
-    Element mElement_ULONG_4;
+    volatile Element mElement_ULONG_2;
+    volatile Element mElement_ULONG_3;
+    volatile Element mElement_ULONG_4;
 
-    Element mElement_LONG_2;
-    Element mElement_LONG_3;
-    Element mElement_LONG_4;
+    volatile Element mElement_LONG_2;
+    volatile Element mElement_LONG_3;
+    volatile Element mElement_LONG_4;
 
-    Element mElement_YUV;
+    volatile Element mElement_YUV;
 
-    Element mElement_MATRIX_4X4;
-    Element mElement_MATRIX_3X3;
-    Element mElement_MATRIX_2X2;
+    volatile Element mElement_MATRIX_4X4;
+    volatile Element mElement_MATRIX_3X3;
+    volatile Element mElement_MATRIX_2X2;
 
-    Sampler mSampler_CLAMP_NEAREST;
-    Sampler mSampler_CLAMP_LINEAR;
-    Sampler mSampler_CLAMP_LINEAR_MIP_LINEAR;
-    Sampler mSampler_WRAP_NEAREST;
-    Sampler mSampler_WRAP_LINEAR;
-    Sampler mSampler_WRAP_LINEAR_MIP_LINEAR;
-    Sampler mSampler_MIRRORED_REPEAT_NEAREST;
-    Sampler mSampler_MIRRORED_REPEAT_LINEAR;
-    Sampler mSampler_MIRRORED_REPEAT_LINEAR_MIP_LINEAR;
+    volatile Sampler mSampler_CLAMP_NEAREST;
+    volatile Sampler mSampler_CLAMP_LINEAR;
+    volatile Sampler mSampler_CLAMP_LINEAR_MIP_LINEAR;
+    volatile Sampler mSampler_WRAP_NEAREST;
+    volatile Sampler mSampler_WRAP_LINEAR;
+    volatile Sampler mSampler_WRAP_LINEAR_MIP_LINEAR;
+    volatile Sampler mSampler_MIRRORED_REPEAT_NEAREST;
+    volatile Sampler mSampler_MIRRORED_REPEAT_LINEAR;
+    volatile Sampler mSampler_MIRRORED_REPEAT_LINEAR_MIP_LINEAR;
 
     ProgramStore mProgramStore_BLEND_NONE_DEPTH_TEST;
     ProgramStore mProgramStore_BLEND_NONE_DEPTH_NO_DEPTH;
diff --git a/rs/java/android/renderscript/Sampler.java b/rs/java/android/renderscript/Sampler.java
index 5c4bae9..70e88bc 100644
--- a/rs/java/android/renderscript/Sampler.java
+++ b/rs/java/android/renderscript/Sampler.java
@@ -98,13 +98,17 @@
      * @return Sampler
      */
     public static Sampler CLAMP_NEAREST(RenderScript rs) {
-        if(rs.mSampler_CLAMP_NEAREST == null) {
-            Builder b = new Builder(rs);
-            b.setMinification(Value.NEAREST);
-            b.setMagnification(Value.NEAREST);
-            b.setWrapS(Value.CLAMP);
-            b.setWrapT(Value.CLAMP);
-            rs.mSampler_CLAMP_NEAREST = b.create();
+        if (rs.mSampler_CLAMP_NEAREST == null) {
+            synchronized (rs) {
+                if (rs.mSampler_CLAMP_NEAREST == null) {
+                    Builder b = new Builder(rs);
+                    b.setMinification(Value.NEAREST);
+                    b.setMagnification(Value.NEAREST);
+                    b.setWrapS(Value.CLAMP);
+                    b.setWrapT(Value.CLAMP);
+                    rs.mSampler_CLAMP_NEAREST = b.create();
+                }
+            }
         }
         return rs.mSampler_CLAMP_NEAREST;
     }
@@ -118,13 +122,17 @@
      * @return Sampler
      */
     public static Sampler CLAMP_LINEAR(RenderScript rs) {
-        if(rs.mSampler_CLAMP_LINEAR == null) {
-            Builder b = new Builder(rs);
-            b.setMinification(Value.LINEAR);
-            b.setMagnification(Value.LINEAR);
-            b.setWrapS(Value.CLAMP);
-            b.setWrapT(Value.CLAMP);
-            rs.mSampler_CLAMP_LINEAR = b.create();
+        if (rs.mSampler_CLAMP_LINEAR == null) {
+            synchronized (rs) {
+                if (rs.mSampler_CLAMP_LINEAR == null) {
+                    Builder b = new Builder(rs);
+                    b.setMinification(Value.LINEAR);
+                    b.setMagnification(Value.LINEAR);
+                    b.setWrapS(Value.CLAMP);
+                    b.setWrapT(Value.CLAMP);
+                    rs.mSampler_CLAMP_LINEAR = b.create();
+                }
+            }
         }
         return rs.mSampler_CLAMP_LINEAR;
     }
@@ -138,13 +146,17 @@
      * @return Sampler
      */
     public static Sampler CLAMP_LINEAR_MIP_LINEAR(RenderScript rs) {
-        if(rs.mSampler_CLAMP_LINEAR_MIP_LINEAR == null) {
-            Builder b = new Builder(rs);
-            b.setMinification(Value.LINEAR_MIP_LINEAR);
-            b.setMagnification(Value.LINEAR);
-            b.setWrapS(Value.CLAMP);
-            b.setWrapT(Value.CLAMP);
-            rs.mSampler_CLAMP_LINEAR_MIP_LINEAR = b.create();
+        if (rs.mSampler_CLAMP_LINEAR_MIP_LINEAR == null) {
+            synchronized (rs) {
+                if (rs.mSampler_CLAMP_LINEAR_MIP_LINEAR == null) {
+                    Builder b = new Builder(rs);
+                    b.setMinification(Value.LINEAR_MIP_LINEAR);
+                    b.setMagnification(Value.LINEAR);
+                    b.setWrapS(Value.CLAMP);
+                    b.setWrapT(Value.CLAMP);
+                    rs.mSampler_CLAMP_LINEAR_MIP_LINEAR = b.create();
+                }
+            }
         }
         return rs.mSampler_CLAMP_LINEAR_MIP_LINEAR;
     }
@@ -158,13 +170,17 @@
      * @return Sampler
      */
     public static Sampler WRAP_NEAREST(RenderScript rs) {
-        if(rs.mSampler_WRAP_NEAREST == null) {
-            Builder b = new Builder(rs);
-            b.setMinification(Value.NEAREST);
-            b.setMagnification(Value.NEAREST);
-            b.setWrapS(Value.WRAP);
-            b.setWrapT(Value.WRAP);
-            rs.mSampler_WRAP_NEAREST = b.create();
+        if (rs.mSampler_WRAP_NEAREST == null) {
+            synchronized (rs) {
+                if (rs.mSampler_WRAP_NEAREST == null) {
+                    Builder b = new Builder(rs);
+                    b.setMinification(Value.NEAREST);
+                    b.setMagnification(Value.NEAREST);
+                    b.setWrapS(Value.WRAP);
+                    b.setWrapT(Value.WRAP);
+                    rs.mSampler_WRAP_NEAREST = b.create();
+                }
+            }
         }
         return rs.mSampler_WRAP_NEAREST;
     }
@@ -178,13 +194,17 @@
      * @return Sampler
      */
     public static Sampler WRAP_LINEAR(RenderScript rs) {
-        if(rs.mSampler_WRAP_LINEAR == null) {
-            Builder b = new Builder(rs);
-            b.setMinification(Value.LINEAR);
-            b.setMagnification(Value.LINEAR);
-            b.setWrapS(Value.WRAP);
-            b.setWrapT(Value.WRAP);
-            rs.mSampler_WRAP_LINEAR = b.create();
+        if (rs.mSampler_WRAP_LINEAR == null) {
+            synchronized (rs) {
+                if (rs.mSampler_WRAP_LINEAR == null) {
+                    Builder b = new Builder(rs);
+                    b.setMinification(Value.LINEAR);
+                    b.setMagnification(Value.LINEAR);
+                    b.setWrapS(Value.WRAP);
+                    b.setWrapT(Value.WRAP);
+                    rs.mSampler_WRAP_LINEAR = b.create();
+                }
+            }
         }
         return rs.mSampler_WRAP_LINEAR;
     }
@@ -198,13 +218,17 @@
      * @return Sampler
      */
     public static Sampler WRAP_LINEAR_MIP_LINEAR(RenderScript rs) {
-        if(rs.mSampler_WRAP_LINEAR_MIP_LINEAR == null) {
-            Builder b = new Builder(rs);
-            b.setMinification(Value.LINEAR_MIP_LINEAR);
-            b.setMagnification(Value.LINEAR);
-            b.setWrapS(Value.WRAP);
-            b.setWrapT(Value.WRAP);
-            rs.mSampler_WRAP_LINEAR_MIP_LINEAR = b.create();
+        if (rs.mSampler_WRAP_LINEAR_MIP_LINEAR == null) {
+            synchronized (rs) {
+                if (rs.mSampler_WRAP_LINEAR_MIP_LINEAR == null) {
+                    Builder b = new Builder(rs);
+                    b.setMinification(Value.LINEAR_MIP_LINEAR);
+                    b.setMagnification(Value.LINEAR);
+                    b.setWrapS(Value.WRAP);
+                    b.setWrapT(Value.WRAP);
+                    rs.mSampler_WRAP_LINEAR_MIP_LINEAR = b.create();
+                }
+            }
         }
         return rs.mSampler_WRAP_LINEAR_MIP_LINEAR;
     }
@@ -218,13 +242,17 @@
      * @return Sampler
      */
     public static Sampler MIRRORED_REPEAT_NEAREST(RenderScript rs) {
-        if(rs.mSampler_MIRRORED_REPEAT_NEAREST == null) {
-            Builder b = new Builder(rs);
-            b.setMinification(Value.NEAREST);
-            b.setMagnification(Value.NEAREST);
-            b.setWrapS(Value.MIRRORED_REPEAT);
-            b.setWrapT(Value.MIRRORED_REPEAT);
-            rs.mSampler_MIRRORED_REPEAT_NEAREST = b.create();
+        if (rs.mSampler_MIRRORED_REPEAT_NEAREST == null) {
+            synchronized (rs) {
+                if (rs.mSampler_MIRRORED_REPEAT_NEAREST == null) {
+                    Builder b = new Builder(rs);
+                    b.setMinification(Value.NEAREST);
+                    b.setMagnification(Value.NEAREST);
+                    b.setWrapS(Value.MIRRORED_REPEAT);
+                    b.setWrapT(Value.MIRRORED_REPEAT);
+                    rs.mSampler_MIRRORED_REPEAT_NEAREST = b.create();
+                }
+            }
         }
         return rs.mSampler_MIRRORED_REPEAT_NEAREST;
     }
@@ -238,13 +266,17 @@
      * @return Sampler
      */
     public static Sampler MIRRORED_REPEAT_LINEAR(RenderScript rs) {
-        if(rs.mSampler_MIRRORED_REPEAT_LINEAR == null) {
-            Builder b = new Builder(rs);
-            b.setMinification(Value.LINEAR);
-            b.setMagnification(Value.LINEAR);
-            b.setWrapS(Value.MIRRORED_REPEAT);
-            b.setWrapT(Value.MIRRORED_REPEAT);
-            rs.mSampler_MIRRORED_REPEAT_LINEAR = b.create();
+        if (rs.mSampler_MIRRORED_REPEAT_LINEAR == null) {
+            synchronized (rs) {
+                if (rs.mSampler_MIRRORED_REPEAT_LINEAR == null) {
+                    Builder b = new Builder(rs);
+                    b.setMinification(Value.LINEAR);
+                    b.setMagnification(Value.LINEAR);
+                    b.setWrapS(Value.MIRRORED_REPEAT);
+                    b.setWrapT(Value.MIRRORED_REPEAT);
+                    rs.mSampler_MIRRORED_REPEAT_LINEAR = b.create();
+                }
+            }
         }
         return rs.mSampler_MIRRORED_REPEAT_LINEAR;
     }
@@ -258,13 +290,17 @@
      * @return Sampler
      */
     public static Sampler MIRRORED_REPEAT_LINEAR_MIP_LINEAR(RenderScript rs) {
-        if(rs.mSampler_MIRRORED_REPEAT_LINEAR_MIP_LINEAR == null) {
-            Builder b = new Builder(rs);
-            b.setMinification(Value.LINEAR_MIP_LINEAR);
-            b.setMagnification(Value.LINEAR);
-            b.setWrapS(Value.MIRRORED_REPEAT);
-            b.setWrapT(Value.MIRRORED_REPEAT);
-            rs.mSampler_MIRRORED_REPEAT_LINEAR_MIP_LINEAR = b.create();
+        if (rs.mSampler_MIRRORED_REPEAT_LINEAR_MIP_LINEAR == null) {
+            synchronized (rs) {
+                if (rs.mSampler_MIRRORED_REPEAT_LINEAR_MIP_LINEAR == null) {
+                    Builder b = new Builder(rs);
+                    b.setMinification(Value.LINEAR_MIP_LINEAR);
+                    b.setMagnification(Value.LINEAR);
+                    b.setWrapS(Value.MIRRORED_REPEAT);
+                    b.setWrapT(Value.MIRRORED_REPEAT);
+                    rs.mSampler_MIRRORED_REPEAT_LINEAR_MIP_LINEAR = b.create();
+                }
+            }
         }
         return rs.mSampler_MIRRORED_REPEAT_LINEAR_MIP_LINEAR;
     }
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index d900b37..1b85016 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -60,7 +60,6 @@
 import android.os.Process;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
-import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -92,7 +91,6 @@
 import com.android.internal.R;
 import com.android.internal.content.PackageMonitor;
 import com.android.internal.os.SomeArgs;
-import com.android.internal.statusbar.IStatusBarService;
 import com.android.server.LocalServices;
 
 import com.android.server.statusbar.StatusBarManagerInternal;
@@ -2298,11 +2296,16 @@
         public boolean bindLocked() {
             UserState userState = getUserStateLocked(mUserId);
             if (!mIsAutomation) {
-                if (mService == null && mContext.bindServiceAsUser(
-                        mIntent, this,
-                        Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
-                        new UserHandle(mUserId))) {
-                    userState.mBindingServices.add(mComponentName);
+                final long identity = Binder.clearCallingIdentity();
+                try {
+                    if (mService == null && mContext.bindServiceAsUser(
+                            mIntent, this,
+                            Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
+                            new UserHandle(mUserId))) {
+                        userState.mBindingServices.add(mComponentName);
+                    }
+                } finally {
+                    Binder.restoreCallingIdentity(identity);
                 }
             } else {
                 userState.mBindingServices.add(mComponentName);
@@ -3315,13 +3318,9 @@
         private void openRecents() {
             final long token = Binder.clearCallingIdentity();
 
-            IStatusBarService statusBarService = IStatusBarService.Stub.asInterface(
-                    ServiceManager.getService("statusbar"));
-            try {
-                statusBarService.toggleRecentApps();
-            } catch (RemoteException e) {
-                Slog.e(LOG_TAG, "Error toggling recent apps.");
-            }
+            StatusBarManagerInternal statusBarService = LocalServices.getService(
+                    StatusBarManagerInternal.class);
+            statusBarService.toggleRecentApps();
 
             Binder.restoreCallingIdentity(token);
         }
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 40d44b4..71506be 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -1419,6 +1419,15 @@
                 log("onRestrictBackgroundChanged(restrictBackground=" + restrictBackground + ")");
             }
         }
+
+        @Override
+        public void onRestrictBackgroundWhitelistChanged(int uid, boolean whitelisted) {
+            if (LOGD_RULES) {
+                // caller is NPMS, since we only register with them
+                log("onRestrictBackgroundWhitelistChanged(uid=" + uid + ", whitelisted="
+                        + whitelisted + ")");
+            }
+        }
     };
 
     /**
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index d61b561..6c05173 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -690,17 +690,17 @@
         final IProgressListener listener = new IProgressListener.Stub() {
             @Override
             public void onStarted(int id, Bundle extras) throws RemoteException {
-                // Ignored
+                Log.d(TAG, "unlockUser started");
             }
 
             @Override
             public void onProgress(int id, int progress, Bundle extras) throws RemoteException {
-                // Ignored
+                Log.d(TAG, "unlockUser progress " + progress);
             }
 
             @Override
             public void onFinished(int id, Bundle extras) throws RemoteException {
-                Log.d(TAG, "unlockUser finished!");
+                Log.d(TAG, "unlockUser finished");
                 latch.countDown();
             }
         };
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 5d83a6e..d7afc13 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1945,6 +1945,9 @@
                     startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
                 }
                 installEncryptionUnawareProviders(userId);
+                if (msg.obj instanceof ProgressReporter) {
+                    ((ProgressReporter) msg.obj).finish();
+                }
                 break;
             }
             case SYSTEM_USER_CURRENT_MSG: {
@@ -20103,6 +20106,9 @@
                 if (DEBUG_OOM_ADJ) Slog.d(TAG_OOM_ADJ, "Keeping last mem factor!");
             }
         }
+        if (memFactor != mLastMemoryLevel) {
+            EventLogTags.writeAmMemFactor(memFactor, mLastMemoryLevel);
+        }
         mLastMemoryLevel = memFactor;
         mLastNumProcesses = mLruProcesses.size();
         boolean allChanged = mProcessStats.setMemFactorLocked(memFactor, !isSleeping(), now);
@@ -20979,6 +20985,36 @@
                 mStackSupervisor.setDockedStackMinimized(minimized);
             }
         }
+
+        @Override
+        public void killForegroundAppsForUser(int userHandle) {
+            synchronized (ActivityManagerService.this) {
+                final ArrayList<ProcessRecord> procs = new ArrayList<>();
+                final int NP = mProcessNames.getMap().size();
+                for (int ip = 0; ip < NP; ip++) {
+                    final SparseArray<ProcessRecord> apps = mProcessNames.getMap().valueAt(ip);
+                    final int NA = apps.size();
+                    for (int ia = 0; ia < NA; ia++) {
+                        final ProcessRecord app = apps.valueAt(ia);
+                        if (app.persistent) {
+                            // We don't kill persistent processes.
+                            continue;
+                        }
+                        if (app.removed) {
+                            procs.add(app);
+                        } else if (app.userId == userHandle && app.foregroundActivities) {
+                            app.removed = true;
+                            procs.add(app);
+                        }
+                    }
+                }
+
+                final int N = procs.size();
+                for (int i = 0; i < N; i++) {
+                    removeProcessLocked(procs.get(i), false, true, "kill all fg");
+                }
+            }
+        }
     }
 
     private final class SleepTokenImpl extends SleepToken {
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 6cd6ff4..2516f5d 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -58,8 +58,8 @@
 import com.android.internal.os.BatteryStatsHelper;
 import com.android.internal.os.BatteryStatsImpl;
 import com.android.internal.os.PowerProfile;
-import com.android.server.FgThread;
 import com.android.server.LocalServices;
+import com.android.server.ServiceThread;
 
 import java.io.File;
 import java.io.FileDescriptor;
@@ -176,7 +176,10 @@
     BatteryStatsService(File systemDir, Handler handler) {
         // Our handler here will be accessing the disk, use a different thread than
         // what the ActivityManagerService gave us (no I/O on that one!).
-        mHandler = new BatteryStatsHandler(FgThread.getHandler().getLooper());
+        final ServiceThread thread = new ServiceThread("batterystats-sync",
+                Process.THREAD_PRIORITY_DEFAULT, true);
+        thread.start();
+        mHandler = new BatteryStatsHandler(thread.getLooper());
 
         // BatteryStatsImpl expects the ActivityManagerService handler, so pass that one through.
         mStats = new BatteryStatsImpl(systemDir, handler, mHandler);
@@ -209,6 +212,9 @@
         synchronized (mStats) {
             mStats.shutdownLocked();
         }
+
+        // Shutdown the thread we made.
+        mHandler.getLooper().quit();
     }
     
     public static IBatteryStats getService() {
diff --git a/services/core/java/com/android/server/am/EventLogTags.logtags b/services/core/java/com/android/server/am/EventLogTags.logtags
index 2329b2f..2762df6 100644
--- a/services/core/java/com/android/server/am/EventLogTags.logtags
+++ b/services/core/java/com/android/server/am/EventLogTags.logtags
@@ -108,3 +108,7 @@
 30048 am_stop_activity (User|1|5),(Token|1|5),(Component Name|3)
 # The activity's onStop has been called.
 30049 am_on_stop_called (User|1|5),(Component Name|3),(Reason|3)
+
+# Report changing memory conditions (Values are ProcessStats.ADJ_MEM_FACTOR* constants)
+30050 am_mem_factor (Current|1|5),(Previous|1|5)
+
diff --git a/services/core/java/com/android/server/am/HealthStatsBatteryStatsWriter.java b/services/core/java/com/android/server/am/HealthStatsBatteryStatsWriter.java
index 9fb51c1..4a87941 100644
--- a/services/core/java/com/android/server/am/HealthStatsBatteryStatsWriter.java
+++ b/services/core/java/com/android/server/am/HealthStatsBatteryStatsWriter.java
@@ -35,12 +35,12 @@
 
 public class HealthStatsBatteryStatsWriter {
 
-    private final long mNowRealtime;
-    private final long mNowUptime;
+    private final long mNowRealtimeMs;
+    private final long mNowUptimeMs;
 
     public HealthStatsBatteryStatsWriter() {
-        mNowRealtime = SystemClock.elapsedRealtime();
-        mNowUptime = SystemClock.uptimeMillis();
+        mNowRealtimeMs = SystemClock.elapsedRealtime();
+        mNowUptimeMs = SystemClock.uptimeMillis();
     }
 
     /**
@@ -62,19 +62,20 @@
 
         // MEASUREMENT_REALTIME_BATTERY_MS
         uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_REALTIME_BATTERY_MS,
-                bs.computeBatteryRealtime(mNowRealtime*1000, STATS_SINCE_UNPLUGGED)/1000);
+                bs.computeBatteryRealtime(mNowRealtimeMs*1000, STATS_SINCE_UNPLUGGED)/1000);
 
         // MEASUREMENT_UPTIME_BATTERY_MS
         uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_UPTIME_BATTERY_MS,
-                bs.computeBatteryUptime(mNowUptime*1000, STATS_SINCE_UNPLUGGED)/1000);
+                bs.computeBatteryUptime(mNowUptimeMs*1000, STATS_SINCE_UNPLUGGED)/1000);
 
         // MEASUREMENT_REALTIME_SCREEN_OFF_BATTERY_MS
         uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_REALTIME_SCREEN_OFF_BATTERY_MS,
-                bs.computeBatteryScreenOffRealtime(mNowRealtime*1000, STATS_SINCE_UNPLUGGED)/1000);
+                bs.computeBatteryScreenOffRealtime(
+                    mNowRealtimeMs*1000, STATS_SINCE_UNPLUGGED)/1000);
 
         // MEASUREMENT_UPTIME_SCREEN_OFF_BATTERY_MS
         uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_UPTIME_SCREEN_OFF_BATTERY_MS,
-                bs.computeBatteryScreenOffUptime(mNowUptime*1000, STATS_SINCE_UNPLUGGED)/1000);
+                bs.computeBatteryScreenOffUptime(mNowUptimeMs*1000, STATS_SINCE_UNPLUGGED)/1000);
 
         //
         // Now on to the real per-uid stats...
@@ -214,20 +215,20 @@
 
         // MEASUREMENT_WIFI_RUNNING_MS
         uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_RUNNING_MS,
-                uid.getWifiRunningTime(mNowRealtime, STATS_SINCE_UNPLUGGED));
+                uid.getWifiRunningTime(mNowRealtimeMs*1000, STATS_SINCE_UNPLUGGED)/1000);
 
         // MEASUREMENT_WIFI_FULL_LOCK_MS
         uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_FULL_LOCK_MS,
-                uid.getFullWifiLockTime(mNowRealtime, STATS_SINCE_UNPLUGGED));
+                uid.getFullWifiLockTime(mNowRealtimeMs*1000, STATS_SINCE_UNPLUGGED)/1000);
 
         // TIMER_WIFI_SCAN
         uidWriter.addTimer(UidHealthStats.TIMER_WIFI_SCAN,
                 uid.getWifiScanCount(STATS_SINCE_UNPLUGGED),
-                uid.getWifiScanTime(mNowRealtime, STATS_SINCE_UNPLUGGED));
+                uid.getWifiScanTime(mNowRealtimeMs*1000, STATS_SINCE_UNPLUGGED)/1000);
 
         // MEASUREMENT_WIFI_MULTICAST_MS
         uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_MULTICAST_MS,
-                uid.getWifiMulticastTime(mNowRealtime, STATS_SINCE_UNPLUGGED));
+                uid.getWifiMulticastTime(mNowRealtimeMs*1000, STATS_SINCE_UNPLUGGED)/1000);
 
         // TIMER_AUDIO
         addTimer(uidWriter, UidHealthStats.TIMER_AUDIO, uid.getAudioTurnedOnTimer());
@@ -355,17 +356,17 @@
                 uid.getMobileRadioActiveCount(STATS_SINCE_UNPLUGGED),
                 uid.getMobileRadioActiveTime(STATS_SINCE_UNPLUGGED));
 
-        // MEASUREMENT_USER_CPU_TIME_US
-        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_USER_CPU_TIME_US,
-                uid.getUserCpuTimeUs(STATS_SINCE_UNPLUGGED));
+        // MEASUREMENT_USER_CPU_TIME_MS
+        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_USER_CPU_TIME_MS,
+                uid.getUserCpuTimeUs(STATS_SINCE_UNPLUGGED)/1000);
 
-        // MEASUREMENT_SYSTEM_CPU_TIME_US
-        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_SYSTEM_CPU_TIME_US,
-                uid.getSystemCpuTimeUs(STATS_SINCE_UNPLUGGED));
+        // MEASUREMENT_SYSTEM_CPU_TIME_MS
+        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_SYSTEM_CPU_TIME_MS,
+                uid.getSystemCpuTimeUs(STATS_SINCE_UNPLUGGED)/1000);
 
-        // MEASUREMENT_CPU_POWER_MAUS
-        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_CPU_POWER_MAUS,
-                uid.getCpuPowerMaUs(STATS_SINCE_UNPLUGGED));
+        // MEASUREMENT_CPU_POWER_MAMS
+        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_CPU_POWER_MAMS,
+                uid.getCpuPowerMaUs(STATS_SINCE_UNPLUGGED)/1000);
     }
 
     /**
@@ -457,7 +458,7 @@
     private void addTimer(HealthStatsWriter writer, int key, BatteryStats.Timer timer) {
         if (timer != null) {
             writer.addTimer(key, timer.getCountLocked(STATS_SINCE_UNPLUGGED),
-                    timer.getTotalTimeLocked(mNowRealtime, STATS_SINCE_UNPLUGGED));
+                    timer.getTotalTimeLocked(mNowRealtimeMs*1000, STATS_SINCE_UNPLUGGED) / 1000);
         }
     }
 
@@ -468,7 +469,7 @@
             BatteryStats.Timer timer) {
         if (timer != null) {
             writer.addTimers(key, name, new TimerStat(timer.getCountLocked(STATS_SINCE_UNPLUGGED),
-                    timer.getTotalTimeLocked(mNowRealtime, STATS_SINCE_UNPLUGGED)));
+                    timer.getTotalTimeLocked(mNowRealtimeMs*1000, STATS_SINCE_UNPLUGGED) / 1000));
         }
     }
 }
diff --git a/services/core/java/com/android/server/am/PreBootBroadcaster.java b/services/core/java/com/android/server/am/PreBootBroadcaster.java
index 0e192ea..1f3ccf5 100644
--- a/services/core/java/com/android/server/am/PreBootBroadcaster.java
+++ b/services/core/java/com/android/server/am/PreBootBroadcaster.java
@@ -78,9 +78,12 @@
         final ResolveInfo ri = mTargets.get(mIndex++);
         final ComponentName componentName = ri.activityInfo.getComponentName();
 
-        final CharSequence label = ri.activityInfo.loadLabel(mService.mContext.getPackageManager());
-        mProgress.setProgress(mIndex, mTargets.size(),
-                mService.mContext.getString(R.string.android_preparing_apk, label));
+        if (mProgress != null) {
+            final CharSequence label = ri.activityInfo
+                    .loadLabel(mService.mContext.getPackageManager());
+            mProgress.setProgress(mIndex, mTargets.size(),
+                    mService.mContext.getString(R.string.android_preparing_apk, label));
+        }
 
         Slog.i(TAG, "Pre-boot of " + componentName.toShortString() + " for user " + mUserId);
         EventLogTags.writeAmPreBoot(mUserId, componentName.getPackageName());
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 4c050c4..75d49c3 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -101,6 +101,7 @@
  */
 final class UserController {
     private static final String TAG = TAG_WITH_CLASS_NAME ? "UserController" : TAG_AM;
+
     // Maximum number of users we allow to be running at a time.
     static final int MAX_RUNNING_USERS = 3;
 
@@ -279,7 +280,8 @@
                 uss.mUnlockProgress.setProgress(20);
 
                 // Dispatch unlocked to system services
-                mHandler.sendMessage(mHandler.obtainMessage(SYSTEM_USER_UNLOCK_MSG, userId, 0));
+                mHandler.obtainMessage(SYSTEM_USER_UNLOCK_MSG, userId, 0, uss.mUnlockProgress)
+                        .sendToTarget();
 
                 // Dispatch unlocked to external apps
                 final Intent unlockedIntent = new Intent(Intent.ACTION_USER_UNLOCKED);
@@ -309,8 +311,7 @@
                 // Send PRE_BOOT broadcasts if fingerprint changed
                 final UserInfo info = getUserInfo(userId);
                 if (!Objects.equals(info.lastLoggedInFingerprint, Build.FINGERPRINT)) {
-                    uss.mUnlockProgress.startSegment(80);
-                    new PreBootBroadcaster(mService, userId, uss.mUnlockProgress) {
+                    new PreBootBroadcaster(mService, userId, null) {
                         @Override
                         public void onFinished() {
                             finishUserUnlocked(uss);
@@ -328,14 +329,6 @@
      * {@link UserState#STATE_RUNNING_UNLOCKED}.
      */
     private void finishUserUnlocked(UserState uss) {
-        try {
-            finishUserUnlockedInternal(uss);
-        } finally {
-            uss.mUnlockProgress.finish();
-        }
-    }
-
-    private void finishUserUnlockedInternal(UserState uss) {
         final int userId = uss.mHandle.getIdentifier();
         synchronized (mService) {
             // Bail if we ended up with a stale user
diff --git a/services/core/java/com/android/server/fingerprint/AuthenticationClient.java b/services/core/java/com/android/server/fingerprint/AuthenticationClient.java
index d2f015f..10284bb 100644
--- a/services/core/java/com/android/server/fingerprint/AuthenticationClient.java
+++ b/services/core/java/com/android/server/fingerprint/AuthenticationClient.java
@@ -39,9 +39,9 @@
     public abstract void resetFailedAttempts();
 
     public AuthenticationClient(Context context, long halDeviceId, IBinder token,
-            IFingerprintServiceReceiver receiver, int userId, int groupId, long opId,
+            IFingerprintServiceReceiver receiver, int callingUserId, int groupId, long opId,
             boolean restricted, String owner) {
-        super(context, halDeviceId, token, receiver, userId, groupId, restricted, owner);
+        super(context, halDeviceId, token, receiver, callingUserId, groupId, restricted, owner);
         mOpId = opId;
     }
 
diff --git a/services/core/java/com/android/server/fingerprint/ClientMonitor.java b/services/core/java/com/android/server/fingerprint/ClientMonitor.java
index 90998ed..45b6d3e 100644
--- a/services/core/java/com/android/server/fingerprint/ClientMonitor.java
+++ b/services/core/java/com/android/server/fingerprint/ClientMonitor.java
@@ -38,7 +38,7 @@
     protected static final boolean DEBUG = FingerprintService.DEBUG;
     private IBinder mToken;
     private IFingerprintServiceReceiver mReceiver;
-    private int mUserId;
+    private int mCallingUserId;
     private int mGroupId;
     private boolean mIsRestricted; // True if client does not have MANAGE_FINGERPRINT permission
     private String mOwner;
@@ -50,20 +50,20 @@
      * @param halDeviceId the HAL device ID of the associated fingerprint hardware
      * @param token a unique token for the client
      * @param receiver recipient of related events (e.g. authentication)
-     * @param userId userId for the fingerprint set
+     * @param callingUserId user id of calling user
      * @param groupId groupId for the fingerprint set
      * @param restricted whether or not client has the {@link Manifest#MANAGE_FINGERPRINT}
      * permission
      * @param owner name of the client that owns this
      */
     public ClientMonitor(Context context, long halDeviceId, IBinder token,
-            IFingerprintServiceReceiver receiver, int userId, int groupId,boolean restricted,
+            IFingerprintServiceReceiver receiver, int callingUserId, int groupId,boolean restricted,
             String owner) {
         mContext = context;
         mHalDeviceId = halDeviceId;
         mToken = token;
         mReceiver = receiver;
-        mUserId = userId;
+        mCallingUserId = callingUserId;
         mGroupId = groupId;
         mIsRestricted = restricted;
         mOwner = owner;
@@ -197,8 +197,8 @@
         return mIsRestricted;
     }
 
-    public final int getUserId() {
-        return mUserId;
+    public final int getCallingUserId() {
+        return mCallingUserId;
     }
 
     public final int getGroupId() {
diff --git a/services/core/java/com/android/server/fingerprint/EnrollClient.java b/services/core/java/com/android/server/fingerprint/EnrollClient.java
index ce5b890..b636ce5 100644
--- a/services/core/java/com/android/server/fingerprint/EnrollClient.java
+++ b/services/core/java/com/android/server/fingerprint/EnrollClient.java
@@ -46,9 +46,12 @@
 
     @Override
     public boolean onEnrollResult(int fingerId, int groupId, int remaining) {
+        if (groupId != getGroupId()) {
+            Slog.w(TAG, "groupId != getGroupId(), groupId: " + groupId +
+                    " getGroupId():" + getGroupId());
+        }
         if (remaining == 0) {
-            FingerprintUtils.getInstance().addFingerprintForUser(getContext(), fingerId,
-                    getUserId());
+            FingerprintUtils.getInstance().addFingerprintForUser(getContext(), fingerId, groupId);
         }
         return sendEnrollResult(fingerId, groupId, remaining);
     }
diff --git a/services/core/java/com/android/server/fingerprint/EnumerateClient.java b/services/core/java/com/android/server/fingerprint/EnumerateClient.java
index b2e4099..e826fee 100644
--- a/services/core/java/com/android/server/fingerprint/EnumerateClient.java
+++ b/services/core/java/com/android/server/fingerprint/EnumerateClient.java
@@ -41,7 +41,7 @@
         try {
             final int result = daemon.enumerate();
             if (result != 0) {
-                Slog.w(TAG, "start enumerate for user " + getUserId()
+                Slog.w(TAG, "start enumerate for user " + getCallingUserId()
                     + " failed, result=" + result);
                 onError(FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE);
                 return result;
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index c770620..fcf7bf5 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -356,7 +356,7 @@
         }
     }
 
-    void startRemove(IBinder token, int fingerId, int userId, int groupId,
+    void startRemove(IBinder token, int fingerId, int callingUserId, int groupId,
             IFingerprintServiceReceiver receiver, boolean restricted) {
         IFingerprintDaemon daemon = getFingerprintDaemon();
         if (daemon == null) {
@@ -364,7 +364,7 @@
             return;
         }
         RemovalClient client = new RemovalClient(getContext(), mHalDeviceId, token,
-                receiver, userId, groupId, fingerId, restricted, token.toString()) {
+                receiver, callingUserId, groupId, fingerId, restricted, token.toString()) {
             @Override
             public void notifyUserActivity() {
                 FingerprintService.this.userActivity();
@@ -372,8 +372,7 @@
 
             @Override
             public IFingerprintDaemon getFingerprintDaemon() {
-                FingerprintService.this.getFingerprintDaemon();
-                return null;
+                return FingerprintService.this.getFingerprintDaemon();
             }
         };
         startClient(client, true);
@@ -494,7 +493,7 @@
         }
     }
 
-    private void startAuthentication(IBinder token, long opId, int realUserId, int groupId,
+    private void startAuthentication(IBinder token, long opId, int callingUserId, int groupId,
                 IFingerprintServiceReceiver receiver, int flags, boolean restricted,
                 String opPackageName) {
         updateActiveGroup(groupId, opPackageName);
@@ -502,7 +501,7 @@
         if (DEBUG) Slog.v(TAG, "startAuthentication(" + opPackageName + ")");
 
         AuthenticationClient client = new AuthenticationClient(getContext(), mHalDeviceId, token,
-                receiver, realUserId, groupId, opId, restricted, opPackageName) {
+                receiver, callingUserId, groupId, opId, restricted, opPackageName) {
             @Override
             public boolean handleFailedAttempt() {
                 mFailedAttempts++;
@@ -541,13 +540,13 @@
         startClient(client, true /* initiatedByClient */);
     }
 
-    private void startEnrollment(IBinder token, byte [] cryptoToken, int userId, int groupId,
+    private void startEnrollment(IBinder token, byte [] cryptoToken, int callingUserId, int groupId,
             IFingerprintServiceReceiver receiver, int flags, boolean restricted,
             String opPackageName) {
         updateActiveGroup(groupId, opPackageName);
 
         EnrollClient client = new EnrollClient(getContext(), mHalDeviceId, token, receiver,
-                userId, groupId, cryptoToken, restricted, opPackageName) {
+                callingUserId, groupId, cryptoToken, restricted, opPackageName) {
 
             @Override
             public IFingerprintDaemon getFingerprintDaemon() {
@@ -687,9 +686,9 @@
             checkPermission(MANAGE_FINGERPRINT);
             final int limit =  mContext.getResources().getInteger(
                     com.android.internal.R.integer.config_fingerprintMaxTemplatesPerUser);
-            final int callingUid = Binder.getCallingUid();
-            final int userId = UserHandle.getUserId(callingUid);
-            final int enrolled = FingerprintService.this.getEnrolledFingerprints(userId).size();
+            final int callingUserId = UserHandle.getCallingUserId();
+            final int enrolled = FingerprintService.this.
+                    getEnrolledFingerprints(callingUserId).size();
             if (enrolled >= limit) {
                 Slog.w(TAG, "Too many fingerprints registered");
                 return;
@@ -705,7 +704,7 @@
             mHandler.post(new Runnable() {
                 @Override
                 public void run() {
-                    startEnrollment(token, cryptoToken, userId, groupId, receiver, flags,
+                    startEnrollment(token, cryptoToken, callingUserId, groupId, receiver, flags,
                             restricted, opPackageName);
                 }
             });
@@ -735,7 +734,8 @@
         public void authenticate(final IBinder token, final long opId, final int groupId,
                 final IFingerprintServiceReceiver receiver, final int flags,
                 final String opPackageName) {
-            final int realUserId = Binder.getCallingUid();
+            final int callingUid = Binder.getCallingUid();
+            final int callingUserId = UserHandle.getCallingUserId();
             final int pid = Binder.getCallingPid();
             final boolean restricted = isRestricted();
             mHandler.post(new Runnable() {
@@ -743,11 +743,11 @@
                 public void run() {
                     MetricsLogger.histogram(mContext, "fingerprint_token", opId != 0L ? 1 : 0);
                     if (!canUseFingerprint(opPackageName, true /* foregroundOnly */,
-                            realUserId, pid)) {
+                            callingUid, pid)) {
                         if (DEBUG) Slog.v(TAG, "authenticate(): reject " + opPackageName);
                         return;
                     }
-                    startAuthentication(token, opId, realUserId, groupId, receiver,
+                    startAuthentication(token, opId, callingUserId, groupId, receiver,
                             flags, restricted, opPackageName);
                 }
             });
@@ -797,11 +797,11 @@
                 final IFingerprintServiceReceiver receiver) {
             checkPermission(MANAGE_FINGERPRINT); // TODO: Maybe have another permission
             final boolean restricted = isRestricted();
-            final int realUserId = Binder.getCallingUid();
+            final int callingUserId = UserHandle.getCallingUserId();
             mHandler.post(new Runnable() {
                 @Override
                 public void run() {
-                    startRemove(token, fingerId, realUserId, groupId, receiver, restricted);
+                    startRemove(token, fingerId, callingUserId, groupId, receiver, restricted);
                 }
             });
 
diff --git a/services/core/java/com/android/server/fingerprint/RemovalClient.java b/services/core/java/com/android/server/fingerprint/RemovalClient.java
index 69a96e1..ffa3c3f 100644
--- a/services/core/java/com/android/server/fingerprint/RemovalClient.java
+++ b/services/core/java/com/android/server/fingerprint/RemovalClient.java
@@ -45,7 +45,7 @@
         IFingerprintDaemon daemon = getFingerprintDaemon();
         // The fingerprint template ids will be removed when we get confirmation from the HAL
         try {
-            final int result = daemon.remove(mFingerId, getUserId());
+            final int result = daemon.remove(mFingerId, getGroupId());
             if (result != 0) {
                 Slog.w(TAG, "startRemove with id = " + mFingerId + " failed, result=" + result);
                 onError(FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE);
diff --git a/services/core/java/com/android/server/input/PersistentDataStore.java b/services/core/java/com/android/server/input/PersistentDataStore.java
index e97aca8..f67e0fd 100644
--- a/services/core/java/com/android/server/input/PersistentDataStore.java
+++ b/services/core/java/com/android/server/input/PersistentDataStore.java
@@ -25,6 +25,7 @@
 import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlSerializer;
 
+import android.annotation.Nullable;
 import android.view.Surface;
 import android.hardware.input.TouchCalibration;
 import android.text.TextUtils;
@@ -342,6 +343,7 @@
                 "x_ymix", "x_offset", "y_xmix", "y_scale", "y_offset" };
 
         private TouchCalibration[] mTouchCalibration = new TouchCalibration[4];
+        @Nullable
         private String mCurrentKeyboardLayout;
         private List<String> mUnassociatedKeyboardLayouts = new ArrayList<>();
         private ArrayMap<InputMethodSubtypeHandle, String> mKeyboardLayouts = new ArrayMap<>();
@@ -368,6 +370,7 @@
             }
         }
 
+        @Nullable
         public String getCurrentKeyboardLayout() {
             return mCurrentKeyboardLayout;
         }
@@ -443,7 +446,7 @@
 
         public boolean switchKeyboardLayout(InputMethodSubtypeHandle imeHandle) {
             final String layout = mKeyboardLayouts.get(imeHandle);
-            if (layout != null && !TextUtils.equals(mCurrentKeyboardLayout, layout)) {
+            if (!TextUtils.equals(mCurrentKeyboardLayout, layout)) {
                 mCurrentKeyboardLayout = layout;
                 return true;
             }
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 3fb786b..433c056 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -1678,7 +1678,7 @@
         // Checks if app was added or removed to the blacklist.
         if ((oldPolicy == POLICY_NONE && policy == POLICY_REJECT_METERED_BACKGROUND)
                 || (oldPolicy == POLICY_REJECT_METERED_BACKGROUND && policy == POLICY_NONE)) {
-            mHandler.obtainMessage(MSG_RESTRICT_BACKGROUND_WHITELIST_CHANGED, uid, 0)
+            mHandler.obtainMessage(MSG_RESTRICT_BACKGROUND_WHITELIST_CHANGED, uid, 1, null)
                     .sendToTarget();
         }
     }
@@ -1970,10 +1970,9 @@
             // ...but always persists the whitelist request.
             writePolicyLocked();
         }
-        if (mRestrictBackground && !oldStatus && needFirewallRules) {
-            mHandler.obtainMessage(MSG_RESTRICT_BACKGROUND_WHITELIST_CHANGED, uid, 0)
-                    .sendToTarget();
-        }
+        int changed = (mRestrictBackground && !oldStatus && needFirewallRules) ? 1 : 0;
+        mHandler.obtainMessage(MSG_RESTRICT_BACKGROUND_WHITELIST_CHANGED, uid, changed,
+                Boolean.TRUE).sendToTarget();
     }
 
     @Override
@@ -1983,10 +1982,8 @@
         synchronized (mRulesLock) {
             changed = removeRestrictBackgroundWhitelistedUidLocked(uid, false, true);
         }
-        if (changed) {
-            mHandler.obtainMessage(MSG_RESTRICT_BACKGROUND_WHITELIST_CHANGED, uid, 0)
-                    .sendToTarget();
-        }
+        mHandler.obtainMessage(MSG_RESTRICT_BACKGROUND_WHITELIST_CHANGED, uid, changed ? 1 : 0,
+                Boolean.FALSE).sendToTarget();
     }
 
     /**
@@ -2924,10 +2921,40 @@
                     return true;
                 }
                 case MSG_RESTRICT_BACKGROUND_WHITELIST_CHANGED: {
+                    // MSG_RESTRICT_BACKGROUND_WHITELIST_CHANGED can be called in 2 occasions:
+                    // - when an app is whitelisted
+                    // - when an app is blacklisted
+                    //
+                    // Whether the internal listeners (INetworkPolicyListener implementations) or
+                    // app broadcast receivers are notified depend on the following rules:
+                    //
+                    // - App receivers are only notified when the app status changed (msg.arg2 = 1)
+                    // - Listeners are only notified when app was whitelisted (msg.obj is not null),
+                    //   since blacklist notifications are handled through MSG_RULES_CHANGED).
                     final int uid = msg.arg1;
+                    final boolean changed = msg.arg2 == 1;
+                    final Boolean whitelisted = (Boolean) msg.obj;
+
+                    if (whitelisted != null) {
+                        final int length = mListeners.beginBroadcast();
+                        for (int i = 0; i < length; i++) {
+                            // First notify internal listeners...
+                            final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
+                            if (listener != null) {
+                                try {
+                                    listener.onRestrictBackgroundWhitelistChanged(uid,
+                                            whitelisted.booleanValue());
+                                } catch (RemoteException e) {
+                                }
+                            }
+                        }
+                        mListeners.finishBroadcast();
+                    }
+
                     final PackageManager pm = mContext.getPackageManager();
                     final String[] packages = pm.getPackagesForUid(uid);
-                    if (packages != null) {
+                    if (changed && packages != null) {
+                        // ...then notify apps listening to ACTION_RESTRICT_BACKGROUND_CHANGED
                         final int userId = UserHandle.getUserId(uid);
                         for (String packageName : packages) {
                             final Intent intent = new Intent(
@@ -2936,8 +2963,6 @@
                             intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
                             mContext.sendBroadcastAsUser(intent, UserHandle.of(userId));
                         }
-                    } else {
-                        Slog.w(TAG, "no packages for uid " + uid);
                     }
                     return true;
                 }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 43250ba..0633625 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -216,6 +216,7 @@
 import android.util.SparseBooleanArray;
 import android.util.SparseIntArray;
 import android.util.Xml;
+import android.util.jar.StrictJarFile;
 import android.view.Display;
 
 import com.android.internal.R;
@@ -7643,6 +7644,52 @@
         }
     }
 
+    /**
+     * Returns {@code true} if the given file contains code. Otherwise {@code false}.
+     */
+    private static boolean apkHasCode(String fileName) {
+        StrictJarFile jarFile = null;
+        try {
+            jarFile = new StrictJarFile(fileName,
+                    false /*verify*/, false /*signatureSchemeRollbackProtectionsEnforced*/);
+            return jarFile.findEntry("classes.dex") != null;
+        } catch (IOException ignore) {
+        } finally {
+            try {
+                jarFile.close();
+            } catch (IOException ignore) {}
+        }
+        return false;
+    }
+
+    /**
+     * Enforces code policy for the package. This ensures that if an APK has
+     * declared hasCode="true" in its manifest that the APK actually contains
+     * code.
+     *
+     * @throws PackageManagerException If bytecode could not be found when it should exist
+     */
+    private static void enforceCodePolicy(PackageParser.Package pkg)
+            throws PackageManagerException {
+        final boolean shouldHaveCode =
+                (pkg.applicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0;
+        if (shouldHaveCode && !apkHasCode(pkg.baseCodePath)) {
+            throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
+                    "Package " + pkg.baseCodePath + " code is missing");
+        }
+
+        if (!ArrayUtils.isEmpty(pkg.splitCodePaths)) {
+            for (int i = 0; i < pkg.splitCodePaths.length; i++) {
+                final boolean splitShouldHaveCode =
+                        (pkg.splitFlags[i] & ApplicationInfo.FLAG_HAS_CODE) != 0;
+                if (splitShouldHaveCode && !apkHasCode(pkg.splitCodePaths[i])) {
+                    throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
+                            "Package " + pkg.splitCodePaths[i] + " code is missing");
+                }
+            }
+        }
+    }
+
     private PackageParser.Package scanPackageDirtyLI(PackageParser.Package pkg,
             final int policyFlags, final int scanFlags, long currentTime, UserHandle user)
             throws PackageManagerException {
@@ -7687,6 +7734,10 @@
             pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
         }
 
+        if ((policyFlags & PackageParser.PARSE_ENFORCE_CODE) != 0) {
+            enforceCodePolicy(pkg);
+        }
+
         if (mCustomResolverComponentName != null &&
                 mCustomResolverComponentName.getPackageName().equals(pkg.packageName)) {
             setUpCustomResolverActivity(pkg);
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 42f7166..93e4d31 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -667,6 +667,8 @@
             long identity = Binder.clearCallingIdentity();
             try {
                 if (enableQuietMode) {
+                    LocalServices.getService(ActivityManagerInternal.class)
+                            .killForegroundAppsForUser(userHandle);
                     ActivityManagerNative.getDefault().stopUser(userHandle, /* force */true, null);
                 } else {
                     ActivityManagerNative.getDefault().startUserInBackground(userHandle);
@@ -2359,11 +2361,13 @@
     public void setApplicationRestrictions(String packageName, Bundle restrictions,
             int userId) {
         checkSystemOrRoot("set application restrictions");
+        if (restrictions != null) {
+            restrictions.setDefusable(true);
+        }
         synchronized (mPackagesLock) {
             if (restrictions == null || restrictions.isEmpty()) {
                 cleanAppRestrictionsForPackage(packageName, userId);
             } else {
-                restrictions.setDefusable(true);
                 // Write the restrictions to XML
                 writeApplicationRestrictionsLP(packageName, restrictions, userId);
             }
diff --git a/services/core/java/com/android/server/policy/BarController.java b/services/core/java/com/android/server/policy/BarController.java
index 0c80ffa..5878709 100644
--- a/services/core/java/com/android/server/policy/BarController.java
+++ b/services/core/java/com/android/server/policy/BarController.java
@@ -18,15 +18,14 @@
 
 import android.app.StatusBarManager;
 import android.os.Handler;
-import android.os.RemoteException;
-import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.util.Slog;
 import android.view.View;
 import android.view.WindowManager;
 import android.view.WindowManagerPolicy.WindowState;
 
-import com.android.internal.statusbar.IStatusBarService;
+import com.android.server.LocalServices;
+import com.android.server.statusbar.StatusBarManagerInternal;
 
 import java.io.PrintWriter;
 
@@ -52,7 +51,7 @@
     private final int mTranslucentWmFlag;
     protected final Handler mHandler;
     private final Object mServiceAquireLock = new Object();
-    protected IStatusBarService mStatusBarService;
+    protected StatusBarManagerInternal mStatusBarInternal;
 
     private WindowState mWin;
     private int mState = StatusBarManager.WINDOW_STATE_SHOWING;
@@ -182,15 +181,9 @@
             mHandler.post(new Runnable() {
                 @Override
                 public void run() {
-                    try {
-                        IStatusBarService statusbar = getStatusBarService();
-                        if (statusbar != null) {
-                            statusbar.setWindowState(mStatusBarManagerId, state);
-                        }
-                    } catch (RemoteException e) {
-                        if (DEBUG) Slog.w(mTag, "Error posting window state", e);
-                        // re-acquire status bar service next time it is needed.
-                        mStatusBarService = null;
+                    StatusBarManagerInternal statusbar = getStatusBarInternal();
+                    if (statusbar != null) {
+                        statusbar.setWindowState(mStatusBarManagerId, state);
                     }
                 }
             });
@@ -276,13 +269,12 @@
         }
     }
 
-    protected IStatusBarService getStatusBarService() {
+    protected StatusBarManagerInternal getStatusBarInternal() {
         synchronized (mServiceAquireLock) {
-            if (mStatusBarService == null) {
-                mStatusBarService = IStatusBarService.Stub.asInterface(
-                        ServiceManager.getService("statusbar"));
+            if (mStatusBarInternal == null) {
+                mStatusBarInternal = LocalServices.getService(StatusBarManagerInternal.class);
             }
-            return mStatusBarService;
+            return mStatusBarInternal;
         }
     }
 
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 1686f14..007190d 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -1467,14 +1467,12 @@
 
     private void requestTvPictureInPictureInternal() {
         try {
-            IStatusBarService statusbar = getStatusBarService();
+            StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
             if (statusbar != null) {
                 statusbar.requestTvPictureInPicture();
             }
-        } catch (RemoteException|IllegalArgumentException e) {
+        } catch (IllegalArgumentException e) {
             Slog.e(TAG, "Cannot handle picture-in-picture key", e);
-            // re-acquire status bar service next time it is needed.
-            mStatusBarService = null;
         }
     }
 
@@ -3562,21 +3560,15 @@
             ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
                     .launchLegacyAssist(hint, UserHandle.myUserId(), args);
         } else {
-            try {
-                if (hint != null) {
-                    if (args == null) {
-                        args = new Bundle();
-                    }
-                    args.putBoolean(hint, true);
+            if (hint != null) {
+                if (args == null) {
+                    args = new Bundle();
                 }
-                IStatusBarService statusbar = getStatusBarService();
-                if (statusbar != null) {
-                    statusbar.startAssist(args);
-                }
-            } catch (RemoteException e) {
-                Slog.e(TAG, "RemoteException when starting assist", e);
-                // re-acquire status bar service next time it is needed.
-                mStatusBarService = null;
+                args.putBoolean(hint, true);
+            }
+            StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
+            if (statusbar != null) {
+                statusbar.startAssist(args);
             }
         }
     }
@@ -3598,45 +3590,27 @@
 
     private void preloadRecentApps() {
         mPreloadedRecentApps = true;
-        try {
-            IStatusBarService statusbar = getStatusBarService();
-            if (statusbar != null) {
-                statusbar.preloadRecentApps();
-            }
-        } catch (RemoteException e) {
-            Slog.e(TAG, "RemoteException when preloading recent apps", e);
-            // re-acquire status bar service next time it is needed.
-            mStatusBarService = null;
+        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
+        if (statusbar != null) {
+            statusbar.preloadRecentApps();
         }
     }
 
     private void cancelPreloadRecentApps() {
         if (mPreloadedRecentApps) {
             mPreloadedRecentApps = false;
-            try {
-                IStatusBarService statusbar = getStatusBarService();
-                if (statusbar != null) {
-                    statusbar.cancelPreloadRecentApps();
-                }
-            } catch (RemoteException e) {
-                Slog.e(TAG, "RemoteException when cancelling recent apps preload", e);
-                // re-acquire status bar service next time it is needed.
-                mStatusBarService = null;
+            StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
+            if (statusbar != null) {
+                statusbar.cancelPreloadRecentApps();
             }
         }
     }
 
     private void toggleRecentApps() {
         mPreloadedRecentApps = false; // preloading no longer needs to be canceled
-        try {
-            IStatusBarService statusbar = getStatusBarService();
-            if (statusbar != null) {
-                statusbar.toggleRecentApps();
-            }
-        } catch (RemoteException e) {
-            Slog.e(TAG, "RemoteException when toggling recent apps", e);
-            // re-acquire status bar service next time it is needed.
-            mStatusBarService = null;
+        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
+        if (statusbar != null) {
+            statusbar.toggleRecentApps();
         }
     }
 
@@ -3648,40 +3622,24 @@
 
     private void showRecentApps(boolean triggeredFromAltTab, boolean fromHome) {
         mPreloadedRecentApps = false; // preloading no longer needs to be canceled
-        try {
-            IStatusBarService statusbar = getStatusBarService();
-            if (statusbar != null) {
-                statusbar.showRecentApps(triggeredFromAltTab, fromHome);
-            }
-        } catch (RemoteException e) {
-            Slog.e(TAG, "RemoteException when showing recent apps", e);
-            // re-acquire status bar service next time it is needed.
-            mStatusBarService = null;
+        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
+        if (statusbar != null) {
+            statusbar.showRecentApps(triggeredFromAltTab, fromHome);
         }
     }
 
     private void toggleKeyboardShortcutsMenu(int deviceId) {
-        try {
-            IStatusBarService statusbar = getStatusBarService();
-            if (statusbar != null) {
-                statusbar.toggleKeyboardShortcutsMenu(deviceId);
-            }
-        } catch (RemoteException e) {
-            Slog.e(TAG, "RemoteException when showing keyboard shortcuts menu", e);
+        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
+        if (statusbar != null) {
+            statusbar.toggleKeyboardShortcutsMenu(deviceId);
         }
     }
 
     private void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHome) {
         mPreloadedRecentApps = false; // preloading no longer needs to be canceled
-        try {
-            IStatusBarService statusbar = getStatusBarService();
-            if (statusbar != null) {
-                statusbar.hideRecentApps(triggeredFromAltTab, triggeredFromHome);
-            }
-        } catch (RemoteException e) {
-            Slog.e(TAG, "RemoteException when closing recent apps", e);
-            // re-acquire status bar service next time it is needed.
-            mStatusBarService = null;
+        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
+        if (statusbar != null) {
+            statusbar.hideRecentApps(triggeredFromAltTab, triggeredFromHome);
         }
     }
 
@@ -7483,13 +7441,9 @@
         if (mKeyguardDelegate != null) {
             mKeyguardDelegate.setCurrentUser(newUserId);
         }
-        IStatusBarService statusBar = getStatusBarService();
+        StatusBarManagerInternal statusBar = getStatusBarManagerInternal();
         if (statusBar != null) {
-            try {
-                statusBar.setCurrentUser(newUserId);
-            } catch (RemoteException e) {
-                // oh well
-            }
+            statusBar.setCurrentUser(newUserId);
         }
         setLastInputMethodWindowLw(null, null);
     }
diff --git a/services/core/java/com/android/server/policy/StatusBarController.java b/services/core/java/com/android/server/policy/StatusBarController.java
index 86d0468..245518c 100644
--- a/services/core/java/com/android/server/policy/StatusBarController.java
+++ b/services/core/java/com/android/server/policy/StatusBarController.java
@@ -18,9 +18,7 @@
 
 import android.app.StatusBarManager;
 import android.os.IBinder;
-import android.os.RemoteException;
 import android.os.SystemClock;
-import android.util.Slog;
 import android.view.View;
 import android.view.WindowManager;
 import android.view.animation.Animation;
@@ -28,7 +26,6 @@
 import android.view.animation.Interpolator;
 import android.view.animation.TranslateAnimation;
 
-import com.android.internal.statusbar.IStatusBarService;
 import com.android.server.LocalServices;
 import com.android.server.statusbar.StatusBarManagerInternal;
 
@@ -49,15 +46,9 @@
             mHandler.post(new Runnable() {
                 @Override
                 public void run() {
-                    try {
-                        IStatusBarService statusbar = getStatusBarService();
-                        if (statusbar != null) {
-                            statusbar.appTransitionPending();
-                        }
-                    } catch (RemoteException e) {
-                        Slog.e(mTag, "RemoteException when app transition is pending", e);
-                        // re-acquire status bar service next time it is needed.
-                        mStatusBarService = null;
+                    StatusBarManagerInternal statusbar = getStatusBarInternal();
+                    if (statusbar != null) {
+                        statusbar.appTransitionPending();
                     }
                 }
             });
@@ -69,19 +60,13 @@
             mHandler.post(new Runnable() {
                 @Override
                 public void run() {
-                    try {
-                        IStatusBarService statusbar = getStatusBarService();
-                        if (statusbar != null) {
-                            long startTime = calculateStatusBarTransitionStartTime(openAnimation,
-                                    closeAnimation);
-                            long duration = closeAnimation != null || openAnimation != null
-                                    ? TRANSITION_DURATION : 0;
-                            statusbar.appTransitionStarting(startTime, duration);
-                        }
-                    } catch (RemoteException e) {
-                        Slog.e(mTag, "RemoteException when app transition is starting", e);
-                        // re-acquire status bar service next time it is needed.
-                        mStatusBarService = null;
+                    StatusBarManagerInternal statusbar = getStatusBarInternal();
+                    if (statusbar != null) {
+                        long startTime = calculateStatusBarTransitionStartTime(openAnimation,
+                                closeAnimation);
+                        long duration = closeAnimation != null || openAnimation != null
+                                ? TRANSITION_DURATION : 0;
+                        statusbar.appTransitionStarting(startTime, duration);
                     }
                 }
             });
@@ -92,15 +77,9 @@
             mHandler.post(new Runnable() {
                 @Override
                 public void run() {
-                    try {
-                        IStatusBarService statusbar = getStatusBarService();
-                        if (statusbar != null) {
-                            statusbar.appTransitionCancelled();
-                        }
-                    } catch (RemoteException e) {
-                        Slog.e(mTag, "RemoteException when app transition is cancelled", e);
-                        // re-acquire status bar service next time it is needed.
-                        mStatusBarService = null;
+                    StatusBarManagerInternal statusbar = getStatusBarInternal();
+                    if (statusbar != null) {
+                        statusbar.appTransitionCancelled();
                     }
                 }
             });
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
index 95923fe..38a3d01 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
@@ -28,6 +28,50 @@
     void notificationLightOff();
     void showScreenPinningRequest(int taskId);
     void showAssistDisclosure();
+
+    void preloadRecentApps();
+
+    void cancelPreloadRecentApps();
+
+    void showRecentApps(boolean triggeredFromAltTab, boolean fromHome);
+
+    void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey);
+
+    void toggleKeyboardShortcutsMenu(int deviceId);
+
+    /**
+     * Request picture-in-picture.
+     *
+     * <p>
+     * This is called when an user presses picture-in-picture key or equivalent.
+     * TV device may start picture-in-picture from foreground activity if there's none.
+     * Picture-in-picture overlay menu will be shown instead otherwise.
+     */
+    void requestTvPictureInPicture();
+
+    void setWindowState(int window, int state);
+
+    /**
+     * Notifies the status bar that an app transition is pending to delay applying some flags with
+     * visual impact until {@link #appTransitionReady} is called.
+     */
+    void appTransitionPending();
+
+    /**
+     * Notifies the status bar that a pending app transition has been cancelled.
+     */
+    void appTransitionCancelled();
+
+    /**
+     * Notifies the status bar that an app transition is now being executed.
+     *
+     * @param statusBarAnimationsStartTime the desired start time for all visual animations in the
+     *        status bar caused by this app transition in uptime millis
+     * @param statusBarAnimationsDuration the duration for all visual animations in the status
+     *        bar caused by this app transition in millis
+     */
+    void appTransitionStarting(long statusBarAnimationsStartTime, long statusBarAnimationsDuration);
+
     void startAssist(Bundle args);
     void onCameraLaunchGestureDetected(int source);
     void topAppWindowChanged(boolean menuVisible);
@@ -35,4 +79,8 @@
             Rect fullscreenBounds, Rect dockedBounds, String cause);
     void toggleSplitScreen();
     void appTransitionFinished();
+
+    void toggleRecentApps();
+
+    void setCurrentUser(int newUserId);
 }
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 981b75a..9020677 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -223,6 +223,114 @@
                 } catch (RemoteException ex) {}
             }
         }
+
+        @Override
+        public void toggleRecentApps() {
+            if (mBar != null) {
+                try {
+                    mBar.toggleRecentApps();
+                } catch (RemoteException ex) {}
+            }
+        }
+
+        @Override
+        public void setCurrentUser(int newUserId) {
+            if (SPEW) Slog.d(TAG, "Setting current user to user " + newUserId);
+            mCurrentUserId = newUserId;
+        }
+
+
+        @Override
+        public void preloadRecentApps() {
+            if (mBar != null) {
+                try {
+                    mBar.preloadRecentApps();
+                } catch (RemoteException ex) {}
+            }
+        }
+
+        @Override
+        public void cancelPreloadRecentApps() {
+            if (mBar != null) {
+                try {
+                    mBar.cancelPreloadRecentApps();
+                } catch (RemoteException ex) {}
+            }
+        }
+
+        @Override
+        public void showRecentApps(boolean triggeredFromAltTab, boolean fromHome) {
+            if (mBar != null) {
+                try {
+                    mBar.showRecentApps(triggeredFromAltTab, fromHome);
+                } catch (RemoteException ex) {}
+            }
+        }
+
+        @Override
+        public void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) {
+            if (mBar != null) {
+                try {
+                    mBar.hideRecentApps(triggeredFromAltTab, triggeredFromHomeKey);
+                } catch (RemoteException ex) {}
+            }
+        }
+
+        @Override
+        public void toggleKeyboardShortcutsMenu(int deviceId) {
+            if (mBar != null) {
+                try {
+                    mBar.toggleKeyboardShortcutsMenu(deviceId);
+                } catch (RemoteException ex) {}
+            }
+        }
+
+        @Override
+        public void requestTvPictureInPicture() {
+            if (mBar != null) {
+                try {
+                    mBar.requestTvPictureInPicture();
+                } catch (RemoteException ex) {}
+            }
+        }
+
+        @Override
+        public void setWindowState(int window, int state) {
+            if (mBar != null) {
+                try {
+                    mBar.setWindowState(window, state);
+                } catch (RemoteException ex) {}
+            }
+        }
+
+        @Override
+        public void appTransitionPending() {
+            if (mBar != null) {
+                try {
+                    mBar.appTransitionPending();
+                } catch (RemoteException ex) {}
+            }
+        }
+
+        @Override
+        public void appTransitionCancelled() {
+            if (mBar != null) {
+                try {
+                    mBar.appTransitionCancelled();
+                } catch (RemoteException ex) {}
+            }
+        }
+
+        @Override
+        public void appTransitionStarting(long statusBarAnimationsStartTime,
+                long statusBarAnimationsDuration) {
+            if (mBar != null) {
+                try {
+                    mBar.appTransitionStarting(
+                            statusBarAnimationsStartTime, statusBarAnimationsDuration);
+                } catch (RemoteException ex) {}
+            }
+        }
     };
 
     // ================================================================================
@@ -527,122 +635,6 @@
         }
     }
 
-    @Override
-    public void toggleRecentApps() {
-        if (mBar != null) {
-            try {
-                mBar.toggleRecentApps();
-            } catch (RemoteException ex) {}
-        }
-    }
-
-    @Override
-    public void preloadRecentApps() {
-        if (mBar != null) {
-            try {
-                mBar.preloadRecentApps();
-            } catch (RemoteException ex) {}
-        }
-    }
-
-    @Override
-    public void cancelPreloadRecentApps() {
-        if (mBar != null) {
-            try {
-                mBar.cancelPreloadRecentApps();
-            } catch (RemoteException ex) {}
-        }
-    }
-
-    @Override
-    public void showRecentApps(boolean triggeredFromAltTab, boolean fromHome) {
-        if (mBar != null) {
-            try {
-                mBar.showRecentApps(triggeredFromAltTab, fromHome);
-            } catch (RemoteException ex) {}
-        }
-    }
-
-    @Override
-    public void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) {
-        if (mBar != null) {
-            try {
-                mBar.hideRecentApps(triggeredFromAltTab, triggeredFromHomeKey);
-            } catch (RemoteException ex) {}
-        }
-    }
-
-    @Override
-    public void toggleKeyboardShortcutsMenu(int deviceId) {
-        if (mBar != null) {
-            try {
-                mBar.toggleKeyboardShortcutsMenu(deviceId);
-            } catch (RemoteException ex) {}
-        }
-    }
-
-    @Override
-    public void requestTvPictureInPicture() {
-        if (mBar != null) {
-            try {
-                mBar.requestTvPictureInPicture();
-            } catch (RemoteException ex) {}
-        }
-    }
-
-    @Override
-    public void setCurrentUser(int newUserId) {
-        if (SPEW) Slog.d(TAG, "Setting current user to user " + newUserId);
-        mCurrentUserId = newUserId;
-    }
-
-    @Override
-    public void setWindowState(int window, int state) {
-        if (mBar != null) {
-            try {
-                mBar.setWindowState(window, state);
-            } catch (RemoteException ex) {}
-        }
-    }
-
-    @Override
-    public void appTransitionPending() {
-        if (mBar != null) {
-            try {
-                mBar.appTransitionPending();
-            } catch (RemoteException ex) {}
-        }
-    }
-
-    @Override
-    public void appTransitionCancelled() {
-        if (mBar != null) {
-            try {
-                mBar.appTransitionCancelled();
-            } catch (RemoteException ex) {}
-        }
-    }
-
-    @Override
-    public void appTransitionStarting(long statusBarAnimationsStartTime,
-            long statusBarAnimationsDuration) {
-        if (mBar != null) {
-            try {
-                mBar.appTransitionStarting(
-                        statusBarAnimationsStartTime, statusBarAnimationsDuration);
-            } catch (RemoteException ex) {}
-        }
-    }
-
-    @Override
-    public void startAssist(Bundle args) {
-        if (mBar != null) {
-            try {
-                mBar.startAssist(args);
-            } catch (RemoteException ex) {}
-        }
-    }
-
     private void enforceStatusBarOrShell() {
         if (Binder.getCallingUid() == Process.SHELL_UID) {
             return;
diff --git a/services/core/java/com/android/server/wm/BoundsAnimationController.java b/services/core/java/com/android/server/wm/BoundsAnimationController.java
index b7d6062..eacdd81 100644
--- a/services/core/java/com/android/server/wm/BoundsAnimationController.java
+++ b/services/core/java/com/android/server/wm/BoundsAnimationController.java
@@ -129,13 +129,16 @@
         public void onAnimationStart(Animator animation) {
             if (DEBUG) Slog.d(TAG, "onAnimationStart: mTarget=" + mTarget
                     + " mReplacement=" + mReplacement);
-            if (animatingToLargerSize()) {
-                mTarget.setPinnedStackSize(mFrom, mTo);
-            }
-
             if (!mReplacement) {
                 mTarget.onAnimationStart();
             }
+
+            // Ensure that we have prepared the target for animation before
+            // we trigger any size changes, so it can swap surfaces
+            // in to appropriate modes, or do as it wishes otherwise.
+            if (animatingToLargerSize()) {
+                mTarget.setPinnedStackSize(mFrom, mTo);
+            }
         }
 
         @Override
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index 0039c0a..b90d0d1 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -663,4 +663,8 @@
     public String toShortString() {
         return TAG;
     }
-}
\ No newline at end of file
+
+    WindowState getWindow() {
+        return mWindow;
+    }
+}
diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java
index aace5e7..ffe0336 100644
--- a/services/core/java/com/android/server/wm/DragState.java
+++ b/services/core/java/com/android/server/wm/DragState.java
@@ -420,12 +420,7 @@
     void notifyLocationLw(float x, float y) {
         // Tell the affected window
         WindowState touchedWin = mDisplayContent.getTouchableWinAtPointLocked(x, y);
-        if (touchedWin == null) {
-            if (DEBUG_DRAG) Slog.d(TAG_WM, "No touched win at x=" + x + " y=" + y);
-            return;
-        }
-
-        if (!isWindowNotified(touchedWin)) {
+        if (touchedWin != null && !isWindowNotified(touchedWin)) {
             // The drag point is over a window which was not notified about a drag start.
             // Pretend it's over empty space.
             touchedWin = null;
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 46a8dff..4f49eed 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -600,7 +600,8 @@
                     //
                     // Anyway we don't need to synchronize position and content updates for these
                     // windows since they aren't at the base layer and could be moved around anyway.
-                    if (!win.computeDragResizing() && win.mAttrs.type == TYPE_BASE_APPLICATION) {
+                    if (!win.computeDragResizing() && win.mAttrs.type == TYPE_BASE_APPLICATION &&
+                            !mStack.getBoundsAnimating()) {
                         win.mResizedWhileNotDragResizing = true;
                     }
                 }
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 872bc6d..1fd2b1f 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -42,6 +42,7 @@
 import android.view.DisplayInfo;
 import android.view.Surface;
 import android.view.animation.PathInterpolator;
+import android.view.SurfaceControl;
 
 import com.android.internal.policy.DividerSnapAlgorithm;
 import com.android.internal.policy.DividerSnapAlgorithm.SnapTarget;
@@ -127,10 +128,12 @@
     private float mAdjustImeAmount;
     private final int mDockedStackMinimizeThickness;
 
-    // If this is true, the task will be down or upscaled
-    // to perfectly fit the region it would have been cropped
-    // to.
-    private boolean mForceScaleToCrop = false;
+    // If this is true, we are in the bounds animating mode.
+    // The task will be down or upscaled to perfectly fit the
+    // region it would have been cropped to. We may also avoid
+    // certain logic we would otherwise apply while resizing,
+    // while resizing in the bounds animating mode.
+    private boolean mBoundsAnimating = false;
     // By default, movement animations are applied to all
     // window movement. If this is true, animations will not
     // be applied within this stack. This is useful for example
@@ -1269,11 +1272,36 @@
         return true;
     }
 
+    void forceWindowsScaleable(boolean force) {
+        SurfaceControl.openTransaction();
+        try {
+            for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) {
+                final ArrayList<AppWindowToken> activities = mTasks.get(taskNdx).mAppTokens;
+                for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
+                    final ArrayList<WindowState> windows = activities.get(activityNdx).allAppWindows;
+                    for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
+                        final WindowStateAnimator winAnimator = windows.get(winNdx).mWinAnimator;
+                        if (winAnimator == null || !winAnimator.hasSurface()) {
+                            continue;
+                        }
+                        winAnimator.mSurfaceController.forceScaleableInTransaction(force);
+                    }
+                }
+            }
+        } finally {
+            SurfaceControl.closeTransaction();
+        }
+    }
+
     @Override  // AnimatesBounds
     public void onAnimationStart() {
         synchronized (mService.mWindowMap) {
+            // We force windows out of SCALING_MODE_FREEZE
+            // so that we can continue to animate them
+            // while a resize is pending.
+            forceWindowsScaleable(true);
             mFreezeMovementAnimations = true;
-            mForceScaleToCrop = true;
+            mBoundsAnimating = true;
         }
     }
 
@@ -1281,7 +1309,8 @@
     public void onAnimationEnd() {
         synchronized (mService.mWindowMap) {
             mFreezeMovementAnimations = false;
-            mForceScaleToCrop = false;
+            mBoundsAnimating = false;
+            forceWindowsScaleable(false);
             mService.requestTraversal();
         }
         if (mStackId == PINNED_STACK_ID) {
@@ -1312,6 +1341,10 @@
     }
 
     public boolean getForceScaleToCrop() {
-        return mForceScaleToCrop;
+        return mBoundsAnimating;
+    }
+
+    public boolean getBoundsAnimating() {
+        return mBoundsAnimating;
     }
 }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 79ff78e..38f12a1 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -1563,6 +1563,16 @@
                     mLayersController.setInputMethodAnimLayerAdjustment(0);
                 }
             }
+
+            // If the docked divider is visible, we still need to go through this whole
+            // excercise to find the appropriate input method target (used for animations
+            // and dialog adjustments), but for purposes of Z ordering we simply wish to
+            // place it above the docked divider.
+            WindowState dockedDivider = w.mDisplayContent.mDividerControllerLocked.getWindow();
+            if (dockedDivider != null && dockedDivider.isVisibleLw()) {
+                int dividerIndex = windows.indexOf(dockedDivider);
+                return dividerIndex > 0 ? dividerIndex + 1 : i + 1;
+            }
             return i+1;
         }
         if (willMove) {
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 5077f32..76fdda01 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2382,6 +2382,9 @@
                 if (stack != null) {
                     pw.print(" stackId="); pw.print(stack.mStackId);
                 }
+                if (mNotOnAppsDisplay) {
+                    pw.print(" mNotOnAppsDisplay="); pw.print(mNotOnAppsDisplay);
+                }
                 pw.print(" mSession="); pw.print(mSession);
                 pw.print(" mClient="); pw.println(mClient.asBinder());
         pw.print(prefix); pw.print("mOwnerUid="); pw.print(mOwnerUid);
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 1f76f31..8c29c9b 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -562,6 +562,7 @@
             Slog.v(TAG, "Finishing drawing window " + mWin + ": mDrawState="
                     + drawStateToString());
         }
+
         if (mWin.mAppToken != null && mWin.mAppToken.mAnimatingWithSavedSurface) {
             // App has drawn something to its windows, we're no longer animating with
             // the saved surfaces. If the user exits now, we only want to save again
@@ -1290,6 +1291,17 @@
     }
     private void adjustCropToStackBounds(WindowState w, Rect clipRect, Rect finalClipRect,
             boolean isFreeformResizing) {
+
+        final DisplayContent displayContent = w.getDisplayContent();
+        if (displayContent != null && !displayContent.isDefaultDisplay) {
+            // There are some windows that live on other displays while their app and main window
+            // live on the default display (e.g. casting...). We don't want to crop this windows
+            // to the stack bounds which is only currently supported on the default display.
+            // TODO(multi-display): Need to support cropping to stack bounds on other displays
+            // when we have stacks on other displays.
+            return;
+        }
+
         final Task task = w.getTask();
         if (task == null || !task.cropWindowsToStackBounds()) {
             return;
@@ -1352,7 +1364,7 @@
         final Task task = w.getTask();
 
         // We got resized, so block all updates until we got the new surface.
-        if (w.mResizedWhileNotDragResizing) {
+        if (w.mResizedWhileNotDragResizing && !w.isGoneForLayoutLw()) {
             return;
         }
 
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index 8799c61..6eed5e7 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -23,6 +23,8 @@
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+import static android.view.Surface.SCALING_MODE_FREEZE;
+import static android.view.Surface.SCALING_MODE_SCALE_TO_WINDOW;
 
 import android.graphics.Point;
 import android.graphics.PointF;
@@ -392,6 +394,13 @@
         mSurfaceControl.deferTransactionUntil(handle, frame);
     }
 
+    void forceScaleableInTransaction(boolean force) {
+        // -1 means we don't override the default or client specified
+        // scaling mode.
+        int scalingMode = force ? SCALING_MODE_SCALE_TO_WINDOW : -1;
+        mSurfaceControl.setOverrideScalingMode(scalingMode);
+    }
+
     boolean clearWindowContentFrameStats() {
         if (mSurfaceControl == null) {
             return false;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index d3d05f3..45a7311 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -2909,6 +2909,54 @@
         }
     }
 
+    public void forceRemoveActiveAdmin(ComponentName adminReceiver, int userHandle) {
+        if (!mHasFeature) {
+            return;
+        }
+        Preconditions.checkNotNull(adminReceiver, "ComponentName is null");
+        enforceShell("forceRemoveActiveAdmin");
+        long ident = mInjector.binderClearCallingIdentity();
+        try {
+            final ApplicationInfo ai;
+            try {
+                ai = mIPackageManager.getApplicationInfo(adminReceiver.getPackageName(),
+                        0, userHandle);
+            } catch (RemoteException e) {
+                throw new IllegalStateException(e);
+            }
+            if (ai == null) {
+                throw new IllegalStateException("Couldn't find package to remove admin "
+                        + adminReceiver.getPackageName() + " " + userHandle);
+            }
+            if ((ai.flags & ApplicationInfo.FLAG_TEST_ONLY) == 0) {
+                throw new SecurityException("Attempt to remove non-test admin " + adminReceiver
+                        + adminReceiver + " " + userHandle);
+            }
+            // If admin is a device or profile owner tidy that up first.
+            synchronized (this)  {
+                if (isDeviceOwner(adminReceiver, userHandle)) {
+                    clearDeviceOwnerLocked(getDeviceOwnerAdminLocked(), userHandle);
+                }
+                if (isProfileOwner(adminReceiver, userHandle)) {
+                    final ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver,
+                            userHandle, /* parent */ false);
+                    clearProfileOwnerLocked(admin, userHandle);
+                }
+            }
+            // Remove the admin skipping sending the broadcast.
+            removeAdminArtifacts(adminReceiver, userHandle);
+        } finally {
+            mInjector.binderRestoreCallingIdentity(ident);
+        }
+    }
+
+    private void enforceShell(String method) {
+        final int callingUid = Binder.getCallingUid();
+        if (callingUid != Process.SHELL_UID && callingUid != Process.ROOT_UID) {
+            throw new SecurityException("Non-shell user attempted to call " + method);
+        }
+    }
+
     @Override
     public void removeActiveAdmin(ComponentName adminReceiver, int userHandle) {
         if (!mHasFeature) {
@@ -5732,32 +5780,37 @@
             enforceUserUnlocked(deviceOwnerUserId);
 
             final ActiveAdmin admin = getDeviceOwnerAdminLocked();
-            if (admin != null) {
-                admin.disableCamera = false;
-                admin.userRestrictions = null;
-                admin.forceEphemeralUsers = false;
-                mUserManagerInternal.setForceEphemeralUsers(admin.forceEphemeralUsers);
-            }
-            clearUserPoliciesLocked(deviceOwnerUserId);
-
-            mOwners.clearDeviceOwner();
-            mOwners.writeDeviceOwner();
-            updateDeviceOwnerLocked();
-            disableSecurityLoggingIfNotCompliant();
-            // Reactivate backup service.
             long ident = mInjector.binderClearCallingIdentity();
             try {
-                mInjector.getIBackupManager().setBackupServiceActive(UserHandle.USER_SYSTEM, true);
-
+                clearDeviceOwnerLocked(admin, deviceOwnerUserId);
                 removeActiveAdminLocked(deviceOwnerComponent, deviceOwnerUserId);
-            } catch (RemoteException e) {
-                throw new IllegalStateException("Failed reactivating backup service.", e);
             } finally {
                 mInjector.binderRestoreCallingIdentity(ident);
             }
         }
     }
 
+    private void clearDeviceOwnerLocked(ActiveAdmin admin, int userId) {
+        if (admin != null) {
+            admin.disableCamera = false;
+            admin.userRestrictions = null;
+            admin.forceEphemeralUsers = false;
+            mUserManagerInternal.setForceEphemeralUsers(admin.forceEphemeralUsers);
+        }
+        clearUserPoliciesLocked(userId);
+
+        mOwners.clearDeviceOwner();
+        mOwners.writeDeviceOwner();
+        updateDeviceOwnerLocked();
+        disableSecurityLoggingIfNotCompliant();
+        try {
+            // Reactivate backup service.
+            mInjector.getIBackupManager().setBackupServiceActive(UserHandle.USER_SYSTEM, true);
+        } catch (RemoteException e) {
+            throw new IllegalStateException("Failed reactivating backup service.", e);
+        }
+    }
+
     @Override
     public boolean setProfileOwner(ComponentName who, String ownerName, int userHandle) {
         if (!mHasFeature) {
@@ -5794,14 +5847,9 @@
         final ActiveAdmin admin =
                 getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
         synchronized (this) {
-            admin.disableCamera = false;
-            admin.userRestrictions = null;
-            clearUserPoliciesLocked(userId);
-            mOwners.removeProfileOwner(userId);
-            mOwners.writeProfileOwner(userId);
-
             final long ident = mInjector.binderClearCallingIdentity();
             try {
+                clearProfileOwnerLocked(admin, userId);
                 removeActiveAdminLocked(who, userId);
             } finally {
                 mInjector.binderRestoreCallingIdentity(ident);
@@ -5809,6 +5857,16 @@
         }
     }
 
+    public void clearProfileOwnerLocked(ActiveAdmin admin, int userId) {
+        if (admin != null) {
+            admin.disableCamera = false;
+            admin.userRestrictions = null;
+        }
+        clearUserPoliciesLocked(userId);
+        mOwners.removeProfileOwner(userId);
+        mOwners.writeProfileOwner(userId);
+    }
+
     @Override
     public void setDeviceOwnerLockScreenInfo(ComponentName who, CharSequence info) {
         Preconditions.checkNotNull(who, "ComponentName is null");
@@ -5842,15 +5900,13 @@
         policy.mUserProvisioningState = DevicePolicyManager.STATE_USER_UNMANAGED;
         saveSettingsLocked(userId);
 
-        final long ident = mInjector.binderClearCallingIdentity();
         try {
             mIPackageManager.updatePermissionFlagsForAllApps(
                     PackageManager.FLAG_PERMISSION_POLICY_FIXED,
                     0  /* flagValues */, userId);
             pushUserRestrictions(userId);
         } catch (RemoteException re) {
-        } finally {
-            mInjector.binderRestoreCallingIdentity(ident);
+            // Shouldn't happen.
         }
     }
 
diff --git a/services/tests/servicestests/Android.mk b/services/tests/servicestests/Android.mk
index 7ffdb35..59c6970 100644
--- a/services/tests/servicestests/Android.mk
+++ b/services/tests/servicestests/Android.mk
@@ -28,10 +28,22 @@
 
 LOCAL_CERTIFICATE := platform
 
-LOCAL_JNI_SHARED_LIBRARIES := \
-    libapfjni \
+# These are not normally accessible from apps so they must be explicitly included.
+LOCAL_JNI_SHARED_LIBRARIES := libservicestestsjni \
+    libbacktrace \
+    libbase \
+    libbinder \
     libc++ \
-    libnativehelper
+    libcutils \
+    liblog \
+    liblzma \
+    libnativehelper \
+    libnetdaidl \
+    libui \
+    libunwind \
+    libutils
+
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 
 include $(BUILD_PACKAGE)
 
@@ -45,22 +57,24 @@
 
 LOCAL_MODULE_TAGS := tests
 
-LOCAL_CFLAGS := -Wall -Werror
+LOCAL_CFLAGS := -Wall -Wextra -Werror
 
 LOCAL_C_INCLUDES := \
   libpcap \
   hardware/google/apf
 
-LOCAL_SRC_FILES := apf_jni.cpp
+LOCAL_SRC_FILES := $(call all-cpp-files-under)
 
 LOCAL_SHARED_LIBRARIES := \
+  libbinder \
+  libcutils \
   libnativehelper \
-  liblog
+  libnetdaidl
 
 LOCAL_STATIC_LIBRARIES := \
   libpcap \
   libapf
 
-LOCAL_MODULE := libapfjni
+LOCAL_MODULE := libservicestestsjni
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/services/tests/servicestests/jni/UidRangeTest.cpp b/services/tests/servicestests/jni/UidRangeTest.cpp
new file mode 100644
index 0000000..7941731
--- /dev/null
+++ b/services/tests/servicestests/jni/UidRangeTest.cpp
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <memory>
+
+#include <binder/Parcel.h>
+
+#include "UidRangeTest.h"
+
+using android::net::UidRange;
+
+extern "C"
+JNIEXPORT jbyteArray Java_android_net_UidRangeTest_readAndWriteNative(JNIEnv* env, jclass,
+        jbyteArray inParcel) {
+    const UidRange range = unmarshall(env, inParcel);
+    return marshall(env, range);
+}
+
+extern "C"
+JNIEXPORT jint Java_android_net_UidRangeTest_getStart(JNIEnv* env, jclass, jbyteArray inParcel) {
+    const UidRange range = unmarshall(env, inParcel);
+    return range.getStart();
+}
+
+extern "C"
+JNIEXPORT jint Java_android_net_UidRangeTest_getStop(JNIEnv* env, jclass, jbyteArray inParcel) {
+    const UidRange range = unmarshall(env, inParcel);
+    return range.getStop();
+}
+
+
+/**
+ * Reads exactly one UidRange from 'parcelData' assuming that it is a Parcel. Any bytes afterward
+ * are ignored.
+ */
+UidRange unmarshall(JNIEnv* env, jbyteArray parcelData) {
+    const int length = env->GetArrayLength(parcelData);
+
+    std::unique_ptr<uint8_t> bytes(new uint8_t[length]);
+    env->GetByteArrayRegion(parcelData, 0, length, reinterpret_cast<jbyte*>(bytes.get()));
+
+    android::Parcel p;
+    p.setData(bytes.get(), length);
+
+    UidRange range;
+    range.readFromParcel(&p);
+    return range;
+}
+
+/**
+ * Creates a Java byte[] array and writes the contents of 'range' to it as a Parcel containing
+ * exactly one object.
+ *
+ * Every UidRange maps to a unique parcel object, so both 'marshall(e, unmarshall(e, x))' and
+ * 'unmarshall(e, marshall(e, x))' should be fixed points.
+ */
+jbyteArray marshall(JNIEnv* env, const UidRange& range) {
+    android::Parcel p;
+    range.writeToParcel(&p);
+    const int length = p.dataSize();
+
+    jbyteArray parcelData = env->NewByteArray(length);
+    env->SetByteArrayRegion(parcelData, 0, length, reinterpret_cast<const jbyte*>(p.data()));
+
+    return parcelData;
+}
diff --git a/services/tests/servicestests/jni/UidRangeTest.h b/services/tests/servicestests/jni/UidRangeTest.h
new file mode 100644
index 0000000..b7e7453
--- /dev/null
+++ b/services/tests/servicestests/jni/UidRangeTest.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _ANDROID_NET_UIDRANGETEST_H_
+#define _ANDROID_NET_UIDRANGETEST_H_
+
+#include <jni.h>
+
+#include "android/net/UidRange.h"
+
+android::net::UidRange unmarshall(JNIEnv* env, jbyteArray parcelData);
+
+jbyteArray marshall(JNIEnv* env, const android::net::UidRange& range);
+
+extern "C"
+JNIEXPORT jbyteArray Java_android_net_UidRangeTest_readAndWriteNative(JNIEnv* env, jclass,
+        jbyteArray inParcel);
+
+extern "C"
+JNIEXPORT jint Java_android_net_UidRangeTest_getStart(JNIEnv* env, jclass, jbyteArray inParcel);
+
+extern "C"
+JNIEXPORT jint Java_android_net_UidRangeTest_getStop(JNIEnv* env, jclass, jbyteArray inParcel);
+
+#endif  //  _ANDROID_NET_UIDRANGETEST_H_
diff --git a/services/tests/servicestests/src/android/net/UidRangeTest.java b/services/tests/servicestests/src/android/net/UidRangeTest.java
new file mode 100644
index 0000000..221fe0f
--- /dev/null
+++ b/services/tests/servicestests/src/android/net/UidRangeTest.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import android.os.Parcel;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import junit.framework.TestCase;
+
+import static org.junit.Assert.assertArrayEquals;
+
+public class UidRangeTest extends TestCase {
+
+    static {
+        System.loadLibrary("servicestestsjni");
+    }
+
+    private static native byte[] readAndWriteNative(byte[] inParcel);
+    private static native int getStart(byte[] inParcel);
+    private static native int getStop(byte[] inParcel);
+
+    @SmallTest
+    public void testNativeParcelUnparcel() {
+        UidRange original = new UidRange(1234, Integer.MAX_VALUE);
+
+        byte[] inParcel = marshall(original);
+        byte[] outParcel = readAndWriteNative(inParcel);
+        UidRange roundTrip = unmarshall(outParcel);
+
+        assertEquals(original, roundTrip);
+        assertArrayEquals(inParcel, outParcel);
+    }
+
+    @SmallTest
+    public void testIndividualNativeFields() {
+        UidRange original = new UidRange(0x11115678, 0x22224321);
+        byte[] originalBytes = marshall(original);
+
+        assertEquals(original.start, getStart(originalBytes));
+        assertEquals(original.stop, getStop(originalBytes));
+    }
+
+    @SmallTest
+    public void testSingleItemUidRangeAllowed() {
+        new UidRange(123, 123);
+        new UidRange(0, 0);
+        new UidRange(Integer.MAX_VALUE, Integer.MAX_VALUE);
+    }
+
+    @SmallTest
+    public void testNegativeUidsDisallowed() {
+        try {
+            new UidRange(-2, 100);
+            fail("Exception not thrown for negative start UID");
+        } catch (IllegalArgumentException expected) {
+        }
+
+        try {
+            new UidRange(-200, -100);
+            fail("Exception not thrown for negative stop UID");
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
+    @SmallTest
+    public void testStopLessThanStartDisallowed() {
+        final int x = 4195000;
+        try {
+            new UidRange(x, x - 1);
+            fail("Exception not thrown for negative-length UID range");
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
+    /**
+     * Write a {@link UidRange} into an empty parcel and return the underlying data.
+     *
+     * @see unmarshall(byte[])
+     */
+    private static byte[] marshall(UidRange range) {
+        Parcel p = Parcel.obtain();
+        range.writeToParcel(p, /* flags */ 0);
+        p.setDataPosition(0);
+        return p.marshall();
+    }
+
+    /**
+     * Read raw bytes into a parcel, and read a {@link UidRange} back out of them.
+     *
+     * @see marshall(UidRange)
+     */
+    private static UidRange unmarshall(byte[] data) {
+        Parcel p = Parcel.obtain();
+        p.unmarshall(data, 0, data.length);
+        p.setDataPosition(0);
+        return UidRange.CREATOR.createFromParcel(p);
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/ApfTest.java b/services/tests/servicestests/src/com/android/server/ApfTest.java
index 640a6c9..9ba27cb 100644
--- a/services/tests/servicestests/src/com/android/server/ApfTest.java
+++ b/services/tests/servicestests/src/com/android/server/ApfTest.java
@@ -43,7 +43,7 @@
     public void setUp() throws Exception {
         super.setUp();
         // Load up native shared library containing APF interpreter exposed via JNI.
-        System.loadLibrary("apfjni");
+        System.loadLibrary("servicestestsjni");
     }
 
     // Expected return codes from APF interpreter.
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index 837b4a4..386c3aa 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -128,6 +128,12 @@
     }
 
     @Override
+    public void onUnlockUser(int userHandle) {
+        mServiceStub.initForUser(userHandle);
+        mServiceStub.switchImplementationIfNeeded(false);
+    }
+
+    @Override
     public void onSwitchUser(int userHandle) {
         mServiceStub.switchUser(userHandle);
     }
@@ -362,6 +368,12 @@
             }
         }
 
+        void switchImplementationIfNeeded(boolean force) {
+            synchronized (this) {
+                switchImplementationIfNeededLocked(force);
+            }
+        }
+
         void switchImplementationIfNeededLocked(boolean force) {
             if (!mSafeMode) {
                 String curService = Settings.Secure.getStringForUser(
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 5ac697f..15d76fd 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -630,6 +630,20 @@
     public static final String KEY_MMS_USER_AGENT_STRING = "userAgent";
 
     /**
+     * If carriers require differentiate un-provisioned status: cold sim or out of credit sim
+     * a package name and activity name can be provided to launch a supported carrier application
+     * that check the sim provisioning status
+     * The first element is the package name and the second element is the activity name
+     * of the provisioning app
+     * example:
+     * <item>com.google.android.carrierPackageName</item>
+     * <item>com.google.android.carrierPackageName.CarrierActivityName</item>
+     * @hide
+     */
+     public static final String KEY_SIM_PROVISIONING_STATUS_DETECTION_CARRIER_APP_STRING_ARRAY =
+            "sim_state_detection_carrier_app_string_array";
+
+    /**
      * Determines whether the carrier supports making non-emergency phone calls while the phone is
      * in emergency callback mode.  Default value is {@code true}, meaning that non-emergency calls
      * are allowed in emergency callback mode.
@@ -798,6 +812,10 @@
         sDefaults.putString(KEY_MMS_USER_AGENT_STRING, "");
         sDefaults.putBoolean(KEY_ALLOW_NON_EMERGENCY_CALLS_IN_ECM_BOOL, true);
         sDefaults.putBoolean(KEY_USE_RCS_PRESENCE_BOOL, false);
+
+        // Used for Sim card State detection app
+        sDefaults.putStringArray(KEY_SIM_PROVISIONING_STATUS_DETECTION_CARRIER_APP_STRING_ARRAY,
+                null);
     }
 
     /**
diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java
index 6229ed9..b5cf212e 100644
--- a/telephony/java/android/telephony/SubscriptionInfo.java
+++ b/telephony/java/android/telephony/SubscriptionInfo.java
@@ -90,6 +90,14 @@
     private int mDataRoaming;
 
     /**
+     * Sim Provisioning Status:
+     * {@See SubscriptionManager#SIM_PROVISIONED}
+     * {@See SubscriptionManager#SIM_UNPROVISIONED_COLD}
+     * {@See SubscriptionManager#SIM_UNPROVISIONED_OUT_OF_CREDIT}
+     */
+    private int mSimProvisioningStatus;
+
+    /**
      * SIM Icon bitmap
      */
     private Bitmap mIconBitmap;
@@ -114,7 +122,7 @@
      */
     public SubscriptionInfo(int id, String iccId, int simSlotIndex, CharSequence displayName,
             CharSequence carrierName, int nameSource, int iconTint, String number, int roaming,
-            Bitmap icon, int mcc, int mnc, String countryIso) {
+            Bitmap icon, int mcc, int mnc, String countryIso, int simProvisioningStatus) {
         this.mId = id;
         this.mIccId = iccId;
         this.mSimSlotIndex = simSlotIndex;
@@ -128,6 +136,7 @@
         this.mMcc = mcc;
         this.mMnc = mnc;
         this.mCountryIso = countryIso;
+        this.mSimProvisioningStatus = simProvisioningStatus;
     }
 
     /**
@@ -264,6 +273,17 @@
     }
 
     /**
+     * @return Sim Provisioning Status
+     * {@See SubscriptionManager#SIM_PROVISIONED}
+     * {@See SubscriptionManager#SIM_UNPROVISIONED_COLD}
+     * {@See SubscriptionManager#SIM_UNPROVISIONED_OUT_OF_CREDIT}
+     * @hide
+     */
+    public int getSimProvisioningStatus() {
+        return this.mSimProvisioningStatus;
+    }
+
+    /**
      * @return the MCC.
      */
     public int getMcc() {
@@ -299,10 +319,12 @@
             int mcc = source.readInt();
             int mnc = source.readInt();
             String countryIso = source.readString();
+            int simProvisioningStatus = source.readInt();
             Bitmap iconBitmap = Bitmap.CREATOR.createFromParcel(source);
 
             return new SubscriptionInfo(id, iccId, simSlotIndex, displayName, carrierName,
-                    nameSource, iconTint, number, dataRoaming, iconBitmap, mcc, mnc, countryIso);
+                    nameSource, iconTint, number, dataRoaming, iconBitmap, mcc, mnc, countryIso,
+                    simProvisioningStatus);
         }
 
         @Override
@@ -325,6 +347,7 @@
         dest.writeInt(mMcc);
         dest.writeInt(mMnc);
         dest.writeString(mCountryIso);
+        dest.writeInt(mSimProvisioningStatus);
         mIconBitmap.writeToParcel(dest, flags);
     }
 
@@ -355,6 +378,6 @@
                 + " displayName=" + mDisplayName + " carrierName=" + mCarrierName
                 + " nameSource=" + mNameSource + " iconTint=" + mIconTint
                 + " dataRoaming=" + mDataRoaming + " iconBitmap=" + mIconBitmap + " mcc " + mMcc
-                + " mnc " + mMnc + "}";
+                + " mnc " + mMnc + " SimProvisioningStatus " + mSimProvisioningStatus +"}";
     }
 }
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index f3b0ce2..c49966a 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -232,6 +232,22 @@
     /** Indicates that data roaming is disabled for a subscription */
     public static final int DATA_ROAMING_DISABLE = 0;
 
+    /** Sim provisioning status: provisioned */
+    /** @hide */
+    public static final int SIM_PROVISIONED = 0;
+
+    /** Sim provisioning status: un-provisioned due to cold sim */
+    /** @hide */
+    public static final int SIM_UNPROVISIONED_COLD = 1;
+
+    /** Sim provisioning status: un-provisioned due to out of credit */
+    /** @hide */
+    public static final int SIM_UNPROVISIONED_OUT_OF_CREDIT = 2;
+
+    /** Maximum possible sim provisioning status */
+    /** @hide */
+    public static final int MAX_SIM_PROVISIONING_STATUS = SIM_UNPROVISIONED_OUT_OF_CREDIT;
+
     /** @hide */
     public static final int DATA_ROAMING_DEFAULT = DATA_ROAMING_DISABLE;
 
@@ -250,6 +266,13 @@
     public static final String MNC = "mnc";
 
     /**
+     * TelephonyProvider column name for the sim provisioning status associated with a SIM.
+     * <P>Type: INTEGER (int)</P>
+     * @hide
+     */
+    public static final String SIM_PROVISIONING_STATUS = "sim_provisioning_status";
+
+    /**
      *  TelephonyProvider column name for extreme threat in CB settings
      * @hide
      */
@@ -820,6 +843,40 @@
     }
 
     /**
+     * Set Sim Provisioning Status by subscription ID
+     * @param simProvisioningStatus with the subscription
+     * {@See SubscriptionManager#SIM_PROVISIONED}
+     * {@See SubscriptionManager#SIM_UNPROVISIONED_COLD}
+     * {@See SubscriptionManager#SIM_UNPROVISIONED_OUT_OF_CREDIT}
+     * @param subId the unique SubInfoRecord index in database
+     * @return the number of records updated
+     * Permissions android.Manifest.permission.MODIFY_PHONE_STATE is required
+     * @hide
+     */
+    public int setSimProvisioningStatus(int simProvisioningStatus, int subId) {
+        if (VDBG) {
+            logd("[setSimProvisioningStatus]+ status:" + simProvisioningStatus + " subId:" + subId);
+        }
+        if (simProvisioningStatus < 0 || simProvisioningStatus > MAX_SIM_PROVISIONING_STATUS ||
+                !isValidSubscriptionId(subId)) {
+            logd("[setSimProvisioningStatus]- fail");
+            return -1;
+        }
+
+        int result = 0;
+
+        try {
+            ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
+            if (iSub != null) {
+                result = iSub.setSimProvisioningStatus(simProvisioningStatus, subId);
+            }
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+        return result;
+    }
+
+    /**
      * Get slotId associated with the subscription.
      * @return slotId as a positive integer or a negative value if an error either
      * SIM_NOT_INSERTED or < 0 if an invalid slot index
diff --git a/telephony/java/com/android/internal/telephony/DctConstants.java b/telephony/java/com/android/internal/telephony/DctConstants.java
index ccabace..e4981ce 100644
--- a/telephony/java/com/android/internal/telephony/DctConstants.java
+++ b/telephony/java/com/android/internal/telephony/DctConstants.java
@@ -103,6 +103,7 @@
     public static final int EVENT_DATA_RAT_CHANGED = BASE + 41;
     public static final int CMD_CLEAR_PROVISIONING_SPINNER = BASE + 42;
     public static final int EVENT_DEVICE_PROVISIONED_CHANGE = BASE + 43;
+    public static final int EVENT_REDIRECTION_DETECTED = BASE + 44;
 
     /***** Constants *****/
 
diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl
index f6aef08..c61ed2a 100755
--- a/telephony/java/com/android/internal/telephony/ISub.aidl
+++ b/telephony/java/com/android/internal/telephony/ISub.aidl
@@ -118,6 +118,17 @@
     int setDisplayName(String displayName, int subId);
 
     /**
+     * Set Sim Provisioning Status by subscription ID
+     * @param simProvisionStatus with the subscription:
+     * {@See SubscriptionManager#SIM_PROVISIONED}
+     * {@See SubscriptionManager#SIM_UNPROVISIONED_COLD}
+     * {@See SubscriptionManager#SIM_UNPROVISIONED_OUT_OF_CREDIT}
+     * @param subId the unique SubInfoRecord index in database
+     * @return the number of records updated
+     */
+    int setSimProvisioningStatus(int simProvisioningStatus, int subId);
+
+    /**
      * Set display name by simInfo index with name source
      * @param displayName the display name of SIM card
      * @param subId the unique SubscriptionInfo index in database
diff --git a/telephony/java/com/android/internal/telephony/TelephonyIntents.java b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
index c70f8cf..eafb3d4 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyIntents.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
@@ -395,4 +395,32 @@
      */
     public static final String ACTION_SET_RADIO_CAPABILITY_FAILED =
             "android.intent.action.ACTION_SET_RADIO_CAPABILITY_FAILED";
+
+    /**
+     * <p>Broadcast Action: when data connections get redirected with validation failure.
+     * intended for sim/account status checks and only sent to the specified carrier app
+     * feedback is via carrier/system APIs to report cold-sim, out-of-credit-sim, etc
+     * The intent will have the following extra values:</p>
+     * <ul>
+     *   <li>redirectUrl</li><dd>A string with the redirection url info.</dd>
+     *   <li>subId</li><dd>Sub Id which associated the data redirection.</dd>
+     * </ul>
+     * <p class="note">This is a protected intent that can only be sent by the system.</p>
+     */
+    public static final String ACTION_DATA_CONNECTION_REDIRECTED =
+            "android.intent.action.REDIRECTION_DETECTED";
+    /**
+     * <p>Broadcast Action: when data connections setup fails.
+     * intended for sim/account status checks and only sent to the specified carrier app
+     * feedback is via carrier/system APIs to report cold-sim, out-of-credit-sim, etc
+     * The intent will have the following extra values:</p>
+     * <ul>
+     *   <li>apnType</li><dd>A string with the apn type.</dd>
+     *   <li>errorCode</li><dd>A integer with dataFailCause.</dd>
+     *   <li>subId</dt><li>Sub Id which associated the data redirection.</dd>
+     * </ul>
+     * <p class="note">This is a protected intent that can only be sent by the system. </p>
+     */
+    public static final String ACTION_REQUEST_NETWORK_FAILED =
+            "android.intent.action.REQUEST_NETWORK_FAILED";
 }