Merge "Cleanup zen rule instances."
diff --git a/api/current.txt b/api/current.txt
index 59b8fb3..8674eef 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -7908,6 +7908,7 @@
     field public static final int MODE_APPEND = 32768; // 0x8000
     field public static final int MODE_ENABLE_WRITE_AHEAD_LOGGING = 8; // 0x8
     field public static final deprecated int MODE_MULTI_PROCESS = 4; // 0x4
+    field public static final int MODE_NO_LOCALIZED_COLLATORS = 16; // 0x10
     field public static final int MODE_PRIVATE = 0; // 0x0
     field public static final deprecated int MODE_WORLD_READABLE = 1; // 0x1
     field public static final deprecated int MODE_WORLD_WRITEABLE = 2; // 0x2
@@ -28060,6 +28061,7 @@
     method public boolean isUserAGoat();
     method public boolean isUserRunning(android.os.UserHandle);
     method public boolean isUserRunningOrStopping(android.os.UserHandle);
+    method public boolean isUserRunningUnlocked(android.os.UserHandle);
     method public deprecated boolean setRestrictionsChallenge(java.lang.String);
     method public deprecated void setUserRestriction(java.lang.String, boolean);
     method public deprecated void setUserRestrictions(android.os.Bundle);
@@ -28864,6 +28866,8 @@
     method public boolean isFailed();
     method public boolean isQueued();
     method public boolean isStarted();
+    method public void setProgress(float);
+    method public void setStatus(java.lang.CharSequence);
     method public boolean setTag(java.lang.String);
     method public boolean start();
   }
diff --git a/api/system-current.txt b/api/system-current.txt
index f029568..ef3361b 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -8155,6 +8155,7 @@
     field public static final int MODE_APPEND = 32768; // 0x8000
     field public static final int MODE_ENABLE_WRITE_AHEAD_LOGGING = 8; // 0x8
     field public static final deprecated int MODE_MULTI_PROCESS = 4; // 0x4
+    field public static final int MODE_NO_LOCALIZED_COLLATORS = 16; // 0x10
     field public static final int MODE_PRIVATE = 0; // 0x0
     field public static final deprecated int MODE_WORLD_READABLE = 1; // 0x1
     field public static final deprecated int MODE_WORLD_WRITEABLE = 2; // 0x2
@@ -30043,6 +30044,7 @@
     method public boolean isUserAGoat();
     method public boolean isUserRunning(android.os.UserHandle);
     method public boolean isUserRunningOrStopping(android.os.UserHandle);
+    method public boolean isUserRunningUnlocked(android.os.UserHandle);
     method public deprecated boolean setRestrictionsChallenge(java.lang.String);
     method public deprecated void setUserRestriction(java.lang.String, boolean);
     method public deprecated void setUserRestrictions(android.os.Bundle);
@@ -30847,6 +30849,8 @@
     method public boolean isFailed();
     method public boolean isQueued();
     method public boolean isStarted();
+    method public void setProgress(float);
+    method public void setStatus(java.lang.CharSequence);
     method public boolean setTag(java.lang.String);
     method public boolean start();
   }
diff --git a/api/test-current.txt b/api/test-current.txt
index 59b8fb3..2eb4356 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -7908,6 +7908,7 @@
     field public static final int MODE_APPEND = 32768; // 0x8000
     field public static final int MODE_ENABLE_WRITE_AHEAD_LOGGING = 8; // 0x8
     field public static final deprecated int MODE_MULTI_PROCESS = 4; // 0x4
+    field public static final int MODE_NO_LOCALIZED_COLLATORS = 16; // 0x10
     field public static final int MODE_PRIVATE = 0; // 0x0
     field public static final deprecated int MODE_WORLD_READABLE = 1; // 0x1
     field public static final deprecated int MODE_WORLD_WRITEABLE = 2; // 0x2
@@ -28060,6 +28061,7 @@
     method public boolean isUserAGoat();
     method public boolean isUserRunning(android.os.UserHandle);
     method public boolean isUserRunningOrStopping(android.os.UserHandle);
+    method public boolean isUserRunningUnlocked(android.os.UserHandle);
     method public deprecated boolean setRestrictionsChallenge(java.lang.String);
     method public deprecated void setUserRestriction(java.lang.String, boolean);
     method public deprecated void setUserRestrictions(android.os.Bundle);
@@ -28745,7 +28747,9 @@
     method public java.lang.String getLabel();
     method public android.print.PageRange[] getPages();
     method public android.print.PrinterId getPrinterId();
+    method public float getProgress();
     method public int getState();
+    method public java.lang.CharSequence getStatus();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.print.PrintJobInfo> CREATOR;
     field public static final int STATE_BLOCKED = 4; // 0x4
@@ -28864,6 +28868,8 @@
     method public boolean isFailed();
     method public boolean isQueued();
     method public boolean isStarted();
+    method public void setProgress(float);
+    method public void setStatus(java.lang.CharSequence);
     method public boolean setTag(java.lang.String);
     method public boolean start();
   }
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index daf01ec..2ad63b5 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -154,7 +154,7 @@
                 "       am switch-user <USER_ID>\n" +
                 "       am start-user <USER_ID>\n" +
                 "       am unlock-user <USER_ID> [TOKEN_HEX]\n" +
-                "       am stop-user [-w] <USER_ID>\n" +
+                "       am stop-user [-w] [-f] <USER_ID>\n" +
                 "       am stack start <DISPLAY_ID> <INTENT>\n" +
                 "       am stack movetask <TASK_ID> <STACK_ID> [true|false]\n" +
                 "       am stack resize <STACK_ID> <LEFT,TOP,RIGHT,BOTTOM>\n" +
@@ -290,6 +290,7 @@
                 "am stop-user: stop execution of USER_ID, not allowing it to run any\n" +
                 "  code until a later explicit start or switch to it.\n" +
                 "  -w: wait for stop-user to complete.\n" +
+                "  -f: force stop even if there are related users that cannot be stopped.\n" +
                 "\n" +
                 "am stack start: start a new activity on <DISPLAY_ID> using <INTENT>.\n" +
                 "\n" +
@@ -1131,10 +1132,13 @@
 
     private void runStopUser() throws Exception {
         boolean wait = false;
-        String opt = null;
+        boolean force = false;
+        String opt;
         while ((opt = nextOption()) != null) {
             if ("-w".equals(opt)) {
                 wait = true;
+            } else if ("-f".equals(opt)) {
+                force = true;
             } else {
                 System.err.println("Error: unknown option: " + opt);
                 return;
@@ -1143,7 +1147,7 @@
         int user = Integer.parseInt(nextArgRequired());
         StopUserCallback callback = wait ? new StopUserCallback() : null;
 
-        int res = mAm.stopUser(user, callback);
+        int res = mAm.stopUser(user, force, callback);
         if (res != ActivityManager.USER_OP_SUCCESS) {
             String txt = "";
             switch (res) {
@@ -1153,6 +1157,13 @@
                 case ActivityManager.USER_OP_UNKNOWN_USER:
                     txt = " (Unknown user " + user + ")";
                     break;
+                case ActivityManager.USER_OP_ERROR_IS_SYSTEM:
+                    txt = " (System user cannot be stopped)";
+                    break;
+                case ActivityManager.USER_OP_ERROR_RELATED_USERS_CANNOT_STOP:
+                    txt = " (Can't stop user " + user
+                            + " - one of its related users can't be stopped)";
+                    break;
             }
             System.err.println("Switch failed: " + res + txt);
         } else if (callback != null) {
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index f1a7de8..c203854 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -265,6 +265,12 @@
     /** @hide User operation call: given user id is the current user, can't be stopped. */
     public static final int USER_OP_IS_CURRENT = -2;
 
+    /** @hide User operation call: system user can't be stopped. */
+    public static final int USER_OP_ERROR_IS_SYSTEM = -3;
+
+    /** @hide User operation call: one of related users cannot be stopped. */
+    public static final int USER_OP_ERROR_RELATED_USERS_CANNOT_STOP = -4;
+
     /** @hide Process does not exist. */
     public static final int PROCESS_STATE_NONEXISTENT = -1;
 
@@ -537,6 +543,11 @@
             return stackId == FREEFORM_WORKSPACE_STACK_ID
                     || stackId == FULLSCREEN_WORKSPACE_STACK_ID || stackId == DOCKED_STACK_ID;
         }
+
+        /** Returns true if the windows in the stack can receive input keys. */
+        public static boolean canReceiveKeys(int stackId) {
+            return stackId != PINNED_STACK_ID;
+        }
     }
 
     /**
@@ -3085,6 +3096,8 @@
     public static final int FLAG_OR_STOPPED = 1 << 0;
     /** {@hide} */
     public static final int FLAG_AND_LOCKED = 1 << 1;
+    /** {@hide} */
+    public static final int FLAG_AND_UNLOCKED = 1 << 2;
 
     /**
      * Return whether the given user is actively running.  This means that
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 19d9fc2..c05d5e8 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1981,9 +1981,10 @@
         case STOP_USER_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             int userid = data.readInt();
+            boolean force = data.readInt() != 0;
             IStopUserCallback callback = IStopUserCallback.Stub.asInterface(
                     data.readStrongBinder());
-            int result = stopUser(userid, callback);
+            int result = stopUser(userid, force, callback);
             reply.writeNoException();
             reply.writeInt(result);
             return true;
@@ -5287,11 +5288,13 @@
         return result;
     }
 
-    public int stopUser(int userid, IStopUserCallback callback) throws RemoteException {
+    public int stopUser(int userid, boolean force, IStopUserCallback callback)
+            throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
         data.writeInt(userid);
+        data.writeInt(force ? 1 : 0);
         data.writeStrongInterface(callback);
         mRemote.transact(STOP_USER_TRANSACTION, data, reply, 0);
         reply.readException();
diff --git a/core/java/android/app/AlarmManager.java b/core/java/android/app/AlarmManager.java
index bf2e13a..b569416 100644
--- a/core/java/android/app/AlarmManager.java
+++ b/core/java/android/app/AlarmManager.java
@@ -25,7 +25,6 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.RemoteException;
-import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.WorkSource;
 import android.text.TextUtils;
@@ -869,13 +868,19 @@
      * {@link Intent#filterEquals}), will be canceled.
      *
      * @param operation IntentSender which matches a previously added
-     * IntentSender.
+     * IntentSender. This parameter must not be {@code null}.
      *
      * @see #set
      */
     public void cancel(PendingIntent operation) {
         if (operation == null) {
-            throw new NullPointerException("operation");
+            final String msg = "cancel() called with a null PendingIntent";
+            if (mTargetSdkVersion >= Build.VERSION_CODES.N) {
+                throw new NullPointerException(msg);
+            } else {
+                Log.e(TAG, msg);
+                return;
+            }
         }
 
         try {
@@ -891,7 +896,7 @@
      */
     public void cancel(OnAlarmListener listener) {
         if (listener == null) {
-            throw new NullPointerException("listener");
+            throw new NullPointerException("cancel() called with a null OnAlarmListener");
         }
 
         ListenerWrapper wrapper = null;
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index c661107..23c4198 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -589,6 +589,9 @@
         if ((mode & MODE_ENABLE_WRITE_AHEAD_LOGGING) != 0) {
             flags |= SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING;
         }
+        if ((mode & MODE_NO_LOCALIZED_COLLATORS) != 0) {
+            flags |= SQLiteDatabase.NO_LOCALIZED_COLLATORS;
+        }
         SQLiteDatabase db = SQLiteDatabase.openDatabase(f.getPath(), factory, flags, errorHandler);
         setFilePermissionsFromMode(f.getPath(), mode, 0);
         return db;
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 09c6c0b..38c7957 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -391,7 +391,7 @@
     public boolean switchUser(int userid) throws RemoteException;
     public boolean startUserInBackground(int userid) throws RemoteException;
     public boolean unlockUser(int userid, byte[] token) throws RemoteException;
-    public int stopUser(int userid, IStopUserCallback callback) throws RemoteException;
+    public int stopUser(int userid, boolean force, IStopUserCallback callback) throws RemoteException;
     public UserInfo getCurrentUser() throws RemoteException;
     public boolean isUserRunning(int userid, int flags) throws RemoteException;
     public int[] getRunningUserIds() throws RemoteException;
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index b73fa50..6cc5497 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -159,6 +159,16 @@
      */
     public static final int MODE_ENABLE_WRITE_AHEAD_LOGGING = 0x0008;
 
+    /**
+     * Database open flag: when set, the database is opened without support for
+     * localized collators.
+     *
+     * @see #openOrCreateDatabase(String, int, CursorFactory)
+     * @see #openOrCreateDatabase(String, int, CursorFactory, DatabaseErrorHandler)
+     * @see SQLiteDatabase#NO_LOCALIZED_COLLATORS
+     */
+    public static final int MODE_NO_LOCALIZED_COLLATORS = 0x0010;
+
     /** @hide */
     @IntDef(flag = true,
             value = {
@@ -1271,6 +1281,7 @@
      *     default operation, {@link #MODE_WORLD_READABLE}
      *     and {@link #MODE_WORLD_WRITEABLE} to control permissions.
      *     Use {@link #MODE_ENABLE_WRITE_AHEAD_LOGGING} to enable write-ahead logging by default.
+     *     Use {@link #MODE_NO_LOCALIZED_COLLATORS} to disable localized collators.
      * @param factory An optional factory class that is called to instantiate a
      *     cursor when query is called.
      *
@@ -1281,6 +1292,7 @@
      * @see #MODE_WORLD_READABLE
      * @see #MODE_WORLD_WRITEABLE
      * @see #MODE_ENABLE_WRITE_AHEAD_LOGGING
+     * @see #MODE_NO_LOCALIZED_COLLATORS
      * @see #deleteDatabase
      */
     public abstract SQLiteDatabase openOrCreateDatabase(String name,
@@ -1298,6 +1310,7 @@
      *     default operation, {@link #MODE_WORLD_READABLE}
      *     and {@link #MODE_WORLD_WRITEABLE} to control permissions.
      *     Use {@link #MODE_ENABLE_WRITE_AHEAD_LOGGING} to enable write-ahead logging by default.
+     *     Use {@link #MODE_NO_LOCALIZED_COLLATORS} to disable localized collators.
      * @param factory An optional factory class that is called to instantiate a
      *     cursor when query is called.
      * @param errorHandler the {@link DatabaseErrorHandler} to be used when sqlite reports database
@@ -1309,6 +1322,7 @@
      * @see #MODE_WORLD_READABLE
      * @see #MODE_WORLD_WRITEABLE
      * @see #MODE_ENABLE_WRITE_AHEAD_LOGGING
+     * @see #MODE_NO_LOCALIZED_COLLATORS
      * @see #deleteDatabase
      */
     public abstract SQLiteDatabase openOrCreateDatabase(String name,
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 1aa5c66..bce38f4 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -169,7 +169,7 @@
     /**
      * Current version of checkin data format.
      */
-    static final String CHECKIN_VERSION = "16";
+    static final String CHECKIN_VERSION = "17";
 
     /**
      * Old version, we hit 9 and ran out of room, need to remove.
@@ -407,17 +407,23 @@
         public abstract Timer getCameraTurnedOnTimer();
         public abstract Timer getForegroundActivityTimer();
 
-        // Time this uid has any processes in foreground state.
-        public static final int PROCESS_STATE_FOREGROUND = 0;
-        // Time this uid has any process in active state (not cached).
-        public static final int PROCESS_STATE_ACTIVE = 1;
+        // Time this uid has any processes in the top state.
+        public static final int PROCESS_STATE_TOP = 0;
+        // Time this uid has any process with a started out bound foreground service.
+        public static final int PROCESS_STATE_FOREGROUND_SERVICE = 1;
+        // Time this uid has any process that is top while the device is sleeping.
+        public static final int PROCESS_STATE_TOP_SLEEPING = 2;
+        // Time this uid has any process in an active foreground state.
+        public static final int PROCESS_STATE_FOREGROUND = 3;
+        // Time this uid has any process in an active background state.
+        public static final int PROCESS_STATE_BACKGROUND = 4;
         // Time this uid has any processes running at all.
-        public static final int PROCESS_STATE_RUNNING = 2;
+        public static final int PROCESS_STATE_CACHED = 5;
         // Total number of process states we track.
-        public static final int NUM_PROCESS_STATE = 3;
+        public static final int NUM_PROCESS_STATE = 6;
 
         static final String[] PROCESS_STATE_NAMES = {
-            "Foreground", "Active", "Running"
+            "Top", "Fg Service", "Top Sleeping", "Foreground", "Background", "Cached"
         };
 
         public abstract long getProcessStateTime(int state, long elapsedRealtimeUs, int which);
@@ -2954,8 +2960,9 @@
             final Object[] stateTimes = new Object[Uid.NUM_PROCESS_STATE];
             long totalStateTime = 0;
             for (int ips=0; ips<Uid.NUM_PROCESS_STATE; ips++) {
-                totalStateTime += u.getProcessStateTime(ips, rawRealtime, which);
-                stateTimes[ips] = (totalStateTime + 500) / 1000;
+                final long time = u.getProcessStateTime(ips, rawRealtime, which);
+                totalStateTime += time;
+                stateTimes[ips] = (time + 500) / 1000;
             }
             if (totalStateTime > 0) {
                 dumpLine(pw, uid, category, STATE_TIME_DATA, stateTimes);
@@ -4122,11 +4129,18 @@
                     sb.append("    ");
                     sb.append(Uid.PROCESS_STATE_NAMES[ips]);
                     sb.append(" for: ");
-                    formatTimeMs(sb, (totalStateTime + 500) / 1000);
+                    formatTimeMs(sb, (time + 500) / 1000);
                     pw.println(sb.toString());
                     uidActivity = true;
                 }
             }
+            if (totalStateTime > 0) {
+                sb.setLength(0);
+                sb.append(prefix);
+                sb.append("    Total running: ");
+                formatTimeMs(sb, (totalStateTime + 500) / 1000);
+                pw.println(sb.toString());
+            }
 
             final long userCpuTimeUs = u.getUserCpuTimeUs(which);
             final long systemCpuTimeUs = u.getSystemCpuTimeUs(which);
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index f26693c..79390d4 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -487,6 +487,19 @@
     public static final String DISALLOW_RECORD_AUDIO = "no_record_audio";
 
     /**
+     * Specifies if a user is not allowed to run in the background and should be stopped during
+     * user switch. The default value is <code>false</code>.
+     *
+     * <p>This restriction can be set by device owners and profile owners.
+     *
+     * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+     * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
+     * @see #getUserRestrictions()
+     * @hide
+     */
+    public static final String DISALLOW_RUN_IN_BACKGROUND = "no_run_in_background";
+
+    /**
      * Specifies if a user is not allowed to use the camera.
      *
      * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
@@ -742,6 +755,23 @@
     }
 
     /**
+     * Return whether the given user is running in an "unlocked" state. A user
+     * is unlocked only after they've entered their credentials (such as a lock
+     * pattern or PIN), and credential-encrypted private app data storage is
+     * available.
+     *
+     * @param user to retrieve the unlocked state for.
+     */
+    public boolean isUserRunningUnlocked(UserHandle user) {
+        try {
+            return ActivityManagerNative.getDefault().isUserRunning(
+                    user.getIdentifier(), ActivityManager.FLAG_AND_UNLOCKED);
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+
+    /**
      * Returns the UserInfo object describing a specific user.
      * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
      * @param userHandle the user handle of the user whose information is being requested.
diff --git a/core/java/android/print/IPrintSpooler.aidl b/core/java/android/print/IPrintSpooler.aidl
index db2bf1a..b7cfbea 100644
--- a/core/java/android/print/IPrintSpooler.aidl
+++ b/core/java/android/print/IPrintSpooler.aidl
@@ -41,6 +41,23 @@
     void createPrintJob(in PrintJobInfo printJob);
     void setPrintJobState(in PrintJobId printJobId, int status, String stateReason,
             IPrintSpoolerCallbacks callback, int sequence);
+
+    /**
+     * Set the progress of this print job
+     *
+     * @param printJobId The print job to update
+     * @param progress The new progress
+     */
+    void setProgress(in PrintJobId printJobId, in float progress);
+
+    /**
+     * Set the status of this print job
+     *
+     * @param printJobId The print job to update
+     * @param status The new status, can be null
+     */
+    void setStatus(in PrintJobId printJobId, in CharSequence status);
+
     void setPrintJobTag(in PrintJobId printJobId, String tag, IPrintSpoolerCallbacks callback,
             int sequence);
     void writePrintJobData(in ParcelFileDescriptor fd, in PrintJobId printJobId);
diff --git a/core/java/android/print/PrintJobInfo.java b/core/java/android/print/PrintJobInfo.java
index 63f94fe..7148c87 100644
--- a/core/java/android/print/PrintJobInfo.java
+++ b/core/java/android/print/PrintJobInfo.java
@@ -16,10 +16,15 @@
 
 package android.print;
 
+import android.annotation.FloatRange;
+import android.annotation.Nullable;
+import android.annotation.TestApi;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import com.android.internal.util.Preconditions;
+
 import java.util.Arrays;
 
 /**
@@ -149,9 +154,6 @@
     /** How many copies to print. */
     private int mCopies;
 
-    /** Reason for the print job being in its current state. */
-    private String mStateReason;
-
     /** The pages to print */
     private PageRange[] mPageRanges;
 
@@ -161,6 +163,12 @@
     /** Information about the printed document. */
     private PrintDocumentInfo mDocumentInfo;
 
+    /** The progress made on printing this job or -1 if not set. */
+    private float mProgress;
+
+    /** A short string describing the status of this job. */
+    private CharSequence mStatus;
+
     /** Advanced printer specific options. */
     private Bundle mAdvancedOptions;
 
@@ -169,7 +177,7 @@
 
     /** @hide*/
     public PrintJobInfo() {
-        /* do nothing */
+        mProgress = -1;
     }
 
     /** @hide */
@@ -183,10 +191,11 @@
         mTag = other.mTag;
         mCreationTime = other.mCreationTime;
         mCopies = other.mCopies;
-        mStateReason = other.mStateReason;
         mPageRanges = other.mPageRanges;
         mAttributes = other.mAttributes;
         mDocumentInfo = other.mDocumentInfo;
+        mProgress = other.mProgress;
+        mStatus = other.mStatus;
         mCanceling = other.mCanceling;
         mAdvancedOptions = other.mAdvancedOptions;
     }
@@ -201,7 +210,6 @@
         mTag = parcel.readString();
         mCreationTime = parcel.readLong();
         mCopies = parcel.readInt();
-        mStateReason = parcel.readString();
         Parcelable[] parcelables = parcel.readParcelableArray(null);
         if (parcelables != null) {
             mPageRanges = new PageRange[parcelables.length];
@@ -211,6 +219,8 @@
         }
         mAttributes = (PrintAttributes) parcel.readParcelable(null);
         mDocumentInfo = (PrintDocumentInfo) parcel.readParcelable(null);
+        mProgress = parcel.readFloat();
+        mStatus = parcel.readCharSequence();
         mCanceling = (parcel.readInt() == 1);
         mAdvancedOptions = parcel.readBundle();
     }
@@ -227,7 +237,7 @@
     /**
      * Sets the unique print job id.
      *
-     * @param The job id.
+     * @param id The job id.
      *
      * @hide
      */
@@ -265,7 +275,7 @@
     }
 
     /**
-     * Sets the unique target pritner id.
+     * Sets the unique target printer id.
      *
      * @param printerId The target printer id.
      *
@@ -326,6 +336,30 @@
     }
 
     /**
+     * Sets the progress of the print job.
+     *
+     * @param progress the progress of the job
+     *
+     * @hide
+     */
+    public void setProgress(@FloatRange(from=0.0, to=1.0) float progress) {
+        Preconditions.checkArgumentInRange(progress, 0, 1, "progress");
+
+        mProgress = progress;
+    }
+
+    /**
+     * Sets the status of the print job.
+     *
+     * @param status the status of the job, can be null
+     *
+     * @hide
+     */
+    public void setStatus(@Nullable CharSequence status) {
+        mStatus = status;
+    }
+
+    /**
      * Sets the owning application id.
      *
      * @return The owning app id.
@@ -416,30 +450,6 @@
     }
 
     /**
-     * Gets the reason for the print job being in the current state.
-     *
-     * @return The reason, or null if there is no reason or the
-     * reason is unknown.
-     *
-     * @hide
-     */
-    public String getStateReason() {
-        return mStateReason;
-    }
-
-    /**
-     * Sets the reason for the print job being in the current state.
-     *
-     * @param stateReason The reason, or null if there is no reason
-     * or the reason is unknown.
-     *
-     * @hide
-     */
-    public void setStateReason(String stateReason) {
-        mStateReason = stateReason;
-    }
-
-    /**
      * Gets the included pages.
      *
      * @return The included pages or <code>null</code> if not set.
@@ -604,10 +614,11 @@
         parcel.writeString(mTag);
         parcel.writeLong(mCreationTime);
         parcel.writeInt(mCopies);
-        parcel.writeString(mStateReason);
         parcel.writeParcelableArray(mPageRanges, flags);
         parcel.writeParcelable(mAttributes, flags);
         parcel.writeParcelable(mDocumentInfo, 0);
+        parcel.writeFloat(mProgress);
+        parcel.writeCharSequence(mStatus);
         parcel.writeInt(mCanceling ? 1 : 0);
         parcel.writeBundle(mAdvancedOptions);
     }
@@ -631,6 +642,9 @@
         builder.append(", pages: " + (mPageRanges != null
                 ? Arrays.toString(mPageRanges) : null));
         builder.append(", hasAdvancedOptions: " + (mAdvancedOptions != null));
+        builder.append(", progress: " + mProgress);
+        builder.append(", status: " + (mStatus != null
+                ? mStatus.toString() : null));
         builder.append("}");
         return builder.toString();
     }
@@ -666,6 +680,28 @@
     }
 
     /**
+     * Get the progress that has been made printing this job.
+     *
+     * @return the print progress or -1 if not set
+     * @hide
+     */
+    @TestApi
+    public float getProgress() {
+        return mProgress;
+    }
+
+    /**
+     * Get the status of this job.
+     *
+     * @return the status of this job or null if not set
+     * @hide
+     */
+    @TestApi
+    public @Nullable CharSequence getStatus() {
+        return mStatus;
+    }
+
+    /**
      * Builder for creating a {@link PrintJobInfo}.
      */
     public static final class Builder {
@@ -711,6 +747,28 @@
         }
 
         /**
+         * Sets the progress of the print job.
+         *
+         * @param progress the progress of the job
+         * @hide
+         */
+        public void setProgress(@FloatRange(from=0.0, to=1.0) float progress) {
+            Preconditions.checkArgumentInRange(progress, 0, 1, "progress");
+
+            mPrototype.mProgress = progress;
+        }
+
+        /**
+         * Sets the status of the print job.
+         *
+         * @param status the status of the job, can be null
+         * @hide
+         */
+        public void setStatus(@Nullable CharSequence status) {
+            mPrototype.mStatus = status;
+        }
+
+        /**
          * Puts an advanced (printer specific) option.
          *
          * @param key The option key.
diff --git a/core/java/android/printservice/IPrintServiceClient.aidl b/core/java/android/printservice/IPrintServiceClient.aidl
index c2dfc30..b4baa48 100644
--- a/core/java/android/printservice/IPrintServiceClient.aidl
+++ b/core/java/android/printservice/IPrintServiceClient.aidl
@@ -35,6 +35,22 @@
     boolean setPrintJobTag(in PrintJobId printJobId, String tag);
     oneway void writePrintJobData(in ParcelFileDescriptor fd, in PrintJobId printJobId);
 
+    /**
+     * Set the progress of this print job
+     *
+     * @param printJobId The print job to update
+     * @param progress The new progress
+     */
+    void setProgress(in PrintJobId printJobId, in float progress);
+
+    /**
+     * Set the status of this print job
+     *
+     * @param printJobId The print job to update
+     * @param status The new status, can be null
+     */
+    void setStatus(in PrintJobId printJobId, in CharSequence status);
+
     void onPrintersAdded(in ParceledListSlice printers);
     void onPrintersRemoved(in ParceledListSlice printerIds);
 }
diff --git a/core/java/android/printservice/PrintJob.java b/core/java/android/printservice/PrintJob.java
index 6fa0bdd..86fc292 100644
--- a/core/java/android/printservice/PrintJob.java
+++ b/core/java/android/printservice/PrintJob.java
@@ -16,6 +16,10 @@
 
 package android.printservice;
 
+import android.annotation.FloatRange;
+import android.annotation.MainThread;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.os.RemoteException;
 import android.print.PrintJobId;
 import android.print.PrintJobInfo;
@@ -41,7 +45,7 @@
 
     private PrintJobInfo mCachedInfo;
 
-    PrintJob(PrintJobInfo jobInfo, IPrintServiceClient client) {
+    PrintJob(@NonNull PrintJobInfo jobInfo, @NonNull IPrintServiceClient client) {
         mCachedInfo = jobInfo;
         mPrintServiceClient = client;
         mDocument = new PrintDocument(mCachedInfo.getId(), client,
@@ -53,6 +57,7 @@
      *
      * @return The id.
      */
+    @MainThread
     public PrintJobId getId() {
         PrintService.throwIfNotCalledOnMainThread();
         return mCachedInfo.getId();
@@ -68,7 +73,8 @@
      *
      * @return The print job info.
      */
-    public PrintJobInfo getInfo() {
+    @MainThread
+    public @NonNull PrintJobInfo getInfo() {
         PrintService.throwIfNotCalledOnMainThread();
         if (isInImmutableState()) {
             return mCachedInfo;
@@ -90,7 +96,8 @@
      *
      * @return The document.
      */
-    public PrintDocument getDocument() {
+    @MainThread
+    public @NonNull PrintDocument getDocument() {
         PrintService.throwIfNotCalledOnMainThread();
         return mDocument;
     }
@@ -104,6 +111,7 @@
      * @see #start()
      * @see #cancel()
      */
+    @MainThread
     public boolean isQueued() {
         PrintService.throwIfNotCalledOnMainThread();
         return getInfo().getState() == PrintJobInfo.STATE_QUEUED;
@@ -117,8 +125,9 @@
      *
      * @see #complete()
      * @see #cancel()
-     * @see #fail(CharSequence)
+     * @see #fail(String)
      */
+    @MainThread
     public boolean isStarted() {
         PrintService.throwIfNotCalledOnMainThread();
         return getInfo().getState() == PrintJobInfo.STATE_STARTED;
@@ -132,8 +141,9 @@
      *
      * @see #start()
      * @see #cancel()
-     * @see #fail(CharSequence)
+     * @see #fail(String)
      */
+    @MainThread
     public boolean isBlocked() {
         PrintService.throwIfNotCalledOnMainThread();
         return getInfo().getState() == PrintJobInfo.STATE_BLOCKED;
@@ -147,6 +157,7 @@
      *
      * @see #complete()
      */
+    @MainThread
     public boolean isCompleted() {
         PrintService.throwIfNotCalledOnMainThread();
         return getInfo().getState() == PrintJobInfo.STATE_COMPLETED;
@@ -158,8 +169,9 @@
      *
      * @return Whether the print job is failed.
      *
-     * @see #fail(CharSequence)
+     * @see #fail(String)
      */
+    @MainThread
     public boolean isFailed() {
         PrintService.throwIfNotCalledOnMainThread();
         return getInfo().getState() == PrintJobInfo.STATE_FAILED;
@@ -173,6 +185,7 @@
      *
      * @see #cancel()
      */
+    @MainThread
     public boolean isCancelled() {
         PrintService.throwIfNotCalledOnMainThread();
         return getInfo().getState() == PrintJobInfo.STATE_CANCELED;
@@ -182,12 +195,16 @@
      * Starts the print job. You should call this method if {@link
      * #isQueued()} or {@link #isBlocked()} returns true and you started
      * resumed printing.
+     * <p>
+     * This resets the print status to null. Set the new status by using {@link #setStatus}.
+     * </p>
      *
      * @return Whether the job was started.
      *
      * @see #isQueued()
      * @see #isBlocked()
      */
+    @MainThread
     public boolean start() {
         PrintService.throwIfNotCalledOnMainThread();
         final int state = getInfo().getState();
@@ -205,18 +222,20 @@
      * paper to continue printing. To resume the print job call {@link
      * #start()}.
      *
+     * @param reason The human readable, short, and translated reason why the print job is blocked.
      * @return Whether the job was blocked.
      *
      * @see #isStarted()
      * @see #isBlocked()
      */
-    public boolean block(String reason) {
+    @MainThread
+    public boolean block(@Nullable String reason) {
         PrintService.throwIfNotCalledOnMainThread();
         PrintJobInfo info = getInfo();
         final int state = info.getState();
         if (state == PrintJobInfo.STATE_STARTED
                 || (state == PrintJobInfo.STATE_BLOCKED
-                        && !TextUtils.equals(info.getStateReason(), reason))) {
+                        && !TextUtils.equals(info.getStatus(), reason))) {
             return setState(PrintJobInfo.STATE_BLOCKED, reason);
         }
         return false;
@@ -230,6 +249,7 @@
      *
      * @see #isStarted()
      */
+    @MainThread
     public boolean complete() {
         PrintService.throwIfNotCalledOnMainThread();
         if (isStarted()) {
@@ -251,7 +271,8 @@
      * @see #isStarted()
      * @see #isBlocked()
      */
-    public boolean fail(String error) {
+    @MainThread
+    public boolean fail(@Nullable String error) {
         PrintService.throwIfNotCalledOnMainThread();
         if (!isInImmutableState()) {
             return setState(PrintJobInfo.STATE_FAILED, error);
@@ -271,6 +292,7 @@
      * @see #isQueued()
      * @see #isBlocked()
      */
+    @MainThread
     public boolean cancel() {
         PrintService.throwIfNotCalledOnMainThread();
         if (!isInImmutableState()) {
@@ -280,6 +302,39 @@
     }
 
     /**
+     * Sets the progress of this print job as a fraction of 1.
+     *
+     * @param progress The new progress
+     */
+    @MainThread
+    public void setProgress(@FloatRange(from=0.0, to=1.0) float progress) {
+        PrintService.throwIfNotCalledOnMainThread();
+
+        try {
+            mPrintServiceClient.setProgress(mCachedInfo.getId(), progress);
+        } catch (RemoteException re) {
+            Log.e(LOG_TAG, "Error setting progress for job: " + mCachedInfo.getId(), re);
+        }
+    }
+
+    /**
+     * Sets the status of this print job. This should be a human readable, short, and translated
+     * description of the current state of the print job.
+     *
+     * @param status The new status. If null the status will be empty.
+     */
+    @MainThread
+    public void setStatus(@Nullable CharSequence status) {
+        PrintService.throwIfNotCalledOnMainThread();
+
+        try {
+            mPrintServiceClient.setStatus(mCachedInfo.getId(), status);
+        } catch (RemoteException re) {
+            Log.e(LOG_TAG, "Error setting status for job: " + mCachedInfo.getId(), re);
+        }
+    }
+
+    /**
      * Sets a tag that is valid in the context of a {@link PrintService}
      * and is not interpreted by the system. For example, a print service
      * may set as a tag the key of the print job returned by a remote
@@ -288,6 +343,7 @@
      * @param tag The tag.
      * @return True if the tag was set, false otherwise.
      */
+    @MainThread
     public boolean setTag(String tag) {
         PrintService.throwIfNotCalledOnMainThread();
         if (isInImmutableState()) {
@@ -319,6 +375,7 @@
      * @param key The option key.
      * @return The option value.
      */
+    @MainThread
     public String getAdvancedStringOption(String key) {
         PrintService.throwIfNotCalledOnMainThread();
         return getInfo().getAdvancedStringOption(key);
@@ -331,6 +388,7 @@
      * @param key The option key.
      * @return Whether the option is present.
      */
+    @MainThread
     public boolean hasAdvancedOption(String key) {
         PrintService.throwIfNotCalledOnMainThread();
         return getInfo().hasAdvancedOption(key);
@@ -342,6 +400,7 @@
      * @param key The option key.
      * @return The option value.
      */
+    @MainThread
     public int getAdvancedIntOption(String key) {
         PrintService.throwIfNotCalledOnMainThread();
         return getInfo().getAdvancedIntOption(key);
@@ -374,14 +433,14 @@
                 || state == PrintJobInfo.STATE_FAILED;
     }
 
-    private boolean setState(int state, String error) {
+    private boolean setState(int state, @Nullable String error) {
         try {
             if (mPrintServiceClient.setPrintJobState(mCachedInfo.getId(), state, error)) {
                 // Best effort - update the state of the cached info since
                 // we may not be able to re-fetch it later if the job gets
                 // removed from the spooler as a result of the state change.
                 mCachedInfo.setState(state);
-                mCachedInfo.setStateReason(error);
+                mCachedInfo.setStatus(error);
                 return true;
             }
         } catch (RemoteException re) {
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index c3d0993..5146bc6 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -17,6 +17,7 @@
 package android.widget;
 
 import android.R;
+import android.annotation.IntDef;
 import android.annotation.Nullable;
 import android.app.PendingIntent;
 import android.app.PendingIntent.CanceledException;
@@ -106,6 +107,8 @@
 import com.android.internal.util.Preconditions;
 import com.android.internal.widget.EditableInputConnection;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.text.BreakIterator;
 import java.util.Arrays;
 import java.util.Comparator;
@@ -4087,7 +4090,17 @@
         }
     }
 
-    private class SelectionStartHandleView extends HandleView {
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({HANDLE_TYPE_SELECTION_START, HANDLE_TYPE_SELECTION_END})
+    public @interface HandleType {}
+    public static final int HANDLE_TYPE_SELECTION_START = 0;
+    public static final int HANDLE_TYPE_SELECTION_END = 1;
+
+    private class SelectionHandleView extends HandleView {
+        // Indicates the handle type, selection start (HANDLE_TYPE_SELECTION_START) or selection
+        // end (HANDLE_TYPE_SELECTION_END).
+        @HandleType
+        private final int mHandleType;
         // Indicates whether the cursor is making adjustments within a word.
         private boolean mInWord = false;
         // Difference between touch position and word boundary position.
@@ -4102,16 +4115,21 @@
         // Used to save text view location.
         private final int[] mTextViewLocation = new int[2];
 
-        public SelectionStartHandleView(Drawable drawableLtr, Drawable drawableRtl) {
-            super(drawableLtr, drawableRtl, com.android.internal.R.id.selection_start_handle);
-            ViewConfiguration viewConfiguration = ViewConfiguration.get(
-                    mTextView.getContext());
+        public SelectionHandleView(Drawable drawableLtr, Drawable drawableRtl, int id,
+                @HandleType int handleType) {
+            super(drawableLtr, drawableRtl, id);
+            mHandleType = handleType;
+            ViewConfiguration viewConfiguration = ViewConfiguration.get(mTextView.getContext());
             mTextViewEdgeSlop = viewConfiguration.getScaledTouchSlop() * 4;
         }
 
+        private boolean isStartHandle() {
+            return mHandleType == HANDLE_TYPE_SELECTION_START;
+        }
+
         @Override
         protected int getHotspotX(Drawable drawable, boolean isRtlRun) {
-            if (isRtlRun) {
+            if (isRtlRun == isStartHandle()) {
                 return drawable.getIntrinsicWidth() / 4;
             } else {
                 return (drawable.getIntrinsicWidth() * 3) / 4;
@@ -4120,18 +4138,23 @@
 
         @Override
         protected int getHorizontalGravity(boolean isRtlRun) {
-            return isRtlRun ? Gravity.LEFT : Gravity.RIGHT;
+            return (isRtlRun == isStartHandle()) ? Gravity.LEFT : Gravity.RIGHT;
         }
 
         @Override
         public int getCurrentCursorOffset() {
-            return mTextView.getSelectionStart();
+            return isStartHandle() ? mTextView.getSelectionStart() : mTextView.getSelectionEnd();
         }
 
         @Override
-        public void updateSelection(int offset) {
-            Selection.setSelection((Spannable) mTextView.getText(), offset,
-                    mTextView.getSelectionEnd());
+        protected void updateSelection(int offset) {
+            if (isStartHandle()) {
+                Selection.setSelection((Spannable) mTextView.getText(), offset,
+                        mTextView.getSelectionEnd());
+            } else {
+                Selection.setSelection((Spannable) mTextView.getText(),
+                        mTextView.getSelectionStart(), offset);
+            }
             updateDrawable();
             if (mTextActionMode != null) {
                 mTextActionMode.invalidate();
@@ -4153,35 +4176,36 @@
             }
 
             boolean positionCursor = false;
-            final int selectionEnd = mTextView.getSelectionEnd();
+            final int anotherHandleOffset =
+                    isStartHandle() ? mTextView.getSelectionEnd() : mTextView.getSelectionStart();
             int currLine = getCurrentLineAdjustedForSlop(layout, mPreviousLineTouched, y);
             int initialOffset = mTextView.getOffsetAtCoordinate(currLine, x);
 
-            if (initialOffset >= selectionEnd) {
-                // Handles have crossed, bound it to the last selected line and
+            if (isStartHandle() && initialOffset >= anotherHandleOffset
+                    || !isStartHandle() && initialOffset <= anotherHandleOffset) {
+                // Handles have crossed, bound it to the first selected line and
                 // adjust by word / char as normal.
-                currLine = layout.getLineForOffset(selectionEnd);
+                currLine = layout.getLineForOffset(anotherHandleOffset);
                 initialOffset = mTextView.getOffsetAtCoordinate(currLine, x);
             }
 
             int offset = initialOffset;
-            int end = getWordEnd(offset);
-            int start = getWordStart(offset);
+            final int wordEnd = getWordEnd(offset);
+            final int wordStart = getWordStart(offset);
 
             if (mPrevX == UNSET_X_VALUE) {
                 mPrevX = x;
             }
 
-            final int selectionStart = mTextView.getSelectionStart();
-            final boolean selectionStartRtl = layout.isRtlCharAt(selectionStart);
+            final int currentOffset = getCurrentCursorOffset();
+            final boolean rtlAtCurrentOffset = layout.isRtlCharAt(currentOffset);
             final boolean atRtl = layout.isRtlCharAt(offset);
             final boolean isLvlBoundary = layout.isLevelBoundary(offset);
-            boolean isExpanding;
 
             // We can't determine if the user is expanding or shrinking the selection if they're
             // on a bi-di boundary, so until they've moved past the boundary we'll just place
             // the cursor at the current position.
-            if (isLvlBoundary || (selectionStartRtl && !atRtl) || (!selectionStartRtl && atRtl)) {
+            if (isLvlBoundary || (rtlAtCurrentOffset && !atRtl) || (!rtlAtCurrentOffset && atRtl)) {
                 // We're on a boundary or this is the first direction change -- just update
                 // to the current position.
                 mLanguageDirectionChanged = true;
@@ -4195,24 +4219,30 @@
                 mTouchWordDelta = 0.0f;
                 mLanguageDirectionChanged = false;
                 return;
+            }
+
+            boolean isExpanding;
+            final float xDiff = x - mPrevX;
+            if (atRtl == isStartHandle()) {
+                isExpanding = xDiff > 0 || currLine > mPreviousLineTouched;
             } else {
-                final float xDiff = x - mPrevX;
-                if (atRtl) {
-                    isExpanding = xDiff > 0 || currLine > mPreviousLineTouched;
-                } else {
-                    isExpanding = xDiff < 0 || currLine < mPreviousLineTouched;
-                }
+                isExpanding = xDiff < 0 || currLine < mPreviousLineTouched;
             }
 
             if (mTextView.getHorizontallyScrolling()) {
                 if (positionNearEdgeOfScrollingView(x, atRtl)
-                        && (mTextView.getScrollX() != 0)
-                        && ((isExpanding && offset < selectionStart) || !isExpanding)) {
-                    // If we're expanding ensure that the offset is smaller than the
-                    // selection start, if the handle snapped to the word, the finger position
+                        && ((isStartHandle() && mTextView.getScrollX() != 0)
+                                || (!isStartHandle()
+                                        && mTextView.canScrollHorizontally(atRtl ? -1 : 1)))
+                        && ((isExpanding && ((isStartHandle() && offset < currentOffset)
+                                || (!isStartHandle() && offset > currentOffset)))
+                                        || !isExpanding)) {
+                    // If we're expanding ensure that the offset is actually expanding compared to
+                    // the current offset, if the handle snapped to the word, the finger position
                     // may be out of sync and we don't want the selection to jump back.
                     mTouchWordDelta = 0.0f;
-                    final int nextOffset = atRtl ? layout.getOffsetToRightOf(mPreviousOffset)
+                    final int nextOffset = (atRtl == isStartHandle())
+                            ? layout.getOffsetToRightOf(mPreviousOffset)
                             : layout.getOffsetToLeftOf(mPreviousOffset);
                     positionAndAdjustForCrossingHandles(nextOffset);
                     return;
@@ -4221,24 +4251,36 @@
 
             if (isExpanding) {
                 // User is increasing the selection.
-                if (!mInWord || currLine < mPrevLine) {
+                final boolean snapToWord = !mInWord
+                        || (isStartHandle() ? currLine < mPrevLine : currLine > mPrevLine);
+                if (snapToWord) {
                     // Sometimes words can be broken across lines (Chinese, hyphenation).
-                    // We still snap to the start of the word but we only use the letters on the
+                    // We still snap to the word boundary but we only use the letters on the
                     // current line to determine if the user is far enough into the word to snap.
-                    int wordStartOnCurrLine = start;
-                    if (layout != null && layout.getLineForOffset(start) != currLine) {
-                        wordStartOnCurrLine = layout.getLineStart(currLine);
+                    int wordBoundary = isStartHandle() ? wordStart : wordEnd;
+                    if (layout != null && layout.getLineForOffset(wordBoundary) != currLine) {
+                        wordBoundary = isStartHandle() ?
+                                layout.getLineStart(currLine) : layout.getLineEnd(currLine);
                     }
-                    int offsetThresholdToSnap = end - ((end - wordStartOnCurrLine) / 2);
-                    if (offset <= offsetThresholdToSnap || currLine < mPrevLine) {
-                        // User is far enough into the word or on a different
-                        // line so we expand by word.
-                        offset = start;
+                    final int offsetThresholdToSnap = isStartHandle()
+                            ? wordEnd - ((wordEnd - wordBoundary) / 2)
+                            : wordStart + ((wordBoundary - wordStart) / 2);
+                    if (isStartHandle()
+                            && (offset <= offsetThresholdToSnap || currLine < mPrevLine)) {
+                        // User is far enough into the word or on a different line so we expand by
+                        // word.
+                        offset = wordStart;
+                    } else if (!isStartHandle()
+                            && (offset >= offsetThresholdToSnap || currLine > mPrevLine)) {
+                        // User is far enough into the word or on a different line so we expand by
+                        // word.
+                        offset = wordEnd;
                     } else {
                         offset = mPreviousOffset;
                     }
                 }
-                if (layout != null && offset < initialOffset) {
+                if (layout != null && (isStartHandle() && offset < initialOffset)
+                        || (!isStartHandle() && offset > initialOffset)) {
                     final float adjustedX = layout.getPrimaryHorizontal(offset);
                     mTouchWordDelta =
                             mTextView.convertToLocalHorizontalCoordinate(x) - adjustedX;
@@ -4249,12 +4291,16 @@
             } else {
                 final int adjustedOffset =
                         mTextView.getOffsetAtCoordinate(currLine, x - mTouchWordDelta);
-                if (adjustedOffset > mPreviousOffset || currLine > mPrevLine) {
+                final boolean shrinking = isStartHandle()
+                        ? adjustedOffset > mPreviousOffset || currLine > mPrevLine
+                        : adjustedOffset < mPreviousOffset || currLine < mPrevLine;
+                if (shrinking) {
                     // User is shrinking the selection.
-                    if (currLine > mPrevLine) {
+                    if (currLine != mPrevLine) {
                         // We're on a different line, so we'll snap to word boundaries.
-                        offset = start;
-                        if (layout != null && offset < initialOffset) {
+                        offset = isStartHandle() ? wordStart : wordEnd;
+                        if (layout != null && (isStartHandle() && offset < initialOffset)
+                                || (!isStartHandle() && offset > initialOffset)) {
                             final float adjustedX = layout.getPrimaryHorizontal(offset);
                             mTouchWordDelta =
                                     mTextView.convertToLocalHorizontalCoordinate(x) - adjustedX;
@@ -4265,11 +4311,12 @@
                         offset = adjustedOffset;
                     }
                     positionCursor = true;
-                } else if (adjustedOffset < mPreviousOffset) {
-                    // Handle has jumped to the start of the word, and the user is moving
+                } else if ((isStartHandle() && adjustedOffset < mPreviousOffset)
+                        || (!isStartHandle() && adjustedOffset > mPreviousOffset)) {
+                    // Handle has jumped to the word boundary, and the user is moving
                     // their finger towards the handle, the delta should be updated.
-                    mTouchWordDelta = mTextView.convertToLocalHorizontalCoordinate(x)
-                            - layout.getPrimaryHorizontal(mPreviousOffset);
+                    mTouchWordDelta = mTextView.convertToLocalHorizontalCoordinate(x) -
+                            layout.getPrimaryHorizontal(mPreviousOffset);
                 }
             }
 
@@ -4280,16 +4327,6 @@
             mPrevX = x;
         }
 
-        private void positionAndAdjustForCrossingHandles(int offset) {
-            final int selectionEnd = mTextView.getSelectionEnd();
-            if (offset >= selectionEnd) {
-                // Handles can not cross and selection is at least one character.
-                offset = getNextCursorOffset(selectionEnd, false);
-                mTouchWordDelta = 0.0f;
-            }
-            positionAtCursorOffset(offset, false);
-        }
-
         /**
          * @param offset Cursor offset. Must be in [-1, length].
          * @param parentScrolled If the parent has been scrolled or not.
@@ -4312,256 +4349,28 @@
             return superResult;
         }
 
-        private boolean positionNearEdgeOfScrollingView(float x, boolean atRtl) {
-            mTextView.getLocationOnScreen(mTextViewLocation);
-            boolean nearEdge;
-            if (atRtl) {
-                int rightEdge = mTextViewLocation[0] + mTextView.getWidth()
-                        - mTextView.getPaddingRight();
-                nearEdge = x > rightEdge - mTextViewEdgeSlop;
-            } else {
-                int leftEdge = mTextViewLocation[0] + mTextView.getPaddingLeft();
-                nearEdge = x < leftEdge + mTextViewEdgeSlop;
-            }
-            return nearEdge;
-        }
-    }
-
-    private class SelectionEndHandleView extends HandleView {
-        // Indicates whether the cursor is making adjustments within a word.
-        private boolean mInWord = false;
-        // Difference between touch position and word boundary position.
-        private float mTouchWordDelta;
-        // X value of the previous updatePosition call.
-        private float mPrevX;
-        // Indicates if the handle has moved a boundary between LTR and RTL text.
-        private boolean mLanguageDirectionChanged = false;
-        // Distance from edge of horizontally scrolling text view
-        // to use to switch to character mode.
-        private final float mTextViewEdgeSlop;
-        // Used to save the text view location.
-        private final int[] mTextViewLocation = new int[2];
-
-        public SelectionEndHandleView(Drawable drawableLtr, Drawable drawableRtl) {
-            super(drawableLtr, drawableRtl, com.android.internal.R.id.selection_end_handle);
-            ViewConfiguration viewConfiguration = ViewConfiguration.get(
-                    mTextView.getContext());
-            mTextViewEdgeSlop = viewConfiguration.getScaledTouchSlop() * 4;
-        }
-
-        @Override
-        protected int getHotspotX(Drawable drawable, boolean isRtlRun) {
-            if (isRtlRun) {
-                return (drawable.getIntrinsicWidth() * 3) / 4;
-            } else {
-                return drawable.getIntrinsicWidth() / 4;
-            }
-        }
-
-        @Override
-        protected int getHorizontalGravity(boolean isRtlRun) {
-            return isRtlRun ? Gravity.RIGHT : Gravity.LEFT;
-        }
-
-        @Override
-        public int getCurrentCursorOffset() {
-            return mTextView.getSelectionEnd();
-        }
-
-        @Override
-        public void updateSelection(int offset) {
-            Selection.setSelection((Spannable) mTextView.getText(),
-                    mTextView.getSelectionStart(), offset);
-            if (mTextActionMode != null) {
-                mTextActionMode.invalidate();
-            }
-            updateDrawable();
-        }
-
-        @Override
-        public void updatePosition(float x, float y) {
-            final Layout layout = mTextView.getLayout();
-            if (layout == null) {
-                // HandleView will deal appropriately in positionAtCursorOffset when
-                // layout is null.
-                positionAndAdjustForCrossingHandles(mTextView.getOffsetForPosition(x, y));
-                return;
-            }
-
-            if (mPreviousLineTouched == UNSET_LINE) {
-                mPreviousLineTouched = mTextView.getLineAtCoordinate(y);
-            }
-
-            boolean positionCursor = false;
-            final int selectionStart = mTextView.getSelectionStart();
-            int currLine = getCurrentLineAdjustedForSlop(layout, mPreviousLineTouched, y);
-            int initialOffset = mTextView.getOffsetAtCoordinate(currLine, x);
-
-            if (initialOffset <= selectionStart) {
-                // Handles have crossed, bound it to the first selected line and
-                // adjust by word / char as normal.
-                currLine = layout.getLineForOffset(selectionStart);
-                initialOffset = mTextView.getOffsetAtCoordinate(currLine, x);
-            }
-
-            int offset = initialOffset;
-            int end = getWordEnd(offset);
-            int start = getWordStart(offset);
-
-            if (mPrevX == UNSET_X_VALUE) {
-                mPrevX = x;
-            }
-
-            final int selectionEnd = mTextView.getSelectionEnd();
-            final boolean selectionEndRtl = layout.isRtlCharAt(selectionEnd);
-            final boolean atRtl = layout.isRtlCharAt(offset);
-            final boolean isLvlBoundary = layout.isLevelBoundary(offset);
-            boolean isExpanding;
-
-            // We can't determine if the user is expanding or shrinking the selection if they're
-            // on a bi-di boundary, so until they've moved past the boundary we'll just place
-            // the cursor at the current position.
-            if (isLvlBoundary || (selectionEndRtl && !atRtl) || (!selectionEndRtl && atRtl)) {
-                // We're on a boundary or this is the first direction change -- just update
-                // to the current position.
-                mLanguageDirectionChanged = true;
-                mTouchWordDelta = 0.0f;
-                positionAndAdjustForCrossingHandles(offset);
-                return;
-            } else if (mLanguageDirectionChanged && !isLvlBoundary) {
-                // We've just moved past the boundary so update the position. After this we can
-                // figure out if the user is expanding or shrinking to go by word or character.
-                positionAndAdjustForCrossingHandles(offset);
-                mTouchWordDelta = 0.0f;
-                mLanguageDirectionChanged = false;
-                return;
-            } else {
-                final float xDiff = x - mPrevX;
-                if (atRtl) {
-                    isExpanding = xDiff < 0 || currLine < mPreviousLineTouched;
-                } else {
-                    isExpanding = xDiff > 0 || currLine > mPreviousLineTouched;
-                }
-            }
-
-            if (mTextView.getHorizontallyScrolling()) {
-                if (positionNearEdgeOfScrollingView(x, atRtl)
-                        && mTextView.canScrollHorizontally(atRtl ? -1 : 1)
-                        && ((isExpanding && offset > selectionEnd) || !isExpanding)) {
-                    // If we're expanding ensure that the offset is actually greater than the
-                    // selection end, if the handle snapped to the word, the finger position
-                    // may be out of sync and we don't want the selection to jump back.
-                    mTouchWordDelta = 0.0f;
-                    final int nextOffset = atRtl ? layout.getOffsetToLeftOf(mPreviousOffset)
-                            : layout.getOffsetToRightOf(mPreviousOffset);
-                    positionAndAdjustForCrossingHandles(nextOffset);
-                    return;
-                }
-            }
-
-            if (isExpanding) {
-                // User is increasing the selection.
-                if (!mInWord || currLine > mPrevLine) {
-                    // Sometimes words can be broken across lines (Chinese, hyphenation).
-                    // We still snap to the end of the word but we only use the letters on the
-                    // current line to determine if the user is far enough into the word to snap.
-                    int wordEndOnCurrLine = end;
-                    if (layout != null && layout.getLineForOffset(end) != currLine) {
-                        wordEndOnCurrLine = layout.getLineEnd(currLine);
-                    }
-                    final int offsetThresholdToSnap = start + ((wordEndOnCurrLine - start) / 2);
-                    if (offset >= offsetThresholdToSnap || currLine > mPrevLine) {
-                        // User is far enough into the word or on a different
-                        // line so we expand by word.
-                        offset = end;
-                    } else {
-                        offset = mPreviousOffset;
-                    }
-                }
-                if (offset > initialOffset) {
-                    final float adjustedX = layout.getPrimaryHorizontal(offset);
-                    mTouchWordDelta =
-                            adjustedX - mTextView.convertToLocalHorizontalCoordinate(x);
-                } else {
-                    mTouchWordDelta = 0.0f;
-                }
-                positionCursor = true;
-            } else {
-                final int adjustedOffset =
-                        mTextView.getOffsetAtCoordinate(currLine, x + mTouchWordDelta);
-                if (adjustedOffset < mPreviousOffset || currLine < mPrevLine) {
-                    // User is shrinking the selection.
-                    if (currLine < mPrevLine) {
-                        // We're on a different line, so we'll snap to word boundaries.
-                        offset = end;
-                        if (offset > initialOffset) {
-                            final float adjustedX = layout.getPrimaryHorizontal(offset);
-                            mTouchWordDelta =
-                                    adjustedX - mTextView.convertToLocalHorizontalCoordinate(x);
-                        } else {
-                            mTouchWordDelta = 0.0f;
-                        }
-                    } else {
-                        offset = adjustedOffset;
-                    }
-                    positionCursor = true;
-                } else if (adjustedOffset > mPreviousOffset) {
-                    // Handle has jumped to the end of the word, and the user is moving
-                    // their finger towards the handle, the delta should be updated.
-                    mTouchWordDelta = layout.getPrimaryHorizontal(mPreviousOffset)
-                            - mTextView.convertToLocalHorizontalCoordinate(x);
-                }
-            }
-
-            if (positionCursor) {
-                mPreviousLineTouched = currLine;
-                positionAndAdjustForCrossingHandles(offset);
-            }
-            mPrevX = x;
-        }
-
         private void positionAndAdjustForCrossingHandles(int offset) {
-            final int selectionStart = mTextView.getSelectionStart();
-            if (offset <= selectionStart) {
+            final int anotherHandleOffset =
+                    isStartHandle() ? mTextView.getSelectionEnd() : mTextView.getSelectionStart();
+            if ((isStartHandle() && offset >= anotherHandleOffset)
+                    || (!isStartHandle() && offset <= anotherHandleOffset)) {
                 // Handles can not cross and selection is at least one character.
-                offset = getNextCursorOffset(selectionStart, true);
+                offset = getNextCursorOffset(anotherHandleOffset, !isStartHandle());
                 mTouchWordDelta = 0.0f;
             }
             positionAtCursorOffset(offset, false);
         }
 
-        /**
-         * @param offset Cursor offset. Must be in [-1, length].
-         * @param parentScrolled If the parent has been scrolled or not.
-         */
-        @Override
-        protected void positionAtCursorOffset(int offset, boolean parentScrolled) {
-            super.positionAtCursorOffset(offset, parentScrolled);
-            mInWord = (offset != -1) && !getWordIteratorWithText().isBoundary(offset);
-        }
-
-        @Override
-        public boolean onTouchEvent(MotionEvent event) {
-            boolean superResult = super.onTouchEvent(event);
-            if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
-                // Reset the touch word offset and x value when the user
-                // re-engages the handle.
-                mTouchWordDelta = 0.0f;
-                mPrevX = UNSET_X_VALUE;
-            }
-            return superResult;
-        }
-
         private boolean positionNearEdgeOfScrollingView(float x, boolean atRtl) {
             mTextView.getLocationOnScreen(mTextViewLocation);
             boolean nearEdge;
-            if (atRtl) {
-                int leftEdge = mTextViewLocation[0] + mTextView.getPaddingLeft();
-                nearEdge = x < leftEdge + mTextViewEdgeSlop;
-            } else {
+            if (atRtl == isStartHandle()) {
                 int rightEdge = mTextViewLocation[0] + mTextView.getWidth()
                         - mTextView.getPaddingRight();
                 nearEdge = x > rightEdge - mTextViewEdgeSlop;
+            } else {
+                int leftEdge = mTextViewLocation[0] + mTextView.getPaddingLeft();
+                nearEdge = x < leftEdge + mTextViewEdgeSlop;
             }
             return nearEdge;
         }
@@ -4673,8 +4482,8 @@
 
     class SelectionModifierCursorController implements CursorController {
         // The cursor controller handles, lazily created when shown.
-        private SelectionStartHandleView mStartHandle;
-        private SelectionEndHandleView mEndHandle;
+        private SelectionHandleView mStartHandle;
+        private SelectionHandleView mEndHandle;
         // The offsets of that last touch down event. Remembered to start selection there.
         private int mMinTouchOffset, mMaxTouchOffset;
 
@@ -4718,10 +4527,14 @@
         private void initHandles() {
             // Lazy object creation has to be done before updatePosition() is called.
             if (mStartHandle == null) {
-                mStartHandle = new SelectionStartHandleView(mSelectHandleLeft, mSelectHandleRight);
+                mStartHandle = new SelectionHandleView(mSelectHandleLeft, mSelectHandleRight,
+                        com.android.internal.R.id.selection_start_handle,
+                        HANDLE_TYPE_SELECTION_START);
             }
             if (mEndHandle == null) {
-                mEndHandle = new SelectionEndHandleView(mSelectHandleRight, mSelectHandleLeft);
+                mEndHandle = new SelectionHandleView(mSelectHandleRight, mSelectHandleLeft,
+                        com.android.internal.R.id.selection_end_handle,
+                        HANDLE_TYPE_SELECTION_END);
             }
 
             mStartHandle.show();
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 0ed72e4d..0dd803a2 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -1666,6 +1666,7 @@
             ViewGroup.LayoutParams layoutParams = target.getLayoutParams();
             if (layoutParams instanceof ViewGroup.MarginLayoutParams) {
                 ((ViewGroup.MarginLayoutParams) layoutParams).setMarginEnd(end);
+                target.setLayoutParams(layoutParams);
             }
         }
 
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 9391c60..4a969b2 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -105,7 +105,7 @@
     private static final int MAGIC = 0xBA757475; // 'BATSTATS'
 
     // Current on-disk Parcel version
-    private static final int VERSION = 136 + (USE_OLD_HISTORY ? 1000 : 0);
+    private static final int VERSION = 138 + (USE_OLD_HISTORY ? 1000 : 0);
 
     // Maximum number of items we will record in the history.
     private static final int MAX_HISTORY_ITEMS = 2000;
@@ -2621,10 +2621,9 @@
         }
     }
 
-    public void noteProcessStateLocked(String name, int uid, int state) {
+    public void noteUidProcessStateLocked(int uid, int state) {
         uid = mapUid(uid);
-        final long elapsedRealtime = SystemClock.elapsedRealtime();
-        getUidStatsLocked(uid).updateProcessStateLocked(name, state, elapsedRealtime);
+        getUidStatsLocked(uid).updateUidProcessStateLocked(state);
     }
 
     public void noteProcessFinishLocked(String name, int uid) {
@@ -2632,13 +2631,11 @@
         if (!mActiveEvents.updateState(HistoryItem.EVENT_PROC_FINISH, name, uid, 0)) {
             return;
         }
-        final long elapsedRealtime = SystemClock.elapsedRealtime();
-        final long uptime = SystemClock.uptimeMillis();
-        getUidStatsLocked(uid).updateProcessStateLocked(name, Uid.PROCESS_STATE_NONE,
-                elapsedRealtime);
         if (!mRecordAllHistory) {
             return;
         }
+        final long elapsedRealtime = SystemClock.elapsedRealtime();
+        final long uptime = SystemClock.uptimeMillis();
         addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PROC_FINISH, name, uid);
     }
 
@@ -4446,8 +4443,7 @@
 
         StopwatchTimer mForegroundActivityTimer;
 
-        static final int PROCESS_STATE_NONE = NUM_PROCESS_STATE;
-        int mProcessState = PROCESS_STATE_NONE;
+        int mProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
         StopwatchTimer[] mProcessStateTimer;
 
         BatchTimer mVibratorOnTimer;
@@ -4812,21 +4808,6 @@
             }
         }
 
-        void updateUidProcessStateLocked(int state, long elapsedRealtimeMs) {
-            if (mProcessState == state) return;
-
-            if (mProcessState != PROCESS_STATE_NONE) {
-                mProcessStateTimer[mProcessState].stopRunningLocked(elapsedRealtimeMs);
-            }
-            mProcessState = state;
-            if (state != PROCESS_STATE_NONE) {
-                if (mProcessStateTimer[state] == null) {
-                    makeProcessState(state, null);
-                }
-                mProcessStateTimer[state].startRunningLocked(elapsedRealtimeMs);
-            }
-        }
-
         public BatchTimer createVibratorOnTimerLocked() {
             if (mVibratorOnTimer == null) {
                 mVibratorOnTimer = new BatchTimer(Uid.this, VIBRATOR_ON, mOnBatteryTimeBase);
@@ -5167,7 +5148,7 @@
                         active |= !mProcessStateTimer[i].reset(false);
                     }
                 }
-                active |= (mProcessState != PROCESS_STATE_NONE);
+                active |= (mProcessState != ActivityManager.PROCESS_STATE_NONEXISTENT);
             }
             if (mVibratorOnTimer != null) {
                 if (mVibratorOnTimer.reset(false)) {
@@ -5261,14 +5242,9 @@
             }
             for (int ip=mProcessStats.size()-1; ip>=0; ip--) {
                 Proc proc = mProcessStats.valueAt(ip);
-                if (proc.mProcessState == PROCESS_STATE_NONE) {
-                    proc.detach();
-                    mProcessStats.removeAt(ip);
-                } else {
-                    proc.reset();
-                    active = true;
-                }
+                proc.detach();
             }
+            mProcessStats.clear();
             if (mPids.size() > 0) {
                 for (int i=mPids.size()-1; i>=0; i--) {
                     Pid pid = mPids.valueAt(i);
@@ -5697,7 +5673,7 @@
             } else {
                 mForegroundActivityTimer = null;
             }
-            mProcessState = PROCESS_STATE_NONE;
+            mProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
             for (int i = 0; i < NUM_PROCESS_STATE; i++) {
                 if (in.readInt() != 0) {
                     makeProcessState(i, in);
@@ -6080,11 +6056,6 @@
              */
             int mUnpluggedNumAnrs;
 
-            /**
-             * Current process state.
-             */
-            int mProcessState = PROCESS_STATE_NONE;
-
             ArrayList<ExcessivePower> mExcessivePower;
 
             Proc(String name) {
@@ -6104,16 +6075,6 @@
             public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
             }
 
-            void reset() {
-                mUserTime = mSystemTime = mForegroundTime = 0;
-                mStarts = mNumCrashes = mNumAnrs = 0;
-                mLoadedUserTime = mLoadedSystemTime = mLoadedForegroundTime = 0;
-                mLoadedStarts = mLoadedNumCrashes = mLoadedNumAnrs = 0;
-                mUnpluggedUserTime = mUnpluggedSystemTime = mUnpluggedForegroundTime = 0;
-                mUnpluggedStarts = mUnpluggedNumCrashes = mUnpluggedNumAnrs = 0;
-                mExcessivePower = null;
-            }
-
             void detach() {
                 mActive = false;
                 mOnBatteryTimeBase.remove(this);
@@ -6668,46 +6629,39 @@
             return ps;
         }
 
-        public void updateProcessStateLocked(String procName, int state, long elapsedRealtimeMs) {
-            int procState;
-            if (state <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {
-                procState = PROCESS_STATE_FOREGROUND;
-            } else if (state <= ActivityManager.PROCESS_STATE_RECEIVER) {
-                procState = PROCESS_STATE_ACTIVE;
+        public void updateUidProcessStateLocked(int procState) {
+            int uidRunningState;
+            if (procState == ActivityManager.PROCESS_STATE_NONEXISTENT) {
+                uidRunningState = ActivityManager.PROCESS_STATE_NONEXISTENT;
+            } else if (procState == ActivityManager.PROCESS_STATE_TOP) {
+                uidRunningState = PROCESS_STATE_TOP;
+            } else if (procState <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) {
+                // Persistent and other foreground states go here.
+                uidRunningState = PROCESS_STATE_FOREGROUND_SERVICE;
+            } else if (procState <= ActivityManager.PROCESS_STATE_TOP_SLEEPING) {
+                uidRunningState = PROCESS_STATE_TOP_SLEEPING;
+            } else if (procState <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {
+                // Persistent and other foreground states go here.
+                uidRunningState = PROCESS_STATE_FOREGROUND;
+            } else if (procState <= ActivityManager.PROCESS_STATE_RECEIVER) {
+                uidRunningState = PROCESS_STATE_BACKGROUND;
             } else {
-                procState = PROCESS_STATE_RUNNING;
+                uidRunningState = PROCESS_STATE_CACHED;
             }
-            updateRealProcessStateLocked(procName, procState, elapsedRealtimeMs);
-        }
 
-        public void updateRealProcessStateLocked(String procName, int procState,
-                long elapsedRealtimeMs) {
-            Proc proc = getProcessStatsLocked(procName);
-            if (proc.mProcessState != procState) {
-                boolean changed;
-                if (procState < proc.mProcessState) {
-                    // Has this process become more important?  If so,
-                    // we may need to change the uid if the currrent uid proc state
-                    // is not as important as what we are now setting.
-                    changed = mProcessState > procState;
-                } else {
-                    // Has this process become less important?  If so,
-                    // we may need to change the uid if the current uid proc state
-                    // is the same importance as the old setting.
-                    changed = mProcessState == proc.mProcessState;
+            if (mProcessState == uidRunningState) return;
+
+            final long elapsedRealtime = SystemClock.elapsedRealtime();
+
+            if (mProcessState != ActivityManager.PROCESS_STATE_NONEXISTENT) {
+                mProcessStateTimer[mProcessState].stopRunningLocked(elapsedRealtime);
+            }
+            mProcessState = uidRunningState;
+            if (uidRunningState != ActivityManager.PROCESS_STATE_NONEXISTENT) {
+                if (mProcessStateTimer[uidRunningState] == null) {
+                    makeProcessState(uidRunningState, null);
                 }
-                proc.mProcessState = procState;
-                if (changed) {
-                    // uid's state may have changed; compute what the new state should be.
-                    int uidProcState = PROCESS_STATE_NONE;
-                    for (int ip=mProcessStats.size()-1; ip>=0; ip--) {
-                        proc = mProcessStats.valueAt(ip);
-                        if (proc.mProcessState < uidProcState) {
-                            uidProcState = proc.mProcessState;
-                        }
-                    }
-                    updateUidProcessStateLocked(uidProcState, elapsedRealtimeMs);
-                }
+                mProcessStateTimer[uidRunningState].startRunningLocked(elapsedRealtime);
             }
         }
 
@@ -9423,7 +9377,7 @@
             if (in.readInt() != 0) {
                 u.createForegroundActivityTimerLocked().readSummaryFromParcelLocked(in);
             }
-            u.mProcessState = Uid.PROCESS_STATE_NONE;
+            u.mProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
             for (int i = 0; i < Uid.NUM_PROCESS_STATE; i++) {
                 if (in.readInt() != 0) {
                     u.makeProcessState(i, null);
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 669eba1..c3f7afc 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -222,6 +222,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Stembystand"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Sluit nou"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Veiligmodus"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-stelsel"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Persoonlik"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index a7af0f1..4de0097 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -222,6 +222,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"የድምጽ እርዳታ"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"አሁን ቆልፍ"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"የሚያስተማምን ሁነታ"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android ስርዓት"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"የግል"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 9be3bfb..0c05bc4 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -226,6 +226,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"المساعد الصوتي"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"قفل الآن"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"الوضع الآمن"</string>
     <string name="android_system_label" msgid="6577375335728551336">"‏نظام Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"شخصي"</string>
diff --git a/core/res/res/values-az-rAZ/strings.xml b/core/res/res/values-az-rAZ/strings.xml
index 54dbc39e..593400e 100644
--- a/core/res/res/values-az-rAZ/strings.xml
+++ b/core/res/res/values-az-rAZ/strings.xml
@@ -222,6 +222,7 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Səs Yardımçısı"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"İndi kilidləyin"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="safeMode" msgid="2788228061547930246">"Təhlükəsiz rejim"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android sistemi"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Şəxsi"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 2617bdb..50f2938 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -222,6 +222,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Гласова помощ"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Заключване сега"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Безопасен режим"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Системно от Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Личен"</string>
diff --git a/core/res/res/values-bn-rBD/strings.xml b/core/res/res/values-bn-rBD/strings.xml
index f5fb017..fdd46172 100644
--- a/core/res/res/values-bn-rBD/strings.xml
+++ b/core/res/res/values-bn-rBD/strings.xml
@@ -222,6 +222,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"ভয়েস সহায়তা"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"এখনই লক করুন"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"৯৯৯+"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"নিরাপদ মোড"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android সিস্টেম"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"ব্যক্তিগত"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 0e731f6..cb24d26 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -222,6 +222,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Assist. per veu"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Bloqueja ara"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"+999"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Mode segur"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Personal"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index fd3ed4b..c2f1364 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -224,6 +224,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Hlas. asistence"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Zamknout"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Nouzový režim"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Systém Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Osobní"</string>
@@ -355,7 +357,7 @@
     <string name="permlab_vibrate" msgid="7696427026057705834">"ovládání vibrací"</string>
     <string name="permdesc_vibrate" msgid="6284989245902300945">"Umožňuje aplikaci ovládat vibrace."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"ovládání kontrolky"</string>
-    <string name="permdesc_flashlight" msgid="6522284794568368310">"Umožňuje aplikaci ovládat baterku."</string>
+    <string name="permdesc_flashlight" msgid="6522284794568368310">"Umožňuje aplikaci ovládat svítilnu."</string>
     <string name="permlab_callPhone" msgid="3925836347681847954">"přímé volání na telefonní čísla"</string>
     <string name="permdesc_callPhone" msgid="3740797576113760827">"Umožňuje aplikaci volat na telefonní čísla bez vašeho přičinění. Může mít za následek neočekávané poplatky nebo hovory. Toto oprávnění neumožňuje aplikaci volat na tísňová čísla. Škodlivé aplikace vás mohou připravit o peníze uskutečňováním hovorů bez vašeho svolení."</string>
     <string name="permlab_accessImsCallService" msgid="3574943847181793918">"přístup ke službě zasílání rychlých zpráv pro účely hovorů"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index dbf85e3..42cb42b 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -222,6 +222,7 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Taleassistent"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Lås nu"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="safeMode" msgid="2788228061547930246">"Sikker tilstand"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-system"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Personlig"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index f8b78c0..d52c728 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -222,6 +222,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Sprachassistent"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Jetzt sperren"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Abgesicherter Modus"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-System"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Privat"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index e00fbec..f86c2fd 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -222,6 +222,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Φων.υποβοηθ."</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Κλείδωμα τώρα"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Ασφαλής λειτουργία"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Σύστημα Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Προσωπικό"</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index c66c55a..e23f8d5 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -222,6 +222,7 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Voice Assist"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Lock now"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android system"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Personal"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index c66c55a..e23f8d5 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -222,6 +222,7 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Voice Assist"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Lock now"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android system"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Personal"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index c66c55a..e23f8d5 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -222,6 +222,7 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Voice Assist"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Lock now"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android system"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Personal"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 19f1bd9..b442bc1f 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -222,6 +222,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Asistente voz"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Bloquear ahora"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Modo seguro"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Personal"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index f290c04..acbef23 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -222,6 +222,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Asistente voz"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Bloquear ahora"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"&gt; 999"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Modo seguro"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Personal"</string>
@@ -243,7 +245,7 @@
     <string name="permgrouplab_phone" msgid="5229115638567440675">"Teléfono"</string>
     <string name="permgroupdesc_phone" msgid="6234224354060641055">"hacer y administrar llamadas de teléfono"</string>
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Sensores corporales"</string>
-    <string name="permgroupdesc_sensors" msgid="7147968539346634043">"acceder a datos del sensor sobre tus constantes vitales"</string>
+    <string name="permgroupdesc_sensors" msgid="7147968539346634043">"acceder a datos de sensores de tus constantes vitales"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Recuperar el contenido de la ventana"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Inspecciona el contenido de una ventana con la que estés interactuando."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"Activar la exploración táctil"</string>
diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml
index ca6ad3c..9a96683 100644
--- a/core/res/res/values-et-rEE/strings.xml
+++ b/core/res/res/values-et-rEE/strings.xml
@@ -222,6 +222,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Häälabi"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Lukusta kohe"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Turvarežiim"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-süsteem"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Isiklik"</string>
diff --git a/core/res/res/values-eu-rES/strings.xml b/core/res/res/values-eu-rES/strings.xml
index 0986b70..a30c437 100644
--- a/core/res/res/values-eu-rES/strings.xml
+++ b/core/res/res/values-eu-rES/strings.xml
@@ -222,6 +222,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Ahots-laguntza"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Blokeatu"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Modu segurua"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android sistema"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Pertsonalak"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index bc5caa2..8672171 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -222,6 +222,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"دستیار صوتی"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"اکنون قفل شود"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"بیشتر از 999"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"حالت ایمن"</string>
     <string name="android_system_label" msgid="6577375335728551336">"‏سیستم Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"شخصی"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 3494d53..8100305 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -222,6 +222,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Ääniapuri"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Lukitse nyt"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Suojattu tila"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-järjestelmä"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Henkilökoht."</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 94f59fa..b273980 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -222,6 +222,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Assist. vocale"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Verrouiller"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"&gt;999"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Mode sécurisé"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Système Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Personnel"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 965b229..850c18a 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -222,6 +222,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Assistance vocale"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Verrouiller"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"&gt;999"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Mode sécurisé"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Système Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Personnel"</string>
diff --git a/core/res/res/values-gl-rES/strings.xml b/core/res/res/values-gl-rES/strings.xml
index a5c42e3..998f494 100644
--- a/core/res/res/values-gl-rES/strings.xml
+++ b/core/res/res/values-gl-rES/strings.xml
@@ -222,6 +222,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Asistente voz"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Bloquear agora"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"&gt;999"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Modo seguro"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Persoal"</string>
diff --git a/core/res/res/values-gu-rIN/strings.xml b/core/res/res/values-gu-rIN/strings.xml
index 6dabd69..7cfd200 100644
--- a/core/res/res/values-gu-rIN/strings.xml
+++ b/core/res/res/values-gu-rIN/strings.xml
@@ -222,6 +222,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"વૉઇસ સહાય"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"હવે લૉક કરો"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"સુરક્ષિત મોડ"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android સિસ્ટમ"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"વ્યક્તિગત"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 47fdd28..a001211 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -222,6 +222,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"वॉइस सहायक"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"अभी लॉक करें"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"सुरक्षित मोड"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android सिस्‍टम"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"व्यक्तिगत"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 2596f1c..55399af 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -223,6 +223,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Glasovna pomoć"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Zaključaj sada"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Siguran način rada"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sustav Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Osobno"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 1c0257f..dc87943 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -222,6 +222,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Hangsegéd"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Zárolás most"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Biztonsági üzemmód"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android rendszer"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Személyes"</string>
diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml
index 29474f0..f1d32d8 100644
--- a/core/res/res/values-hy-rAM/strings.xml
+++ b/core/res/res/values-hy-rAM/strings.xml
@@ -222,6 +222,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Ձայնային օգնութ"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Կողպել հիմա"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Անվտանգ ռեժիմ"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android համակարգ"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Անձնական"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 9a3ae05..8e18dae 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -222,6 +222,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Bantuan Suara"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Kunci sekarang"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Mode aman"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistem Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Pribadi"</string>
diff --git a/core/res/res/values-is-rIS/strings.xml b/core/res/res/values-is-rIS/strings.xml
index 23db2d2..b2c98f0 100644
--- a/core/res/res/values-is-rIS/strings.xml
+++ b/core/res/res/values-is-rIS/strings.xml
@@ -222,6 +222,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Raddaðstoð"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Læsa núna"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Örugg stilling"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android kerfið"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Persónulegt"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index ff005ee..b36e2e5 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -222,6 +222,7 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Voice Assist"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Blocca ora"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="safeMode" msgid="2788228061547930246">"Modalità provvisoria"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Personale"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 06cf587..cf4ca52 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -224,6 +224,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Voice Assist"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"נעל עכשיו"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"מצב בטוח"</string>
     <string name="android_system_label" msgid="6577375335728551336">"‏מערכת Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"אישי"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 807dbd3..1ebf699 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -222,6 +222,7 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"音声アシスト"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"今すぐロック"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g> 件)"</string>
     <string name="safeMode" msgid="2788228061547930246">"セーフモード"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Androidシステム"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"個人用"</string>
diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml
index 9ce703f..604323a 100644
--- a/core/res/res/values-ka-rGE/strings.xml
+++ b/core/res/res/values-ka-rGE/strings.xml
@@ -222,6 +222,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"ხმოვანი ასისტ."</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"ახლა ჩაკეტვა"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"უსაფრთხო რეჟიმი"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-ის სისტემა"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"პირადი"</string>
diff --git a/core/res/res/values-kk-rKZ/strings.xml b/core/res/res/values-kk-rKZ/strings.xml
index 7b3c756..323be5d 100644
--- a/core/res/res/values-kk-rKZ/strings.xml
+++ b/core/res/res/values-kk-rKZ/strings.xml
@@ -222,6 +222,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Дауыс көмекшісі"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Қазір бекіту"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Қауіпсіз режим"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android жүйесі"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Жеке"</string>
diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml
index ad3b9bd..c00bc14 100644
--- a/core/res/res/values-km-rKH/strings.xml
+++ b/core/res/res/values-km-rKH/strings.xml
@@ -222,6 +222,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"ជំនួយសម្លេង"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"ចាក់សោ​ឥឡូវនេះ"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"របៀប​​​សុវត្ថិភាព"</string>
     <string name="android_system_label" msgid="6577375335728551336">"ប្រព័ន្ធ​​ Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"ផ្ទាល់ខ្លួន"</string>
diff --git a/core/res/res/values-kn-rIN/strings.xml b/core/res/res/values-kn-rIN/strings.xml
index e828ce0..1aba0bb 100644
--- a/core/res/res/values-kn-rIN/strings.xml
+++ b/core/res/res/values-kn-rIN/strings.xml
@@ -222,6 +222,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"ಧ್ವನಿ ಸಹಾಯಕ"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"ಈಗ ಲಾಕ್ ಮಾಡಿ"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"ಸುರಕ್ಷಿತ ಮೋಡ್"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android ಸಿಸ್ಟಂ"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"ವೈಯಕ್ತಿಕ"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 8e546ba..3384f09 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -222,6 +222,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"음성 지원"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"지금 잠그기"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"안전 모드"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android 시스템"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"개인"</string>
@@ -229,7 +231,7 @@
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"주소록"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"주소록 액세스"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"위치"</string>
-    <string name="permgroupdesc_location" msgid="1346617465127855033">"이 기기의 위치에 액세스하기"</string>
+    <string name="permgroupdesc_location" msgid="1346617465127855033">"이 기기의 위치에 액세스"</string>
     <string name="permgrouplab_calendar" msgid="5863508437783683902">"캘린더"</string>
     <string name="permgroupdesc_calendar" msgid="3889615280211184106">"캘린더 액세스"</string>
     <string name="permgrouplab_sms" msgid="228308803364967808">"SMS"</string>
@@ -239,7 +241,7 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"마이크"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"오디오 녹음"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"카메라"</string>
-    <string name="permgroupdesc_camera" msgid="3250611594678347720">"사진 찍기 및 동영상 녹화"</string>
+    <string name="permgroupdesc_camera" msgid="3250611594678347720">"사진 및 동영상 촬영"</string>
     <string name="permgrouplab_phone" msgid="5229115638567440675">"전화"</string>
     <string name="permgroupdesc_phone" msgid="6234224354060641055">"전화 걸기 및 관리"</string>
     <string name="permgrouplab_sensors" msgid="416037179223226722">"신체 센서"</string>
diff --git a/core/res/res/values-ky-rKG/strings.xml b/core/res/res/values-ky-rKG/strings.xml
index 55dd4ec..870c858 100644
--- a/core/res/res/values-ky-rKG/strings.xml
+++ b/core/res/res/values-ky-rKG/strings.xml
@@ -222,6 +222,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Үн жардамчысы"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Азыр кулпулоо"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Коопсуз режим"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android Тутуму"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Жеке"</string>
diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml
index fa3be85..d5484d3 100644
--- a/core/res/res/values-lo-rLA/strings.xml
+++ b/core/res/res/values-lo-rLA/strings.xml
@@ -222,6 +222,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"ຊ່ວຍ​ເຫຼືອ​ທາງ​ສຽງ"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"ລັອກ​ດຽວ​ນີ້"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
     <string name="android_system_label" msgid="6577375335728551336">"ລະບົບ Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"​ສ່ວນ​ໂຕ"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index cfcb639..6ee24cf 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -224,6 +224,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Voice Assist"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Užrakinti dabar"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Saugos režimas"</string>
     <string name="android_system_label" msgid="6577375335728551336">"„Android“ sistema"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Asmeninė"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 23be85a..7785965 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -223,6 +223,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Balss palīgs"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Bloķēt tūlīt"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"Pārsniedz"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Drošais režīms"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android sistēma"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Personisks"</string>
diff --git a/core/res/res/values-mk-rMK/strings.xml b/core/res/res/values-mk-rMK/strings.xml
index 99d5d46..eb90369 100644
--- a/core/res/res/values-mk-rMK/strings.xml
+++ b/core/res/res/values-mk-rMK/strings.xml
@@ -222,6 +222,7 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Гласовна помош"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Заклучи сега"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="safeMode" msgid="2788228061547930246">"Безбеден режим"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Систем Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Лични"</string>
diff --git a/core/res/res/values-ml-rIN/strings.xml b/core/res/res/values-ml-rIN/strings.xml
index f114cb9..a83928e 100644
--- a/core/res/res/values-ml-rIN/strings.xml
+++ b/core/res/res/values-ml-rIN/strings.xml
@@ -222,6 +222,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"വോയ്‌സ് സഹായം"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"ഇപ്പോൾ ലോക്കുചെയ്യുക"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"സുരക്ഷിത മോഡ്"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android സിസ്റ്റം"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"വ്യക്തിഗതം"</string>
diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml
index ac226a4..a9fb8593 100644
--- a/core/res/res/values-mn-rMN/strings.xml
+++ b/core/res/res/values-mn-rMN/strings.xml
@@ -222,6 +222,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Дуут туслах"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Одоо түгжих"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Аюулгүй горим"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Андройд систем"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Хувийн"</string>
diff --git a/core/res/res/values-mr-rIN/strings.xml b/core/res/res/values-mr-rIN/strings.xml
index 6ae6e82..a8896c3 100644
--- a/core/res/res/values-mr-rIN/strings.xml
+++ b/core/res/res/values-mr-rIN/strings.xml
@@ -222,6 +222,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"व्हॉइस सहाय्य"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"आता लॉक करा"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"सुरक्षित मोड"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android सिस्‍टम"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"वैयक्तिक"</string>
diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml
index d9175c2..cababdd 100644
--- a/core/res/res/values-ms-rMY/strings.xml
+++ b/core/res/res/values-ms-rMY/strings.xml
@@ -222,6 +222,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Bantuan Suara"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Kunci sekarang"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Mod selamat"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistem Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Peribadi"</string>
diff --git a/core/res/res/values-my-rMM/strings.xml b/core/res/res/values-my-rMM/strings.xml
index 4a0a227..8e61f41 100644
--- a/core/res/res/values-my-rMM/strings.xml
+++ b/core/res/res/values-my-rMM/strings.xml
@@ -222,6 +222,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"အသံ အကူအညီ"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"ယခု သော့ပိတ်ရန်"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"၉၉၉+"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"အန္တရာယ်ကင်းမှု စနစ်(Safe mode)"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android စနစ်"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"ကိုယ်ရေး"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index f504175..f29a903 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -222,6 +222,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Talehjelp"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Lås nå"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Sikkermodus"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-system"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Personlig"</string>
@@ -235,7 +237,7 @@
     <string name="permgrouplab_sms" msgid="228308803364967808">"SMS"</string>
     <string name="permgroupdesc_sms" msgid="4656988620100940350">"sende og lese SMS-meldinger"</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Lagring"</string>
-    <string name="permgroupdesc_storage" msgid="637758554581589203">"åpne bilder, media og filer på enheten din"</string>
+    <string name="permgroupdesc_storage" msgid="637758554581589203">"åpne bilder, medier og filer på enheten din"</string>
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Mikrofon"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"spill inn lyd"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Kamera"</string>
diff --git a/core/res/res/values-ne-rNP/strings.xml b/core/res/res/values-ne-rNP/strings.xml
index 7867c59..a33289f 100644
--- a/core/res/res/values-ne-rNP/strings.xml
+++ b/core/res/res/values-ne-rNP/strings.xml
@@ -222,6 +222,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"आवाज सहायता"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"अब बन्द गर्नुहोस्"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"९९९+"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"सुरक्षित मोड"</string>
     <string name="android_system_label" msgid="6577375335728551336">"एन्ड्रोइड प्रणाली"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"व्यक्तिगत"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index d04e10b..53b45b0 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -222,6 +222,7 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Spraakassistent"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Nu vergrendelen"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999 +"</string>
+    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="safeMode" msgid="2788228061547930246">"Veilige modus"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-systeem"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Persoonlijk"</string>
@@ -243,7 +244,7 @@
     <string name="permgrouplab_phone" msgid="5229115638567440675">"Telefoon"</string>
     <string name="permgroupdesc_phone" msgid="6234224354060641055">"bellen en telefoontjes beheren"</string>
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Lichaamssensoren"</string>
-    <string name="permgroupdesc_sensors" msgid="7147968539346634043">"toegang tot sensorgegevens over je vitale functies"</string>
+    <string name="permgroupdesc_sensors" msgid="7147968539346634043">"toegang krijgen tot sensorgegevens over je vitale functies"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Inhoud van vensters ophalen"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"De inhoud inspecteren van een venster waarmee je interactie hebt."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"\'Verkennen via aanraking\' inschakelen"</string>
diff --git a/core/res/res/values-pa-rIN/strings.xml b/core/res/res/values-pa-rIN/strings.xml
index c3df4ac..d450bf9 100644
--- a/core/res/res/values-pa-rIN/strings.xml
+++ b/core/res/res/values-pa-rIN/strings.xml
@@ -222,6 +222,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"ਵੌਇਸ ਅਸਿਸਟ"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"ਹੁਣ ਲੌਕ ਕਰੋ"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"ਸੁਰੱਖਿਅਤ ਮੋਡ"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android System"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"ਨਿੱਜੀ"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index ad826262..b7f984d 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -224,6 +224,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Asystent głosowy"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Zablokuj teraz"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"&gt;999"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Tryb awaryjny"</string>
     <string name="android_system_label" msgid="6577375335728551336">"System Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Osobiste"</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index c338b3b..4464259 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -222,6 +222,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Ajuda de voz"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Bloquear agora"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"&gt;999"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Modo de segurança"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Pessoal"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 6b0581f..af38435 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -222,6 +222,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Assist. de voz"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Bloquear agora"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Modo seguro"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Pessoal"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index c338b3b..4464259 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -222,6 +222,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Ajuda de voz"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Bloquear agora"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"&gt;999"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Modo de segurança"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Pessoal"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 9e676fd..7ac92c3 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -223,6 +223,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Asistent vocal"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Blocați acum"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"˃999"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Mod sigur"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistemul Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Personal"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index ca1a986..b7ba99f 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -224,6 +224,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Аудиоподсказки"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Заблокировать"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"&gt;999"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Безопасный режим"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Система Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Личные данные"</string>
diff --git a/core/res/res/values-si-rLK/strings.xml b/core/res/res/values-si-rLK/strings.xml
index 66061d1..4e265177 100644
--- a/core/res/res/values-si-rLK/strings.xml
+++ b/core/res/res/values-si-rLK/strings.xml
@@ -222,6 +222,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"හඬ සහායක"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"දැන් අගුළු දමන්න"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"ආරක්‍ෂිත ආකාරය"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android පද්ධතිය"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"පෞද්ගලික"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 72e8db2..ba5465e 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -224,6 +224,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Hlasový asistent"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Uzamknúť"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Núdzový režim"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Systém Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Osobné"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 9f1c669..04b7fc7 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -224,6 +224,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Glas. pomočnik"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Zakleni zdaj"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999 +"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Varni način"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistem Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Osebno"</string>
diff --git a/core/res/res/values-sq-rAL/strings.xml b/core/res/res/values-sq-rAL/strings.xml
index d67a5fe..b8ca565 100644
--- a/core/res/res/values-sq-rAL/strings.xml
+++ b/core/res/res/values-sq-rAL/strings.xml
@@ -222,6 +222,7 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Ndihma zanore"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Kyç tani"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="safeMode" msgid="2788228061547930246">"Modaliteti i sigurisë"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistemi \"android\""</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Personal"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index ddb9ba7..4118c63 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -223,6 +223,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Гласовна помоћ"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Закључај одмах"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Безбедни режим"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android систем"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Лично"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index f5172fe..40141de 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -222,6 +222,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Voice Assist"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Lås nu"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Säkert läge"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-system"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Personligt"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 3de8eeb..196d5dc 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -224,6 +224,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Usaidizi wa Sauti"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Funga sasa"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Mtindo salama"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Mfumo wa Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Binafsi"</string>
diff --git a/core/res/res/values-ta-rIN/strings.xml b/core/res/res/values-ta-rIN/strings.xml
index 30b326a..1113776 100644
--- a/core/res/res/values-ta-rIN/strings.xml
+++ b/core/res/res/values-ta-rIN/strings.xml
@@ -222,6 +222,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"குரல் உதவி"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"இப்போது பூட்டு"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"பாதுகாப்பு பயன்முறை"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android அமைப்பு"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"தனிப்பட்ட"</string>
diff --git a/core/res/res/values-te-rIN/strings.xml b/core/res/res/values-te-rIN/strings.xml
index 3659080..c563e7c 100644
--- a/core/res/res/values-te-rIN/strings.xml
+++ b/core/res/res/values-te-rIN/strings.xml
@@ -222,6 +222,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"వాయిస్ సహాయకం"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"ఇప్పుడు లాక్ చేయండి"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"సురక్షిత మోడ్"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android సిస్టమ్"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"వ్యక్తిగతం"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 81bc75f..0080f51 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -222,6 +222,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"ตัวช่วยเสียง"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"ล็อกเลย"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"โหมดปลอดภัย"</string>
     <string name="android_system_label" msgid="6577375335728551336">"ระบบ Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"ส่วนตัว"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 29efae69..4f907c1 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -222,6 +222,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Voice Assist"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"I-lock ngayon"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android System"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Personal"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index dac5259..06f8c75 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -222,6 +222,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Sesli Yardım"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Şimdi kilitle"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Güvenli mod"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android Sistemi"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Kişisel"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 7522e4e..721f24d 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -224,6 +224,7 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Голос. підказки"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Блокувати зараз"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="safeMode" msgid="2788228061547930246">"Безп. режим"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Система Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Особисті дані"</string>
diff --git a/core/res/res/values-ur-rPK/strings.xml b/core/res/res/values-ur-rPK/strings.xml
index 388b790..e31fa57 100644
--- a/core/res/res/values-ur-rPK/strings.xml
+++ b/core/res/res/values-ur-rPK/strings.xml
@@ -222,6 +222,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Voice Assist"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"ابھی مقفل کریں"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"‎999+‎"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"حفاظتی وضع"</string>
     <string name="android_system_label" msgid="6577375335728551336">"‏Android سسٹم"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"ذاتی"</string>
diff --git a/core/res/res/values-uz-rUZ/strings.xml b/core/res/res/values-uz-rUZ/strings.xml
index bafedfc..0489638 100644
--- a/core/res/res/values-uz-rUZ/strings.xml
+++ b/core/res/res/values-uz-rUZ/strings.xml
@@ -222,6 +222,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Ovozli yordam"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Qulflash"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Xavfsiz usul"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android tizimi"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Shaxsiy"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 9165f4d..ccd1345 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -222,6 +222,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Trợ lý thoại"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Khóa ngay"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Chế độ an toàn"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Hệ thống Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Cá nhân"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 36a1a7f..1afede0 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -222,6 +222,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"语音助理"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"立即锁定"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"安全模式"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android 系统"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"个人"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index efab307..84c85bf 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -222,6 +222,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"語音助手"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"立即鎖定"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"安全模式"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android 系統"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"個人"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index e938fb8..b45fe75 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -222,6 +222,8 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"語音小幫手"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"立即鎖定"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"超過 999"</string>
+    <!-- no translation found for notification_children_count_bracketed (1769425473168347839) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"安全模式"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android 系統"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"個人"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index bd566cd..c2159d7 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -222,6 +222,7 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Isisekeli sezwi"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"Khiya manje"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
+    <string name="notification_children_count_bracketed" msgid="1769425473168347839">"(<xliff:g id="NOTIFICATIONCOUNT">%d</xliff:g>)"</string>
     <string name="safeMode" msgid="2788228061547930246">"Imodi ephephile"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Uhlelo lwe-Android"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"Okomuntu siqu"</string>
diff --git a/core/tests/coretests/apks/install_complete_package_info/Android.mk b/core/tests/coretests/apks/install_complete_package_info/Android.mk
index 1edccb4..19bf356 100644
--- a/core/tests/coretests/apks/install_complete_package_info/Android.mk
+++ b/core/tests/coretests/apks/install_complete_package_info/Android.mk
@@ -5,7 +5,9 @@
 
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
-LOCAL_PACKAGE_NAME := FrameworkCoreTests_install_complete_package_info
+LOCAL_PACKAGE_NAME := install_complete_package_info
+#LOCAL_MANIFEST_FILE := api_test/AndroidManifest.xml
 
-include $(BUILD_PACKAGE)
+include $(FrameworkCoreTests_BUILD_PACKAGE)
+#include $(BUILD_PACKAGE)
 
diff --git a/core/tests/coretests/apks/keyset/api_test/AndroidManifest.xml b/core/tests/coretests/apks/keyset/api_test/AndroidManifest.xml
index 4c7e968..2897bd5 100644
--- a/core/tests/coretests/apks/keyset/api_test/AndroidManifest.xml
+++ b/core/tests/coretests/apks/keyset/api_test/AndroidManifest.xml
@@ -17,4 +17,11 @@
         package="com.android.frameworks.coretests.keysets_api">
     <application android:hasCode="false">
     </application>
+    <key-sets>
+        <key-set android:name="A" >
+          <public-key android:name="keyA"
+                      android:value="MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJoN1Nsgqf0V4C/bbN8wo8O2X/S5D76+5Mb9mlIsHkUTUTbHCNk+LxHIUYLm89YbP9zImrV0bUHLUAZUyoMUCiMCAwEAAQ=="/>
+        </key-set>
+    </key-sets>
+
 </manifest>
diff --git a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
index 9498f4c..b5f0617 100644
--- a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
+++ b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
@@ -73,7 +73,6 @@
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
-@Suppress  // Failing.
 public class PackageManagerTests extends AndroidTestCase {
     private static final boolean localLOGV = true;
 
@@ -434,14 +433,6 @@
                             SECURE_CONTAINERS_PREFIX, publicSrcPath);
                     assertStartsWith("The native library path should point to the ASEC",
                             SECURE_CONTAINERS_PREFIX, info.nativeLibraryDir);
-                    try {
-                        String compatLib = new File(info.dataDir + "/lib").getCanonicalPath();
-                        assertEquals("The compatibility lib directory should be a symbolic link to "
-                                + info.nativeLibraryDir,
-                                info.nativeLibraryDir, compatLib);
-                    } catch (IOException e) {
-                        fail("compat check: Can't read " + info.dataDir + "/lib");
-                    }
                 } else {
                     assertFalse(
                             (info.privateFlags & ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK) != 0);
@@ -1014,7 +1005,8 @@
 
     private static void assertUninstalled(ApplicationInfo info) throws Exception {
         File nativeLibraryFile = new File(info.nativeLibraryDir);
-        assertFalse("Native library directory should be erased", nativeLibraryFile.exists());
+        assertFalse("Native library directory " + info.nativeLibraryDir
+                + " should be erased", nativeLibraryFile.exists());
     }
 
     public void deleteFromRawResource(int iFlags, int dFlags) throws Exception {
@@ -1650,15 +1642,10 @@
                             (info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0);
                     assertStartsWith("Native library dir should point to ASEC",
                             SECURE_CONTAINERS_PREFIX, info.nativeLibraryDir);
-                    final File nativeLibSymLink = new File(info.dataDir, "lib");
-                    assertStartsWith("The data directory should have a 'lib' symlink that points to the ASEC container",
-                            SECURE_CONTAINERS_PREFIX, nativeLibSymLink.getCanonicalPath());
                 }
             }
         } catch (NameNotFoundException e) {
             failStr("Pkg hasnt been installed correctly");
-        } catch (Exception e) {
-            failStr("Failed with exception : " + e);
         } finally {
             if (ip != null) {
                 cleanUpInstall(ip);
@@ -1689,6 +1676,7 @@
         sampleMoveFromRawResource(installFlags, moveFlags, fail, result);
     }
 
+    @Suppress
     @LargeTest
     public void testMoveAppInternalToInternal() throws Exception {
         int installFlags = PackageManager.INSTALL_INTERNAL;
@@ -2157,6 +2145,7 @@
                 -1);
     }
 
+    @Suppress
     @LargeTest
     public void testFlagFExistingI() throws Exception {
         int iFlags = PackageManager.INSTALL_INTERNAL;
@@ -3272,14 +3261,15 @@
             assertTrue(false); // should have thrown
         } catch (IllegalArgumentException e) {
         }
-        installFromRawResource("keysetApi.apk", R.raw.keyset_splat_api,
+        final InstallParams ip = installFromRawResource("keysetApi.apk", R.raw.keyset_splat_api,
                 0, false, false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
         try {
             ks = pm.getSigningKeySet(otherPkgName);
             assertTrue(false); // should have thrown
         } catch (SecurityException e) {
+        } finally {
+            cleanUpInstall(ip);
         }
-        cleanUpInstall(otherPkgName);
         ks = pm.getSigningKeySet(mContext.getPackageName());
         assertNotNull(ks);
     }
@@ -3318,16 +3308,20 @@
             assertTrue(false); // should have thrown
         } catch(IllegalArgumentException e) {
         }
-        installFromRawResource("keysetApi.apk", R.raw.keyset_splat_api,
+
+        // make sure we can get a KeySet from our pkg
+        ks = pm.getKeySetByAlias(mPkgName, "A");
+        assertNotNull(ks);
+
+        // and another
+        final InstallParams ip = installFromRawResource("keysetApi.apk", R.raw.keyset_splat_api,
                 0, false, false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
         try {
             ks = pm.getKeySetByAlias(otherPkgName, "A");
-            assertTrue(false); // should have thrown
-        } catch (SecurityException e) {
+            assertNotNull(ks);
+        } finally {
+            cleanUpInstall(ip);
         }
-        cleanUpInstall(otherPkgName);
-        ks = pm.getKeySetByAlias(mPkgName, "A");
-        assertNotNull(ks);
     }
 
     public void testIsSignedBy() throws Exception {
@@ -3360,17 +3354,23 @@
         assertFalse(pm.isSignedBy(mPkgName, new KeySet(new Binder())));
         assertTrue(pm.isSignedBy(mPkgName, mSigningKS));
 
-        installFromRawResource("keysetApi.apk", R.raw.keyset_splat_api,
+        final InstallParams ip1 = installFromRawResource("keysetApi.apk", R.raw.keyset_splat_api,
                 0, false, false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
-        assertFalse(pm.isSignedBy(otherPkgName, mDefinedKS));
-        assertTrue(pm.isSignedBy(otherPkgName, mSigningKS));
-        cleanUpInstall(otherPkgName);
+        try {
+            assertFalse(pm.isSignedBy(otherPkgName, mDefinedKS));
+            assertTrue(pm.isSignedBy(otherPkgName, mSigningKS));
+        } finally {
+            cleanUpInstall(ip1);
+        }
 
-        installFromRawResource("keysetApi.apk", R.raw.keyset_splata_api,
+        final InstallParams ip2 = installFromRawResource("keysetApi.apk", R.raw.keyset_splata_api,
                 0, false, false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
-        assertTrue(pm.isSignedBy(otherPkgName, mDefinedKS));
-        assertTrue(pm.isSignedBy(otherPkgName, mSigningKS));
-        cleanUpInstall(otherPkgName);
+        try {
+            assertTrue(pm.isSignedBy(otherPkgName, mDefinedKS));
+            assertTrue(pm.isSignedBy(otherPkgName, mSigningKS));
+        } finally {
+            cleanUpInstall(ip2);
+        }
     }
 
     public void testIsSignedByExactly() throws Exception {
@@ -3402,17 +3402,23 @@
         assertFalse(pm.isSignedByExactly(mPkgName, new KeySet(new Binder())));
         assertTrue(pm.isSignedByExactly(mPkgName, mSigningKS));
 
-        installFromRawResource("keysetApi.apk", R.raw.keyset_splat_api,
+        final InstallParams ip1 = installFromRawResource("keysetApi.apk", R.raw.keyset_splat_api,
                 0, false, false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
-        assertFalse(pm.isSignedByExactly(otherPkgName, mDefinedKS));
-        assertTrue(pm.isSignedByExactly(otherPkgName, mSigningKS));
-        cleanUpInstall(otherPkgName);
+        try {
+            assertFalse(pm.isSignedByExactly(otherPkgName, mDefinedKS));
+            assertTrue(pm.isSignedByExactly(otherPkgName, mSigningKS));
+        } finally {
+            cleanUpInstall(ip1);
+        }
 
-        installFromRawResource("keysetApi.apk", R.raw.keyset_splata_api,
+        final InstallParams ip2 = installFromRawResource("keysetApi.apk", R.raw.keyset_splata_api,
                 0, false, false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
-        assertFalse(pm.isSignedByExactly(otherPkgName, mDefinedKS));
-        assertFalse(pm.isSignedByExactly(otherPkgName, mSigningKS));
-        cleanUpInstall(otherPkgName);
+        try {
+            assertFalse(pm.isSignedByExactly(otherPkgName, mDefinedKS));
+            assertFalse(pm.isSignedByExactly(otherPkgName, mSigningKS));
+        } finally {
+            cleanUpInstall(ip2);
+        }
     }
 
 
@@ -3465,11 +3471,10 @@
         int apk2 = APP2_CERT1_CERT2;
         String apk1Name = "install1.apk";
         String apk2Name = "install2.apk";
-        InstallParams ip1 = null;
 
+        final InstallParams ip = installFromRawResource(apk1Name, apk1, 0, false,
+                false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
         try {
-            ip1 = installFromRawResource(apk1Name, apk1, 0, false,
-                    false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
             PackageManager pm = mContext.getPackageManager();
             // Delete app2
             File filesDir = mContext.getFilesDir();
@@ -3480,12 +3485,10 @@
             getPm().deletePackage(pkg.packageName, null, PackageManager.DELETE_ALL_USERS);
             // Check signatures now
             int match = mContext.getPackageManager().checkSignatures(
-                    ip1.pkg.packageName, pkg.packageName);
+                    ip.pkg.packageName, pkg.packageName);
             assertEquals(PackageManager.SIGNATURE_UNKNOWN_PACKAGE, match);
         } finally {
-            if (ip1 != null) {
-                cleanUpInstall(ip1);
-            }
+            cleanUpInstall(ip);
         }
     }
 
@@ -3493,14 +3496,10 @@
     public void testInstallNoCertificates() throws Exception {
         int apk1 = APP1_UNSIGNED;
         String apk1Name = "install1.apk";
-        InstallParams ip1 = null;
 
-        try {
-            installFromRawResource(apk1Name, apk1, 0, false,
-                    true, PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES,
-                    PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
-        } finally {
-        }
+        installFromRawResource(apk1Name, apk1, 0, false,
+                true, PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES,
+                PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
     }
 
     /*
@@ -3766,35 +3765,43 @@
      * Test that getInstalledPackages returns all the data specified in flags.
      */
     public void testGetInstalledPackagesAll() throws Exception {
-        int flags = PackageManager.GET_ACTIVITIES | PackageManager.GET_GIDS
+        final int flags = PackageManager.GET_ACTIVITIES | PackageManager.GET_GIDS
                 | PackageManager.GET_CONFIGURATIONS | PackageManager.GET_INSTRUMENTATION
                 | PackageManager.GET_PERMISSIONS | PackageManager.GET_PROVIDERS
                 | PackageManager.GET_RECEIVERS | PackageManager.GET_SERVICES
                 | PackageManager.GET_SIGNATURES | PackageManager.GET_UNINSTALLED_PACKAGES;
 
-        List<PackageInfo> packages = getPm().getInstalledPackages(flags);
-        assertNotNull("installed packages cannot be null", packages);
-        assertTrue("installed packages cannot be empty", packages.size() > 0);
+        final InstallParams ip =
+                installFromRawResource("install.apk", R.raw.install_complete_package_info,
+                        0 /*flags*/, false /*cleanUp*/, false /*fail*/, -1 /*result*/,
+                        PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
+        try {
+            final List<PackageInfo> packages = getPm().getInstalledPackages(flags);
+            assertNotNull("installed packages cannot be null", packages);
+            assertTrue("installed packages cannot be empty", packages.size() > 0);
 
-        PackageInfo packageInfo = null;
+            PackageInfo packageInfo = null;
 
-        // Find the package with all components specified in the AndroidManifest
-        // to ensure no null values
-        for (PackageInfo pi : packages) {
-            if ("com.android.frameworks.coretests.install_complete_package_info"
-                    .equals(pi.packageName)) {
-                packageInfo = pi;
-                break;
+            // Find the package with all components specified in the AndroidManifest
+            // to ensure no null values
+            for (PackageInfo pi : packages) {
+                if ("com.android.frameworks.coretests.install_complete_package_info"
+                        .equals(pi.packageName)) {
+                    packageInfo = pi;
+                    break;
+                }
             }
+            assertNotNull("activities should not be null", packageInfo.activities);
+            assertNotNull("configPreferences should not be null", packageInfo.configPreferences);
+            assertNotNull("instrumentation should not be null", packageInfo.instrumentation);
+            assertNotNull("permissions should not be null", packageInfo.permissions);
+            assertNotNull("providers should not be null", packageInfo.providers);
+            assertNotNull("receivers should not be null", packageInfo.receivers);
+            assertNotNull("services should not be null", packageInfo.services);
+            assertNotNull("signatures should not be null", packageInfo.signatures);
+        } finally {
+            cleanUpInstall(ip);
         }
-        assertNotNull("activities should not be null", packageInfo.activities);
-        assertNotNull("configPreferences should not be null", packageInfo.configPreferences);
-        assertNotNull("instrumentation should not be null", packageInfo.instrumentation);
-        assertNotNull("permissions should not be null", packageInfo.permissions);
-        assertNotNull("providers should not be null", packageInfo.providers);
-        assertNotNull("receivers should not be null", packageInfo.receivers);
-        assertNotNull("services should not be null", packageInfo.services);
-        assertNotNull("signatures should not be null", packageInfo.signatures);
     }
 
     /**
@@ -3802,38 +3809,52 @@
      * flags when the GET_UNINSTALLED_PACKAGES flag is set.
      */
     public void testGetUnInstalledPackagesAll() throws Exception {
-        int flags = PackageManager.GET_UNINSTALLED_PACKAGES
+        final int flags = PackageManager.GET_UNINSTALLED_PACKAGES
                 | PackageManager.GET_ACTIVITIES | PackageManager.GET_GIDS
                 | PackageManager.GET_CONFIGURATIONS | PackageManager.GET_INSTRUMENTATION
                 | PackageManager.GET_PERMISSIONS | PackageManager.GET_PROVIDERS
                 | PackageManager.GET_RECEIVERS | PackageManager.GET_SERVICES
                 | PackageManager.GET_SIGNATURES | PackageManager.GET_UNINSTALLED_PACKAGES;
 
-        List<PackageInfo> packages = getPm().getInstalledPackages(flags);
-        assertNotNull("installed packages cannot be null", packages);
-        assertTrue("installed packages cannot be empty", packages.size() > 0);
+        // first, install the package
+        final InstallParams ip =
+                installFromRawResource("install.apk", R.raw.install_complete_package_info,
+                        0 /*flags*/, false /*cleanUp*/, false /*fail*/, -1 /*result*/,
+                        PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
+        try {
+            // then, remove it, keeping it's data around
+            final GenericReceiver receiver = new DeleteReceiver(ip.pkg.packageName);
+            invokeDeletePackage(ip.pkg.packageName, PackageManager.DELETE_KEEP_DATA, receiver);
 
-        PackageInfo packageInfo = null;
+            final List<PackageInfo> packages = getPm().getInstalledPackages(flags);
+            assertNotNull("installed packages cannot be null", packages);
+            assertTrue("installed packages cannot be empty", packages.size() > 0);
 
-        // Find the package with all components specified in the AndroidManifest
-        // to ensure no null values
-        for (PackageInfo pi : packages) {
-            if ("com.android.frameworks.coretests.install_complete_package_info"
-                    .equals(pi.packageName)) {
-                packageInfo = pi;
-                break;
+            PackageInfo packageInfo = null;
+
+            // Find the package with all components specified in the AndroidManifest
+            // to ensure no null values
+            for (PackageInfo pi : packages) {
+                if ("com.android.frameworks.coretests.install_complete_package_info"
+                        .equals(pi.packageName)) {
+                    packageInfo = pi;
+                    break;
+                }
             }
+            assertNotNull("activities should not be null", packageInfo.activities);
+            assertNotNull("configPreferences should not be null", packageInfo.configPreferences);
+            assertNotNull("instrumentation should not be null", packageInfo.instrumentation);
+            assertNotNull("permissions should not be null", packageInfo.permissions);
+            assertNotNull("providers should not be null", packageInfo.providers);
+            assertNotNull("receivers should not be null", packageInfo.receivers);
+            assertNotNull("services should not be null", packageInfo.services);
+            assertNotNull("signatures should not be null", packageInfo.signatures);
+        } finally {
+            cleanUpInstall(ip);
         }
-        assertNotNull("activities should not be null", packageInfo.activities);
-        assertNotNull("configPreferences should not be null", packageInfo.configPreferences);
-        assertNotNull("instrumentation should not be null", packageInfo.instrumentation);
-        assertNotNull("permissions should not be null", packageInfo.permissions);
-        assertNotNull("providers should not be null", packageInfo.providers);
-        assertNotNull("receivers should not be null", packageInfo.receivers);
-        assertNotNull("services should not be null", packageInfo.services);
-        assertNotNull("signatures should not be null", packageInfo.signatures);
     }
 
+    @Suppress
     public void testInstall_BadDex_CleanUp() throws Exception {
         int retCode = PackageManager.INSTALL_FAILED_DEXOPT;
         installFromRawResource("install.apk", R.raw.install_bad_dex, 0, true, true, retCode,
diff --git a/media/jni/soundpool/SoundPool.cpp b/media/jni/soundpool/SoundPool.cpp
index 090be88..70d651f 100644
--- a/media/jni/soundpool/SoundPool.cpp
+++ b/media/jni/soundpool/SoundPool.cpp
@@ -187,6 +187,17 @@
     return mDecodeThread != NULL;
 }
 
+sp<Sample> SoundPool::findSample(int sampleID)
+{
+    Mutex::Autolock lock(&mLock);
+    return findSample_l(sampleID);
+}
+
+sp<Sample> SoundPool::findSample_l(int sampleID)
+{
+    return mSamples.valueFor(sampleID);
+}
+
 SoundChannel* SoundPool::findChannel(int channelID)
 {
     for (int i = 0; i < mMaxChannels; ++i) {
@@ -211,18 +222,21 @@
 {
     ALOGV("load: fd=%d, offset=%" PRId64 ", length=%" PRId64 ", priority=%d",
             fd, offset, length, priority);
-    Mutex::Autolock lock(&mLock);
-    sp<Sample> sample = new Sample(++mNextSampleID, fd, offset, length);
-    mSamples.add(sample->sampleID(), sample);
-    doLoad(sample);
-    return sample->sampleID();
-}
-
-void SoundPool::doLoad(sp<Sample>& sample)
-{
-    ALOGV("doLoad: loading sample sampleID=%d", sample->sampleID());
-    sample->startLoad();
-    mDecodeThread->loadSample(sample->sampleID());
+    int sampleID;
+    {
+        Mutex::Autolock lock(&mLock);
+        sampleID = ++mNextSampleID;
+        sp<Sample> sample = new Sample(sampleID, fd, offset, length);
+        mSamples.add(sampleID, sample);
+        sample->startLoad();
+    }
+    // mDecodeThread->loadSample() must be called outside of mLock.
+    // mDecodeThread->loadSample() may block on mDecodeThread message queue space;
+    // the message queue emptying may block on SoundPool::findSample().
+    //
+    // It theoretically possible that sample loads might decode out-of-order.
+    mDecodeThread->loadSample(sampleID);
+    return sampleID;
 }
 
 bool SoundPool::unload(int sampleID)
@@ -237,7 +251,6 @@
 {
     ALOGV("play sampleID=%d, leftVolume=%f, rightVolume=%f, priority=%d, loop=%d, rate=%f",
             sampleID, leftVolume, rightVolume, priority, loop, rate);
-    sp<Sample> sample;
     SoundChannel* channel;
     int channelID;
 
@@ -247,7 +260,7 @@
         return 0;
     }
     // is sample ready?
-    sample = findSample(sampleID);
+    sp<Sample> sample(findSample_l(sampleID));
     if ((sample == 0) || (sample->state() != Sample::READY)) {
         ALOGW("  sample %d not READY", sampleID);
         return 0;
diff --git a/media/jni/soundpool/SoundPool.h b/media/jni/soundpool/SoundPool.h
index 4aacf53..98d2fa2 100644
--- a/media/jni/soundpool/SoundPool.h
+++ b/media/jni/soundpool/SoundPool.h
@@ -180,6 +180,7 @@
 
     // called from SoundPoolThread
     void sampleLoaded(int sampleID);
+    sp<Sample> findSample(int sampleID);
 
     // called from AudioTrack thread
     void done_l(SoundChannel* channel);
@@ -191,8 +192,7 @@
 private:
     SoundPool() {} // no default constructor
     bool startThreads();
-    void doLoad(sp<Sample>& sample);
-    sp<Sample> findSample(int sampleID) { return mSamples.valueFor(sampleID); }
+    sp<Sample> findSample_l(int sampleID);
     SoundChannel* findChannel (int channelID);
     SoundChannel* findNextChannel (int channelID);
     SoundChannel* allocateChannel_l(int priority, int sampleID);
diff --git a/packages/DocumentsUI/AndroidManifest.xml b/packages/DocumentsUI/AndroidManifest.xml
index 595928a..60f5d60 100644
--- a/packages/DocumentsUI/AndroidManifest.xml
+++ b/packages/DocumentsUI/AndroidManifest.xml
@@ -39,7 +39,7 @@
         </activity>
 
         <activity
-            android:name=".ManageRootActivity"
+            android:name=".DownloadsActivity"
             android:theme="@style/DocumentsFullScreenTheme"
             android:icon="@drawable/ic_doc_text">
             <intent-filter>
diff --git a/packages/DocumentsUI/src/com/android/documentsui/ManageRootActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DownloadsActivity.java
similarity index 95%
rename from packages/DocumentsUI/src/com/android/documentsui/ManageRootActivity.java
rename to packages/DocumentsUI/src/com/android/documentsui/DownloadsActivity.java
index 3045fa8..f224343 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/ManageRootActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DownloadsActivity.java
@@ -50,8 +50,11 @@
 import java.util.Arrays;
 import java.util.List;
 
-public class ManageRootActivity extends BaseActivity {
-    private static final String TAG = "ManageRootsActivity";
+// Let's face it. MANAGE_ROOT is used almost exclusively
+// for downloads, and is specialized for this purpose.
+// So it is now thusly christened.
+public class DownloadsActivity extends BaseActivity {
+    private static final String TAG = "DownloadsActivity";
 
     private Toolbar mToolbar;
     private Spinner mToolbarStack;
@@ -59,7 +62,7 @@
     private ItemSelectedListener mStackListener;
     private BaseAdapter mStackAdapter;
 
-    public ManageRootActivity() {
+    public DownloadsActivity() {
         super(R.layout.manage_roots_activity, TAG);
     }
 
@@ -250,7 +253,7 @@
         finish();
     }
 
-    public static ManageRootActivity get(Fragment fragment) {
-        return (ManageRootActivity) fragment.getActivity();
+    public static DownloadsActivity get(Fragment fragment) {
+        return (DownloadsActivity) fragment.getActivity();
     }
 }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
index b0421b0..be3013b 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
@@ -741,45 +741,45 @@
 
             Selection selection = mSelectionManager.getSelection(new Selection());
 
-            final int id = item.getItemId();
-            if (id == R.id.menu_open) {
-                openDocuments(selection);
-                mode.finish();
-                return true;
+            switch (item.getItemId()) {
+                case R.id.menu_open:
+                    openDocuments(selection);
+                    mode.finish();
+                    return true;
 
-            } else if (id == R.id.menu_share) {
-                shareDocuments(selection);
-                mode.finish();
-                return true;
+                case R.id.menu_share:
+                    shareDocuments(selection);
+                    mode.finish();
+                    return true;
 
-            } else if (id == R.id.menu_delete) {
-                // Exit selection mode first, so we avoid deselecting deleted documents.
-                mode.finish();
-                deleteDocuments(selection);
-                return true;
+                case R.id.menu_delete:
+                    // Exit selection mode first, so we avoid deselecting deleted documents.
+                    mode.finish();
+                    deleteDocuments(selection);
+                    return true;
 
-            } else if (id == R.id.menu_copy_to) {
-                transferDocuments(selection, CopyService.TRANSFER_MODE_COPY);
-                mode.finish();
-                return true;
+                case R.id.menu_copy_to:
+                    transferDocuments(selection, CopyService.TRANSFER_MODE_COPY);
+                    mode.finish();
+                    return true;
 
-            } else if (id == R.id.menu_move_to) {
-                // Exit selection mode first, so we avoid deselecting deleted documents.
-                mode.finish();
-                transferDocuments(selection, CopyService.TRANSFER_MODE_MOVE);
-                return true;
+                case R.id.menu_move_to:
+                    // Exit selection mode first, so we avoid deselecting deleted documents.
+                    mode.finish();
+                    transferDocuments(selection, CopyService.TRANSFER_MODE_MOVE);
+                    return true;
 
-            } else if (id == R.id.menu_copy_to_clipboard) {
-                copySelectionToClipboard(selection);
-                mode.finish();
-                return true;
+                case R.id.menu_copy_to_clipboard:
+                    copySelectionToClipboard(selection);
+                    return true;
 
-            } else if (id == R.id.menu_select_all) {
-                selectAllFiles();
-                return true;
+                case R.id.menu_select_all:
+                    selectAllFiles();
+                    return true;
 
-            } else {
-                return false;
+                default:
+                    if (DEBUG) Log.d(TAG, "Unhandled menu item selected: " + item);
+                    return false;
             }
         }
     }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java
index 38d3805..ef6d2c9 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java
@@ -176,7 +176,6 @@
             final MenuItem moveTo = menu.findItem(R.id.menu_move_to);
 
             open.setVisible(false);
-            share.setVisible(false);
             delete.setVisible(canDelete);
             copyTo.setVisible(true);
             copyTo.setEnabled(true);
diff --git a/packages/PrintSpooler/src/com/android/printspooler/model/NotificationController.java b/packages/PrintSpooler/src/com/android/printspooler/model/NotificationController.java
index f006ccb..82fd512 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/model/NotificationController.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/model/NotificationController.java
@@ -16,6 +16,8 @@
 
 package com.android.printspooler.model;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.app.Notification;
 import android.app.Notification.Action;
 import android.app.Notification.InboxStyle;
@@ -129,68 +131,69 @@
                 mContext.getString(R.string.cancel), createCancelIntent(printJob)).build();
     }
 
-    private void createPrintingNotification(PrintJobInfo printJob) {
+    /**
+     * Create a notification for a print job.
+     *
+     * @param printJob the job the notification is for
+     * @param firstAction the first action shown in the notification
+     * @param secondAction the second action shown in the notification
+     */
+    private void createNotification(@NonNull PrintJobInfo printJob, @Nullable Action firstAction,
+            @Nullable Action secondAction) {
         Notification.Builder builder = new Notification.Builder(mContext)
                 .setContentIntent(createContentIntent(printJob.getId()))
                 .setSmallIcon(computeNotificationIcon(printJob))
                 .setContentTitle(computeNotificationTitle(printJob))
-                .addAction(createCancelAction(printJob))
-                .setContentText(printJob.getPrinterName())
                 .setWhen(System.currentTimeMillis())
                 .setOngoing(true)
                 .setShowWhen(true)
                 .setColor(mContext.getColor(
                         com.android.internal.R.color.system_notification_accent_color));
+
+        if (firstAction != null) {
+            builder.addAction(firstAction);
+        }
+
+        if (secondAction != null) {
+            builder.addAction(secondAction);
+        }
+
+        if (printJob.getState() == PrintJobInfo.STATE_STARTED) {
+            float progress = printJob.getProgress();
+            if (progress >= 0) {
+                builder.setProgress(Integer.MAX_VALUE, (int)(Integer.MAX_VALUE * progress),
+                        false);
+            }
+        }
+
+        CharSequence status = printJob.getStatus();
+        if (status != null) {
+            builder.setContentText(status);
+        } else {
+            builder.setContentText(printJob.getPrinterName());
+        }
+
         mNotificationManager.notify(0, builder.build());
     }
 
+    private void createPrintingNotification(PrintJobInfo printJob) {
+        createNotification(printJob, createCancelAction(printJob), null);
+    }
+
     private void createFailedNotification(PrintJobInfo printJob) {
         Action.Builder restartActionBuilder = new Action.Builder(
                 Icon.createWithResource(mContext, R.drawable.ic_restart),
                 mContext.getString(R.string.restart), createRestartIntent(printJob.getId()));
 
-        Notification.Builder builder = new Notification.Builder(mContext)
-                .setContentIntent(createContentIntent(printJob.getId()))
-                .setSmallIcon(computeNotificationIcon(printJob))
-                .setContentTitle(computeNotificationTitle(printJob))
-                .addAction(createCancelAction(printJob))
-                .addAction(restartActionBuilder.build())
-                .setContentText(printJob.getPrinterName())
-                .setWhen(System.currentTimeMillis())
-                .setOngoing(true)
-                .setShowWhen(true)
-                .setColor(mContext.getColor(
-                        com.android.internal.R.color.system_notification_accent_color));
-        mNotificationManager.notify(0, builder.build());
+        createNotification(printJob, createCancelAction(printJob), restartActionBuilder.build());
     }
 
     private void createBlockedNotification(PrintJobInfo printJob) {
-        Notification.Builder builder = new Notification.Builder(mContext)
-                .setContentIntent(createContentIntent(printJob.getId()))
-                .setSmallIcon(computeNotificationIcon(printJob))
-                .setContentTitle(computeNotificationTitle(printJob))
-                .addAction(createCancelAction(printJob))
-                .setContentText(printJob.getPrinterName())
-                .setWhen(System.currentTimeMillis())
-                .setOngoing(true)
-                .setShowWhen(true)
-                .setColor(mContext.getColor(
-                        com.android.internal.R.color.system_notification_accent_color));
-           mNotificationManager.notify(0, builder.build());
+        createNotification(printJob, createCancelAction(printJob), null);
     }
 
     private void createCancellingNotification(PrintJobInfo printJob) {
-        Notification.Builder builder = new Notification.Builder(mContext)
-                .setContentIntent(createContentIntent(printJob.getId()))
-                .setSmallIcon(computeNotificationIcon(printJob))
-                .setContentTitle(computeNotificationTitle(printJob))
-                .setContentText(printJob.getPrinterName())
-                .setWhen(System.currentTimeMillis())
-                .setOngoing(true)
-                .setShowWhen(true)
-                .setColor(mContext.getColor(
-                        com.android.internal.R.color.system_notification_accent_color));
-        mNotificationManager.notify(0, builder.build());
+        createNotification(printJob, null, null);
     }
 
     private void createStackedNotification(List<PrintJobInfo> printJobs) {
diff --git a/packages/PrintSpooler/src/com/android/printspooler/model/PrintSpoolerService.java b/packages/PrintSpooler/src/com/android/printspooler/model/PrintSpoolerService.java
index 7adcfec..b92a389 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/model/PrintSpoolerService.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/model/PrintSpoolerService.java
@@ -16,6 +16,9 @@
 
 package com.android.printspooler.model;
 
+import android.annotation.FloatRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.app.Service;
 import android.content.ComponentName;
 import android.content.Context;
@@ -497,7 +500,7 @@
                 success = true;
 
                 printJob.setState(state);
-                printJob.setStateReason(error);
+                printJob.setStatus(error);
                 printJob.setCancelling(false);
 
                 if (DEBUG_PRINT_JOB_LIFECYCLE) {
@@ -547,6 +550,35 @@
         return success;
     }
 
+    /**
+     * Set the progress for a print job.
+     *
+     * @param printJobId ID of the print job to update
+     * @param progress the new progress
+     */
+    public void setProgress(@NonNull PrintJobId printJobId,
+            @FloatRange(from=0.0, to=1.0) float progress) {
+        synchronized (mLock) {
+            getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY).setProgress(progress);
+
+            mNotificationController.onUpdateNotifications(mPrintJobs);
+        }
+    }
+
+   /**
+    * Set the status for a print job.
+    *
+    * @param printJobId ID of the print job to update
+    * @param status the new status
+    */
+   public void setStatus(@NonNull PrintJobId printJobId, @Nullable CharSequence status) {
+       synchronized (mLock) {
+           getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY).setStatus(status);
+
+           mNotificationController.onUpdateNotifications(mPrintJobs);
+       }
+   }
+
     public boolean hasActivePrintJobsLocked() {
         final int printJobCount = mPrintJobs.size();
         for (int i = 0; i < printJobCount; i++) {
@@ -693,6 +725,8 @@
         private static final String ATTR_COPIES = "copies";
         private static final String ATTR_PRINTER_NAME = "printerName";
         private static final String ATTR_STATE_REASON = "stateReason";
+        private static final String ATTR_STATUS = "status";
+        private static final String ATTR_PROGRESS = "progress";
         private static final String ATTR_CANCELLING = "cancelling";
 
         private static final String TAG_ADVANCED_OPTIONS = "advancedOptions";
@@ -801,13 +835,19 @@
                     if (!TextUtils.isEmpty(printerName)) {
                         serializer.attribute(null, ATTR_PRINTER_NAME, printerName);
                     }
-                    String stateReason = printJob.getStateReason();
-                    if (!TextUtils.isEmpty(stateReason)) {
-                        serializer.attribute(null, ATTR_STATE_REASON, stateReason);
-                    }
                     serializer.attribute(null, ATTR_CANCELLING, String.valueOf(
                             printJob.isCancelling()));
 
+                    float progress = printJob.getProgress();
+                    if (progress != Float.NaN) {
+                        serializer.attribute(null, ATTR_PROGRESS, String.valueOf(progress));
+                    }
+
+                    CharSequence status = printJob.getStatus();
+                    if (!TextUtils.isEmpty(status)) {
+                        serializer.attribute(null, ATTR_STATUS, status.toString());
+                    }
+
                     PrinterId printerId = printJob.getPrinterId();
                     if (printerId != null) {
                         serializer.startTag(null, TAG_PRINTER_ID);
@@ -1025,8 +1065,25 @@
             printJob.setCopies(Integer.parseInt(copies));
             String printerName = parser.getAttributeValue(null, ATTR_PRINTER_NAME);
             printJob.setPrinterName(printerName);
+
+            String progressString = parser.getAttributeValue(null, ATTR_PROGRESS);
+            if (progressString != null) {
+                float progress = Float.parseFloat(progressString);
+
+                if (progress != Float.NaN) {
+                    printJob.setProgress(progress);
+                }
+            }
+
+            CharSequence status = parser.getAttributeValue(null, ATTR_STATUS);
+            printJob.setStatus(status);
+
+            // stateReason is deprecated, but might be used by old print jobs
             String stateReason = parser.getAttributeValue(null, ATTR_STATE_REASON);
-            printJob.setStateReason(stateReason);
+            if (stateReason != null) {
+                printJob.setStatus(stateReason);
+            }
+
             String cancelling = parser.getAttributeValue(null, ATTR_CANCELLING);
             printJob.setCancelling(!TextUtils.isEmpty(cancelling)
                     ? Boolean.parseBoolean(cancelling) : false);
@@ -1323,6 +1380,18 @@
                     .removeApprovedService(serviceToRemove);
         }
 
+        @Override
+        public void setProgress(@NonNull PrintJobId printJobId,
+                @FloatRange(from=0.0, to=1.0) float progress) throws RemoteException {
+            PrintSpoolerService.this.setProgress(printJobId, progress);
+        }
+
+        @Override
+        public void setStatus(@NonNull PrintJobId printJobId,
+                @Nullable CharSequence status) throws RemoteException {
+            PrintSpoolerService.this.setStatus(printJobId, status);
+        }
+
         public PrintSpoolerService getService() {
             return PrintSpoolerService.this;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
index f32cfdc..4cc2b8d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
@@ -222,7 +222,6 @@
         final ImageView icon = new ImageView(mContext);
         icon.setId(android.R.id.icon);
         icon.setScaleType(ScaleType.CENTER_INSIDE);
-        icon.setImageTintList(ColorStateList.valueOf(getContext().getColor(android.R.color.white)));
         return icon;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CustomTile.java
index b0d885a..d26e8d6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CustomTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CustomTile.java
@@ -23,6 +23,7 @@
 import android.content.ServiceConnection;
 import android.content.pm.PackageManager;
 import android.content.pm.ServiceInfo;
+import android.graphics.drawable.Drawable;
 import android.os.IBinder;
 import android.os.UserHandle;
 import android.service.quicksettings.IQSTileService;
@@ -132,7 +133,9 @@
     @Override
     protected void handleUpdateState(State state, Object arg) {
         state.visible = true;
-        state.icon = new DrawableIcon(mTile.getIcon().loadDrawable(mContext));
+        Drawable drawable = mTile.getIcon().loadDrawable(mContext);
+        drawable.setTint(mContext.getColor(android.R.color.white));
+        state.icon = new DrawableIcon(drawable);
         state.label = mTile.getLabel();
         if (mTile.getContentDescription() != null) {
             state.contentDescription = mTile.getContentDescription();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
index 6f8cd8c..da3cd54 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
@@ -130,6 +130,7 @@
     private final int mLowPriorityColor;
     private boolean mIsBelowSpeedBump;
     private FalsingManager mFalsingManager;
+    private boolean mTrackTouch;
 
     public ActivatableNotificationView(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -175,15 +176,30 @@
     };
 
     @Override
-    public boolean onTouchEvent(MotionEvent event) {
-        if (mDimmed) {
+    public boolean dispatchTouchEvent(MotionEvent event) {
+        if (mDimmed && !mActivated) {
             return handleTouchEventDimmed(event);
         } else {
-            return super.onTouchEvent(event);
+            return super.dispatchTouchEvent(event);
         }
     }
 
     @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        boolean result;
+        if (mDimmed && mActivated) {
+            result = handleTouchEventDimmed(event);
+        } else {
+            result = super.onTouchEvent(event);
+        }
+        if (mActivated && result && event.getAction() == MotionEvent.ACTION_UP) {
+            mFalsingManager.onNotificationDoubleTap();
+            removeCallbacks(mTapTimeoutRunnable);
+        }
+        return result;
+    }
+
+    @Override
     public void drawableHotspotChanged(float x, float y) {
         if (!mDimmed){
             mBackgroundNormal.drawableHotspotChanged(x, y);
@@ -206,14 +222,15 @@
             case MotionEvent.ACTION_DOWN:
                 mDownX = event.getX();
                 mDownY = event.getY();
+                mTrackTouch = true;
                 if (mDownY > getActualHeight()) {
-                    return false;
+                    mTrackTouch = false;
                 }
                 break;
             case MotionEvent.ACTION_MOVE:
                 if (!isWithinTouchSlop(event)) {
                     makeInactive(true /* animate */);
-                    return false;
+                    mTrackTouch = false;
                 }
                 break;
             case MotionEvent.ACTION_UP:
@@ -222,23 +239,23 @@
                         makeActive();
                         postDelayed(mTapTimeoutRunnable, DOUBLETAP_TIMEOUT_MS);
                     } else {
-                        mFalsingManager.onNotificationDoubleTap();
-                        boolean performed = performClick();
-                        if (performed) {
-                            removeCallbacks(mTapTimeoutRunnable);
+                        if (!performClick()) {
+                            return false;
                         }
                     }
                 } else {
                     makeInactive(true /* animate */);
+                    mTrackTouch = false;
                 }
                 break;
             case MotionEvent.ACTION_CANCEL:
                 makeInactive(true /* animate */);
+                mTrackTouch = false;
                 break;
             default:
                 break;
         }
-        return true;
+        return mTrackTouch;
     }
 
     private void makeActive() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 5d4c64e..3c7ff7f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -116,7 +116,8 @@
 
 public abstract class BaseStatusBar extends SystemUI implements
         CommandQueue.Callbacks, ActivatableNotificationView.OnActivatedListener,
-        ExpandableNotificationRow.ExpansionLogger, NotificationData.Environment {
+        ExpandableNotificationRow.ExpansionLogger, NotificationData.Environment,
+        ExpandableNotificationRow.OnExpandClickListener {
     public static final String TAG = "StatusBar";
     public static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
     public static final boolean MULTIUSER_DEBUG = false;
@@ -1298,9 +1299,14 @@
             // Since the number of notifications is determined based on the height of the view, we
             // need to update them.
             updateRowStates();
+            mStackScroller.onHeightChanged(null, false);
         }
     }
 
+    @Override
+    public void onExpandClicked(View clickedView, boolean nowExpanded) {
+    }
+
     protected class H extends Handler {
         public void handleMessage(Message m) {
             switch (m.what) {
@@ -1381,6 +1387,7 @@
                     parent, false);
             row.setExpansionLogger(this, entry.notification.getKey());
             row.setGroupManager(mGroupManager);
+            row.setOnExpandClickListener(this);
         }
 
         workAroundBadLayerDrawableOpacity(row);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 81e20aa..7a94a58 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -104,14 +104,20 @@
     private boolean mIconAnimationRunning;
     private boolean mShowNoBackground;
     private ExpandableNotificationRow mNotificationParent;
+    private OnExpandClickListener mOnExpandClickListener;
     private OnClickListener mExpandClickListener = new OnClickListener() {
         @Override
         public void onClick(View v) {
             if (mGroupManager.isSummaryOfGroup(mStatusBarNotification)) {
                 mGroupManager.toggleGroupExpansion(mStatusBarNotification);
+                mOnExpandClickListener.onExpandClicked(ExpandableNotificationRow.this,
+                        mGroupManager.isGroupExpanded(mStatusBarNotification));
             } else {
-                setUserExpanded(!isExpanded());
+                boolean nowExpanded = !isExpanded();
+                setUserExpanded(nowExpanded);
                 notifyHeightChanged(true);
+                mOnExpandClickListener.onExpandClicked(ExpandableNotificationRow.this,
+                        nowExpanded);
             }
         }
     };
@@ -421,6 +427,10 @@
         mPrivateLayout.setSubTextVisible(visible);
     }
 
+    public void setOnExpandClickListener(OnExpandClickListener onExpandClickListener) {
+        mOnExpandClickListener = onExpandClickListener;
+    }
+
     public interface ExpansionLogger {
         public void logNotificationExpansion(String key, boolean userAction, boolean expanded);
     }
@@ -986,4 +996,8 @@
             mLogger.logNotificationExpansion(mLoggingKey, userAction, nowExpanded) ;
         }
     }
+
+    public interface OnExpandClickListener {
+        void onExpandClicked(View clickedView, boolean nowExpanded);
+    }
 }
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 c0e3ec1..73ee363 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -955,15 +955,7 @@
                 mQsTracking = false;
                 mTrackingPointer = -1;
                 trackMovement(event);
-                float fraction = getQsExpansionFraction();
-                if ((fraction != 0f || y >= mInitialTouchY)
-                        && (fraction != 1f || y <= mInitialTouchY)) {
-                    flingQsWithCurrentVelocity(y,
-                            event.getActionMasked() == MotionEvent.ACTION_CANCEL);
-                } else {
-                    logQsSwipeDown(y);
-                    mScrollYOverride = -1;
-                }
+                flingQsWithCurrentVelocity(y, event.getActionMasked() == MotionEvent.ACTION_CANCEL);
                 if (mVelocityTracker != null) {
                     mVelocityTracker.recycle();
                     mVelocityTracker = null;
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 05660ec..685c4e5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -25,7 +25,6 @@
 import android.app.IActivityManager;
 import android.app.Notification;
 import android.app.PendingIntent;
-import android.app.RemoteInput;
 import android.app.StatusBarManager;
 import android.content.BroadcastReceiver;
 import android.content.ComponentCallbacks2;
@@ -3999,6 +3998,13 @@
         }
     }
 
+    @Override
+    public void onExpandClicked(View clickedView, boolean nowExpanded) {
+        if (mState == StatusBarState.KEYGUARD && nowExpanded) {
+            goToLockedShade(clickedView);
+        }
+    }
+
     /**
      * Goes back to the keyguard after hanging around in {@link StatusBarState#SHADE_LOCKED}.
      */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index e00b890..b010761 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -342,7 +342,7 @@
 
     private void stopUserId(int id) {
         try {
-            ActivityManagerNative.getDefault().stopUser(id, null);
+            ActivityManagerNative.getDefault().stopUser(id, /* force= */ false, null);
         } catch (RemoteException e) {
             Log.e(TAG, "Couldn't stop user.", e);
         }
diff --git a/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java b/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java
index 76b2346..2fe6648 100644
--- a/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java
+++ b/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.content.DialogInterface;
 import android.net.IConnectivityManager;
+import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
 import android.os.ServiceManager;
@@ -50,8 +51,8 @@
     private Handler mHandler;
 
     @Override
-    protected void onResume() {
-        super.onResume();
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
 
         if (getCallingPackage() != null) {
             Log.e(TAG, getCallingPackage() + " cannot start this activity");
@@ -108,11 +109,11 @@
     }
 
     @Override
-    protected void onPause() {
-        super.onPause();
+    protected void onDestroy() {
         if (!isFinishing()) {
             finish();
         }
+        super.onDestroy();
     }
 
     @Override
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index f6dee89..b0f1fc8 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -2771,57 +2771,60 @@
     }
 
     final void setFocusedActivityLocked(ActivityRecord r, String reason) {
-        if (r != null && mFocusedActivity != r) {
-            if (DEBUG_FOCUS) Slog.d(TAG_FOCUS, "setFocusedActivityLocked: r=" + r);
-            ActivityRecord last = mFocusedActivity;
-            mFocusedActivity = r;
-            if (r.task.taskType != ActivityRecord.HOME_ACTIVITY_TYPE
-                    && r.task.taskType != ActivityRecord.RECENTS_ACTIVITY_TYPE) {
-                if (mCurAppTimeTracker != r.appTimeTracker) {
-                    // We are switching app tracking.  Complete the current one.
-                    if (mCurAppTimeTracker != null) {
-                        mCurAppTimeTracker.stop();
-                        mHandler.obtainMessage(REPORT_TIME_TRACKER_MSG,
-                                mCurAppTimeTracker).sendToTarget();
-                        mStackSupervisor.clearOtherAppTimeTrackers(r.appTimeTracker);
-                        mCurAppTimeTracker = null;
-                    }
-                    if (r.appTimeTracker != null) {
-                        mCurAppTimeTracker = r.appTimeTracker;
-                        startTimeTrackingFocusedActivityLocked();
-                    }
-                } else {
+        if (r == null || mFocusedActivity == r) {
+            return;
+        }
+
+        if (DEBUG_FOCUS) Slog.d(TAG_FOCUS, "setFocusedActivityLocked: r=" + r);
+        final ActivityRecord last = mFocusedActivity;
+        mFocusedActivity = r;
+        if (r.task.isApplicationTask()) {
+            if (mCurAppTimeTracker != r.appTimeTracker) {
+                // We are switching app tracking.  Complete the current one.
+                if (mCurAppTimeTracker != null) {
+                    mCurAppTimeTracker.stop();
+                    mHandler.obtainMessage(
+                            REPORT_TIME_TRACKER_MSG, mCurAppTimeTracker).sendToTarget();
+                    mStackSupervisor.clearOtherAppTimeTrackers(r.appTimeTracker);
+                    mCurAppTimeTracker = null;
+                }
+                if (r.appTimeTracker != null) {
+                    mCurAppTimeTracker = r.appTimeTracker;
                     startTimeTrackingFocusedActivityLocked();
                 }
             } else {
-                r.appTimeTracker = null;
+                startTimeTrackingFocusedActivityLocked();
             }
-            if (r.task != null && r.task.voiceInteractor != null) {
-                startRunningVoiceLocked(r.task.voiceSession, r.info.applicationInfo.uid);
-            } else {
-                finishRunningVoiceLocked();
-                if (last != null && last.task.voiceSession != null) {
-                    // We had been in a voice interaction session, but now focused has
-                    // move to something different.  Just finish the session, we can't
-                    // return to it and retain the proper state and synchronization with
-                    // the voice interaction service.
-                    finishVoiceTask(last.task.voiceSession);
-                }
-            }
-            if (mStackSupervisor.setFocusedStack(r, reason + " setFocusedActivity")) {
-                mWindowManager.setFocusedApp(r.appToken, true);
-            }
-            applyUpdateLockStateLocked(r);
-            if (mFocusedActivity.userId != mLastFocusedUserId) {
-                mHandler.removeMessages(FOREGROUND_PROFILE_CHANGED_MSG);
-                mHandler.sendMessage(mHandler.obtainMessage(FOREGROUND_PROFILE_CHANGED_MSG,
-                        mFocusedActivity.userId, 0));
-                mLastFocusedUserId = mFocusedActivity.userId;
+        } else {
+            r.appTimeTracker = null;
+        }
+        if (r.task.voiceInteractor != null) {
+            startRunningVoiceLocked(r.task.voiceSession, r.info.applicationInfo.uid);
+        } else {
+            finishRunningVoiceLocked();
+            if (last != null && last.task.voiceSession != null) {
+                // We had been in a voice interaction session, but now focused has
+                // move to something different.  Just finish the session, we can't
+                // return to it and retain the proper state and synchronization with
+                // the voice interaction service.
+                finishVoiceTask(last.task.voiceSession);
             }
         }
-        EventLog.writeEvent(EventLogTags.AM_FOCUSED_ACTIVITY,
+        if (mStackSupervisor.setFocusedStack(r, reason + " setFocusedActivity")) {
+            mWindowManager.setFocusedApp(r.appToken, true);
+        }
+        applyUpdateLockStateLocked(r);
+        if (mFocusedActivity.userId != mLastFocusedUserId) {
+            mHandler.removeMessages(FOREGROUND_PROFILE_CHANGED_MSG);
+            mHandler.obtainMessage(
+                    FOREGROUND_PROFILE_CHANGED_MSG, mFocusedActivity.userId, 0).sendToTarget();
+            mLastFocusedUserId = mFocusedActivity.userId;
+        }
+
+        EventLogTags.writeAmFocusedActivity(
                 mFocusedActivity == null ? -1 : mFocusedActivity.userId,
-                mFocusedActivity == null ? "NULL" : mFocusedActivity.shortComponentName);
+                mFocusedActivity == null ? "NULL" : mFocusedActivity.shortComponentName,
+                reason);
     }
 
     final void clearFocusedActivity(ActivityRecord r) {
@@ -2837,7 +2840,7 @@
                 }
             }
             mFocusedActivity = null;
-            EventLog.writeEvent(EventLogTags.AM_FOCUSED_ACTIVITY, -1, "NULL");
+            EventLogTags.writeAmFocusedActivity(-1, "NULL", "clearFocusedActivity");
         }
     }
 
@@ -6074,6 +6077,8 @@
                         "No more processes in " + old.uidRecord);
                 enqueueUidChangeLocked(old.uidRecord, -1, UidRecord.CHANGE_GONE);
                 mActiveUids.remove(uid);
+                mBatteryStatsService.noteUidProcessState(uid,
+                        ActivityManager.PROCESS_STATE_NONEXISTENT);
             }
             old.uidRecord = null;
         }
@@ -6098,6 +6103,7 @@
             if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
                     "Creating new process uid: " + uidRec);
             mActiveUids.put(proc.uid, uidRec);
+            mBatteryStatsService.noteUidProcessState(uidRec.uid, uidRec.curProcState);
             enqueueUidChangeLocked(uidRec, -1, UidRecord.CHANGE_ACTIVE);
         }
         proc.uidRecord = uidRec;
@@ -19499,10 +19505,6 @@
             if (proc.baseProcessTracker != null) {
                 proc.baseProcessTracker.setState(proc.repProcState, memFactor, now, proc.pkgList);
             }
-            if (proc.repProcState >= 0) {
-                mBatteryStatsService.noteProcessState(proc.processName, proc.info.uid,
-                        proc.repProcState);
-            }
         }
     }
 
@@ -20002,6 +20004,7 @@
                 }
                 uidRec.setProcState = uidRec.curProcState;
                 enqueueUidChangeLocked(uidRec, -1, uidChange);
+                mBatteryStatsService.noteUidProcessState(uidRec.uid, uidRec.curProcState);
             }
         }
 
@@ -20429,8 +20432,8 @@
     }
 
     @Override
-    public int stopUser(final int userId, final IStopUserCallback callback) {
-        return mUserController.stopUser(userId, callback);
+    public int stopUser(final int userId, boolean force, final IStopUserCallback callback) {
+        return mUserController.stopUser(userId, force, callback);
     }
 
     void onUserRemovedLocked(int userId) {
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index da2c8c5c..02a372a 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -54,7 +54,6 @@
 import android.app.ResultInfo;
 import android.app.ActivityManager.RunningTaskInfo;
 import android.content.ComponentName;
-import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
@@ -73,7 +72,6 @@
 import android.os.SystemClock;
 import android.os.Trace;
 import android.os.UserHandle;
-import android.provider.Settings;
 import android.service.voice.IVoiceInteractionSession;
 import android.util.EventLog;
 import android.util.Slog;
@@ -2827,41 +2825,43 @@
     }
 
     private void adjustFocusedActivityLocked(ActivityRecord r, String reason) {
-        if (mStackSupervisor.isFocusedStack(this) && mService.mFocusedActivity == r) {
-            ActivityRecord next = topRunningActivityLocked();
-            final String myReason = reason + " adjustFocus";
-            if (next != r) {
-                if (next != null && StackId.keepFocusInStackIfPossible(mStackId)) {
-                    // For freeform, docked, and pinned stacks we always keep the focus within the
-                    // stack as long as there is a running activity in the stack that we can adjust
-                    // focus to.
-                    mService.setFocusedActivityLocked(next, myReason);
-                    return;
-                } else {
-                    final TaskRecord task = r.task;
-                    if (r.frontOfTask && task == topTask() && task.isOverHomeStack()) {
-                        // For non-fullscreen stack, we want to move the focus to the next visible
-                        // stack to prevent the home screen from moving to the top and obscuring
-                        // other visible stacks.
-                        if (!mFullscreen
-                                && adjustFocusToNextVisibleStackLocked(null, myReason)) {
-                            return;
-                        }
-                        // Move the home stack to the top if this stack is fullscreen or there is no
-                        // other visible stack.
-                        if (mStackSupervisor.moveHomeStackTaskToTop(
-                                task.getTaskToReturnTo(), myReason)) {
-                            // Activity focus was already adjusted. Nothing else to do...
-                            return;
-                        }
+        if (!mStackSupervisor.isFocusedStack(this) || mService.mFocusedActivity != r) {
+            return;
+        }
+
+        final ActivityRecord next = topRunningActivityLocked();
+        final String myReason = reason + " adjustFocus";
+        if (next != r) {
+            if (next != null && StackId.keepFocusInStackIfPossible(mStackId)) {
+                // For freeform, docked, and pinned stacks we always keep the focus within the
+                // stack as long as there is a running activity in the stack that we can adjust
+                // focus to.
+                mService.setFocusedActivityLocked(next, myReason);
+                return;
+            } else {
+                final TaskRecord task = r.task;
+                if (r.frontOfTask && task == topTask() && task.isOverHomeStack()) {
+                    // For non-fullscreen stack, we want to move the focus to the next visible
+                    // stack to prevent the home screen from moving to the top and obscuring
+                    // other visible stacks.
+                    if (!mFullscreen
+                            && adjustFocusToNextVisibleStackLocked(null, myReason)) {
+                        return;
+                    }
+                    // Move the home stack to the top if this stack is fullscreen or there is no
+                    // other visible stack.
+                    if (mStackSupervisor.moveHomeStackTaskToTop(
+                            task.getTaskToReturnTo(), myReason)) {
+                        // Activity focus was already adjusted. Nothing else to do...
+                        return;
                     }
                 }
             }
+        }
 
-            final ActivityRecord top = mStackSupervisor.topRunningActivityLocked();
-            if (top != null) {
-                mService.setFocusedActivityLocked(top, myReason);
-            }
+        final ActivityRecord top = mStackSupervisor.topRunningActivityLocked();
+        if (top != null) {
+            mService.setFocusedActivityLocked(top, myReason);
         }
     }
 
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index c7228ce..f64b803 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -272,18 +272,18 @@
         }
     }
 
-    void noteProcessState(String name, int uid, int state) {
-        synchronized (mStats) {
-            mStats.noteProcessStateLocked(name, uid, state);
-        }
-    }
-
     void noteProcessFinish(String name, int uid) {
         synchronized (mStats) {
             mStats.noteProcessFinishLocked(name, uid);
         }
     }
 
+    void noteUidProcessState(int uid, int state) {
+        synchronized (mStats) {
+            mStats.noteUidProcessStateLocked(uid, state);
+        }
+    }
+
     // Public interface...
 
     public byte[] getStatistics() {
diff --git a/services/core/java/com/android/server/am/EventLogTags.logtags b/services/core/java/com/android/server/am/EventLogTags.logtags
index 78b5f33..0397553 100644
--- a/services/core/java/com/android/server/am/EventLogTags.logtags
+++ b/services/core/java/com/android/server/am/EventLogTags.logtags
@@ -91,7 +91,7 @@
 30042 am_activity_fully_drawn_time (User|1|5),(Token|1|5),(Component Name|3),(time|2|3)
 
 # Activity focused
-30043 am_focused_activity (User|1|5),(Component Name|3)
+30043 am_focused_activity (User|1|5),(Component Name|3),(Reason|3)
 
 # Stack focus
 30044 am_focused_stack (User|1|5),(Focused Stack Id|1|5),(Last Focused Stack Id|1|5),(Reason|3)
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 9c29149..3e0ae17 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -18,6 +18,8 @@
 
 import static android.Manifest.permission.INTERACT_ACROSS_USERS;
 import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
+import static android.app.ActivityManager.USER_OP_ERROR_IS_SYSTEM;
+import static android.app.ActivityManager.USER_OP_ERROR_RELATED_USERS_CANNOT_STOP;
 import static android.app.ActivityManager.USER_OP_IS_CURRENT;
 import static android.app.ActivityManager.USER_OP_SUCCESS;
 import static android.os.Process.SYSTEM_UID;
@@ -34,6 +36,7 @@
 import static com.android.server.am.ActivityManagerService.SYSTEM_USER_START_MSG;
 import static com.android.server.am.ActivityManagerService.USER_SWITCH_TIMEOUT_MSG;
 
+import android.annotation.NonNull;
 import android.app.ActivityManager;
 import android.app.AppOpsManager;
 import android.app.Dialog;
@@ -56,11 +59,11 @@
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.storage.IMountService;
 import android.os.storage.StorageManager;
+import android.util.IntArray;
 import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseArray;
@@ -78,6 +81,8 @@
 import java.util.List;
 import java.util.Set;
 
+import libcore.util.EmptyArray;
+
 /**
  * Helper class for {@link ActivityManagerService} responsible for multi-user functionality.
  */
@@ -152,39 +157,44 @@
             finishUserBoot(uss);
 
             startProfilesLocked();
+            stopRunningUsersLocked(MAX_RUNNING_USERS);
+        }
+    }
 
-            int num = mUserLru.size();
-            int i = 0;
-            while (num > MAX_RUNNING_USERS && i < mUserLru.size()) {
-                Integer oldUserId = mUserLru.get(i);
-                UserState oldUss = mStartedUsers.get(oldUserId);
-                if (oldUss == null) {
-                    // Shouldn't happen, but be sane if it does.
-                    mUserLru.remove(i);
-                    num--;
-                    continue;
-                }
-                if (oldUss.mState == UserState.STATE_STOPPING
-                        || oldUss.mState == UserState.STATE_SHUTDOWN) {
-                    // This user is already stopping, doesn't count.
-                    num--;
-                    i++;
-                    continue;
-                }
-                if (oldUserId == UserHandle.USER_SYSTEM || oldUserId == mCurrentUserId) {
-                    // Owner/System user and current user can't be stopped. We count it as running
-                    // when it is not a pure system user.
-                    if (UserInfo.isSystemOnly(oldUserId)) {
-                        num--;
-                    }
-                    i++;
-                    continue;
-                }
-                // This is a user to be stopped.
-                stopUserLocked(oldUserId, null);
+    void stopRunningUsersLocked(int maxRunningUsers) {
+        int num = mUserLru.size();
+        int i = 0;
+        while (num > maxRunningUsers && i < mUserLru.size()) {
+            Integer oldUserId = mUserLru.get(i);
+            UserState oldUss = mStartedUsers.get(oldUserId);
+            if (oldUss == null) {
+                // Shouldn't happen, but be sane if it does.
+                mUserLru.remove(i);
+                num--;
+                continue;
+            }
+            if (oldUss.mState == UserState.STATE_STOPPING
+                    || oldUss.mState == UserState.STATE_SHUTDOWN) {
+                // This user is already stopping, doesn't count.
                 num--;
                 i++;
+                continue;
             }
+            if (oldUserId == UserHandle.USER_SYSTEM || oldUserId == mCurrentUserId) {
+                // Owner/System user and current user can't be stopped. We count it as running
+                // when it is not a pure system user.
+                if (UserInfo.isSystemOnly(oldUserId)) {
+                    num--;
+                }
+                i++;
+                continue;
+            }
+            // This is a user to be stopped.
+            if (stopUsersLocked(oldUserId, false, null) != USER_OP_SUCCESS) {
+                num--;
+            }
+            num--;
+            i++;
         }
     }
 
@@ -205,7 +215,7 @@
         }
     }
 
-    int stopUser(final int userId, final IStopUserCallback callback) {
+    int stopUser(final int userId, final boolean force, final IStopUserCallback callback) {
         if (mService.checkCallingPermission(INTERACT_ACROSS_USERS_FULL)
                 != PackageManager.PERMISSION_GRANTED) {
             String msg = "Permission Denial: switchUser() from pid="
@@ -221,16 +231,44 @@
         mService.enforceShellRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES,
                 userId);
         synchronized (mService) {
-            return stopUserLocked(userId, callback);
+            return stopUsersLocked(userId, force, callback);
         }
     }
 
-    private int stopUserLocked(final int userId, final IStopUserCallback callback) {
-        if (DEBUG_MU) Slog.i(TAG, "stopUserLocked userId=" + userId);
-        if (mCurrentUserId == userId && mTargetUserId == UserHandle.USER_NULL) {
+    /**
+     * Stops the user along with its related users. The method calls
+     * {@link #getUsersToStopLocked(int)} to determine the list of users that should be stopped.
+     */
+    private int stopUsersLocked(final int userId, boolean force, final IStopUserCallback callback) {
+        if (userId == UserHandle.USER_SYSTEM) {
+            return USER_OP_ERROR_IS_SYSTEM;
+        }
+        if (isCurrentUserLocked(userId)) {
             return USER_OP_IS_CURRENT;
         }
+        int[] usersToStop = getUsersToStopLocked(userId);
+        // If one of related users is system or current, no related users should be stopped
+        for (int i = 0; i < usersToStop.length; i++) {
+            int relatedUserId = usersToStop[i];
+            if ((UserHandle.USER_SYSTEM == relatedUserId) || isCurrentUserLocked(relatedUserId)) {
+                if (DEBUG_MU) Slog.i(TAG, "stopUsersLocked cannot stop related user "
+                        + relatedUserId);
+                // We still need to stop the requested user if it's a force stop.
+                if (force) {
+                    stopSingleUserLocked(userId, callback);
+                }
+                return USER_OP_ERROR_RELATED_USERS_CANNOT_STOP;
+            }
+        }
+        if (DEBUG_MU) Slog.i(TAG, "stopUsersLocked usersToStop=" + Arrays.toString(usersToStop));
+        for (int userIdToStop : usersToStop) {
+            stopSingleUserLocked(userIdToStop, userIdToStop == userId ? callback : null);
+        }
+        return USER_OP_SUCCESS;
+    }
 
+    private void stopSingleUserLocked(final int userId, final IStopUserCallback callback) {
+        if (DEBUG_MU) Slog.i(TAG, "stopSingleUserLocked userId=" + userId);
         final UserState uss = mStartedUsers.get(userId);
         if (uss == null) {
             // User is not started, nothing to do...  but we do need to
@@ -246,7 +284,7 @@
                     }
                 });
             }
-            return USER_OP_SUCCESS;
+            return;
         }
 
         if (callback != null) {
@@ -307,8 +345,6 @@
                 Binder.restoreCallingIdentity(ident);
             }
         }
-
-        return USER_OP_SUCCESS;
     }
 
     void finishUserStop(UserState uss) {
@@ -350,6 +386,36 @@
         }
     }
 
+    /**
+     * Determines the list of users that should be stopped together with the specified
+     * {@code userId}. The returned list includes {@code userId}.
+     */
+    private @NonNull int[] getUsersToStopLocked(int userId) {
+        int startedUsersSize = mStartedUsers.size();
+        IntArray userIds = new IntArray();
+        userIds.add(userId);
+        synchronized (mUserProfileGroupIdsSelfLocked) {
+            int userGroupId = mUserProfileGroupIdsSelfLocked.get(userId,
+                    UserInfo.NO_PROFILE_GROUP_ID);
+            for (int i = 0; i < startedUsersSize; i++) {
+                UserState uss = mStartedUsers.valueAt(i);
+                int startedUserId = uss.mHandle.getIdentifier();
+                // Skip unrelated users (profileGroupId mismatch)
+                int startedUserGroupId = mUserProfileGroupIdsSelfLocked.get(startedUserId,
+                        UserInfo.NO_PROFILE_GROUP_ID);
+                boolean sameGroup = (userGroupId != UserInfo.NO_PROFILE_GROUP_ID)
+                        && (userGroupId == startedUserGroupId);
+                // userId has already been added
+                boolean sameUserId = startedUserId == userId;
+                if (!sameGroup || sameUserId) {
+                    continue;
+                }
+                userIds.add(startedUserId);
+            }
+        }
+        return userIds.toArray();
+    }
+
     private void forceStopUserLocked(int userId, String reason) {
         mService.forceStopPackageLocked(null, -1, false, false, true, false, false,
                 userId, reason);
@@ -362,7 +428,6 @@
                 null, false, false, MY_PID, SYSTEM_UID, UserHandle.USER_ALL);
     }
 
-
     /**
      * Stops the guest user if it has gone to the background.
      */
@@ -380,7 +445,7 @@
                 UserInfo userInfo = getUserInfo(oldUserId);
                 if (userInfo.isGuest()) {
                     // This is a user to be stopped.
-                    stopUserLocked(oldUserId, null);
+                    stopUsersLocked(oldUserId, true, null);
                     break;
                 }
             }
@@ -476,7 +541,7 @@
                 // If the user we are switching to is not currently started, then
                 // we need to start it now.
                 if (mStartedUsers.get(userId) == null) {
-                    mStartedUsers.put(userId, new UserState(new UserHandle(userId)));
+                    mStartedUsers.put(userId, new UserState(UserHandle.of(userId)));
                     updateStartedUserArrayLocked();
                     needStart = true;
                 }
@@ -695,6 +760,24 @@
         mUserSwitchObservers.finishBroadcast();
     }
 
+    private void stopBackgroundUsersIfEnforced(int oldUserId) {
+        // Never stop system user
+        if (oldUserId == UserHandle.USER_SYSTEM) {
+            return;
+        }
+        // For now, only check for user restriction. Additional checks can be added here
+        boolean disallowRunInBg = hasUserRestriction(UserManager.DISALLOW_RUN_IN_BACKGROUND,
+                oldUserId);
+        if (!disallowRunInBg) {
+            return;
+        }
+        synchronized (mService) {
+            if (DEBUG_MU) Slog.i(TAG, "stopBackgroundUsersIfEnforced stopping " + oldUserId
+                    + " and related users");
+            stopUsersLocked(oldUserId, false, null);
+        }
+    }
+
     void timeoutUserSwitch(UserState uss, int oldUserId, int newUserId) {
         synchronized (mService) {
             Slog.wtf(TAG, "User switch timeout: from " + oldUserId + " to " + newUserId);
@@ -747,7 +830,7 @@
     }
 
     void continueUserSwitch(UserState uss, int oldUserId, int newUserId) {
-        completeSwitchAndInitialize(uss, newUserId, false, true);
+        completeSwitchAndInitialize(uss, oldUserId, newUserId, false, true);
     }
 
     void onUserInitialized(UserState uss, boolean foreground, int oldUserId, int newUserId) {
@@ -756,10 +839,10 @@
                 moveUserToForegroundLocked(uss, oldUserId, newUserId);
             }
         }
-        completeSwitchAndInitialize(uss, newUserId, true, false);
+        completeSwitchAndInitialize(uss, oldUserId, newUserId, true, false);
     }
 
-    void completeSwitchAndInitialize(UserState uss, int newUserId,
+    void completeSwitchAndInitialize(UserState uss, int oldUserId, int newUserId,
             boolean clearInitializing, boolean clearSwitching) {
         boolean unfrozen = false;
         synchronized (mService) {
@@ -781,6 +864,7 @@
                     newUserId, 0));
         }
         stopGuestUserIfBackground();
+        stopBackgroundUsersIfEnforced(oldUserId);
     }
 
     void moveUserToForegroundLocked(UserState uss, int oldUserId, int newUserId) {
@@ -1033,12 +1117,11 @@
         if ((flags & ActivityManager.FLAG_OR_STOPPED) != 0) {
             return true;
         }
-        if ((flags & ActivityManager.FLAG_AND_LOCKED) != 0) {
-            // If user is currently locked, we fall through to default "running"
-            // behavior below
-            if (state.unlocked) {
-                return false;
-            }
+        if ((flags & ActivityManager.FLAG_AND_LOCKED) != 0 && state.unlocked) {
+            return false;
+        }
+        if ((flags & ActivityManager.FLAG_AND_UNLOCKED) != 0 && !state.unlocked) {
+            return false;
         }
         return state.mState != UserState.STATE_STOPPING
                 && state.mState != UserState.STATE_SHUTDOWN;
@@ -1074,6 +1157,10 @@
         return mCurrentUserId;
     }
 
+    private boolean isCurrentUserLocked(int userId) {
+        return mCurrentUserId == userId || mTargetUserId == userId;
+    }
+
     int setTargetUserIdLocked(int targetUserId) {
         return mTargetUserId = targetUserId;
     }
diff --git a/services/core/java/com/android/server/audio/MediaFocusControl.java b/services/core/java/com/android/server/audio/MediaFocusControl.java
index d44d89d..278d70b 100644
--- a/services/core/java/com/android/server/audio/MediaFocusControl.java
+++ b/services/core/java/com/android/server/audio/MediaFocusControl.java
@@ -387,8 +387,11 @@
     /** @see AudioManager#requestAudioFocus(AudioManager.OnAudioFocusChangeListener, int, int, int) */
     protected int requestAudioFocus(AudioAttributes aa, int focusChangeHint, IBinder cb,
             IAudioFocusDispatcher fd, String clientId, String callingPackageName, int flags) {
-        Log.i(TAG, " AudioFocus  requestAudioFocus() from " + clientId + " req=" + focusChangeHint +
-                "flags=0x" + Integer.toHexString(flags));
+        Log.i(TAG, " AudioFocus  requestAudioFocus() from uid/pid " + Binder.getCallingUid()
+                + "/" + Binder.getCallingPid()
+                + " clientId=" + clientId
+                + " req=" + focusChangeHint
+                + " flags=0x" + Integer.toHexString(flags));
         // we need a valid binder callback for clients
         if (!cb.pingBinder()) {
             Log.e(TAG, " AudioFocus DOA client for requestAudioFocus(), aborting.");
@@ -481,7 +484,9 @@
      * */
     protected int abandonAudioFocus(IAudioFocusDispatcher fl, String clientId, AudioAttributes aa) {
         // AudioAttributes are currently ignored, to be used for zones
-        Log.i(TAG, " AudioFocus  abandonAudioFocus() from " + clientId);
+        Log.i(TAG, " AudioFocus  abandonAudioFocus() from uid/pid " + Binder.getCallingUid()
+                + "/" + Binder.getCallingPid()
+                + " clientId=" + clientId);
         try {
             // this will take care of notifying the new focus owner if needed
             synchronized(mAudioFocusLock) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 358d6f8..0fde27f 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -11628,7 +11628,7 @@
         }
 
         int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
-            if (origin.staged) {
+            if (origin.staged && origin.cid != null) {
                 if (DEBUG_INSTALL) Slog.d(TAG, origin.cid + " already staged; skipping copy");
                 cid = origin.cid;
                 setMountPath(PackageHelper.getSdDir(cid));
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index da10a94..b31d731 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -869,10 +869,8 @@
         mHandler.post(new Runnable() {
             @Override
             public void run() {
-                synchronized (mRestrictionsLock) {
-                    UserRestrictionsUtils.applyUserRestrictionsLR(
-                            mContext, userId, newRestrictionsFinal, prevRestrictionsFinal);
-                }
+                UserRestrictionsUtils.applyUserRestrictions(
+                        mContext, userId, newRestrictionsFinal, prevRestrictionsFinal);
 
                 final UserRestrictionsListener[] listeners;
                 synchronized (mUserRestrictionsListeners) {
@@ -1811,8 +1809,8 @@
             if (DBG) Slog.i(LOG_TAG, "Stopping user " + userHandle);
             int res;
             try {
-                res = ActivityManagerNative.getDefault().stopUser(userHandle,
-                        new IStopUserCallback.Stub() {
+                res = ActivityManagerNative.getDefault().stopUser(userHandle, /* force= */ true,
+                new IStopUserCallback.Stub() {
                             @Override
                             public void userStopped(int userId) {
                                 finishRemoveUser(userId);
diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
index 77abd3e..816903e 100644
--- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
+++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
@@ -22,11 +22,14 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.app.ActivityManager;
+import android.app.ActivityManagerNative;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Bundle;
+import android.os.RemoteException;
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -84,7 +87,8 @@
             UserManager.DISALLOW_SAFE_BOOT,
             UserManager.ALLOW_PARENT_PROFILE_APP_LINKING,
             UserManager.DISALLOW_RECORD_AUDIO,
-            UserManager.DISALLOW_CAMERA
+            UserManager.DISALLOW_CAMERA,
+            UserManager.DISALLOW_RUN_IN_BACKGROUND
     );
 
     /**
@@ -126,6 +130,7 @@
      */
     private static final Set<String> GLOBAL_RESTRICTIONS = Sets.newArraySet(
             UserManager.DISALLOW_ADJUST_VOLUME,
+            UserManager.DISALLOW_RUN_IN_BACKGROUND,
             UserManager.DISALLOW_UNMUTE_MICROPHONE
     );
 
@@ -263,34 +268,28 @@
      * Takes a new use restriction set and the previous set, and apply the restrictions that have
      * changed.
      *
-     * <p>Note this method is called by {@link UserManagerService} while holding
-     * {@code mRestrictionLock}. Be aware when calling into other services, which could cause
-     * a deadlock.
+     * <p>Note this method is called by {@link UserManagerService} without holding any locks.
      */
-    public static void applyUserRestrictionsLR(Context context, int userId,
+    public static void applyUserRestrictions(Context context, int userId,
             Bundle newRestrictions, Bundle prevRestrictions) {
         for (String key : USER_RESTRICTIONS) {
             final boolean newValue = newRestrictions.getBoolean(key);
             final boolean prevValue = prevRestrictions.getBoolean(key);
 
             if (newValue != prevValue) {
-                applyUserRestrictionLR(context, userId, key, newValue);
+                applyUserRestriction(context, userId, key, newValue);
             }
         }
     }
-    
+
     /**
      * Apply each user restriction.
      *
-     * <p>Note this method is called by {@link UserManagerService} while holding
-     * {@code mRestrictionLock}. Be aware when calling into other services, which could cause
-     * a deadlock.
-     *
      * <p>See also {@link
      * com.android.providers.settings.SettingsProvider#isGlobalOrSecureSettingRestrictedForUser},
      * which should be in sync with this method.
      */
-    private static void applyUserRestrictionLR(Context context, int userId, String key,
+    private static void applyUserRestriction(Context context, int userId, String key,
             boolean newValue) {
         if (UserManagerService.DBG) {
             Log.d(TAG, "Applying user restriction: userId=" + userId
@@ -365,6 +364,17 @@
                                 userId);
                     }
                     break;
+                case UserManager.DISALLOW_RUN_IN_BACKGROUND:
+                    if (newValue) {
+                        int currentUser = ActivityManager.getCurrentUser();
+                        if (currentUser != userId && userId != UserHandle.USER_SYSTEM) {
+                            try {
+                                ActivityManagerNative.getDefault().stopUser(userId, false, null);
+                            } catch (RemoteException e) {
+                                throw e.rethrowAsRuntimeException();
+                            }
+                        }
+                    }
             }
         } finally {
             Binder.restoreCallingIdentity(id);
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 3301c49..3d00e02 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -269,6 +269,10 @@
         return candidate;
     }
 
+    boolean stackCanReceiveKeys() {
+        return (windows.size() > 0) ? windows.get(windows.size() - 1).stackCanReceiveKeys() : false;
+    }
+
     boolean isVisible() {
         final int N = allAppWindows.size();
         for (int i=0; i<N; i++) {
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 15a3c48..22f1d63 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -562,8 +562,10 @@
     }
 
     public void printTo(String prefix, PrintWriter pw) {
-        pw.print(prefix); pw.print("taskId="); pw.print(mTaskId);
-                pw.print(prefix); pw.print("appTokens="); pw.print(mAppTokens);
-                pw.print(prefix); pw.print("mdr="); pw.println(mDeferRemoval);
+        pw.print(prefix); pw.print("taskId="); pw.println(mTaskId);
+            pw.print(prefix + prefix); pw.print("mFullscreen="); pw.println(mFullscreen);
+            pw.print(prefix + prefix); pw.print("mBounds="); pw.println(mBounds.toShortString());
+            pw.print(prefix + prefix); pw.print("mdr="); pw.println(mDeferRemoval);
+            pw.print(prefix + prefix); pw.print("appTokens="); pw.println(mAppTokens);
     }
 }
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 9788975..611ad40 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -602,6 +602,8 @@
     public void dump(String prefix, PrintWriter pw) {
         pw.print(prefix); pw.print("mStackId="); pw.println(mStackId);
         pw.print(prefix); pw.print("mDeferDetach="); pw.println(mDeferDetach);
+        pw.print(prefix); pw.print("mFullscreen="); pw.println(mFullscreen);
+        pw.print(prefix); pw.print("mBounds="); pw.println(mBounds.toShortString());
         for (int taskNdx = 0; taskNdx < mTasks.size(); ++taskNdx) {
             pw.print(prefix);
             mTasks.get(taskNdx).printTo(prefix + " ", pw);
@@ -700,26 +702,4 @@
         }
         return false;
     }
-
-    /**
-     * Returns true if this stack has a window that is fully visible, doesn't perform an entry
-     * animation and is just positioned where it's supposed to be.
-     */
-    boolean hasWindowWithFinalVisibility() {
-        for (int i = mTasks.size() - 1; i >= 0; i--) {
-            Task task = mTasks.get(i);
-            for (int j = task.mAppTokens.size() - 1; j >= 0; j--) {
-                final AppWindowToken token = task.mAppTokens.get(j);
-                if (token.mAppAnimator.animating || token.mWillReplaceWindow) {
-                    continue;
-                }
-                WindowState win = token.findMainWindow();
-                if (win != null && !win.mWinAnimator.mEnterAnimationPending
-                        && !win.mWinAnimator.mEnteringAnimation) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
 }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index dab195f..1bb5ad0 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2528,10 +2528,12 @@
                             + "attached to a parent win=" + win);
                 }
 
-                win.mFrame.left = left;
-                win.mFrame.top = top;
-                win.mFrame.right = right;
-                win.mFrame.bottom = bottom;
+                win.mAttrs.x = left;
+                win.mAttrs.y = top;
+                win.mAttrs.width = right - left;
+                win.mAttrs.height = bottom - top;
+
+                win.setWindowScale(win.mRequestedWidth, win.mRequestedHeight);
 
                 win.mWinAnimator.computeShownFrameLocked();
 
@@ -9129,8 +9131,9 @@
                         if (wtoken == token) {
                             break;
                         }
-                        if (mFocusedApp == token) {
-                            // Whoops, we are below the focused app...  no focus for you!
+                        if (mFocusedApp == token && token.stackCanReceiveKeys()) {
+                            // Whoops, we are below the focused app whose stack can receive keys...
+                            // No focus for you!!!
                             if (localLOGV || DEBUG_FOCUS_LIGHT) Slog.v(TAG,
                                     "findFocusedWindow: Reached focused app=" + mFocusedApp);
                             return null;
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 29cadf3..cfa2bb3 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -56,6 +56,7 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 
+import static android.app.ActivityManager.StackId;
 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
 import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT;
 import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME;
@@ -1564,13 +1565,17 @@
         }
     }
 
-    /**
-     * @return true if this window desires key events.
-     */
-    public final boolean canReceiveKeys() {
+    /** @return true if this window desires key events. */
+    boolean canReceiveKeys() {
         return isVisibleOrAdding()
                 && (mViewVisibility == View.VISIBLE)
-                && ((mAttrs.flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) == 0);
+                && ((mAttrs.flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) == 0)
+                && stackCanReceiveKeys();
+    }
+
+    boolean stackCanReceiveKeys() {
+        final TaskStack stack = getStack();
+        return stack != null && StackId.canReceiveKeys(stack.mStackId);
     }
 
     @Override
diff --git a/services/print/java/com/android/server/print/RemotePrintService.java b/services/print/java/com/android/server/print/RemotePrintService.java
index 0ab1657..77a47f8 100644
--- a/services/print/java/com/android/server/print/RemotePrintService.java
+++ b/services/print/java/com/android/server/print/RemotePrintService.java
@@ -16,6 +16,9 @@
 
 package com.android.server.print;
 
+import android.annotation.FloatRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -757,6 +760,33 @@
         }
 
         @Override
+        public void setProgress(@NonNull PrintJobId printJobId,
+                @FloatRange(from=0.0, to=1.0) float progress) {
+            RemotePrintService service = mWeakService.get();
+            if (service != null) {
+                final long identity = Binder.clearCallingIdentity();
+                try {
+                    service.mSpooler.setProgress(printJobId, progress);
+                } finally {
+                    Binder.restoreCallingIdentity(identity);
+                }
+            }
+        }
+
+        @Override
+        public void setStatus(@NonNull PrintJobId printJobId, @Nullable CharSequence status) {
+            RemotePrintService service = mWeakService.get();
+            if (service != null) {
+                final long identity = Binder.clearCallingIdentity();
+                try {
+                    service.mSpooler.setStatus(printJobId, status);
+                } finally {
+                    Binder.restoreCallingIdentity(identity);
+                }
+            }
+        }
+
+        @Override
         @SuppressWarnings({"rawtypes", "unchecked"})
         public void onPrintersAdded(ParceledListSlice printers) {
             RemotePrintService service = mWeakService.get();
diff --git a/services/print/java/com/android/server/print/RemotePrintSpooler.java b/services/print/java/com/android/server/print/RemotePrintSpooler.java
index e5370f4..c506b6f 100644
--- a/services/print/java/com/android/server/print/RemotePrintSpooler.java
+++ b/services/print/java/com/android/server/print/RemotePrintSpooler.java
@@ -16,6 +16,9 @@
 
 package com.android.server.print;
 
+import android.annotation.FloatRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -229,6 +232,61 @@
         return false;
     }
 
+    /**
+     * Set progress of a print job.
+     *
+     * @param printJobId The print job to update
+     * @param progress The new progress
+     */
+    public final void setProgress(@NonNull PrintJobId printJobId,
+            @FloatRange(from=0.0, to=1.0) float progress) {
+        throwIfCalledOnMainThread();
+        synchronized (mLock) {
+            throwIfDestroyedLocked();
+            mCanUnbind = false;
+        }
+        try {
+            getRemoteInstanceLazy().setProgress(printJobId, progress);
+        } catch (RemoteException|TimeoutException re) {
+            Slog.e(LOG_TAG, "Error setting progress.", re);
+        } finally {
+            if (DEBUG) {
+                Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] setProgress()");
+            }
+            synchronized (mLock) {
+                mCanUnbind = true;
+                mLock.notifyAll();
+            }
+        }
+    }
+
+    /**
+     * Set status of a print job.
+     *
+     * @param printJobId The print job to update
+     * @param status The new status
+     */
+    public final void setStatus(@NonNull PrintJobId printJobId, @Nullable CharSequence status) {
+        throwIfCalledOnMainThread();
+        synchronized (mLock) {
+            throwIfDestroyedLocked();
+            mCanUnbind = false;
+        }
+        try {
+            getRemoteInstanceLazy().setStatus(printJobId, status);
+        } catch (RemoteException|TimeoutException re) {
+            Slog.e(LOG_TAG, "Error setting status.", re);
+        } finally {
+            if (DEBUG) {
+                Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] setStatus()");
+            }
+            synchronized (mLock) {
+                mCanUnbind = true;
+                mLock.notifyAll();
+            }
+        }
+    }
+
     public final boolean setPrintJobTag(PrintJobId printJobId, String tag) {
         throwIfCalledOnMainThread();
         synchronized (mLock) {
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
index 66c7dbb..b4bca3e 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
@@ -31,7 +31,8 @@
 
 /** Test {@link UserManager} functionality. */
 public class UserManagerTest extends AndroidTestCase {
-
+    private static final int REMOVE_CHECK_INTERVAL = 500;
+    private static final int REMOVE_TIMEOUT = 60 * 1000;
     private UserManager mUserManager = null;
     private final Object mUserLock = new Object();
     private List<Integer> usersToRemove;
@@ -227,10 +228,16 @@
     private void removeUser(int userId) {
         synchronized (mUserLock) {
             mUserManager.removeUser(userId);
+            long time = System.currentTimeMillis();
             while (mUserManager.getUserInfo(userId) != null) {
                 try {
-                    mUserLock.wait(500);
+                    mUserLock.wait(REMOVE_CHECK_INTERVAL);
                 } catch (InterruptedException ie) {
+                    Thread.currentThread().interrupt();
+                    return;
+                }
+                if (System.currentTimeMillis() - time > REMOVE_TIMEOUT) {
+                    fail("Timeout waiting for removeUser. userId = " + userId);
                 }
             }
         }