Merge "Enable default system IMEs for system user"
diff --git a/api/current.txt b/api/current.txt
index e912440..666bf83 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -4830,17 +4830,17 @@
     field public android.app.Notification.Action[] actions;
     field public android.media.AudioAttributes audioAttributes;
     field public deprecated int audioStreamType;
-    field public android.widget.RemoteViews bigContentView;
+    field public deprecated android.widget.RemoteViews bigContentView;
     field public java.lang.String category;
     field public int color;
     field public android.app.PendingIntent contentIntent;
-    field public android.widget.RemoteViews contentView;
+    field public deprecated android.widget.RemoteViews contentView;
     field public int defaults;
     field public android.app.PendingIntent deleteIntent;
     field public android.os.Bundle extras;
     field public int flags;
     field public android.app.PendingIntent fullScreenIntent;
-    field public android.widget.RemoteViews headsUpContentView;
+    field public deprecated android.widget.RemoteViews headsUpContentView;
     field public deprecated int icon;
     field public int iconLevel;
     field public deprecated android.graphics.Bitmap largeIcon;
@@ -4931,14 +4931,22 @@
     method public android.app.Notification.Builder extend(android.app.Notification.Extender);
     method public android.os.Bundle getExtras();
     method public deprecated android.app.Notification getNotification();
+    method public android.widget.RemoteViews makeBigContentView();
+    method public android.widget.RemoteViews makeContentView();
+    method public android.widget.RemoteViews makeHeadsUpContentView();
+    method public static android.app.Notification.Builder recoverBuilder(android.content.Context, android.app.Notification);
+    method public android.app.Notification.Builder setActions(android.app.Notification.Action...);
     method public android.app.Notification.Builder setAutoCancel(boolean);
     method public android.app.Notification.Builder setCategory(java.lang.String);
     method public android.app.Notification.Builder setColor(int);
-    method public android.app.Notification.Builder setContent(android.widget.RemoteViews);
+    method public deprecated android.app.Notification.Builder setContent(android.widget.RemoteViews);
     method public android.app.Notification.Builder setContentInfo(java.lang.CharSequence);
     method public android.app.Notification.Builder setContentIntent(android.app.PendingIntent);
     method public android.app.Notification.Builder setContentText(java.lang.CharSequence);
     method public android.app.Notification.Builder setContentTitle(java.lang.CharSequence);
+    method public android.app.Notification.Builder setCustomBigContentView(android.widget.RemoteViews);
+    method public android.app.Notification.Builder setCustomContentView(android.widget.RemoteViews);
+    method public android.app.Notification.Builder setCustomHeadsUpContentView(android.widget.RemoteViews);
     method public android.app.Notification.Builder setDefaults(int);
     method public android.app.Notification.Builder setDeleteIntent(android.app.PendingIntent);
     method public android.app.Notification.Builder setExtras(android.os.Bundle);
@@ -9409,6 +9417,7 @@
     field public static final java.lang.String FEATURE_FAKETOUCH_MULTITOUCH_DISTINCT = "android.hardware.faketouch.multitouch.distinct";
     field public static final java.lang.String FEATURE_FAKETOUCH_MULTITOUCH_JAZZHAND = "android.hardware.faketouch.multitouch.jazzhand";
     field public static final java.lang.String FEATURE_FINGERPRINT = "android.hardware.fingerprint";
+    field public static final java.lang.String FEATURE_FREEFORM_WINDOW_MANAGEMENT = "android.software.freeform_window_management";
     field public static final java.lang.String FEATURE_GAMEPAD = "android.hardware.gamepad";
     field public static final java.lang.String FEATURE_HIFI_SENSORS = "android.hardware.sensor.hifi_sensors";
     field public static final java.lang.String FEATURE_HOME_SCREEN = "android.software.home_screen";
@@ -22153,6 +22162,7 @@
     field public static final int GL_ACTIVE_PROGRAM = 33369; // 0x8259
     field public static final int GL_ACTIVE_RESOURCES = 37621; // 0x92f5
     field public static final int GL_ACTIVE_VARIABLES = 37637; // 0x9305
+    field public static final int GL_ALL_BARRIER_BITS = -1; // 0xffffffff
     field public static final int GL_ALL_SHADER_BITS = -1; // 0xffffffff
     field public static final int GL_ARRAY_SIZE = 37627; // 0x92fb
     field public static final int GL_ARRAY_STRIDE = 37630; // 0x92fe
@@ -22176,6 +22186,7 @@
     field public static final int GL_DISPATCH_INDIRECT_BUFFER_BINDING = 37103; // 0x90ef
     field public static final int GL_DRAW_INDIRECT_BUFFER = 36671; // 0x8f3f
     field public static final int GL_DRAW_INDIRECT_BUFFER_BINDING = 36675; // 0x8f43
+    field public static final int GL_ELEMENT_ARRAY_BARRIER_BIT = 2; // 0x2
     field public static final int GL_FRAGMENT_SHADER_BIT = 2; // 0x2
     field public static final int GL_FRAMEBUFFER_BARRIER_BIT = 1024; // 0x400
     field public static final int GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS = 37652; // 0x9314
@@ -22265,6 +22276,7 @@
     field public static final int GL_SAMPLE_MASK = 36433; // 0x8e51
     field public static final int GL_SAMPLE_MASK_VALUE = 36434; // 0x8e52
     field public static final int GL_SAMPLE_POSITION = 36432; // 0x8e50
+    field public static final int GL_SHADER_IMAGE_ACCESS_BARRIER_BIT = 32; // 0x20
     field public static final int GL_SHADER_STORAGE_BARRIER_BIT = 8192; // 0x2000
     field public static final int GL_SHADER_STORAGE_BLOCK = 37606; // 0x92e6
     field public static final int GL_SHADER_STORAGE_BUFFER = 37074; // 0x90d2
@@ -22310,6 +22322,7 @@
     field public static final int GL_UNSIGNED_INT_IMAGE_3D = 36964; // 0x9064
     field public static final int GL_UNSIGNED_INT_IMAGE_CUBE = 36966; // 0x9066
     field public static final int GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE = 37130; // 0x910a
+    field public static final int GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT = 1; // 0x1
     field public static final int GL_VERTEX_ATTRIB_BINDING = 33492; // 0x82d4
     field public static final int GL_VERTEX_ATTRIB_RELATIVE_OFFSET = 33493; // 0x82d5
     field public static final int GL_VERTEX_BINDING_BUFFER = 36687; // 0x8f4f
diff --git a/api/system-current.txt b/api/system-current.txt
index b996af3..3554e0f 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -4947,17 +4947,17 @@
     field public android.app.Notification.Action[] actions;
     field public android.media.AudioAttributes audioAttributes;
     field public deprecated int audioStreamType;
-    field public android.widget.RemoteViews bigContentView;
+    field public deprecated android.widget.RemoteViews bigContentView;
     field public java.lang.String category;
     field public int color;
     field public android.app.PendingIntent contentIntent;
-    field public android.widget.RemoteViews contentView;
+    field public deprecated android.widget.RemoteViews contentView;
     field public int defaults;
     field public android.app.PendingIntent deleteIntent;
     field public android.os.Bundle extras;
     field public int flags;
     field public android.app.PendingIntent fullScreenIntent;
-    field public android.widget.RemoteViews headsUpContentView;
+    field public deprecated android.widget.RemoteViews headsUpContentView;
     field public deprecated int icon;
     field public int iconLevel;
     field public deprecated android.graphics.Bitmap largeIcon;
@@ -5048,14 +5048,22 @@
     method public android.app.Notification.Builder extend(android.app.Notification.Extender);
     method public android.os.Bundle getExtras();
     method public deprecated android.app.Notification getNotification();
+    method public android.widget.RemoteViews makeBigContentView();
+    method public android.widget.RemoteViews makeContentView();
+    method public android.widget.RemoteViews makeHeadsUpContentView();
+    method public static android.app.Notification.Builder recoverBuilder(android.content.Context, android.app.Notification);
+    method public android.app.Notification.Builder setActions(android.app.Notification.Action...);
     method public android.app.Notification.Builder setAutoCancel(boolean);
     method public android.app.Notification.Builder setCategory(java.lang.String);
     method public android.app.Notification.Builder setColor(int);
-    method public android.app.Notification.Builder setContent(android.widget.RemoteViews);
+    method public deprecated android.app.Notification.Builder setContent(android.widget.RemoteViews);
     method public android.app.Notification.Builder setContentInfo(java.lang.CharSequence);
     method public android.app.Notification.Builder setContentIntent(android.app.PendingIntent);
     method public android.app.Notification.Builder setContentText(java.lang.CharSequence);
     method public android.app.Notification.Builder setContentTitle(java.lang.CharSequence);
+    method public android.app.Notification.Builder setCustomBigContentView(android.widget.RemoteViews);
+    method public android.app.Notification.Builder setCustomContentView(android.widget.RemoteViews);
+    method public android.app.Notification.Builder setCustomHeadsUpContentView(android.widget.RemoteViews);
     method public android.app.Notification.Builder setDefaults(int);
     method public android.app.Notification.Builder setDeleteIntent(android.app.PendingIntent);
     method public android.app.Notification.Builder setExtras(android.os.Bundle);
@@ -9703,6 +9711,7 @@
     field public static final java.lang.String FEATURE_FAKETOUCH_MULTITOUCH_DISTINCT = "android.hardware.faketouch.multitouch.distinct";
     field public static final java.lang.String FEATURE_FAKETOUCH_MULTITOUCH_JAZZHAND = "android.hardware.faketouch.multitouch.jazzhand";
     field public static final java.lang.String FEATURE_FINGERPRINT = "android.hardware.fingerprint";
+    field public static final java.lang.String FEATURE_FREEFORM_WINDOW_MANAGEMENT = "android.software.freeform_window_management";
     field public static final java.lang.String FEATURE_GAMEPAD = "android.hardware.gamepad";
     field public static final java.lang.String FEATURE_HIFI_SENSORS = "android.hardware.sensor.hifi_sensors";
     field public static final java.lang.String FEATURE_HOME_SCREEN = "android.software.home_screen";
@@ -24098,6 +24107,7 @@
     field public static final int GL_ACTIVE_PROGRAM = 33369; // 0x8259
     field public static final int GL_ACTIVE_RESOURCES = 37621; // 0x92f5
     field public static final int GL_ACTIVE_VARIABLES = 37637; // 0x9305
+    field public static final int GL_ALL_BARRIER_BITS = -1; // 0xffffffff
     field public static final int GL_ALL_SHADER_BITS = -1; // 0xffffffff
     field public static final int GL_ARRAY_SIZE = 37627; // 0x92fb
     field public static final int GL_ARRAY_STRIDE = 37630; // 0x92fe
@@ -24121,6 +24131,7 @@
     field public static final int GL_DISPATCH_INDIRECT_BUFFER_BINDING = 37103; // 0x90ef
     field public static final int GL_DRAW_INDIRECT_BUFFER = 36671; // 0x8f3f
     field public static final int GL_DRAW_INDIRECT_BUFFER_BINDING = 36675; // 0x8f43
+    field public static final int GL_ELEMENT_ARRAY_BARRIER_BIT = 2; // 0x2
     field public static final int GL_FRAGMENT_SHADER_BIT = 2; // 0x2
     field public static final int GL_FRAMEBUFFER_BARRIER_BIT = 1024; // 0x400
     field public static final int GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS = 37652; // 0x9314
@@ -24210,6 +24221,7 @@
     field public static final int GL_SAMPLE_MASK = 36433; // 0x8e51
     field public static final int GL_SAMPLE_MASK_VALUE = 36434; // 0x8e52
     field public static final int GL_SAMPLE_POSITION = 36432; // 0x8e50
+    field public static final int GL_SHADER_IMAGE_ACCESS_BARRIER_BIT = 32; // 0x20
     field public static final int GL_SHADER_STORAGE_BARRIER_BIT = 8192; // 0x2000
     field public static final int GL_SHADER_STORAGE_BLOCK = 37606; // 0x92e6
     field public static final int GL_SHADER_STORAGE_BUFFER = 37074; // 0x90d2
@@ -24255,6 +24267,7 @@
     field public static final int GL_UNSIGNED_INT_IMAGE_3D = 36964; // 0x9064
     field public static final int GL_UNSIGNED_INT_IMAGE_CUBE = 36966; // 0x9066
     field public static final int GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE = 37130; // 0x910a
+    field public static final int GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT = 1; // 0x1
     field public static final int GL_VERTEX_ATTRIB_BINDING = 33492; // 0x82d4
     field public static final int GL_VERTEX_ATTRIB_RELATIVE_OFFSET = 33493; // 0x82d5
     field public static final int GL_VERTEX_BINDING_BUFFER = 36687; // 0x8f4f
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index 3f8e311..2960cdc 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -283,7 +283,7 @@
             } else if (args.length == 2) {
                 if (args[0].equalsIgnoreCase("-p")) {
                     validCommand = true;
-                    return displayPackageFilePath(args[1], UserHandle.USER_OWNER);
+                    return displayPackageFilePath(args[1], UserHandle.USER_SYSTEM);
                 }
             }
             return 1;
@@ -767,7 +767,7 @@
     }
 
     private int runPath() {
-        int userId = UserHandle.USER_OWNER;
+        int userId = UserHandle.USER_SYSTEM;
         String option = nextOption();
         if (option != null && option.equals("--user")) {
             String optionData = nextOptionData();
@@ -1650,7 +1650,7 @@
     }
 
     private int runClear() {
-        int userId = UserHandle.USER_OWNER;
+        int userId = UserHandle.USER_SYSTEM;
         String option = nextOption();
         if (option != null && option.equals("--user")) {
             String optionData = nextOptionData();
@@ -1722,7 +1722,7 @@
     }
 
     private int runSetEnabledSetting(int state) {
-        int userId = UserHandle.USER_OWNER;
+        int userId = UserHandle.USER_SYSTEM;
         String option = nextOption();
         if (option != null && option.equals("--user")) {
             String optionData = nextOptionData();
@@ -1771,7 +1771,7 @@
     }
 
     private int runSetHiddenSetting(boolean state) {
-        int userId = UserHandle.USER_OWNER;
+        int userId = UserHandle.USER_SYSTEM;
         String option = nextOption();
         if (option != null && option.equals("--user")) {
             String optionData = nextOptionData();
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 6ae32d0..fce1b2e 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -1200,6 +1200,12 @@
         public int id;
 
         /**
+         * The stack that currently contains this task.
+         * @hide
+         */
+        public int stackId;
+
+        /**
          * The component launched as the first activity in the task.  This can
          * be considered the "application" of this task.
          */
@@ -1248,6 +1254,7 @@
 
         public void writeToParcel(Parcel dest, int flags) {
             dest.writeInt(id);
+            dest.writeInt(stackId);
             ComponentName.writeToParcel(baseActivity, dest);
             ComponentName.writeToParcel(topActivity, dest);
             if (thumbnail != null) {
@@ -1264,6 +1271,7 @@
 
         public void readFromParcel(Parcel source) {
             id = source.readInt();
+            stackId = source.readInt();
             baseActivity = ComponentName.readFromParcel(source);
             topActivity = ComponentName.readFromParcel(source);
             if (source.readInt() != 0) {
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 933f98d..821621e 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -16,6 +16,8 @@
 
 package android.app;
 
+import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
+
 import android.content.Context;
 import android.content.Intent;
 import android.graphics.Bitmap;
@@ -127,6 +129,12 @@
     public static final String KEY_ANIM_START_LISTENER = "android:activity.animStartListener";
 
     /**
+     * Where the docked stack should be positioned.
+     * @hide
+     */
+    private static final String KEY_DOCK_CREATE_MODE = "android:activity.dockCreateMode";
+
+    /**
      * For Activity transitions, the calling Activity's TransitionListener used to
      * notify the called Activity when the shared element and the exit transitions
      * complete.
@@ -190,6 +198,7 @@
     private int mResultCode;
     private int mExitCoordinatorIndex;
     private PendingIntent mUsageTimeReport;
+    private int mDockCreateMode = DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
 
     /**
      * Create an ActivityOptions specifying a custom animation to run when
@@ -688,6 +697,7 @@
                 mExitCoordinatorIndex = opts.getInt(KEY_EXIT_COORDINATOR_INDEX);
                 break;
         }
+        mDockCreateMode = opts.getInt(KEY_DOCK_CREATE_MODE, DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT);
     }
 
     /** @hide */
@@ -806,6 +816,14 @@
         }
     }
 
+    /** @hide */
+    public int getDockCreateMode() { return mDockCreateMode; }
+
+    /** @hide */
+    public void setDockCreateMode(int dockCreateMode) {
+        mDockCreateMode = dockCreateMode;
+    }
+
     /**
      * Update the current values in this ActivityOptions from those supplied
      * in <var>otherOptions</var>.  Any values
@@ -945,6 +963,7 @@
                 b.putInt(KEY_EXIT_COORDINATOR_INDEX, mExitCoordinatorIndex);
                 break;
         }
+        b.putInt(KEY_DOCK_CREATE_MODE, mDockCreateMode);
 
         return b;
     }
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index db18722..49edff4 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -251,15 +251,26 @@
     public RemoteViews tickerView;
 
     /**
-     * The view that will represent this notification in the expanded status bar.
+     * The view that will represent this notification in the notification list (which is pulled
+     * down from the status bar).
+     *
+     * As of N, this field is not used. The notification view is determined by the inputs to
+     * {@link Notification.Builder}; a custom RemoteViews can optionally be
+     * supplied with {@link Notification.Builder#setCustomContentView(RemoteViews)}.
      */
+    @Deprecated
     public RemoteViews contentView;
 
     /**
      * A large-format version of {@link #contentView}, giving the Notification an
      * opportunity to show more detail. The system UI may choose to show this
      * instead of the normal content view at its discretion.
+     *
+     * As of N, this field is not used. The expanded notification view is determined by the
+     * inputs to {@link Notification.Builder}; a custom RemoteViews can optionally be
+     * supplied with {@link Notification.Builder#setCustomBigContentView(RemoteViews)}.
      */
+    @Deprecated
     public RemoteViews bigContentView;
 
 
@@ -268,7 +279,12 @@
      * opportunity to add action buttons to contentView. At its discretion, the system UI may
      * choose to show this as a heads-up notification, which will pop up so the user can see
      * it without leaving their current activity.
+     *
+     * As of N, this field is not used. The heads-up notification view is determined by the
+     * inputs to {@link Notification.Builder}; a custom RemoteViews can optionally be
+     * supplied with {@link Notification.Builder#setCustomHeadsUpContentView(RemoteViews)}.
      */
+    @Deprecated
     public RemoteViews headsUpContentView;
 
     /**
@@ -867,6 +883,11 @@
     public static final String EXTRA_ORIGINATING_USERID = "android.originatingUserId";
 
     /**
+     * @hide
+     */
+    public static final String EXTRA_BUILDER_APPLICATION_INFO = "android.appInfo";
+
+    /**
      * Value for {@link #EXTRA_AS_HEADS_UP} that indicates this notification should not be
      * displayed in the heads up space.
      *
@@ -1707,8 +1728,6 @@
             extras.remove(Notification.EXTRA_LARGE_ICON_BIG);
             extras.remove(Notification.EXTRA_PICTURE);
             extras.remove(Notification.EXTRA_BIG_TEXT);
-            // Prevent light notifications from being rebuilt.
-            extras.remove(Builder.EXTRA_NEEDS_REBUILD);
         }
     }
 
@@ -1901,21 +1920,13 @@
     @Deprecated
     public void setLatestEventInfo(Context context,
             CharSequence contentTitle, CharSequence contentText, PendingIntent contentIntent) {
-        Notification.Builder builder = new Notification.Builder(context);
+        if (context.getApplicationInfo().targetSdkVersion > Build.VERSION_CODES.LOLLIPOP_MR1){
+            Log.e(TAG, "setLatestEventInfo() is deprecated and you should feel deprecated.",
+                    new Throwable());
+        }
 
-        // First, ensure that key pieces of information that may have been set directly
-        // are preserved
-        builder.setWhen(this.when);
-        builder.setSmallIcon(this.icon);
-        builder.setPriority(this.priority);
-        builder.setTicker(this.tickerText);
-        builder.setNumber(this.number);
-        builder.setColor(this.color);
-        builder.mFlags = this.flags;
-        builder.setSound(this.sound, this.audioStreamType);
-        builder.setDefaults(this.defaults);
-        builder.setVibrate(this.vibrate);
-        builder.setDeleteIntent(this.deleteIntent);
+        // ensure that any information already set directly is preserved
+        final Notification.Builder builder = new Notification.Builder(context, this);
 
         // now apply the latestEventInfo fields
         if (contentTitle != null) {
@@ -1925,7 +1936,8 @@
             builder.setContentText(contentText);
         }
         builder.setContentIntent(contentIntent);
-        builder.buildInto(this);
+
+        builder.build(); // callers expect this notification to be ready to use
     }
 
     @Override
@@ -2080,15 +2092,6 @@
     /**
      * @hide
      */
-    public boolean isValid() {
-        // Would like to check for icon!=0 here, too, but NotificationManagerService accepts that
-        // for legacy reasons.
-        return contentView != null || extras.getBoolean(Builder.EXTRA_REBUILD_CONTENT_VIEW);
-    }
-
-    /**
-     * @hide
-     */
     public boolean isGroupSummary() {
         return mGroupKey != null && (flags & FLAG_GROUP_SUMMARY) != 0;
     }
@@ -2125,99 +2128,14 @@
         private static final int MAX_ACTION_BUTTONS = 3;
         private static final float LARGE_TEXT_SCALE = 1.3f;
 
-        /**
-         * @hide
-         */
-        public static final String EXTRA_NEEDS_REBUILD = "android.rebuild";
-
-        /**
-         * @hide
-         */
-        public static final String EXTRA_REBUILD_LARGE_ICON = "android.rebuild.largeIcon";
-        /**
-         * @hide
-         */
-        public static final String EXTRA_REBUILD_CONTENT_VIEW = "android.rebuild.contentView";
-        /**
-         * @hide
-         */
-        public static final String EXTRA_REBUILD_CONTENT_VIEW_ACTION_COUNT =
-                "android.rebuild.contentViewActionCount";
-        /**
-         * @hide
-         */
-        public static final String EXTRA_REBUILD_BIG_CONTENT_VIEW
-                = "android.rebuild.bigView";
-        /**
-         * @hide
-         */
-        public static final String EXTRA_REBUILD_BIG_CONTENT_VIEW_ACTION_COUNT
-                = "android.rebuild.bigViewActionCount";
-        /**
-         * @hide
-         */
-        public static final String EXTRA_REBUILD_HEADS_UP_CONTENT_VIEW
-                = "android.rebuild.hudView";
-        /**
-         * @hide
-         */
-        public static final String EXTRA_REBUILD_HEADS_UP_CONTENT_VIEW_ACTION_COUNT
-                = "android.rebuild.hudViewActionCount";
-
-        /**
-         * The ApplicationInfo of the package that created the notification, used to create
-         * a context to rebuild the notification via a Builder.
-         * @hide
-         */
-        private static final String EXTRA_REBUILD_CONTEXT_APPLICATION_INFO =
-                "android.rebuild.applicationInfo";
-
-        // Whether to enable stripping (at post time) & rebuilding (at listener receive time) of
-        // memory intensive resources.
-        private static final boolean STRIP_AND_REBUILD = true;
-
         private Context mContext;
-
-        private long mWhen;
-        private Icon mSmallIcon, mLargeIcon;
-        private int mSmallIconLevel;
-        private int mNumber;
-        private CharSequence mContentTitle;
-        private CharSequence mContentText;
-        private CharSequence mContentInfo;
-        private CharSequence mSubText;
-        private PendingIntent mContentIntent;
-        private RemoteViews mContentView;
-        private PendingIntent mDeleteIntent;
-        private PendingIntent mFullScreenIntent;
-        private CharSequence mTickerText;
-        private RemoteViews mTickerView;
-        private Uri mSound;
-        private int mAudioStreamType;
-        private AudioAttributes mAudioAttributes;
-        private long[] mVibrate;
-        private int mLedArgb;
-        private int mLedOnMs;
-        private int mLedOffMs;
-        private int mDefaults;
-        private int mFlags;
-        private int mProgressMax;
-        private int mProgress;
-        private boolean mProgressIndeterminate;
-        private String mCategory;
-        private String mGroupKey;
-        private String mSortKey;
-        private Bundle mExtras;
-        private int mPriority;
-        private ArrayList<Action> mActions = new ArrayList<Action>(MAX_ACTION_BUTTONS);
-        private boolean mUseChronometer;
+        private Notification mN;
+        private Bundle mUserExtras = new Bundle();
         private Style mStyle;
-        private boolean mShowWhen = true;
-        private int mVisibility = VISIBILITY_PRIVATE;
-        private Notification mPublicVersion = null;
-        private final NotificationColorUtil mColorUtil;
-        private ArrayList<String> mPeople;
-        private int mColor = COLOR_DEFAULT;
+        private ArrayList<Action> mActions = new ArrayList<Action>(MAX_ACTION_BUTTONS);
+        private ArrayList<String> mPersonList = new ArrayList<String>();
+        private NotificationColorUtil mColorUtil;
+        private boolean mColorUtilInited = false;
         private List<Topic> mTopics = new ArrayList<>();
 
         /**
@@ -2226,25 +2144,6 @@
         private int mOriginatingUserId;
 
         /**
-         * Contains extras related to rebuilding during the build phase.
-         */
-        private Bundle mRebuildBundle = new Bundle();
-        /**
-         * Contains the notification to rebuild when this Builder is in "rebuild" mode.
-         * Null otherwise.
-         */
-        private Notification mRebuildNotification = null;
-
-        /**
-         * Whether the build notification has three lines. This is used to make the top padding for
-         * both the contracted and expanded layout consistent.
-         *
-         * <p>
-         * This field is only valid during the build phase.
-         */
-        private boolean mHasThreeLines;
-
-        /**
          * Constructs a new Builder with the defaults:
          *
 
@@ -2264,61 +2163,67 @@
          *            object.
          */
         public Builder(Context context) {
-            /*
-             * Important compatibility note!
-             * Some apps out in the wild create a Notification.Builder in their Activity subclass
-             * constructor for later use. At this point Activities - themselves subclasses of
-             * ContextWrapper - do not have their inner Context populated yet. This means that
-             * any calls to Context methods from within this constructor can cause NPEs in existing
-             * apps. Any data populated from mContext should therefore be populated lazily to
-             * preserve compatibility.
-             */
-            mContext = context;
-
-            // Set defaults to match the defaults of a Notification
-            mWhen = System.currentTimeMillis();
-            mAudioStreamType = STREAM_DEFAULT;
-            mAudioAttributes = AUDIO_ATTRIBUTES_DEFAULT;
-            mPriority = PRIORITY_DEFAULT;
-            mPeople = new ArrayList<String>();
-
-            mColorUtil = context.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.LOLLIPOP ?
-                    NotificationColorUtil.getInstance(mContext) : null;
+            this(context, null);
         }
 
         /**
-         * Creates a Builder for rebuilding the given Notification.
-         * <p>
-         * Call {@link #rebuild()} to retrieve the rebuilt version of 'n'.
+         * @hide
          */
-        private Builder(Context context, Notification n) {
-            this(context);
-            mRebuildNotification = n;
-            restoreFromNotification(n);
+        public Builder(Context context, Notification toAdopt) {
+            mContext = context;
 
-            Style style = null;
-            Bundle extras = n.extras;
-            String templateClass = extras.getString(EXTRA_TEMPLATE);
-            if (!TextUtils.isEmpty(templateClass)) {
-                Class<? extends Style> styleClass = getNotificationStyleClass(templateClass);
-                if (styleClass == null) {
-                    Log.d(TAG, "Unknown style class: " + styleClass);
-                    return;
+            if (toAdopt == null) {
+                mN = new Notification();
+                mN.extras.putBoolean(EXTRA_SHOW_WHEN, true);
+                mN.priority = PRIORITY_DEFAULT;
+                mN.visibility = VISIBILITY_PRIVATE;
+            } else {
+                mN = toAdopt;
+                if (mN.actions != null) {
+                    Collections.addAll(mActions, mN.actions);
                 }
 
-                try {
-                    Constructor<? extends Style> constructor = styleClass.getConstructor();
-                    constructor.setAccessible(true);
-                    style = constructor.newInstance();
-                    style.restoreFromExtras(extras);
-                } catch (Throwable t) {
-                    Log.e(TAG, "Could not create Style", t);
-                    return;
+                if (mN.extras.containsKey(EXTRA_PEOPLE)) {
+                    Collections.addAll(mPersonList, mN.extras.getStringArray(EXTRA_PEOPLE));
+                }
+
+                if (mN.getTopics() != null) {
+                    Collections.addAll(mTopics, mN.getTopics());
+                }
+
+                String templateClass = mN.extras.getString(EXTRA_TEMPLATE);
+                if (!TextUtils.isEmpty(templateClass)) {
+                    final Class<? extends Style> styleClass
+                            = getNotificationStyleClass(templateClass);
+                    if (styleClass == null) {
+                        Log.d(TAG, "Unknown style class: " + templateClass);
+                    } else {
+                        try {
+                            final Constructor<? extends Style> ctor = styleClass.getConstructor();
+                            ctor.setAccessible(true);
+                            final Style style = ctor.newInstance();
+                            style.restoreFromExtras(mN.extras);
+
+                            if (style != null) {
+                                setStyle(style);
+                            }
+                        } catch (Throwable t) {
+                            Log.e(TAG, "Could not create Style", t);
+                        }
+                    }
+                }
+
+            }
+        }
+
+        private NotificationColorUtil getColorUtil() {
+            if (!mColorUtilInited) {
+                mColorUtilInited = true;
+                if (mContext.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.LOLLIPOP) {
+                    mColorUtil = NotificationColorUtil.getInstance(mContext);
                 }
             }
-            if (style != null) {
-                setStyle(style);
-            }
+            return mColorUtil;
         }
 
         /**
@@ -2329,7 +2234,7 @@
          * @see Notification#when
          */
         public Builder setWhen(long when) {
-            mWhen = when;
+            mN.when = when;
             return this;
         }
 
@@ -2338,7 +2243,7 @@
          * in the content view.
          */
         public Builder setShowWhen(boolean show) {
-            mShowWhen = show;
+            mN.extras.putBoolean(EXTRA_SHOW_WHEN, show);
             return this;
         }
 
@@ -2354,7 +2259,7 @@
          * @see Notification#when
          */
         public Builder setUsesChronometer(boolean b) {
-            mUseChronometer = b;
+            mN.extras.putBoolean(EXTRA_SHOW_CHRONOMETER, b);
             return this;
         }
 
@@ -2390,7 +2295,7 @@
          * @see Notification#iconLevel
          */
         public Builder setSmallIcon(@DrawableRes int icon, int level) {
-            mSmallIconLevel = level;
+            mN.iconLevel = level;
             return setSmallIcon(icon);
         }
 
@@ -2403,7 +2308,10 @@
          * @see Notification#icon
          */
         public Builder setSmallIcon(Icon icon) {
-            mSmallIcon = icon;
+            mN.setSmallIcon(icon);
+            if (icon != null && icon.getType() == Icon.TYPE_RESOURCE) {
+                mN.icon = icon.getResId();
+            }
             return this;
         }
 
@@ -2411,7 +2319,7 @@
          * Set the first line of text in the platform notification template.
          */
         public Builder setContentTitle(CharSequence title) {
-            mContentTitle = safeCharSequence(title);
+            mN.extras.putCharSequence(EXTRA_TITLE, safeCharSequence(title));
             return this;
         }
 
@@ -2419,7 +2327,7 @@
          * Set the second line of text in the platform notification template.
          */
         public Builder setContentText(CharSequence text) {
-            mContentText = safeCharSequence(text);
+            mN.extras.putCharSequence(EXTRA_TEXT, safeCharSequence(text));
             return this;
         }
 
@@ -2429,7 +2337,7 @@
          * same location in the standard template.
          */
         public Builder setSubText(CharSequence text) {
-            mSubText = safeCharSequence(text);
+            mN.extras.putCharSequence(EXTRA_SUB_TEXT, safeCharSequence(text));
             return this;
         }
 
@@ -2439,7 +2347,7 @@
          * font size for readability.
          */
         public Builder setNumber(int number) {
-            mNumber = number;
+            mN.number = number;
             return this;
         }
 
@@ -2450,7 +2358,7 @@
          * right (to the right of a smallIcon if it has been placed there).
          */
         public Builder setContentInfo(CharSequence info) {
-            mContentInfo = safeCharSequence(info);
+            mN.extras.putCharSequence(EXTRA_INFO_TEXT, safeCharSequence(info));
             return this;
         }
 
@@ -2460,19 +2368,52 @@
          * The platform template will represent this using a {@link ProgressBar}.
          */
         public Builder setProgress(int max, int progress, boolean indeterminate) {
-            mProgressMax = max;
-            mProgress = progress;
-            mProgressIndeterminate = indeterminate;
+            mN.extras.putInt(EXTRA_PROGRESS, progress);
+            mN.extras.putInt(EXTRA_PROGRESS_MAX, max);
+            mN.extras.putBoolean(EXTRA_PROGRESS_INDETERMINATE, indeterminate);
             return this;
         }
 
         /**
          * Supply a custom RemoteViews to use instead of the platform template.
          *
-         * @see Notification#contentView
+         * Use {@link #setCustomContentView(RemoteViews)} instead.
          */
+        @Deprecated
         public Builder setContent(RemoteViews views) {
-            mContentView = views;
+            return setCustomContentView(views);
+        }
+
+        /**
+         * Supply custom RemoteViews to use instead of the platform template.
+         *
+         * This will override the layout that would otherwise be constructed by this Builder
+         * object.
+         */
+        public Builder setCustomContentView(RemoteViews contentView) {
+            mN.contentView = contentView;
+            return this;
+        }
+
+        /**
+         * Supply custom RemoteViews to use instead of the platform template in the expanded form.
+         *
+         * This will override the expanded layout that would otherwise be constructed by this
+         * Builder object.
+         */
+        public Builder setCustomBigContentView(RemoteViews contentView) {
+            mN.bigContentView = contentView;
+            return this;
+        }
+
+        /**
+         * Supply custom RemoteViews to use instead of the platform template in the heads up dialog.
+         *
+         * This will override the heads-up layout that would otherwise be constructed by this
+         * Builder object.
+         */
+        public Builder setCustomHeadsUpContentView(RemoteViews contentView) {
+            mN.headsUpContentView = contentView;
             return this;
         }
 
@@ -2488,7 +2429,7 @@
          * @see Notification#contentIntent Notification.contentIntent
          */
         public Builder setContentIntent(PendingIntent intent) {
-            mContentIntent = intent;
+            mN.contentIntent = intent;
             return this;
         }
 
@@ -2498,7 +2439,7 @@
          * @see Notification#deleteIntent
          */
         public Builder setDeleteIntent(PendingIntent intent) {
-            mDeleteIntent = intent;
+            mN.deleteIntent = intent;
             return this;
         }
 
@@ -2523,7 +2464,7 @@
          * @see Notification#fullScreenIntent
          */
         public Builder setFullScreenIntent(PendingIntent intent, boolean highPriority) {
-            mFullScreenIntent = intent;
+            mN.fullScreenIntent = intent;
             setFlag(FLAG_HIGH_PRIORITY, highPriority);
             return this;
         }
@@ -2534,7 +2475,7 @@
          * @see Notification#tickerText
          */
         public Builder setTicker(CharSequence tickerText) {
-            mTickerText = safeCharSequence(tickerText);
+            mN.tickerText = safeCharSequence(tickerText);
             return this;
         }
 
@@ -2544,8 +2485,8 @@
          */
         @Deprecated
         public Builder setTicker(CharSequence tickerText, RemoteViews views) {
-            mTickerText = safeCharSequence(tickerText);
-            mTickerView = views; // we'll save it for you anyway
+            setTicker(tickerText);
+            // views is ignored
             return this;
         }
 
@@ -2568,7 +2509,8 @@
          * badge atop the large icon).
          */
         public Builder setLargeIcon(Icon icon) {
-            mLargeIcon = icon;
+            mN.mLargeIcon = icon;
+            mN.extras.putParcelable(EXTRA_LARGE_ICON, icon);
             return this;
         }
 
@@ -2585,8 +2527,8 @@
          * @see Notification#sound
          */
         public Builder setSound(Uri sound) {
-            mSound = sound;
-            mAudioAttributes = AUDIO_ATTRIBUTES_DEFAULT;
+            mN.sound = sound;
+            mN.audioAttributes = AUDIO_ATTRIBUTES_DEFAULT;
             return this;
         }
 
@@ -2603,8 +2545,8 @@
          */
         @Deprecated
         public Builder setSound(Uri sound, int streamType) {
-            mSound = sound;
-            mAudioStreamType = streamType;
+            mN.sound = sound;
+            mN.audioStreamType = streamType;
             return this;
         }
 
@@ -2619,8 +2561,8 @@
          * @see Notification#sound
          */
         public Builder setSound(Uri sound, AudioAttributes audioAttributes) {
-            mSound = sound;
-            mAudioAttributes = audioAttributes;
+            mN.sound = sound;
+            mN.audioAttributes = audioAttributes;
             return this;
         }
 
@@ -2637,7 +2579,7 @@
          * @see Notification#vibrate
          */
         public Builder setVibrate(long[] pattern) {
-            mVibrate = pattern;
+            mN.vibrate = pattern;
             return this;
         }
 
@@ -2654,9 +2596,9 @@
          * @see Notification#ledOffMS
          */
         public Builder setLights(@ColorInt int argb, int onMs, int offMs) {
-            mLedArgb = argb;
-            mLedOnMs = onMs;
-            mLedOffMs = offMs;
+            mN.ledARGB = argb;
+            mN.ledOnMS = onMs;
+            mN.ledOffMS = offMs;
             return this;
         }
 
@@ -2724,7 +2666,7 @@
          * For all default values, use {@link #DEFAULT_ALL}.
          */
         public Builder setDefaults(int defaults) {
-            mDefaults = defaults;
+            mN.defaults = defaults;
             return this;
         }
 
@@ -2734,7 +2676,7 @@
          * @see Notification#priority
          */
         public Builder setPriority(@Priority int pri) {
-            mPriority = pri;
+            mN.priority = pri;
             return this;
         }
 
@@ -2744,7 +2686,7 @@
          * @see Notification#category
          */
         public Builder setCategory(String category) {
-            mCategory = category;
+            mN.category = category;
             return this;
         }
 
@@ -2771,7 +2713,7 @@
          * @see Notification#EXTRA_PEOPLE
          */
         public Builder addPerson(String uri) {
-            mPeople.add(uri);
+            mPersonList.add(uri);
             return this;
         }
 
@@ -2787,7 +2729,7 @@
          * @return this object for method chaining
          */
         public Builder setGroup(String groupKey) {
-            mGroupKey = groupKey;
+            mN.mGroupKey = groupKey;
             return this;
         }
 
@@ -2816,7 +2758,7 @@
          * @see String#compareTo(String)
          */
         public Builder setSortKey(String sortKey) {
-            mSortKey = sortKey;
+            mN.mSortKey = sortKey;
             return this;
         }
 
@@ -2829,11 +2771,7 @@
          */
         public Builder addExtras(Bundle extras) {
             if (extras != null) {
-                if (mExtras == null) {
-                    mExtras = new Bundle(extras);
-                } else {
-                    mExtras.putAll(extras);
-                }
+                mUserExtras.putAll(extras);
             }
             return this;
         }
@@ -2851,7 +2789,9 @@
          * @see Notification#extras
          */
         public Builder setExtras(Bundle extras) {
-            mExtras = extras;
+            if (extras != null) {
+                mUserExtras = extras;
+            }
             return this;
         }
 
@@ -2866,10 +2806,13 @@
          * @see Notification#extras
          */
         public Bundle getExtras() {
-            if (mExtras == null) {
-                mExtras = new Bundle();
-            }
-            return mExtras;
+            return mUserExtras;
+        }
+
+        private Bundle getAllExtras() {
+            final Bundle saveExtras = (Bundle) mUserExtras.clone();
+            saveExtras.putAll(mN.extras);
+            return saveExtras;
         }
 
         /**
@@ -2918,6 +2861,21 @@
         }
 
         /**
+         * Alter the complete list of actions attached to this notification.
+         * @see #addAction(Action).
+         *
+         * @param actions
+         * @return
+         */
+        public Builder setActions(Action... actions) {
+            mActions.clear();
+            for (int i = 0; i < actions.length; i++) {
+                mActions.add(actions[i]);
+            }
+            return this;
+        }
+
+        /**
          * Add a rich notification style to be applied at build time.
          *
          * @param style Object responsible for modifying the notification style.
@@ -2927,6 +2885,9 @@
                 mStyle = style;
                 if (mStyle != null) {
                     mStyle.setBuilder(this);
+                    mN.extras.putString(EXTRA_TEMPLATE, style.getClass().getName());
+                }  else {
+                    mN.extras.remove(EXTRA_TEMPLATE);
                 }
             }
             return this;
@@ -2941,7 +2902,7 @@
          * @return The same Builder.
          */
         public Builder setVisibility(int visibility) {
-            mVisibility = visibility;
+            mN.visibility = visibility;
             return this;
         }
 
@@ -2952,7 +2913,12 @@
          * @return The same Builder.
          */
         public Builder setPublicVersion(Notification n) {
-            mPublicVersion = n;
+            if (n != null) {
+                mN.publicVersion = new Notification();
+                n.cloneInto(mN.publicVersion, /*heavy=*/ true);
+            } else {
+                mN.publicVersion = null;
+            }
             return this;
         }
 
@@ -2970,9 +2936,9 @@
          */
         public void setFlag(int mask, boolean value) {
             if (value) {
-                mFlags |= mask;
+                mN.flags |= mask;
             } else {
-                mFlags &= ~mask;
+                mN.flags &= ~mask;
             }
         }
 
@@ -2984,7 +2950,7 @@
          * @return The same Builder.
          */
         public Builder setColor(@ColorInt int argb) {
-            mColor = argb;
+            mN.color = argb;
             return this;
         }
 
@@ -3075,7 +3041,6 @@
             contentView.setViewVisibility(R.id.overflow_divider, View.GONE);
             contentView.setViewVisibility(R.id.progress, View.GONE);
             contentView.setViewVisibility(R.id.chronometer, View.GONE);
-            contentView.setViewVisibility(R.id.time, View.GONE);
         }
 
         private RemoteViews applyStandardTemplate(int resId) {
@@ -3093,39 +3058,43 @@
             boolean showLine3 = false;
             boolean showLine2 = false;
             boolean contentTextInLine2 = false;
+            final Bundle ex = mN.extras;
 
-            if (mLargeIcon != null) {
-                contentView.setImageViewIcon(R.id.icon, mLargeIcon);
-                processLargeLegacyIcon(mLargeIcon, contentView);
-                contentView.setImageViewIcon(R.id.right_icon, mSmallIcon);
+            if (mN.mLargeIcon != null) {
+                contentView.setImageViewIcon(R.id.icon, mN.mLargeIcon);
+                processLargeLegacyIcon(mN.mLargeIcon, contentView);
+                contentView.setImageViewIcon(R.id.right_icon, mN.mSmallIcon);
                 contentView.setViewVisibility(R.id.right_icon, View.VISIBLE);
-                processSmallRightIcon(mSmallIcon, contentView);
+                processSmallRightIcon(mN.mSmallIcon, contentView);
             } else { // small icon at left
-                contentView.setImageViewIcon(R.id.icon, mSmallIcon);
+                contentView.setImageViewIcon(R.id.icon, mN.mSmallIcon);
                 contentView.setViewVisibility(R.id.icon, View.VISIBLE);
-                processSmallIconAsLarge(mSmallIcon, contentView);
+                processSmallIconAsLarge(mN.mSmallIcon, contentView);
             }
-            if (mContentTitle != null) {
-                contentView.setTextViewText(R.id.title, processLegacyText(mContentTitle));
+            if (ex.getCharSequence(EXTRA_TITLE) != null) {
+                contentView.setTextViewText(R.id.title,
+                        processLegacyText(ex.getCharSequence(EXTRA_TITLE)));
             }
-            if (mContentText != null) {
-                contentView.setTextViewText(R.id.text, processLegacyText(mContentText));
+            if (ex.getCharSequence(EXTRA_TEXT) != null) {
+                contentView.setTextViewText(R.id.text,
+                        processLegacyText(ex.getCharSequence(EXTRA_TEXT)));
                 showLine3 = true;
             }
-            if (mContentInfo != null) {
-                contentView.setTextViewText(R.id.info, processLegacyText(mContentInfo));
+            if (ex.getCharSequence(EXTRA_INFO_TEXT) != null) {
+                contentView.setTextViewText(R.id.info,
+                        processLegacyText(ex.getCharSequence(EXTRA_INFO_TEXT)));
                 contentView.setViewVisibility(R.id.info, View.VISIBLE);
                 showLine3 = true;
-            } else if (mNumber > 0) {
+            } else if (mN.number > 0) {
                 final int tooBig = mContext.getResources().getInteger(
                         R.integer.status_bar_notification_info_maxnum);
-                if (mNumber > tooBig) {
+                if (mN.number > tooBig) {
                     contentView.setTextViewText(R.id.info, processLegacyText(
                             mContext.getResources().getString(
                                     R.string.status_bar_notification_info_overflow)));
                 } else {
                     NumberFormat f = NumberFormat.getIntegerInstance();
-                    contentView.setTextViewText(R.id.info, processLegacyText(f.format(mNumber)));
+                    contentView.setTextViewText(R.id.info, processLegacyText(f.format(mN.number)));
                 }
                 contentView.setViewVisibility(R.id.info, View.VISIBLE);
                 showLine3 = true;
@@ -3134,10 +3103,12 @@
             }
 
             // Need to show three lines?
-            if (mSubText != null) {
-                contentView.setTextViewText(R.id.text, processLegacyText(mSubText));
-                if (mContentText != null) {
-                    contentView.setTextViewText(R.id.text2, processLegacyText(mContentText));
+            if (ex.getCharSequence(EXTRA_SUB_TEXT) != null) {
+                contentView.setTextViewText(R.id.text,
+                        processLegacyText(ex.getCharSequence(EXTRA_SUB_TEXT)));
+                if (ex.getCharSequence(EXTRA_TEXT) != null) {
+                    contentView.setTextViewText(R.id.text2,
+                            processLegacyText(ex.getCharSequence(EXTRA_TEXT)));
                     contentView.setViewVisibility(R.id.text2, View.VISIBLE);
                     showLine2 = true;
                     contentTextInLine2 = true;
@@ -3146,15 +3117,18 @@
                 }
             } else {
                 contentView.setViewVisibility(R.id.text2, View.GONE);
-                if (hasProgress && (mProgressMax != 0 || mProgressIndeterminate)) {
+                final int max = ex.getInt(EXTRA_PROGRESS_MAX, 0);
+                final int progress = ex.getInt(EXTRA_PROGRESS, 0);
+                final boolean ind = ex.getBoolean(EXTRA_PROGRESS_INDETERMINATE);
+                if (hasProgress && (max != 0 || ind)) {
                     contentView.setViewVisibility(R.id.progress, View.VISIBLE);
                     contentView.setProgressBar(
-                            R.id.progress, mProgressMax, mProgress, mProgressIndeterminate);
+                            R.id.progress, max, progress, ind);
                     contentView.setProgressBackgroundTintList(
                             R.id.progress, ColorStateList.valueOf(mContext.getColor(
                                     R.color.notification_progress_background_color)));
-                    if (mColor != COLOR_DEFAULT) {
-                        ColorStateList colorStateList = ColorStateList.valueOf(mColor);
+                    if (mN.color != COLOR_DEFAULT) {
+                        ColorStateList colorStateList = ColorStateList.valueOf(mN.color);
                         contentView.setProgressTintList(R.id.progress, colorStateList);
                         contentView.setProgressIndeterminateTintList(R.id.progress, colorStateList);
                     }
@@ -3170,20 +3144,21 @@
             }
 
             if (showsTimeOrChronometer()) {
-                if (mUseChronometer) {
+                if (ex.getBoolean(EXTRA_SHOW_CHRONOMETER)) {
                     contentView.setViewVisibility(R.id.chronometer, View.VISIBLE);
                     contentView.setLong(R.id.chronometer, "setBase",
-                            mWhen + (SystemClock.elapsedRealtime() - System.currentTimeMillis()));
+                            mN.when + (SystemClock.elapsedRealtime() - System.currentTimeMillis()));
                     contentView.setBoolean(R.id.chronometer, "setStarted", true);
                 } else {
                     contentView.setViewVisibility(R.id.time, View.VISIBLE);
-                    contentView.setLong(R.id.time, "setTime", mWhen);
+                    contentView.setLong(R.id.time, "setTime", mN.when);
                 }
             }
 
             // Adjust padding depending on line count and font size.
-            contentView.setViewPadding(R.id.line1, 0, calculateTopPadding(mContext,
-                    mHasThreeLines, mContext.getResources().getConfiguration().fontScale),
+            contentView.setViewPadding(R.id.line1, 0,
+                    calculateTopPadding(mContext, hasThreeLines(),
+                            mContext.getResources().getConfiguration().fontScale),
                     0, 0);
 
             // We want to add badge to first line of text.
@@ -3196,7 +3171,8 @@
 
             // Note getStandardView may hide line 3 again.
             contentView.setViewVisibility(R.id.line3, showLine3 ? View.VISIBLE : View.GONE);
-            contentView.setViewVisibility(R.id.overflow_divider, showLine3 ? View.VISIBLE : View.GONE);
+            contentView.setViewVisibility(R.id.overflow_divider,
+                    showLine3 ? View.VISIBLE : View.GONE);
             return contentView;
         }
 
@@ -3205,7 +3181,7 @@
          *         otherwise
          */
         private boolean showsTimeOrChronometer() {
-            return mWhen != 0 && mShowWhen;
+            return mN.when != 0 && mN.extras.getBoolean(EXTRA_SHOW_WHEN);
         }
 
         /**
@@ -3216,15 +3192,19 @@
          *         is going to have one or two lines
          */
         private boolean hasThreeLines() {
-            boolean contentTextInLine2 = mSubText != null && mContentText != null;
+            final CharSequence subText = mN.extras.getCharSequence(EXTRA_SUB_TEXT);
+            final CharSequence text = mN.extras.getCharSequence(EXTRA_TEXT);
+            boolean contentTextInLine2 = subText != null && text != null;
             boolean hasProgress = mStyle == null || mStyle.hasProgress();
             // If we have content text in line 2, badge goes into line 2, or line 3 otherwise
             boolean badgeInLine3 = getProfileBadgeDrawable() != null && !contentTextInLine2;
-            boolean hasLine3 = mContentText != null || mContentInfo != null || mNumber > 0
-                    || badgeInLine3;
-            boolean hasLine2 = (mSubText != null && mContentText != null) ||
-                    (hasProgress && mSubText == null
-                            && (mProgressMax != 0 || mProgressIndeterminate));
+            boolean hasLine3 = text != null || mN.extras.getCharSequence(EXTRA_INFO_TEXT) != null
+                    || mN.number > 0 || badgeInLine3;
+            final Bundle ex = mN.extras;
+            final int max = ex.getInt(EXTRA_PROGRESS_MAX, 0);
+            final boolean ind = ex.getBoolean(EXTRA_PROGRESS_INDETERMINATE);
+            boolean hasLine2 = (subText != null && text != null) ||
+                    (hasProgress && subText == null && (max != 0 || ind));
             return hasLine2 && hasLine3;
         }
 
@@ -3271,29 +3251,48 @@
             return big;
         }
 
-        private RemoteViews makeContentView() {
-            if (mContentView != null) {
-                return mContentView;
-            } else {
-                return applyStandardTemplate(getBaseLayoutResource());
+        /**
+         * Construct a RemoteViews for the final 1U notification layout. In order:
+         *   1. Custom contentView from the caller
+         *   2. Style's proposed content view
+         *   3. Standard template view
+         */
+        public RemoteViews makeContentView() {
+            if (mN.contentView != null) {
+                return mN.contentView;
+            } else if (mStyle != null) {
+                final RemoteViews styleView = mStyle.makeContentView();
+                if (styleView != null) {
+                    return styleView;
+                }
             }
+            return applyStandardTemplate(getBaseLayoutResource());
         }
 
-        private RemoteViews makeTickerView() {
-            if (mTickerView != null) {
-                return mTickerView;
-            }
-            return null; // tickers are not created by default anymore
-        }
-
-        private RemoteViews makeBigContentView() {
-            if (mActions.size() == 0) return null;
+        /**
+         * Construct a RemoteViews for the final big notification layout.
+         */
+        public RemoteViews makeBigContentView() {
+            if (mStyle != null) {
+                final RemoteViews styleView = mStyle.makeBigContentView();
+                if (styleView != null) {
+                    return styleView;
+                }
+            } else if (mActions.size() == 0) return null;
 
             return applyStandardTemplateWithActions(getBigBaseLayoutResource());
         }
 
-        private RemoteViews makeHeadsUpContentView() {
-            if (mActions.size() == 0) return null;
+        /**
+         * Construct a RemoteViews for the final heads-up notification layout.
+         */
+        public RemoteViews makeHeadsUpContentView() {
+            if (mStyle != null) {
+                final RemoteViews styleView = mStyle.makeHeadsUpContentView();
+                if (styleView != null) {
+                    return styleView;
+                }
+            } else if (mActions.size() == 0) return null;
 
             return applyStandardTemplateWithActions(getBigBaseLayoutResource());
         }
@@ -3320,11 +3319,11 @@
          *         doesn't create material notifications by itself) app.
          */
         private boolean isLegacy() {
-            return mColorUtil != null;
+            return getColorUtil() != null;
         }
 
         private void processLegacyAction(Action action, RemoteViews button) {
-            if (!isLegacy() || mColorUtil.isGrayscaleIcon(mContext, action.getIcon())) {
+            if (!isLegacy() || getColorUtil().isGrayscaleIcon(mContext, action.getIcon())) {
                 button.setTextViewCompoundDrawablesRelativeColorFilter(R.id.action0, 0,
                         mContext.getColor(R.color.notification_action_color_filter),
                         PorterDuff.Mode.MULTIPLY);
@@ -3333,7 +3332,7 @@
 
         private CharSequence processLegacyText(CharSequence charSequence) {
             if (isLegacy()) {
-                return mColorUtil.invertCharSequenceColors(charSequence);
+                return getColorUtil().invertCharSequenceColors(charSequence);
             } else {
                 return charSequence;
             }
@@ -3349,7 +3348,7 @@
                         PorterDuff.Mode.SRC_ATOP, -1);
                 applyLargeIconBackground(contentView);
             } else {
-                if (mColorUtil.isGrayscaleIcon(mContext, largeIcon)) {
+                if (getColorUtil().isGrayscaleIcon(mContext, largeIcon)) {
                     applyLargeIconBackground(contentView);
                 }
             }
@@ -3362,7 +3361,7 @@
         // TODO: also check bounds, transparency, that sort of thing.
         private void processLargeLegacyIcon(Icon largeIcon, RemoteViews contentView) {
             if (largeIcon != null && isLegacy()
-                    && mColorUtil.isGrayscaleIcon(mContext, largeIcon)) {
+                    && getColorUtil().isGrayscaleIcon(mContext, largeIcon)) {
                 applyLargeIconBackground(contentView);
             } else {
                 removeLargeIconBackground(contentView);
@@ -3404,7 +3403,7 @@
             }
             final boolean gray = isLegacy()
                     && smallIcon.getType() == Icon.TYPE_RESOURCE
-                    && mColorUtil.isGrayscaleIcon(mContext, smallIcon.getResId());
+                    && getColorUtil().isGrayscaleIcon(mContext, smallIcon.getResId());
             if (!isLegacy() || gray) {
                 contentView.setInt(R.id.right_icon,
                         "setBackgroundResource",
@@ -3421,17 +3420,17 @@
         }
 
         private int sanitizeColor() {
-            if (mColor != COLOR_DEFAULT) {
-                mColor |= 0xFF000000; // no alpha for custom colors
+            if (mN.color != COLOR_DEFAULT) {
+                mN.color |= 0xFF000000; // no alpha for custom colors
             }
-            return mColor;
+            return mN.color;
         }
 
         private int resolveColor() {
-            if (mColor == COLOR_DEFAULT) {
+            if (mN.color == COLOR_DEFAULT) {
                 return mContext.getColor(R.color.notification_icon_bg_color);
             }
-            return mColor;
+            return mN.color;
         }
 
         /**
@@ -3439,165 +3438,25 @@
          * @hide
          */
         public Notification buildUnstyled() {
-            Notification n = new Notification();
-            n.when = mWhen;
-            n.mSmallIcon = mSmallIcon;
-            if (mSmallIcon != null && mSmallIcon.getType() == Icon.TYPE_RESOURCE) {
-                n.icon = mSmallIcon.getResId();
-            }
-            n.iconLevel = mSmallIconLevel;
-            n.number = mNumber;
-
-            n.color = sanitizeColor();
-
-            setBuilderContentView(n, makeContentView());
-            n.contentIntent = mContentIntent;
-            n.deleteIntent = mDeleteIntent;
-            n.fullScreenIntent = mFullScreenIntent;
-            n.tickerText = mTickerText;
-            n.tickerView = makeTickerView();
-            n.mLargeIcon = mLargeIcon;
-            if (mLargeIcon != null && mLargeIcon.getType() == Icon.TYPE_BITMAP) {
-                n.largeIcon = mLargeIcon.getBitmap();
-            }
-            n.sound = mSound;
-            n.audioStreamType = mAudioStreamType;
-            n.audioAttributes = mAudioAttributes;
-            n.vibrate = mVibrate;
-            n.ledARGB = mLedArgb;
-            n.ledOnMS = mLedOnMs;
-            n.ledOffMS = mLedOffMs;
-            n.defaults = mDefaults;
-            n.flags = mFlags;
-            setBuilderBigContentView(n, makeBigContentView());
-            setBuilderHeadsUpContentView(n, makeHeadsUpContentView());
-            if (mLedOnMs != 0 || mLedOffMs != 0) {
-                n.flags |= FLAG_SHOW_LIGHTS;
-            }
-            if ((mDefaults & DEFAULT_LIGHTS) != 0) {
-                n.flags |= FLAG_SHOW_LIGHTS;
-            }
-            n.category = mCategory;
-            n.mGroupKey = mGroupKey;
-            n.mSortKey = mSortKey;
-            n.priority = mPriority;
             if (mActions.size() > 0) {
-                n.actions = new Action[mActions.size()];
-                mActions.toArray(n.actions);
+                mN.actions = new Action[mActions.size()];
+                mActions.toArray(mN.actions);
             }
-            n.visibility = mVisibility;
-
-            if (mPublicVersion != null) {
-                n.publicVersion = new Notification();
-                mPublicVersion.cloneInto(n.publicVersion, true);
+            if (!mPersonList.isEmpty()) {
+                mN.extras.putStringArray(EXTRA_PEOPLE,
+                        mPersonList.toArray(new String[mPersonList.size()]));
             }
             if (mTopics.size() > 0) {
-                n.topics = new Topic[mTopics.size()];
-                mTopics.toArray(n.topics);
+                mN.topics = new Topic[mTopics.size()];
+                mTopics.toArray(mN.topics);
             }
-            // Note: If you're adding new fields, also update restoreFromNotitification().
-            return n;
+            return mN;
         }
 
-        /**
-         * Capture, in the provided bundle, semantic information used in the construction of
-         * this Notification object.
-         * @hide
-         */
-        public void populateExtras(Bundle extras) {
-            // Store original information used in the construction of this object
-            extras.putInt(EXTRA_ORIGINATING_USERID, mOriginatingUserId);
-            extras.putParcelable(EXTRA_REBUILD_CONTEXT_APPLICATION_INFO,
-                    mContext.getApplicationInfo());
-            extras.putCharSequence(EXTRA_TITLE, mContentTitle);
-            extras.putCharSequence(EXTRA_TEXT, mContentText);
-            extras.putCharSequence(EXTRA_SUB_TEXT, mSubText);
-            extras.putCharSequence(EXTRA_INFO_TEXT, mContentInfo);
-            extras.putParcelable(EXTRA_SMALL_ICON, mSmallIcon);
-            extras.putInt(EXTRA_PROGRESS, mProgress);
-            extras.putInt(EXTRA_PROGRESS_MAX, mProgressMax);
-            extras.putBoolean(EXTRA_PROGRESS_INDETERMINATE, mProgressIndeterminate);
-            extras.putBoolean(EXTRA_SHOW_CHRONOMETER, mUseChronometer);
-            extras.putBoolean(EXTRA_SHOW_WHEN, mShowWhen);
-            if (mLargeIcon != null) {
-                extras.putParcelable(EXTRA_LARGE_ICON, mLargeIcon);
-            }
-            if (!mPeople.isEmpty()) {
-                extras.putStringArray(EXTRA_PEOPLE, mPeople.toArray(new String[mPeople.size()]));
-            }
-            // NOTE: If you're adding new extras also update restoreFromNotification().
-        }
-
-
-        /**
-         * @hide
-         */
-        public static void stripForDelivery(Notification n) {
-            if (!STRIP_AND_REBUILD) {
-                return;
-            }
-
-            String templateClass = n.extras.getString(EXTRA_TEMPLATE);
-            // Only strip views for known Styles because we won't know how to
-            // re-create them otherwise.
-            boolean stripViews = TextUtils.isEmpty(templateClass) ||
-                    getNotificationStyleClass(templateClass) != null;
-
-            boolean isStripped = false;
-
-            if (n.largeIcon != null && n.extras.containsKey(EXTRA_LARGE_ICON)) {
-                // TODO: Would like to check for equality here, but if the notification
-                // has been cloned, we can't.
-                n.largeIcon = null;
-                n.extras.putBoolean(EXTRA_REBUILD_LARGE_ICON, true);
-                isStripped = true;
-            }
-            // Get rid of unmodified BuilderRemoteViews.
-
-            if (stripViews &&
-                    n.contentView instanceof BuilderRemoteViews &&
-                    n.extras.getInt(EXTRA_REBUILD_CONTENT_VIEW_ACTION_COUNT, -1) ==
-                            n.contentView.getSequenceNumber()) {
-                n.contentView = null;
-                n.extras.putBoolean(EXTRA_REBUILD_CONTENT_VIEW, true);
-                n.extras.remove(EXTRA_REBUILD_CONTENT_VIEW_ACTION_COUNT);
-                isStripped = true;
-            }
-            if (stripViews &&
-                    n.bigContentView instanceof BuilderRemoteViews &&
-                    n.extras.getInt(EXTRA_REBUILD_BIG_CONTENT_VIEW_ACTION_COUNT, -1) ==
-                            n.bigContentView.getSequenceNumber()) {
-                n.bigContentView = null;
-                n.extras.putBoolean(EXTRA_REBUILD_BIG_CONTENT_VIEW, true);
-                n.extras.remove(EXTRA_REBUILD_BIG_CONTENT_VIEW_ACTION_COUNT);
-                isStripped = true;
-            }
-            if (stripViews &&
-                    n.headsUpContentView instanceof BuilderRemoteViews &&
-                    n.extras.getInt(EXTRA_REBUILD_HEADS_UP_CONTENT_VIEW_ACTION_COUNT, -1) ==
-                            n.headsUpContentView.getSequenceNumber()) {
-                n.headsUpContentView = null;
-                n.extras.putBoolean(EXTRA_REBUILD_HEADS_UP_CONTENT_VIEW, true);
-                n.extras.remove(EXTRA_REBUILD_HEADS_UP_CONTENT_VIEW_ACTION_COUNT);
-                isStripped = true;
-            }
-
-            if (isStripped) {
-                n.extras.putBoolean(EXTRA_NEEDS_REBUILD, true);
-            }
-        }
-
-        /**
-         * @hide
-         */
-        public static Notification rebuild(Context context, Notification n) {
-            Bundle extras = n.extras;
-            if (!extras.getBoolean(EXTRA_NEEDS_REBUILD)) return n;
-            extras.remove(EXTRA_NEEDS_REBUILD);
-
+        public static Notification.Builder recoverBuilder(Context context, Notification n) {
             // Re-create notification context so we can access app resources.
-            ApplicationInfo applicationInfo = extras.getParcelable(
-                    EXTRA_REBUILD_CONTEXT_APPLICATION_INFO);
+            ApplicationInfo applicationInfo = n.extras.getParcelable(
+                    EXTRA_BUILDER_APPLICATION_INFO);
             Context builderContext;
             try {
                 builderContext = context.createApplicationContext(applicationInfo,
@@ -3607,58 +3466,7 @@
                 builderContext = context;  // try with our context
             }
 
-            Builder b = new Builder(builderContext, n);
-            return b.rebuild();
-        }
-
-        /**
-         * Rebuilds the notification passed in to the rebuild-constructor
-         * {@link #Builder(Context, Notification)}.
-         *
-         * <p>
-         * Throws IllegalStateException when invoked on a Builder that isn't in rebuild mode.
-         *
-         * @hide
-         */
-        private Notification rebuild() {
-            if (mRebuildNotification == null) {
-                throw new IllegalStateException("rebuild() only valid when in 'rebuild' mode.");
-            }
-            mHasThreeLines = hasThreeLines();
-
-            Bundle extras = mRebuildNotification.extras;
-
-            if (extras.getBoolean(EXTRA_REBUILD_LARGE_ICON)) {
-                mRebuildNotification.largeIcon = extras.getParcelable(EXTRA_LARGE_ICON);
-            }
-            extras.remove(EXTRA_REBUILD_LARGE_ICON);
-
-            if (extras.getBoolean(EXTRA_REBUILD_CONTENT_VIEW)) {
-                setBuilderContentView(mRebuildNotification, makeContentView());
-                if (mStyle != null) {
-                    mStyle.populateContentView(mRebuildNotification);
-                }
-            }
-            extras.remove(EXTRA_REBUILD_CONTENT_VIEW);
-
-            if (extras.getBoolean(EXTRA_REBUILD_BIG_CONTENT_VIEW)) {
-                setBuilderBigContentView(mRebuildNotification, makeBigContentView());
-                if (mStyle != null) {
-                    mStyle.populateBigContentView(mRebuildNotification);
-                }
-            }
-            extras.remove(EXTRA_REBUILD_BIG_CONTENT_VIEW);
-
-            if (extras.getBoolean(EXTRA_REBUILD_HEADS_UP_CONTENT_VIEW)) {
-                setBuilderHeadsUpContentView(mRebuildNotification, makeHeadsUpContentView());
-                if (mStyle != null) {
-                    mStyle.populateHeadsUpContentView(mRebuildNotification);
-                }
-            }
-            extras.remove(EXTRA_REBUILD_HEADS_UP_CONTENT_VIEW);
-
-            mHasThreeLines = false;
-            return mRebuildNotification;
+            return new Builder(builderContext, n);
         }
 
         private static Class<? extends Style> getNotificationStyleClass(String templateClass) {
@@ -3674,91 +3482,15 @@
 
         private void setBuilderContentView(Notification n, RemoteViews contentView) {
             n.contentView = contentView;
-            if (contentView instanceof BuilderRemoteViews) {
-                mRebuildBundle.putInt(Builder.EXTRA_REBUILD_CONTENT_VIEW_ACTION_COUNT,
-                        contentView.getSequenceNumber());
-            }
         }
 
         private void setBuilderBigContentView(Notification n, RemoteViews bigContentView) {
             n.bigContentView = bigContentView;
-            if (bigContentView instanceof BuilderRemoteViews) {
-                mRebuildBundle.putInt(Builder.EXTRA_REBUILD_BIG_CONTENT_VIEW_ACTION_COUNT,
-                        bigContentView.getSequenceNumber());
-            }
         }
 
         private void setBuilderHeadsUpContentView(Notification n,
                 RemoteViews headsUpContentView) {
             n.headsUpContentView = headsUpContentView;
-            if (headsUpContentView instanceof BuilderRemoteViews) {
-                mRebuildBundle.putInt(Builder.EXTRA_REBUILD_HEADS_UP_CONTENT_VIEW_ACTION_COUNT,
-                        headsUpContentView.getSequenceNumber());
-            }
-        }
-
-        private void restoreFromNotification(Notification n) {
-
-            // Notification fields.
-            mWhen = n.when;
-            mSmallIcon = n.mSmallIcon;
-            mSmallIconLevel = n.iconLevel;
-            mNumber = n.number;
-
-            mColor = n.color;
-
-            mContentView = n.contentView;
-            mDeleteIntent = n.deleteIntent;
-            mFullScreenIntent = n.fullScreenIntent;
-            mTickerText = n.tickerText;
-            mTickerView = n.tickerView;
-            mLargeIcon = n.mLargeIcon;
-            mSound = n.sound;
-            mAudioStreamType = n.audioStreamType;
-            mAudioAttributes = n.audioAttributes;
-
-            mVibrate = n.vibrate;
-            mLedArgb = n.ledARGB;
-            mLedOnMs = n.ledOnMS;
-            mLedOffMs = n.ledOffMS;
-            mDefaults = n.defaults;
-            mFlags = n.flags;
-
-            mCategory = n.category;
-            mGroupKey = n.mGroupKey;
-            mSortKey = n.mSortKey;
-            mPriority = n.priority;
-            mActions.clear();
-            if (n.actions != null) {
-                Collections.addAll(mActions, n.actions);
-            }
-            mVisibility = n.visibility;
-
-            mPublicVersion = n.publicVersion;
-
-            if (n.topics != null) {
-                Collections.addAll(mTopics, n.topics);
-            }
-
-            // Extras.
-            Bundle extras = n.extras;
-            mOriginatingUserId = extras.getInt(EXTRA_ORIGINATING_USERID);
-            mContentTitle = extras.getCharSequence(EXTRA_TITLE);
-            mContentText = extras.getCharSequence(EXTRA_TEXT);
-            mSubText = extras.getCharSequence(EXTRA_SUB_TEXT);
-            mContentInfo = extras.getCharSequence(EXTRA_INFO_TEXT);
-            mProgress = extras.getInt(EXTRA_PROGRESS);
-            mProgressMax = extras.getInt(EXTRA_PROGRESS_MAX);
-            mProgressIndeterminate = extras.getBoolean(EXTRA_PROGRESS_INDETERMINATE);
-            mUseChronometer = extras.getBoolean(EXTRA_SHOW_CHRONOMETER);
-            mShowWhen = extras.getBoolean(EXTRA_SHOW_WHEN);
-            if (extras.containsKey(EXTRA_LARGE_ICON)) {
-                mLargeIcon = extras.getParcelable(EXTRA_LARGE_ICON);
-            }
-            if (extras.containsKey(EXTRA_PEOPLE)) {
-                mPeople.clear();
-                Collections.addAll(mPeople, extras.getStringArray(EXTRA_PEOPLE));
-            }
         }
 
         /**
@@ -3774,38 +3506,23 @@
          * object.
          */
         public Notification build() {
-            if (mSmallIcon != null) {
-                mSmallIcon.convertToAshmem();
+            // first, add any extras from the calling code
+            if (mUserExtras != null) {
+                mN.extras = getAllExtras();
             }
-            if (mLargeIcon != null) {
-                mLargeIcon.convertToAshmem();
-            }
+
+            // lazy stuff from mContext; see comment in Builder(Context, Notification)
+            mN.extras.putParcelable(EXTRA_BUILDER_APPLICATION_INFO, mContext.getApplicationInfo());
             mOriginatingUserId = mContext.getUserId();
-            mHasThreeLines = hasThreeLines();
+            mN.extras.putInt(EXTRA_ORIGINATING_USERID, mOriginatingUserId);
 
-            Notification n = buildUnstyled();
+            buildUnstyled();
 
             if (mStyle != null) {
-                mStyle.purgeResources();
-                n = mStyle.buildStyled(n);
+                mStyle.buildStyled(mN);
             }
 
-            if (mExtras != null) {
-                n.extras.putAll(mExtras);
-            }
-
-            if (mRebuildBundle.size() > 0) {
-                n.extras.putAll(mRebuildBundle);
-                mRebuildBundle.clear();
-            }
-
-            populateExtras(n.extras);
-            if (mStyle != null) {
-                mStyle.addExtras(n.extras);
-            }
-
-            mHasThreeLines = false;
-            return n;
+            return mN;
         }
 
         /**
@@ -3901,14 +3618,15 @@
             checkBuilder();
 
             // Nasty.
-            CharSequence oldBuilderContentTitle = mBuilder.mContentTitle;
+            CharSequence oldBuilderContentTitle =
+                    mBuilder.getAllExtras().getCharSequence(EXTRA_TITLE);
             if (mBigContentTitle != null) {
                 mBuilder.setContentTitle(mBigContentTitle);
             }
 
             RemoteViews contentView = mBuilder.applyStandardTemplateWithActions(layoutId);
 
-            mBuilder.mContentTitle = oldBuilderContentTitle;
+            mBuilder.getAllExtras().putCharSequence(EXTRA_TITLE, oldBuilderContentTitle);
 
             if (mBigContentTitle != null && mBigContentTitle.equals("")) {
                 contentView.setViewVisibility(R.id.line1, View.GONE);
@@ -3919,7 +3637,7 @@
             // The last line defaults to the subtext, but can be replaced by mSummaryText
             final CharSequence overflowText =
                     mSummaryTextSet ? mSummaryText
-                                    : mBuilder.mSubText;
+                                    : mBuilder.getAllExtras().getCharSequence(EXTRA_SUB_TEXT);
             if (overflowText != null) {
                 contentView.setTextViewText(R.id.text, mBuilder.processLegacyText(overflowText));
                 contentView.setViewVisibility(R.id.overflow_divider, View.VISIBLE);
@@ -3935,6 +3653,31 @@
         }
 
         /**
+         * Construct a Style-specific RemoteViews for the final 1U notification layout.
+         * The default implementation has nothing additional to add.
+         * @hide
+         */
+        public RemoteViews makeContentView() {
+            return null;
+        }
+
+        /**
+         * Construct a Style-specific RemoteViews for the final big notification layout.
+         * @hide
+         */
+        public RemoteViews makeBigContentView() {
+            return null;
+        }
+
+        /**
+         * Construct a Style-specific RemoteViews for the final HUN layout.
+         * @hide
+         */
+        public RemoteViews makeHeadsUpContentView() {
+            return null;
+        }
+
+        /**
          * Changes the padding of the first line such that the big and small content view have the
          * same top padding.
          *
@@ -3942,12 +3685,13 @@
          */
         protected void applyTopPadding(RemoteViews contentView) {
             int topPadding = Builder.calculateTopPadding(mBuilder.mContext,
-                    mBuilder.mHasThreeLines,
+                    mBuilder.hasThreeLines(),
                     mBuilder.mContext.getResources().getConfiguration().fontScale);
             contentView.setViewPadding(R.id.line1, 0, topPadding, 0, 0);
         }
 
         /**
+         * Apply any style-specific extras to this notification before shipping it out.
          * @hide
          */
         public void addExtras(Bundle extras) {
@@ -3961,6 +3705,7 @@
         }
 
         /**
+         * Reconstruct the internal state of this Style object from extras.
          * @hide
          */
         protected void restoreFromExtras(Bundle extras) {
@@ -3978,10 +3723,7 @@
          * @hide
          */
         public Notification buildStyled(Notification wip) {
-            populateTickerView(wip);
-            populateContentView(wip);
-            populateBigContentView(wip);
-            populateHeadsUpContentView(wip);
+            addExtras(wip.extras);
             return wip;
         }
 
@@ -3990,26 +3732,6 @@
          */
         public void purgeResources() {}
 
-        // The following methods are split out so we can re-create notification partially.
-        /**
-         * @hide
-         */
-        protected void populateTickerView(Notification wip) {}
-        /**
-         * @hide
-         */
-        protected void populateContentView(Notification wip) {}
-
-        /**
-         * @hide
-         */
-        protected void populateBigContentView(Notification wip) {}
-
-        /**
-         * @hide
-         */
-        protected void populateHeadsUpContentView(Notification wip) {}
-
         /**
          * Calls {@link android.app.Notification.Builder#build()} on the Builder this Style is
          * attached to.
@@ -4115,29 +3837,33 @@
             }
         }
 
-        private RemoteViews makeBigContentView() {
-            // Replace mLargeIcon with mBigLargeIcon if mBigLargeIconSet
+        /**
+         * @hide
+         */
+        public RemoteViews makeBigContentView() {
+            // Replace mN.mLargeIcon with mBigLargeIcon if mBigLargeIconSet
             // This covers the following cases:
             //   1. mBigLargeIconSet -> mBigLargeIcon (null or non-null) applies, overrides
-            //          mLargeIcon
-            //   2. !mBigLargeIconSet -> mLargeIcon applies
+            //          mN.mLargeIcon
+            //   2. !mBigLargeIconSet -> mN.mLargeIcon applies
             Icon oldLargeIcon = null;
             if (mBigLargeIconSet) {
-                oldLargeIcon = mBuilder.mLargeIcon;
-                mBuilder.mLargeIcon = mBigLargeIcon;
+                oldLargeIcon = mBuilder.mN.mLargeIcon;
+                mBuilder.mN.mLargeIcon = mBigLargeIcon;
             }
 
             RemoteViews contentView = getStandardView(mBuilder.getBigPictureLayoutResource());
 
             if (mBigLargeIconSet) {
-                mBuilder.mLargeIcon = oldLargeIcon;
+                mBuilder.mN.mLargeIcon = oldLargeIcon;
             }
 
             contentView.setImageViewBitmap(R.id.big_picture, mPicture);
 
             applyTopPadding(contentView);
 
-            boolean twoTextLines = mBuilder.mSubText != null && mBuilder.mContentText != null;
+            boolean twoTextLines = mBuilder.getAllExtras().getCharSequence(EXTRA_SUB_TEXT) != null
+                    && mBuilder.getAllExtras().getCharSequence(EXTRA_TEXT) != null;
             mBuilder.addProfileBadge(contentView,
                     twoTextLines ? R.id.profile_badge_line2 : R.id.profile_badge_line3);
             return contentView;
@@ -4168,14 +3894,6 @@
             }
             mPicture = extras.getParcelable(EXTRA_PICTURE);
         }
-
-        /**
-         * @hide
-         */
-        @Override
-        public void populateBigContentView(Notification wip) {
-            mBuilder.setBuilderBigContentView(wip, makeBigContentView());
-        }
     }
 
     /**
@@ -4255,15 +3973,19 @@
             mBigText = extras.getCharSequence(EXTRA_BIG_TEXT);
         }
 
-        private RemoteViews makeBigContentView() {
+        /**
+         * @hide
+         */
+        public RemoteViews makeBigContentView() {
 
             // Nasty
-            CharSequence oldBuilderContentText = mBuilder.mContentText;
-            mBuilder.mContentText = null;
+            CharSequence oldBuilderContentText =
+                    mBuilder.getAllExtras().getCharSequence(EXTRA_TEXT);
+            mBuilder.getAllExtras().putCharSequence(EXTRA_TEXT, null);
 
             RemoteViews contentView = getStandardView(mBuilder.getBigTextLayoutResource());
 
-            mBuilder.mContentText = oldBuilderContentText;
+            mBuilder.getAllExtras().putCharSequence(EXTRA_TEXT, oldBuilderContentText);
 
             contentView.setTextViewText(R.id.big_text, mBuilder.processLegacyText(mBigText));
             contentView.setViewVisibility(R.id.big_text, View.VISIBLE);
@@ -4282,7 +4004,8 @@
         private int calculateMaxLines() {
             int lineCount = MAX_LINES;
             boolean hasActions = mBuilder.mActions.size() > 0;
-            boolean hasSummary = (mSummaryTextSet ? mSummaryText : mBuilder.mSubText) != null;
+            boolean hasSummary = (mSummaryTextSet ? mSummaryText
+                    : mBuilder.getAllExtras().getCharSequence(EXTRA_SUB_TEXT)) != null;
             if (hasActions) {
                 lineCount -= LINES_CONSUMED_BY_ACTIONS;
             }
@@ -4291,19 +4014,11 @@
             }
 
             // If we have less top padding at the top, we can fit less lines.
-            if (!mBuilder.mHasThreeLines) {
+            if (!mBuilder.hasThreeLines()) {
                 lineCount--;
             }
             return lineCount;
         }
-
-        /**
-         * @hide
-         */
-        @Override
-        public void populateBigContentView(Notification wip) {
-            mBuilder.setBuilderBigContentView(wip, makeBigContentView());
-        }
     }
 
     /**
@@ -4384,16 +4099,18 @@
             }
         }
 
-        private RemoteViews makeBigContentView() {
+        /**
+         * @hide
+         */
+        public RemoteViews makeBigContentView() {
             // Remove the content text so line3 disappears unless you have a summary
-
             // Nasty
-            CharSequence oldBuilderContentText = mBuilder.mContentText;
-            mBuilder.mContentText = null;
+            CharSequence oldBuilderContentText = mBuilder.mN.extras.getCharSequence(EXTRA_TEXT);
+            mBuilder.getAllExtras().putCharSequence(EXTRA_TEXT, null);
 
             RemoteViews contentView = getStandardView(mBuilder.getInboxLayoutResource());
 
-            mBuilder.mContentText = oldBuilderContentText;
+            mBuilder.getAllExtras().putCharSequence(EXTRA_TEXT, oldBuilderContentText);
 
             contentView.setViewVisibility(R.id.text2, View.GONE);
 
@@ -4437,14 +4154,6 @@
 
             return contentView;
         }
-
-        /**
-         * @hide
-         */
-        @Override
-        public void populateBigContentView(Notification wip) {
-            mBuilder.setBuilderBigContentView(wip, makeBigContentView());
-        }
     }
 
     /**
@@ -4536,16 +4245,16 @@
          * @hide
          */
         @Override
-        public void populateContentView(Notification wip) {
-            mBuilder.setBuilderContentView(wip, makeMediaContentView());
+        public RemoteViews makeContentView() {
+            return makeMediaContentView();
         }
 
         /**
          * @hide
          */
         @Override
-        public void populateBigContentView(Notification wip) {
-            mBuilder.setBuilderBigContentView(wip, makeMediaBigContentView());
+        public RemoteViews makeBigContentView() {
+            return makeMediaBigContentView();
         }
 
         /** @hide */
@@ -4659,7 +4368,7 @@
                     R.color.notification_media_secondary_color);
             contentView.setTextColor(R.id.title, primaryColor);
             if (mBuilder.showsTimeOrChronometer()) {
-                if (mBuilder.mUseChronometer) {
+                if (mBuilder.getAllExtras().getBoolean(EXTRA_SHOW_CHRONOMETER)) {
                     contentView.setTextColor(R.id.chronometer, secondaryColor);
                 } else {
                     contentView.setTextColor(R.id.time, secondaryColor);
@@ -5503,7 +5212,7 @@
         /**
          * Gets the accent color.
          *
-         * @see setColor
+         * @see #setColor
          */
         @ColorInt
         public int getColor() {
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index cb0ff33..f75b22a 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -207,33 +207,7 @@
      */
     public void notify(String tag, int id, Notification notification)
     {
-        int[] idOut = new int[1];
-        INotificationManager service = getService();
-        String pkg = mContext.getPackageName();
-        if (notification.sound != null) {
-            notification.sound = notification.sound.getCanonicalUri();
-            if (StrictMode.vmFileUriExposureEnabled()) {
-                notification.sound.checkFileUriExposed("Notification.sound");
-            }
-        }
-        fixLegacySmallIcon(notification, pkg);
-        if (mContext.getApplicationInfo().targetSdkVersion > Build.VERSION_CODES.LOLLIPOP_MR1) {
-            if (notification.getSmallIcon() == null) {
-                throw new IllegalArgumentException("Invalid notification (no valid small icon): "
-                    + notification);
-            }
-        }
-        if (localLOGV) Log.v(TAG, pkg + ": notify(" + id + ", " + notification + ")");
-        Notification stripped = notification.clone();
-        Builder.stripForDelivery(stripped);
-        try {
-            service.enqueueNotificationWithTag(pkg, mContext.getOpPackageName(), tag, id,
-                    stripped, idOut, UserHandle.myUserId());
-            if (id != idOut[0]) {
-                Log.w(TAG, "notify: id corrupted: sent " + id + ", got back " + idOut[0]);
-            }
-        } catch (RemoteException e) {
-        }
+        notifyAsUser(tag, id, notification, new UserHandle(UserHandle.myUserId()));
     }
 
     /**
@@ -251,12 +225,17 @@
             }
         }
         fixLegacySmallIcon(notification, pkg);
+        if (mContext.getApplicationInfo().targetSdkVersion > Build.VERSION_CODES.LOLLIPOP_MR1) {
+            if (notification.getSmallIcon() == null) {
+                throw new IllegalArgumentException("Invalid notification (no valid small icon): "
+                        + notification);
+            }
+        }
         if (localLOGV) Log.v(TAG, pkg + ": notify(" + id + ", " + notification + ")");
-        Notification stripped = notification.clone();
-        Builder.stripForDelivery(stripped);
+        final Notification copy = notification.clone();
         try {
             service.enqueueNotificationWithTag(pkg, mContext.getOpPackageName(), tag, id,
-                    stripped, idOut, user.getIdentifier());
+                    copy, idOut, user.getIdentifier());
             if (id != idOut[0]) {
                 Log.w(TAG, "notify: id corrupted: sent " + id + ", got back " + idOut[0]);
             }
@@ -287,13 +266,7 @@
      */
     public void cancel(String tag, int id)
     {
-        INotificationManager service = getService();
-        String pkg = mContext.getPackageName();
-        if (localLOGV) Log.v(TAG, pkg + ": cancel(" + id + ")");
-        try {
-            service.cancelNotificationWithTag(pkg, tag, id, UserHandle.myUserId());
-        } catch (RemoteException e) {
-        }
+        cancelAsUser(tag, id, new UserHandle(UserHandle.myUserId()));
     }
 
     /**
diff --git a/core/java/android/app/admin/DevicePolicyManagerInternal.java b/core/java/android/app/admin/DevicePolicyManagerInternal.java
index 0a0d77d..4270e16 100644
--- a/core/java/android/app/admin/DevicePolicyManagerInternal.java
+++ b/core/java/android/app/admin/DevicePolicyManagerInternal.java
@@ -16,6 +16,8 @@
 
 package android.app.admin;
 
+import android.os.Bundle;
+
 import java.util.List;
 
 /**
@@ -69,4 +71,13 @@
      * @return true if the uid is an active admin with the given policy.
      */
     public abstract boolean isActiveAdminWithPolicy(int uid, int reqPolicy);
+
+    /**
+     * Takes a {@link Bundle} containing "base" user restrictions stored in
+     * {@link com.android.server.pm.UserManagerService}, mixes restrictions set by the device owner
+     * and the profile owner and returns the merged restrictions.
+     *
+     * This method always returns a new {@link Bundle}.
+     */
+    public abstract Bundle getComposedUserRestrictions(int userId, Bundle inBundle);
 }
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index aed1a0b..27ecf9f 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1708,6 +1708,15 @@
     public static final String FEATURE_BACKUP = "android.software.backup";
 
     /**
+     * Feature for {@link #getSystemAvailableFeatures} and
+     * {@link #hasSystemFeature}: The device supports freeform window management.
+     * Windows have title bars and can be moved and resized.
+     */
+    @SdkConstant(SdkConstantType.FEATURE)
+    public static final String FEATURE_FREEFORM_WINDOW_MANAGEMENT
+            = "android.software.freeform_window_management";
+
+    /**
      * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}:
      * The device supports creating secondary users and managed profiles via
      * {@link DevicePolicyManager}.
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index 6bfa2a4..1bb0fbb 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -119,8 +119,12 @@
             //
             // For one such example of this, see b/18867306.
             //
-            // TODO: Remove this special case altogether.
-            if (before.isIPv4Provisioned() && !after.isIPv4Provisioned()) {
+            // Additionally, losing IPv6 provisioning can result in TCP
+            // connections getting stuck until timeouts fire and other
+            // baffling failures. Therefore, loss of either IPv4 or IPv6 on a
+            // previously dualstack network is deemed a lost of provisioning.
+            if ((before.isIPv4Provisioned() && !after.isIPv4Provisioned()) ||
+                (before.isIPv6Provisioned() && !after.isIPv6Provisioned())) {
                 return ProvisioningChange.LOST_PROVISIONING;
             }
             return ProvisioningChange.STILL_PROVISIONED;
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index 3ade170..12cac85 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -55,14 +55,12 @@
     int getUserHandle(int userSerialNumber);
     Bundle getUserRestrictions(int userHandle);
     boolean hasUserRestriction(in String restrictionKey, int userHandle);
-    void setUserRestrictions(in Bundle restrictions, int userHandle);
     void setUserRestriction(String key, boolean value, int userId);
     void setSystemControlledUserRestriction(String key, boolean value, int userId);
     void setApplicationRestrictions(in String packageName, in Bundle restrictions,
             int userHandle);
     Bundle getApplicationRestrictions(in String packageName);
     Bundle getApplicationRestrictionsForUser(in String packageName, int userHandle);
-    void removeRestrictions();
     void setDefaultGuestRestrictions(in Bundle restrictions);
     Bundle getDefaultGuestRestrictions();
     boolean markGuestForDeletion(int userHandle);
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 1c1575e..909d33c 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -21,6 +21,7 @@
 import android.app.ActivityManager;
 import android.app.ActivityManagerNative;
 import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.UserInfo;
 import android.content.res.Resources;
@@ -55,7 +56,8 @@
      *
      * <p/>Key for user restrictions.
      * <p/>Type: Boolean
-     * @see #setUserRestrictions(Bundle)
+     * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+     * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
      */
     public static final String DISALLOW_MODIFY_ACCOUNTS = "no_modify_accounts";
@@ -67,7 +69,8 @@
      *
      * <p/>Key for user restrictions.
      * <p/>Type: Boolean
-     * @see #setUserRestrictions(Bundle)
+     * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+     * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
      */
     public static final String DISALLOW_CONFIG_WIFI = "no_config_wifi";
@@ -78,7 +81,8 @@
      *
      * <p/>Key for user restrictions.
      * <p/>Type: Boolean
-     * @see #setUserRestrictions(Bundle)
+     * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+     * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
      */
     public static final String DISALLOW_INSTALL_APPS = "no_install_apps";
@@ -89,7 +93,8 @@
      *
      * <p/>Key for user restrictions.
      * <p/>Type: Boolean
-     * @see #setUserRestrictions(Bundle)
+     * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+     * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
      */
     public static final String DISALLOW_UNINSTALL_APPS = "no_uninstall_apps";
@@ -102,7 +107,8 @@
      *
      * <p/>Key for user restrictions.
      * <p/>Type: Boolean
-     * @see #setUserRestrictions(Bundle)
+     * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+     * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
      */
     public static final String DISALLOW_SHARE_LOCATION = "no_share_location";
@@ -114,7 +120,8 @@
      *
      * <p/>Key for user restrictions.
      * <p/>Type: Boolean
-     * @see #setUserRestrictions(Bundle)
+     * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+     * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
      */
     public static final String DISALLOW_INSTALL_UNKNOWN_SOURCES = "no_install_unknown_sources";
@@ -127,7 +134,8 @@
      *
      * <p/>Key for user restrictions.
      * <p/>Type: Boolean
-     * @see #setUserRestrictions(Bundle)
+     * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+     * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
      */
     public static final String DISALLOW_CONFIG_BLUETOOTH = "no_config_bluetooth";
@@ -139,7 +147,8 @@
      *
      * <p/>Key for user restrictions.
      * <p/>Type: Boolean
-     * @see #setUserRestrictions(Bundle)
+     * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+     * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
      */
     public static final String DISALLOW_USB_FILE_TRANSFER = "no_usb_file_transfer";
@@ -150,7 +159,8 @@
      *
      * <p/>Key for user restrictions.
      * <p/>Type: Boolean
-     * @see #setUserRestrictions(Bundle)
+     * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+     * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
      */
     public static final String DISALLOW_CONFIG_CREDENTIALS = "no_config_credentials";
@@ -163,7 +173,8 @@
      *
      * <p/>Key for user restrictions.
      * <p/>Type: Boolean
-     * @see #setUserRestrictions(Bundle)
+     * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+     * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
      */
     public static final String DISALLOW_REMOVE_USER = "no_remove_user";
@@ -174,7 +185,8 @@
      *
      * <p/>Key for user restrictions.
      * <p/>Type: Boolean
-     * @see #setUserRestrictions(Bundle)
+     * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+     * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
      */
     public static final String DISALLOW_DEBUGGING_FEATURES = "no_debugging_features";
@@ -187,7 +199,8 @@
      *
      * <p/>Key for user restrictions.
      * <p/>Type: Boolean
-     * @see #setUserRestrictions(Bundle)
+     * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+     * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
      */
     public static final String DISALLOW_CONFIG_VPN = "no_config_vpn";
@@ -199,7 +212,8 @@
      *
      * <p/>Key for user restrictions.
      * <p/>Type: Boolean
-     * @see #setUserRestrictions(Bundle)
+     * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+     * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
      */
     public static final String DISALLOW_CONFIG_TETHERING = "no_config_tethering";
@@ -213,7 +227,8 @@
      *
      * <p/>Key for user restrictions.
      * <p/>Type: Boolean
-     * @see #setUserRestrictions(Bundle)
+     * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+     * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
      */
     public static final String DISALLOW_NETWORK_RESET = "no_network_reset";
@@ -227,7 +242,8 @@
      *
      * <p/>Key for user restrictions.
      * <p/>Type: Boolean
-     * @see #setUserRestrictions(Bundle)
+     * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+     * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
      */
     public static final String DISALLOW_FACTORY_RESET = "no_factory_reset";
@@ -241,7 +257,8 @@
      *
      * <p/>Key for user restrictions.
      * <p/>Type: Boolean
-     * @see #setUserRestrictions(Bundle)
+     * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+     * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
      */
     public static final String DISALLOW_ADD_USER = "no_add_user";
@@ -252,7 +269,8 @@
      *
      * <p/>Key for user restrictions.
      * <p/>Type: Boolean
-     * @see #setUserRestrictions(Bundle)
+     * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+     * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
      */
     public static final String ENSURE_VERIFY_APPS = "ensure_verify_apps";
@@ -266,7 +284,8 @@
      *
      * <p/>Key for user restrictions.
      * <p/>Type: Boolean
-     * @see #setUserRestrictions(Bundle)
+     * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+     * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
      */
     public static final String DISALLOW_CONFIG_CELL_BROADCASTS = "no_config_cell_broadcasts";
@@ -280,7 +299,8 @@
      *
      * <p/>Key for user restrictions.
      * <p/>Type: Boolean
-     * @see #setUserRestrictions(Bundle)
+     * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+     * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
      */
     public static final String DISALLOW_CONFIG_MOBILE_NETWORKS = "no_config_mobile_networks";
@@ -300,7 +320,8 @@
      *
      * <p/>Key for user restrictions.
      * <p/>Type: Boolean
-     * @see #setUserRestrictions(Bundle)
+     * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+     * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
      */
     public static final String DISALLOW_APPS_CONTROL = "no_control_apps";
@@ -312,7 +333,8 @@
      *
      * <p/>Key for user restrictions.
      * <p/>Type: Boolean
-     * @see #setUserRestrictions(Bundle)
+     * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+     * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
      */
     public static final String DISALLOW_MOUNT_PHYSICAL_MEDIA = "no_physical_media";
@@ -324,7 +346,8 @@
      *
      * <p/>Key for user restrictions.
      * <p/>Type: Boolean
-     * @see #setUserRestrictions(Bundle)
+     * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+     * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
      */
     public static final String DISALLOW_UNMUTE_MICROPHONE = "no_unmute_microphone";
@@ -336,7 +359,8 @@
      *
      * <p/>Key for user restrictions.
      * <p/>Type: Boolean
-     * @see #setUserRestrictions(Bundle)
+     * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+     * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
      */
     public static final String DISALLOW_ADJUST_VOLUME = "no_adjust_volume";
@@ -350,7 +374,8 @@
      *
      * <p/>Key for user restrictions.
      * <p/>Type: Boolean
-     * @see #setUserRestrictions(Bundle)
+     * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+     * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
      */
     public static final String DISALLOW_OUTGOING_CALLS = "no_outgoing_calls";
@@ -361,7 +386,8 @@
      *
      * <p/>Key for user restrictions.
      * <p/>Type: Boolean
-     * @see #setUserRestrictions(Bundle)
+     * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+     * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
      */
     public static final String DISALLOW_SMS = "no_sms";
@@ -373,7 +399,8 @@
      *
      * <p/>Key for user restrictions.
      * <p/>Type: Boolean
-     * @see #setUserRestrictions(Bundle)
+     * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+     * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
      */
     public static final String DISALLOW_FUN = "no_fun";
@@ -393,7 +420,8 @@
      *
      * <p/>Key for user restrictions.
      * <p/>Type: Boolean
-     * @see #setUserRestrictions(Bundle)
+     * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+     * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
      */
     public static final String DISALLOW_CREATE_WINDOWS = "no_create_windows";
@@ -406,7 +434,8 @@
      *
      * <p/>Key for user restrictions.
      * <p/>Type: Boolean
-     * @see #setUserRestrictions(Bundle)
+     * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+     * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
      */
     public static final String DISALLOW_CROSS_PROFILE_COPY_PASTE = "no_cross_profile_copy_paste";
@@ -417,7 +446,8 @@
      *
      * <p/>Key for user restrictions.
      * <p/>Type: Boolean
-     * @see #setUserRestrictions(Bundle)
+     * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+     * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
      */
     public static final String DISALLOW_OUTGOING_BEAM = "no_outgoing_beam";
@@ -426,7 +456,8 @@
      * Hidden user restriction to disallow access to wallpaper manager APIs. This user restriction
      * is always set for managed profiles.
      * @hide
-     * @see #setUserRestrictions(Bundle)
+     * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+     * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
      */
     public static final String DISALLOW_WALLPAPER = "no_wallpaper";
@@ -438,7 +469,8 @@
      *
      * <p/>Key for user restrictions.
      * <p/>Type: Boolean
-     * @see #setUserRestrictions(Bundle)
+     * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+     * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
      */
     public static final String DISALLOW_SAFE_BOOT = "no_safe_boot";
@@ -447,7 +479,8 @@
      * Specifies if a user is not allowed to record audio. This restriction is always enabled for
      * background users. The default value is <code>false</code>.
      *
-     * @see #setUserRestrictions(Bundle)
+     * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+     * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
      * @hide
      */
@@ -466,7 +499,8 @@
      *
      * <p/>Key for user restrictions.
      * <p/>Type: Boolean
-     * @see #setUserRestrictions(Bundle)
+     * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+     * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
      */
     public static final String ALLOW_PARENT_PROFILE_APP_LINKING
@@ -740,36 +774,20 @@
     }
 
     /**
-     * Sets all the user-wide restrictions for this user.
-     * Requires the MANAGE_USERS permission.
-     * @param restrictions the Bundle containing all the restrictions.
-     * @deprecated use {@link android.app.admin.DevicePolicyManager#addUserRestriction(
-     * android.content.ComponentName, String)} or
-     * {@link android.app.admin.DevicePolicyManager#clearUserRestriction(
-     * android.content.ComponentName, String)} instead.
+     * This will no longer work.  Use {@link #setUserRestriction(String, boolean)} instead.
      */
     @Deprecated
     public void setUserRestrictions(Bundle restrictions) {
-        setUserRestrictions(restrictions, Process.myUserHandle());
+        throw new UnsupportedOperationException("This method is no longer supported");
     }
 
     /**
-     * Sets all the user-wide restrictions for the specified user.
-     * Requires the MANAGE_USERS permission.
-     * @param restrictions the Bundle containing all the restrictions.
-     * @param userHandle the UserHandle of the user for whom to set the restrictions.
-     * @deprecated use {@link android.app.admin.DevicePolicyManager#addUserRestriction(
-     * android.content.ComponentName, String)} or
-     * {@link android.app.admin.DevicePolicyManager#clearUserRestriction(
-     * android.content.ComponentName, String)} instead.
+     * This will no longer work.  Use {@link #setUserRestriction(String, boolean, UserHandle)}
+     * instead.
      */
     @Deprecated
     public void setUserRestrictions(Bundle restrictions, UserHandle userHandle) {
-        try {
-            mService.setUserRestrictions(restrictions, userHandle.getIdentifier());
-        } catch (RemoteException re) {
-            Log.w(TAG, "Could not set user restrictions", re);
-        }
+        throw new UnsupportedOperationException("This method is no longer supported");
     }
 
     /**
@@ -784,9 +802,7 @@
      */
     @Deprecated
     public void setUserRestriction(String key, boolean value) {
-        Bundle bundle = getUserRestrictions();
-        bundle.putBoolean(key, value);
-        setUserRestrictions(bundle);
+        setUserRestriction(key, value, Process.myUserHandle());
     }
 
     /**
@@ -882,9 +898,8 @@
         try {
             user = mService.createUser(name, flags);
             if (user != null && !user.isAdmin()) {
-                Bundle userRestrictions = mService.getUserRestrictions(user.id);
-                addDefaultUserRestrictions(userRestrictions);
-                mService.setUserRestrictions(userRestrictions, user.id);
+                mService.setUserRestriction(DISALLOW_SMS, true, user.id);
+                mService.setUserRestriction(DISALLOW_OUTGOING_CALLS, true, user.id);
             }
         } catch (RemoteException re) {
             Log.w(TAG, "Could not create a user", re);
@@ -899,27 +914,22 @@
      * @hide
      */
     public UserInfo createGuest(Context context, String name) {
-        UserInfo guest = createUser(name, UserInfo.FLAG_GUEST);
-        if (guest != null) {
-            Settings.Secure.putStringForUser(context.getContentResolver(),
-                    Settings.Secure.SKIP_FIRST_USE_HINTS, "1", guest.id);
-            try {
-                Bundle guestRestrictions = mService.getDefaultGuestRestrictions();
-                guestRestrictions.putBoolean(DISALLOW_SMS, true);
-                guestRestrictions.putBoolean(DISALLOW_INSTALL_UNKNOWN_SOURCES, true);
-                mService.setUserRestrictions(guestRestrictions, guest.id);
-            } catch (RemoteException re) {
-                Log.w(TAG, "Could not update guest restrictions");
+        UserInfo guest = null;
+        try {
+            guest = mService.createUser(name, UserInfo.FLAG_GUEST);
+            if (guest != null) {
+                Settings.Secure.putStringForUser(context.getContentResolver(),
+                        Settings.Secure.SKIP_FIRST_USE_HINTS, "1", guest.id);
+
+                mService.setUserRestriction(DISALLOW_SMS, true, guest.id);
+                mService.setUserRestriction(DISALLOW_INSTALL_UNKNOWN_SOURCES, true, guest.id);
             }
+        } catch (RemoteException re) {
+            Log.w(TAG, "Could not create a user", re);
         }
         return guest;
     }
 
-    private static void addDefaultUserRestrictions(Bundle restrictions) {
-        restrictions.putBoolean(DISALLOW_OUTGOING_CALLS, true);
-        restrictions.putBoolean(DISALLOW_SMS, true);
-    }
-
     /**
      * Creates a user with the specified name and options as a profile of another user.
      * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
@@ -1465,15 +1475,6 @@
         return false;
     }
 
-    /** @hide */
-    public void removeRestrictions() {
-        try {
-            mService.removeRestrictions();
-        } catch (RemoteException re) {
-            Log.w(TAG, "Could not change restrictions pin");
-        }
-    }
-
     /**
      * @hide
      * Set restrictions that should apply to any future guest user that's created.
diff --git a/core/java/android/os/UserManagerInternal.java b/core/java/android/os/UserManagerInternal.java
new file mode 100644
index 0000000..d7be6d8
--- /dev/null
+++ b/core/java/android/os/UserManagerInternal.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.os;
+
+/**
+ * @hide Only for use within the system server.
+ */
+public abstract class UserManagerInternal {
+    /**
+     * Lock that must be held when calling certain methods in this class.
+     *
+     * This is used to avoid dead lock between
+     * {@link com.android.server.pm.UserManagerService} and
+     * {@link com.android.server.devicepolicy.DevicePolicyManagerService}.  This lock should not
+     * be newly taken while holding the DPMS lock, which would cause a dead lock.  Take this
+     * lock first before taking the DPMS lock to avoid that.
+     */
+    public abstract Object getUserRestrictionsLock();
+
+    /**
+     * Called by {@link com.android.server.devicepolicy.DevicePolicyManagerService} to get
+     * {@link com.android.server.pm.UserManagerService} to update effective user restrictions.
+     *
+     * Must be called while taking the {@link #getUserRestrictionsLock()} lock.
+     */
+    public abstract void updateEffectiveUserRestrictionsRL(int userId);
+
+    /**
+     * Called by {@link com.android.server.devicepolicy.DevicePolicyManagerService} to get
+     * {@link com.android.server.pm.UserManagerService} to update effective user restrictions.
+     *
+     * Must be called while taking the {@link #getUserRestrictionsLock()} lock.
+     */
+    public abstract void updateEffectiveUserRestrictionsForAllUsersRL();
+
+    /**
+     * Returns the "base" user restrictions.
+     *
+     * Used by {@link com.android.server.devicepolicy.DevicePolicyManagerService} for upgrading
+     * from MNC.
+     */
+    public abstract Bundle getBaseUserRestrictions(int userId);
+
+    /**
+     * Called by {@link com.android.server.devicepolicy.DevicePolicyManagerService} for upgrading
+     * from MNC.
+     */
+    public abstract void setBaseUserRestrictionsByDpmsForMigration(int userId,
+            Bundle baseRestrictions);
+}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 11effd0..a1f9743 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -6277,6 +6277,15 @@
         */
        public static final String FORCE_ALLOW_ON_EXTERNAL = "force_allow_on_external";
 
+        /**
+         * Whether any activity can be resized. When this is true, any
+         * activity, regardless of manifest values, can be resized for multi-window.
+         * (0 = false, 1 = true)
+         * @hide
+         */
+        public static final String DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES
+                = "force_resizable_activities";
+
        /**
         * Whether user has enabled development settings.
         */
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index d424546..7e7b5fc 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -31,6 +31,7 @@
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.Icon;
 import android.graphics.Bitmap;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.Parcel;
@@ -472,9 +473,10 @@
                 StatusBarNotification sbn = list.get(i);
                 Notification notification = sbn.getNotification();
                 try {
-                    Builder.rebuild(getContext(), notification);
                     // convert icon metadata to legacy format for older clients
                     createLegacyIconExtras(notification);
+                    // populate remote views for older clients.
+                    maybePopulateRemoteViews(notification);
                 } catch (IllegalArgumentException e) {
                     if (corruptNotifications == null) {
                         corruptNotifications = new ArrayList<>(N);
@@ -676,6 +678,18 @@
         }
     }
 
+    /**
+     * Populates remote views for pre-N targeting apps.
+     */
+    private void maybePopulateRemoteViews(Notification notification) {
+        if (getContext().getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.N) {
+            Builder builder = Builder.recoverBuilder(getContext(), notification);
+            notification.contentView = builder.makeContentView();
+            notification.bigContentView = builder.makeBigContentView();
+            notification.headsUpContentView = builder.makeHeadsUpContentView();
+        }
+    }
+
     private class INotificationListenerWrapper extends INotificationListener.Stub {
         @Override
         public void onNotificationPosted(IStatusBarNotificationHolder sbnHolder,
@@ -689,9 +703,10 @@
             }
 
             try {
-                Notification.Builder.rebuild(getContext(), sbn.getNotification());
+                Notification notification = sbn.getNotification();
                 // convert icon metadata to legacy format for older clients
                 createLegacyIconExtras(sbn.getNotification());
+                maybePopulateRemoteViews(sbn.getNotification());
             } catch (IllegalArgumentException e) {
                 // drop corrupt notification
                 sbn = null;
diff --git a/core/java/android/text/method/ArrowKeyMovementMethod.java b/core/java/android/text/method/ArrowKeyMovementMethod.java
index de509b2..2459cfa 100644
--- a/core/java/android/text/method/ArrowKeyMovementMethod.java
+++ b/core/java/android/text/method/ArrowKeyMovementMethod.java
@@ -238,6 +238,7 @@
             initialScrollY = Touch.getInitialScrollY(widget, buffer);
         }
 
+        boolean wasTouchSelecting = isTouchSelecting(isMouse, buffer);
         boolean handled = Touch.onTouchEvent(widget, buffer, event);
 
         if (widget.didTouchFocusSelect() && !isMouse) {
@@ -267,9 +268,9 @@
                 // Cursor can be active at any location in the text while mouse pointer can start
                 // selection from a totally different location. Use LAST_TAP_DOWN span to ensure
                 // text selection will start from mouse pointer location.
+                final int startOffset = buffer.getSpanStart(LAST_TAP_DOWN);
                 if (isMouse && Touch.isSelectionStarted(buffer)) {
-                    int offset = buffer.getSpanStart(LAST_TAP_DOWN);
-                    Selection.setSelection(buffer, offset);
+                    Selection.setSelection(buffer, startOffset);
                 }
 
                 if (isTouchSelecting(isMouse, buffer) && handled) {
@@ -284,9 +285,9 @@
                     // Update selection as we're moving the selection area.
 
                     // Get the current touch position
-                    int offset = widget.getOffsetForPosition(event.getX(), event.getY());
-
-                    Selection.extendSelection(buffer, offset);
+                    final int offset = widget.getOffsetForPosition(event.getX(), event.getY());
+                    Selection.setSelection(buffer, Math.min(startOffset, offset),
+                            Math.max(startOffset, offset));
                     return true;
                 }
             } else if (action == MotionEvent.ACTION_UP) {
@@ -300,10 +301,12 @@
                     return true;
                 }
 
-                int offset = widget.getOffsetForPosition(event.getX(), event.getY());
-                if (isTouchSelecting(isMouse, buffer)) {
+                if (wasTouchSelecting) {
+                    final int startOffset = buffer.getSpanStart(LAST_TAP_DOWN);
+                    final int endOffset = widget.getOffsetForPosition(event.getX(), event.getY());
+                    Selection.setSelection(buffer, Math.min(startOffset, endOffset),
+                            Math.max(startOffset, endOffset));
                     buffer.removeSpan(LAST_TAP_DOWN);
-                    Selection.extendSelection(buffer, offset);
                 }
 
                 MetaKeyKeyListener.adjustMetaAfterKeypress(buffer);
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 7d39a0c..e17bdd7 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -4191,7 +4191,10 @@
 
                     if (mPointerIconShape != pointerShape) {
                         mPointerIconShape = pointerShape;
-                        event.getDevice().setPointerShape(pointerShape);
+                        final InputDevice inputDevice = event.getDevice();
+                        if (inputDevice != null) {
+                            inputDevice.setPointerShape(pointerShape);
+                        }
                     }
                 } else if (event.getActionMasked() == MotionEvent.ACTION_HOVER_MOVE) {
                     mPointerIconShape = PointerIcon.STYLE_NOT_SPECIFIED;
diff --git a/core/tests/coretests/src/android/net/LinkPropertiesTest.java b/core/tests/coretests/src/android/net/LinkPropertiesTest.java
index b6b4f4f..d5f6321 100644
--- a/core/tests/coretests/src/android/net/LinkPropertiesTest.java
+++ b/core/tests/coretests/src/android/net/LinkPropertiesTest.java
@@ -561,9 +561,13 @@
         assertTrue(v46lp.isProvisioned());
 
         assertEquals(ProvisioningChange.STILL_PROVISIONED,
+                LinkProperties.compareProvisioning(v4lp, v46lp));
+        assertEquals(ProvisioningChange.STILL_PROVISIONED,
                 LinkProperties.compareProvisioning(v6lp, v46lp));
         assertEquals(ProvisioningChange.LOST_PROVISIONING,
                 LinkProperties.compareProvisioning(v46lp, v6lp));
+        assertEquals(ProvisioningChange.LOST_PROVISIONING,
+                LinkProperties.compareProvisioning(v46lp, v4lp));
 
         // Check that losing and gaining a secondary router does not change
         // the provisioning status.
diff --git a/core/tests/coretests/src/android/widget/TextViewActivityMouseTest.java b/core/tests/coretests/src/android/widget/TextViewActivityMouseTest.java
new file mode 100644
index 0000000..c5e2ae6
--- /dev/null
+++ b/core/tests/coretests/src/android/widget/TextViewActivityMouseTest.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.widget;
+
+import static android.widget.espresso.TextViewActions.mouseDragOnText;
+import static android.widget.espresso.TextViewAssertions.hasSelection;
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.action.ViewActions.click;
+import static android.support.test.espresso.action.ViewActions.typeTextIntoFocusedView;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+
+import com.android.frameworks.coretests.R;
+
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * Tests mouse interaction of the TextView widget from an Activity
+ */
+public class TextViewActivityMouseTest extends ActivityInstrumentationTestCase2<TextViewActivity>{
+
+    public TextViewActivityMouseTest() {
+        super(TextViewActivity.class);
+    }
+
+    @SmallTest
+    public void testSelectTextByDrag() throws Exception {
+        getActivity();
+
+        final String helloWorld = "Hello world!";
+        onView(withId(R.id.textview)).perform(click());
+        onView(withId(R.id.textview)).perform(typeTextIntoFocusedView(helloWorld));
+        onView(withId(R.id.textview)).perform(
+                mouseDragOnText(helloWorld.indexOf("llo"), helloWorld.indexOf("ld!")));
+
+        onView(withId(R.id.textview)).check(hasSelection("llo wor"));
+    }
+
+    @SmallTest
+    public void testSelectTextByDrag_reverse() throws Exception {
+        getActivity();
+
+        final String helloWorld = "Hello world!";
+        onView(withId(R.id.textview)).perform(click());
+        onView(withId(R.id.textview)).perform(typeTextIntoFocusedView(helloWorld));
+        onView(withId(R.id.textview)).perform(
+                mouseDragOnText( helloWorld.indexOf("ld!"), helloWorld.indexOf("llo")));
+
+        onView(withId(R.id.textview)).check(hasSelection("llo wor"));
+    }
+}
diff --git a/core/tests/coretests/src/android/widget/espresso/DragOnTextViewActions.java b/core/tests/coretests/src/android/widget/espresso/DragOnTextViewActions.java
index a0cd848..9ff8e82 100644
--- a/core/tests/coretests/src/android/widget/espresso/DragOnTextViewActions.java
+++ b/core/tests/coretests/src/android/widget/espresso/DragOnTextViewActions.java
@@ -20,25 +20,22 @@
 import static android.support.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed;
 import static com.android.internal.util.Preconditions.checkNotNull;
 import static org.hamcrest.Matchers.allOf;
-
 import android.annotation.Nullable;
 import android.os.SystemClock;
 import android.support.test.espresso.UiController;
 import android.support.test.espresso.PerformException;
 import android.support.test.espresso.ViewAction;
 import android.support.test.espresso.action.CoordinatesProvider;
-import android.support.test.espresso.action.GeneralClickAction;
 import android.support.test.espresso.action.MotionEvents;
 import android.support.test.espresso.action.PrecisionDescriber;
-import android.support.test.espresso.action.Press;
 import android.support.test.espresso.action.Swiper;
-import android.support.test.espresso.action.Tap;
 import android.support.test.espresso.util.HumanReadables;
 import android.util.Log;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewConfiguration;
 import android.widget.TextView;
+
 import org.hamcrest.Matcher;
 
 
@@ -51,11 +48,48 @@
  * <ul>
  */
 public final class DragOnTextViewActions implements ViewAction {
+    public interface Dragger extends Swiper {
+        UiController wrapUiController(UiController uiController);
+    }
 
     /**
      * Executes different "drag on text" types to given positions.
      */
-    public enum Drag implements Swiper {
+    public enum Drag implements Dragger {
+
+        /**
+         * Starts a drag with a mouse down.
+         */
+        MOUSE_DOWN {
+            private DownMotionPerformer downMotion = new DownMotionPerformer() {
+                @Override
+                public MotionEvent perform(
+                        UiController uiController, float[] coordinates, float[] precision) {
+                    MotionEvent downEvent = MotionEvents.sendDown(
+                            uiController, coordinates, precision)
+                            .down;
+                    return downEvent;
+                }
+            };
+
+            @Override
+            public Status sendSwipe(
+                    UiController uiController,
+                    float[] startCoordinates, float[] endCoordinates, float[] precision) {
+                return sendLinearDrag(
+                        uiController, downMotion, startCoordinates, endCoordinates, precision);
+            }
+
+            @Override
+            public String toString() {
+                return "mouse down and drag to select";
+            }
+
+            @Override
+            public UiController wrapUiController(UiController uiController) {
+                return new MouseUiController(uiController);
+            }
+        },
 
         /**
          * Starts a drag with a long-press.
@@ -197,6 +231,11 @@
 
             return res;
         }
+
+        @Override
+        public UiController wrapUiController(UiController uiController) {
+            return uiController;
+        }
     }
 
     /**
@@ -215,13 +254,13 @@
         MotionEvent perform(UiController uiController, float[] coordinates, float[] precision);
     }
 
-    private final Swiper mDragger;
+    private final Dragger mDragger;
     private final CoordinatesProvider mStartCoordinatesProvider;
     private final CoordinatesProvider mEndCoordinatesProvider;
     private final PrecisionDescriber mPrecisionDescriber;
 
     public DragOnTextViewActions(
-            Swiper dragger,
+            Dragger dragger,
             CoordinatesProvider startCoordinatesProvider,
             CoordinatesProvider endCoordinatesProvider,
             PrecisionDescriber precisionDescriber) {
@@ -242,6 +281,8 @@
         checkNotNull(uiController);
         checkNotNull(view);
 
+        uiController = mDragger.wrapUiController(uiController);
+
         float[] startCoordinates = mStartCoordinatesProvider.calculateCoordinates(view);
         float[] endCoordinates = mEndCoordinatesProvider.calculateCoordinates(view);
         float[] precision = mPrecisionDescriber.describePrecision();
diff --git a/core/tests/coretests/src/android/widget/espresso/MouseUiController.java b/core/tests/coretests/src/android/widget/espresso/MouseUiController.java
new file mode 100644
index 0000000..f1387f8
--- /dev/null
+++ b/core/tests/coretests/src/android/widget/espresso/MouseUiController.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.widget.espresso;
+
+import android.support.test.espresso.InjectEventSecurityException;
+import android.support.test.espresso.UiController;
+import android.view.InputDevice;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+
+/**
+ * Class to wrap an UiController to overwrite source of motion events to SOURCE_MOUSE.
+ * Note that this doesn't change the tool type.
+ */
+public class MouseUiController implements UiController {
+    private final UiController mUiController;
+
+    public MouseUiController(UiController uiController) {
+        mUiController = uiController;
+    }
+
+    @Override
+    public boolean injectKeyEvent(KeyEvent event) throws InjectEventSecurityException {
+        return mUiController.injectKeyEvent(event);
+    }
+
+    @Override
+    public boolean injectMotionEvent(MotionEvent event) throws InjectEventSecurityException {
+        // Modify the event to mimic mouse primary button event.
+        event.setSource(InputDevice.SOURCE_MOUSE);
+        event.setButtonState(MotionEvent.BUTTON_PRIMARY);
+        return mUiController.injectMotionEvent(event);
+    }
+
+    @Override
+    public boolean injectString(String str) throws InjectEventSecurityException {
+        return mUiController.injectString(str);
+    }
+
+    @Override
+    public void loopMainThreadForAtLeast(long millisDelay) {
+        mUiController.loopMainThreadForAtLeast(millisDelay);
+    }
+
+    @Override
+    public void loopMainThreadUntilIdle() {
+        mUiController.loopMainThreadUntilIdle();
+    }
+}
diff --git a/core/tests/coretests/src/android/widget/espresso/TextViewActions.java b/core/tests/coretests/src/android/widget/espresso/TextViewActions.java
index 835b1b9..4f5a72b 100644
--- a/core/tests/coretests/src/android/widget/espresso/TextViewActions.java
+++ b/core/tests/coretests/src/android/widget/espresso/TextViewActions.java
@@ -124,6 +124,27 @@
     }
 
     /**
+     * Returns an action that click then drags by mouse on text from startIndex to endIndex on the
+     * TextView.<br>
+     * <br>
+     * View constraints:
+     * <ul>
+     * <li>must be a TextView displayed on screen
+     * <ul>
+     *
+     * @param startIndex The index of the TextView's text to start a drag from
+     * @param endIndex The index of the TextView's text to end the drag at
+     */
+    public static ViewAction mouseDragOnText(int startIndex, int endIndex) {
+        return actionWithAssertions(
+                new DragOnTextViewActions(
+                        DragOnTextViewActions.Drag.MOUSE_DOWN,
+                        new TextCoordinates(startIndex),
+                        new TextCoordinates(endIndex),
+                        Press.PINPOINT));
+    }
+
+    /**
      * A provider of the x, y coordinates of the text at the specified index in a text view.
      */
     private static final class TextCoordinates implements CoordinatesProvider {
diff --git a/location/java/android/location/Location.java b/location/java/android/location/Location.java
index bf3387b..4d0d1bd 100644
--- a/location/java/android/location/Location.java
+++ b/location/java/android/location/Location.java
@@ -78,32 +78,51 @@
      */
     public static final String EXTRA_NO_GPS_LOCATION = "noGPSLocation";
 
+    /**
+     * Bit mask for mFieldsMask indicating the presence of mAltitude.
+     */
+    private static final byte HAS_ALTITUDE_MASK = 1;
+    /**
+     * Bit mask for mFieldsMask indicating the presence of mSpeed.
+     */
+    private static final byte HAS_SPEED_MASK = 2;
+    /**
+     * Bit mask for mFieldsMask indicating the presence of mBearing.
+     */
+    private static final byte HAS_BEARING_MASK = 4;
+    /**
+     * Bit mask for mFieldsMask indicating the presence of mAccuracy.
+     */
+    private static final byte HAS_ACCURACY_MASK = 8;
+    /**
+     * Bit mask for mFieldsMask indicating location is from a mock provider.
+     */
+    private static final byte HAS_MOCK_PROVIDER_MASK = 16;
+
+    // Cached data to make bearing/distance computations more efficient for the case
+    // where distanceTo and bearingTo are called in sequence.  Assume this typically happens
+    // on the same thread for caching purposes.
+    private static ThreadLocal<BearingDistanceCache> sBearingDistanceCache
+            = new ThreadLocal<BearingDistanceCache>() {
+        @Override
+        protected BearingDistanceCache initialValue() {
+            return new BearingDistanceCache();
+        }
+    };
+
     private String mProvider;
     private long mTime = 0;
     private long mElapsedRealtimeNanos = 0;
     private double mLatitude = 0.0;
     private double mLongitude = 0.0;
-    private boolean mHasAltitude = false;
     private double mAltitude = 0.0f;
-    private boolean mHasSpeed = false;
     private float mSpeed = 0.0f;
-    private boolean mHasBearing = false;
     private float mBearing = 0.0f;
-    private boolean mHasAccuracy = false;
     private float mAccuracy = 0.0f;
     private Bundle mExtras = null;
-    private boolean mIsFromMockProvider = false;
 
-    // Cache the inputs and outputs of computeDistanceAndBearing
-    // so calls to distanceTo() and bearingTo() can share work
-    private double mLat1 = 0.0;
-    private double mLon1 = 0.0;
-    private double mLat2 = 0.0;
-    private double mLon2 = 0.0;
-    private float mDistance = 0.0f;
-    private float mInitialBearing = 0.0f;
-    // Scratchpad
-    private final float[] mResults = new float[2];
+    // A bitmask of fields present in this object (see HAS_* constants defined above).
+    private byte mFieldsMask = 0;
 
     /**
      * Construct a new Location with a named provider.
@@ -131,18 +150,14 @@
         mProvider = l.mProvider;
         mTime = l.mTime;
         mElapsedRealtimeNanos = l.mElapsedRealtimeNanos;
+        mFieldsMask = l.mFieldsMask;
         mLatitude = l.mLatitude;
         mLongitude = l.mLongitude;
-        mHasAltitude = l.mHasAltitude;
         mAltitude = l.mAltitude;
-        mHasSpeed = l.mHasSpeed;
         mSpeed = l.mSpeed;
-        mHasBearing = l.mHasBearing;
         mBearing = l.mBearing;
-        mHasAccuracy = l.mHasAccuracy;
         mAccuracy = l.mAccuracy;
         mExtras = (l.mExtras == null) ? null : new Bundle(l.mExtras);
-        mIsFromMockProvider = l.mIsFromMockProvider;
     }
 
     /**
@@ -152,18 +167,14 @@
         mProvider = null;
         mTime = 0;
         mElapsedRealtimeNanos = 0;
+        mFieldsMask = 0;
         mLatitude = 0;
         mLongitude = 0;
-        mHasAltitude = false;
         mAltitude = 0;
-        mHasSpeed = false;
         mSpeed = 0;
-        mHasBearing = false;
         mBearing = 0;
-        mHasAccuracy = false;
         mAccuracy = 0;
         mExtras = null;
-        mIsFromMockProvider = false;
     }
 
     /**
@@ -257,11 +268,13 @@
             int deg = Integer.parseInt(degrees);
             double min;
             double sec = 0.0;
+            boolean secPresent = false;
 
             if (st.hasMoreTokens()) {
                 min = Integer.parseInt(minutes);
                 String seconds = st.nextToken();
                 sec = Double.parseDouble(seconds);
+                secPresent = true;
             } else {
                 min = Double.parseDouble(minutes);
             }
@@ -273,11 +286,15 @@
             if ((deg < 0.0) || (deg > 179 && !isNegative180)) {
                 throw new IllegalArgumentException("coordinate=" + coordinate);
             }
-            if (min < 0 || min > 59) {
+
+            // min must be in [0, 59] if seconds are present, otherwise [0.0, 60.0)
+            if (min < 0 || min >= 60 || (secPresent && (min > 59))) {
                 throw new IllegalArgumentException("coordinate=" +
                         coordinate);
             }
-            if (sec < 0 || sec > 59) {
+
+            // sec must be in [0.0, 60.0)
+            if (sec < 0 || sec >= 60) {
                 throw new IllegalArgumentException("coordinate=" +
                         coordinate);
             }
@@ -291,7 +308,7 @@
     }
 
     private static void computeDistanceAndBearing(double lat1, double lon1,
-        double lat2, double lon2, float[] results) {
+        double lat2, double lon2, BearingDistanceCache results) {
         // Based on http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf
         // using the "Inverse Formula" (section 4)
 
@@ -376,19 +393,19 @@
         }
 
         float distance = (float) (b * A * (sigma - deltaSigma));
-        results[0] = distance;
-        if (results.length > 1) {
-            float initialBearing = (float) Math.atan2(cosU2 * sinLambda,
-                cosU1 * sinU2 - sinU1 * cosU2 * cosLambda);
-            initialBearing *= 180.0 / Math.PI;
-            results[1] = initialBearing;
-            if (results.length > 2) {
-                float finalBearing = (float) Math.atan2(cosU1 * sinLambda,
-                    -sinU1 * cosU2 + cosU1 * sinU2 * cosLambda);
-                finalBearing *= 180.0 / Math.PI;
-                results[2] = finalBearing;
-            }
-        }
+        results.mDistance = distance;
+        float initialBearing = (float) Math.atan2(cosU2 * sinLambda,
+            cosU1 * sinU2 - sinU1 * cosU2 * cosLambda);
+        initialBearing *= 180.0 / Math.PI;
+        results.mInitialBearing = initialBearing;
+        float finalBearing = (float) Math.atan2(cosU1 * sinLambda,
+                -sinU1 * cosU2 + cosU1 * sinU2 * cosLambda);
+        finalBearing *= 180.0 / Math.PI;
+        results.mFinalBearing = finalBearing;
+        results.mLat1 = lat1;
+        results.mLat2 = lat2;
+        results.mLon1 = lon1;
+        results.mLon2 = lon2;
     }
 
     /**
@@ -414,8 +431,16 @@
         if (results == null || results.length < 1) {
             throw new IllegalArgumentException("results is null or has length < 1");
         }
+        BearingDistanceCache cache = sBearingDistanceCache.get();
         computeDistanceAndBearing(startLatitude, startLongitude,
-            endLatitude, endLongitude, results);
+                endLatitude, endLongitude, cache);
+        results[0] = cache.mDistance;
+        if (results.length > 1) {
+            results[1] = cache.mInitialBearing;
+            if (results.length > 2) {
+                results[2] = cache.mFinalBearing;
+            }
+        }
     }
 
     /**
@@ -427,21 +452,14 @@
      * @return the approximate distance in meters
      */
     public float distanceTo(Location dest) {
+        BearingDistanceCache cache = sBearingDistanceCache.get();
         // See if we already have the result
-        synchronized (mResults) {
-            if (mLatitude != mLat1 || mLongitude != mLon1 ||
-                dest.mLatitude != mLat2 || dest.mLongitude != mLon2) {
-                computeDistanceAndBearing(mLatitude, mLongitude,
-                    dest.mLatitude, dest.mLongitude, mResults);
-                mLat1 = mLatitude;
-                mLon1 = mLongitude;
-                mLat2 = dest.mLatitude;
-                mLon2 = dest.mLongitude;
-                mDistance = mResults[0];
-                mInitialBearing = mResults[1];
-            }
-            return mDistance;
+        if (mLatitude != cache.mLat1 || mLongitude != cache.mLon1 ||
+            dest.mLatitude != cache.mLat2 || dest.mLongitude != cache.mLon2) {
+            computeDistanceAndBearing(mLatitude, mLongitude,
+                dest.mLatitude, dest.mLongitude, cache);
         }
+        return cache.mDistance;
     }
 
     /**
@@ -455,21 +473,14 @@
      * @return the initial bearing in degrees
      */
     public float bearingTo(Location dest) {
-        synchronized (mResults) {
-            // See if we already have the result
-            if (mLatitude != mLat1 || mLongitude != mLon1 ||
-                            dest.mLatitude != mLat2 || dest.mLongitude != mLon2) {
-                computeDistanceAndBearing(mLatitude, mLongitude,
-                    dest.mLatitude, dest.mLongitude, mResults);
-                mLat1 = mLatitude;
-                mLon1 = mLongitude;
-                mLat2 = dest.mLatitude;
-                mLon2 = dest.mLongitude;
-                mDistance = mResults[0];
-                mInitialBearing = mResults[1];
-            }
-            return mInitialBearing;
+        BearingDistanceCache cache = sBearingDistanceCache.get();
+        // See if we already have the result
+        if (mLatitude != cache.mLat1 || mLongitude != cache.mLon1 ||
+                        dest.mLatitude != cache.mLat2 || dest.mLongitude != cache.mLon2) {
+            computeDistanceAndBearing(mLatitude, mLongitude,
+                dest.mLatitude, dest.mLongitude, cache);
         }
+        return cache.mInitialBearing;
     }
 
     /**
@@ -585,7 +596,7 @@
      * True if this location has an altitude.
      */
     public boolean hasAltitude() {
-        return mHasAltitude;
+        return (mFieldsMask & HAS_ALTITUDE_MASK) != 0;
     }
 
     /**
@@ -605,7 +616,7 @@
      */
     public void setAltitude(double altitude) {
         mAltitude = altitude;
-        mHasAltitude = true;
+        mFieldsMask |= HAS_ALTITUDE_MASK;
     }
 
     /**
@@ -616,14 +627,14 @@
      */
     public void removeAltitude() {
         mAltitude = 0.0f;
-        mHasAltitude = false;
+        mFieldsMask &= ~HAS_ALTITUDE_MASK;
     }
 
     /**
      * True if this location has a speed.
      */
     public boolean hasSpeed() {
-        return mHasSpeed;
+        return (mFieldsMask & HAS_SPEED_MASK) != 0;
     }
 
     /**
@@ -642,7 +653,7 @@
      */
     public void setSpeed(float speed) {
         mSpeed = speed;
-        mHasSpeed = true;
+        mFieldsMask |= HAS_SPEED_MASK;
     }
 
     /**
@@ -653,14 +664,14 @@
      */
     public void removeSpeed() {
         mSpeed = 0.0f;
-        mHasSpeed = false;
+        mFieldsMask &= ~HAS_SPEED_MASK;
     }
 
     /**
      * True if this location has a bearing.
      */
     public boolean hasBearing() {
-        return mHasBearing;
+        return (mFieldsMask & HAS_BEARING_MASK) != 0;
     }
 
     /**
@@ -692,7 +703,7 @@
             bearing -= 360.0f;
         }
         mBearing = bearing;
-        mHasBearing = true;
+        mFieldsMask |= HAS_BEARING_MASK;
     }
 
     /**
@@ -703,7 +714,7 @@
      */
     public void removeBearing() {
         mBearing = 0.0f;
-        mHasBearing = false;
+        mFieldsMask &= ~HAS_BEARING_MASK;
     }
 
     /**
@@ -713,7 +724,7 @@
      * accuracy.
      */
     public boolean hasAccuracy() {
-        return mHasAccuracy;
+        return (mFieldsMask & HAS_ACCURACY_MASK) != 0;
     }
 
     /**
@@ -751,7 +762,7 @@
      */
     public void setAccuracy(float accuracy) {
         mAccuracy = accuracy;
-        mHasAccuracy = true;
+        mFieldsMask |= HAS_ACCURACY_MASK;
     }
 
     /**
@@ -762,7 +773,7 @@
      */
     public void removeAccuracy() {
         mAccuracy = 0.0f;
-        mHasAccuracy = false;
+        mFieldsMask &= ~HAS_ACCURACY_MASK;
     }
 
     /**
@@ -780,7 +791,7 @@
     @SystemApi
     public boolean isComplete() {
         if (mProvider == null) return false;
-        if (!mHasAccuracy) return false;
+        if (!hasAccuracy()) return false;
         if (mTime == 0) return false;
         if (mElapsedRealtimeNanos == 0) return false;
         return true;
@@ -798,8 +809,8 @@
     @SystemApi
     public void makeComplete() {
         if (mProvider == null) mProvider = "?";
-        if (!mHasAccuracy) {
-            mHasAccuracy = true;
+        if (!hasAccuracy()) {
+            mFieldsMask |= HAS_ACCURACY_MASK;
             mAccuracy = 100.0f;
         }
         if (mTime == 0) mTime = System.currentTimeMillis();
@@ -838,7 +849,7 @@
         s.append("Location[");
         s.append(mProvider);
         s.append(String.format(" %.6f,%.6f", mLatitude, mLongitude));
-        if (mHasAccuracy) s.append(String.format(" acc=%.0f", mAccuracy));
+        if (hasAccuracy()) s.append(String.format(" acc=%.0f", mAccuracy));
         else s.append(" acc=???");
         if (mTime == 0) {
             s.append(" t=?!?");
@@ -849,10 +860,10 @@
             s.append(" et=");
             TimeUtils.formatDuration(mElapsedRealtimeNanos / 1000000L, s);
         }
-        if (mHasAltitude) s.append(" alt=").append(mAltitude);
-        if (mHasSpeed) s.append(" vel=").append(mSpeed);
-        if (mHasBearing) s.append(" bear=").append(mBearing);
-        if (mIsFromMockProvider) s.append(" mock");
+        if (hasAltitude()) s.append(" alt=").append(mAltitude);
+        if (hasSpeed()) s.append(" vel=").append(mSpeed);
+        if (hasBearing()) s.append(" bear=").append(mBearing);
+        if (isFromMockProvider()) s.append(" mock");
 
         if (mExtras != null) {
             s.append(" {").append(mExtras).append('}');
@@ -873,18 +884,14 @@
             Location l = new Location(provider);
             l.mTime = in.readLong();
             l.mElapsedRealtimeNanos = in.readLong();
+            l.mFieldsMask = in.readByte();
             l.mLatitude = in.readDouble();
             l.mLongitude = in.readDouble();
-            l.mHasAltitude = in.readInt() != 0;
             l.mAltitude = in.readDouble();
-            l.mHasSpeed = in.readInt() != 0;
             l.mSpeed = in.readFloat();
-            l.mHasBearing = in.readInt() != 0;
             l.mBearing = in.readFloat();
-            l.mHasAccuracy = in.readInt() != 0;
             l.mAccuracy = in.readFloat();
             l.mExtras = in.readBundle();
-            l.mIsFromMockProvider = in.readInt() != 0;
             return l;
         }
 
@@ -904,18 +911,14 @@
         parcel.writeString(mProvider);
         parcel.writeLong(mTime);
         parcel.writeLong(mElapsedRealtimeNanos);
+        parcel.writeByte(mFieldsMask);
         parcel.writeDouble(mLatitude);
         parcel.writeDouble(mLongitude);
-        parcel.writeInt(mHasAltitude ? 1 : 0);
         parcel.writeDouble(mAltitude);
-        parcel.writeInt(mHasSpeed ? 1 : 0);
         parcel.writeFloat(mSpeed);
-        parcel.writeInt(mHasBearing ? 1 : 0);
         parcel.writeFloat(mBearing);
-        parcel.writeInt(mHasAccuracy ? 1 : 0);
         parcel.writeFloat(mAccuracy);
         parcel.writeBundle(mExtras);
-        parcel.writeInt(mIsFromMockProvider? 1 : 0);
     }
 
     /**
@@ -940,7 +943,7 @@
      * Attaches an extra {@link Location} to this Location.
      *
      * @param key the key associated with the Location extra
-     * @param location the Location to attach
+     * @param value the Location to attach
      * @hide
      */
     public void setExtraLocation(String key, Location value) {
@@ -956,7 +959,7 @@
      * @return true if this Location came from a mock provider, false otherwise
      */
     public boolean isFromMockProvider() {
-        return mIsFromMockProvider;
+        return (mFieldsMask & HAS_MOCK_PROVIDER_MASK) != 0;
     }
 
     /**
@@ -967,6 +970,24 @@
      */
     @SystemApi
     public void setIsFromMockProvider(boolean isFromMockProvider) {
-        mIsFromMockProvider = isFromMockProvider;
+        if (isFromMockProvider) {
+            mFieldsMask |= HAS_MOCK_PROVIDER_MASK;
+        } else {
+            mFieldsMask &= ~HAS_MOCK_PROVIDER_MASK;
+        }
+    }
+
+    /**
+     * Caches data used to compute distance and bearing (so successive calls to {@link #distanceTo}
+     * and {@link #bearingTo} don't duplicate work.
+     */
+    private static class BearingDistanceCache {
+        private double mLat1 = 0.0;
+        private double mLon1 = 0.0;
+        private double mLat2 = 0.0;
+        private double mLon2 = 0.0;
+        private float mDistance = 0.0f;
+        private float mInitialBearing = 0.0f;
+        private float mFinalBearing = 0.0f;
     }
 }
diff --git a/location/tests/locationtests/src/android/location/LocationTest.java b/location/tests/locationtests/src/android/location/LocationTest.java
index 847ac7a..dc8d0f7 100644
--- a/location/tests/locationtests/src/android/location/LocationTest.java
+++ b/location/tests/locationtests/src/android/location/LocationTest.java
@@ -16,6 +16,7 @@
 
 package android.location;
 
+import android.os.Parcel;
 import android.test.suitebuilder.annotation.SmallTest;
 
 import junit.framework.TestCase;
@@ -225,6 +226,40 @@
         assertEquals(message, loc.getBearing(), 0, 0);
     }
 
+    public void testParcel() {
+        final double expectedLat = 33;
+        final double expectedLon = -122;
+        final float expectedAccuracy = 15;
+        final float expectedSpeed = 5;
+        Location loc = new Location("test");
+        loc.setLatitude(expectedLat);
+        loc.setLongitude(expectedLon);
+        loc.setAccuracy(expectedAccuracy);
+        loc.setSpeed(expectedSpeed);
+
+        // Serialize location object into bytes via parcelable capability
+        Parcel parcel = Parcel.obtain();
+        loc.writeToParcel(parcel, 0);
+        byte[] rawBytes = parcel.marshall();
+        parcel.recycle();
+
+        // Turn the bytes back into a location object
+        parcel = Parcel.obtain();
+        parcel.unmarshall(rawBytes, 0, rawBytes.length);
+        parcel.setDataPosition(0);
+        Location deserialized = Location.CREATOR.createFromParcel(parcel);
+        parcel.recycle();
+
+        assertEquals(expectedLat, deserialized.getLatitude());
+        assertEquals(expectedLon, deserialized.getLongitude());
+        assertEquals(expectedAccuracy, deserialized.getAccuracy());
+        assertTrue(deserialized.hasAccuracy());
+        assertEquals(expectedSpeed, deserialized.getSpeed());
+        assertTrue(deserialized.hasSpeed());
+        assertFalse(deserialized.hasBearing());
+        assertFalse(deserialized.hasAltitude());
+        assertFalse(deserialized.isFromMockProvider());
+    }
 }
 
 
diff --git a/media/java/android/media/browse/MediaBrowser.java b/media/java/android/media/browse/MediaBrowser.java
index ba867e1..5476651 100644
--- a/media/java/android/media/browse/MediaBrowser.java
+++ b/media/java/android/media/browse/MediaBrowser.java
@@ -249,7 +249,7 @@
      */
     public @NonNull String getRoot() {
         if (!isConnected()) {
-            throw new IllegalStateException("getSessionToken() called while not connected (state="
+            throw new IllegalStateException("getRoot() called while not connected (state="
                     + getStateLabel(mState) + ")");
         }
         return mRootId;
diff --git a/opengl/java/android/opengl/GLES31.java b/opengl/java/android/opengl/GLES31.java
index 3cbaa60..805930e 100644
--- a/opengl/java/android/opengl/GLES31.java
+++ b/opengl/java/android/opengl/GLES31.java
@@ -24,9 +24,14 @@
 
     public static final int GL_VERTEX_SHADER_BIT                            = 0x00000001;
     public static final int GL_FRAGMENT_SHADER_BIT                          = 0x00000002;
+    public static final int GL_COMPUTE_SHADER_BIT                           = 0x00000020;
+    public static final int GL_ALL_SHADER_BITS                              = -1; // 0xFFFFFFFF
+
+    public static final int GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT              = 0x00000001;
+    public static final int GL_ELEMENT_ARRAY_BARRIER_BIT                    = 0x00000002;
     public static final int GL_UNIFORM_BARRIER_BIT                          = 0x00000004;
     public static final int GL_TEXTURE_FETCH_BARRIER_BIT                    = 0x00000008;
-    public static final int GL_COMPUTE_SHADER_BIT                           = 0x00000020;
+    public static final int GL_SHADER_IMAGE_ACCESS_BARRIER_BIT              = 0x00000020;
     public static final int GL_COMMAND_BARRIER_BIT                          = 0x00000040;
     public static final int GL_PIXEL_BUFFER_BARRIER_BIT                     = 0x00000080;
     public static final int GL_TEXTURE_UPDATE_BARRIER_BIT                   = 0x00000100;
@@ -35,7 +40,8 @@
     public static final int GL_TRANSFORM_FEEDBACK_BARRIER_BIT               = 0x00000800;
     public static final int GL_ATOMIC_COUNTER_BARRIER_BIT                   = 0x00001000;
     public static final int GL_SHADER_STORAGE_BARRIER_BIT                   = 0x00002000;
-    public static final int GL_ALL_SHADER_BITS                              = -1; // 0xFFFFFFFF
+    public static final int GL_ALL_BARRIER_BITS                             = -1; // 0xFFFFFFFF
+
 
     public static final int GL_TEXTURE_WIDTH                                = 0x1000;
     public static final int GL_TEXTURE_HEIGHT                               = 0x1001;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
index 0dcd02d..d75b6fd 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
@@ -287,33 +287,24 @@
             super(context, 0);
 
             final List<RootItem> libraries = new ArrayList<>();
-            final List<RootItem> clouds = new ArrayList<>();
-            final List<RootItem> locals = new ArrayList<>();
+            final List<RootItem> others = new ArrayList<>();
 
-            for (RootInfo root : roots) {
-                RootItem item = new RootItem(root);
-                switch (root.derivedType) {
-                    case RootInfo.TYPE_LOCAL:
-                        locals.add(item);
-                        break;
-                    case RootInfo.TYPE_CLOUD:
-                        clouds.add(item);
-                        break;
-                    default:
-                        libraries.add(item);
-                        break;
+            for (final RootInfo root : roots) {
+                final RootItem item = new RootItem(root);
+                if (root.isLibrary()) {
+                    libraries.add(item);
+                } else {
+                    others.add(item);
                 }
             }
 
             final RootComparator comp = new RootComparator();
             Collections.sort(libraries, comp);
-            Collections.sort(locals, comp);
-            Collections.sort(clouds, comp);
+            Collections.sort(others, comp);
 
             addAll(libraries);
             add(new SpacerItem());
-            addAll(locals);
-            addAll(clouds);
+            addAll(others);
 
             if (includeApps != null) {
                 final PackageManager pm = context.getPackageManager();
diff --git a/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java b/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
index 17e6a80..501392c 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
@@ -51,7 +51,8 @@
     public static final int TYPE_RECENTS = 4;
     public static final int TYPE_DOWNLOADS = 5;
     public static final int TYPE_LOCAL = 6;
-    public static final int TYPE_CLOUD = 7;
+    public static final int TYPE_MTP = 7;
+    public static final int TYPE_CLOUD = 8;
 
     public String authority;
     public String rootId;
@@ -184,6 +185,8 @@
             derivedType = TYPE_AUDIO;
         } else if (isRecents()) {
             derivedType = TYPE_RECENTS;
+        } else if (isMtp()) {
+            derivedType = TYPE_MTP;
         } else {
             derivedType = TYPE_CLOUD;
         }
@@ -216,6 +219,15 @@
                 && "audio_root".equals(rootId);
     }
 
+    public boolean isMtp() {
+        return "com.android.mtp.documents".equals(authority);
+    }
+
+    public boolean isLibrary() {
+        return derivedType == TYPE_IMAGES || derivedType == TYPE_VIDEO || derivedType == TYPE_AUDIO
+                || derivedType == TYPE_RECENTS || derivedType == TYPE_DOWNLOADS;
+    }
+
     @Override
     public String toString() {
         return "Root{authority=" + authority + ", rootId=" + rootId + ", title=" + title + "}";
diff --git a/packages/DocumentsUI/testing/TestDocumentsProvider/Android.mk b/packages/DocumentsUI/testing/TestDocumentsProvider/Android.mk
deleted file mode 100644
index 8baadba..0000000
--- a/packages/DocumentsUI/testing/TestDocumentsProvider/Android.mk
+++ /dev/null
@@ -1,14 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := TestDocumentsProvider
-LOCAL_CERTIFICATE := platform
-LOCAL_MODULE_TAGS := tests
-#LOCAL_SDK_VERSION := current
-
-LOCAL_PROGUARD_ENABLED := disabled
-LOCAL_DEX_PREOPT := false
-
-include $(BUILD_PACKAGE)
diff --git a/packages/DocumentsUI/testing/TestDocumentsProvider/AndroidManifest.xml b/packages/DocumentsUI/testing/TestDocumentsProvider/AndroidManifest.xml
deleted file mode 100644
index 66988a1..0000000
--- a/packages/DocumentsUI/testing/TestDocumentsProvider/AndroidManifest.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="com.android.documentsui.testing">
-    <application>
-        <provider android:name="TestDocumentsProvider"
-                android:authorities="com.android.documentsui.testing"
-                android:exported="true"
-                android:grantUriPermissions="true"
-                android:permission="android.permission.MANAGE_DOCUMENTS">
-            <intent-filter>
-                <action android:name="android.content.action.DOCUMENTS_PROVIDER" />
-            </intent-filter>
-        </provider>
-    </application>
-</manifest>
diff --git a/packages/DocumentsUI/testing/TestDocumentsProvider/src/com/android/documentsui/testing/TestDocumentsProvider.java b/packages/DocumentsUI/testing/TestDocumentsProvider/src/com/android/documentsui/testing/TestDocumentsProvider.java
deleted file mode 100644
index 63ff0de..0000000
--- a/packages/DocumentsUI/testing/TestDocumentsProvider/src/com/android/documentsui/testing/TestDocumentsProvider.java
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.documentsui.testing;
-
-import android.database.Cursor;
-import android.database.MatrixCursor;
-import android.database.MatrixCursor.RowBuilder;
-import android.os.AsyncTask;
-import android.os.CancellationSignal;
-import android.os.ParcelFileDescriptor;
-import android.provider.DocumentsContract.Document;
-import android.provider.DocumentsContract.Root;
-import android.provider.DocumentsProvider;
-import android.util.Log;
-
-import java.io.ByteArrayOutputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-public class TestDocumentsProvider extends DocumentsProvider {
-    private static final String TAG = "TestDocumentsProvider";
-
-    private static final String[] DEFAULT_ROOT_PROJECTION = new String[] {
-            Root.COLUMN_ROOT_ID,
-            Root.COLUMN_FLAGS,
-            Root.COLUMN_ICON,
-            Root.COLUMN_TITLE,
-            Root.COLUMN_DOCUMENT_ID, Root.COLUMN_AVAILABLE_BYTES,
-    };
-
-    private static final String[] DEFAULT_DOCUMENT_PROJECTION = new String[] {
-            Document.COLUMN_DOCUMENT_ID,
-            Document.COLUMN_MIME_TYPE,
-            Document.COLUMN_DISPLAY_NAME,
-            Document.COLUMN_LAST_MODIFIED,
-            Document.COLUMN_FLAGS,
-            Document.COLUMN_SIZE,
-    };
-
-    private static String[] resolveRootProjection(String[] projection) {
-        return projection != null ? projection : DEFAULT_ROOT_PROJECTION;
-    }
-
-    private static String[] resolveDocumentProjection(String[] projection) {
-        return projection != null ? projection : DEFAULT_DOCUMENT_PROJECTION;
-    }
-
-    @Override
-    public boolean onCreate() {
-        resetRoots();
-        return true;
-    }
-
-    @Override
-    public Cursor queryRoots(String[] projection) throws FileNotFoundException {
-        final MatrixCursor result = new MatrixCursor(resolveRootProjection(projection));
-
-        RowBuilder row = result.newRow();
-        row.add(Root.COLUMN_ROOT_ID, "local");
-        row.add(Root.COLUMN_FLAGS, Root.FLAG_LOCAL_ONLY);
-        row.add(Root.COLUMN_TITLE, "TEST-Local");
-        row.add(Root.COLUMN_SUMMARY, "TEST-LocalSummary");
-        row.add(Root.COLUMN_DOCUMENT_ID, "doc:local");
-
-        row = result.newRow();
-        row.add(Root.COLUMN_ROOT_ID, "create");
-        row.add(Root.COLUMN_FLAGS, Root.FLAG_SUPPORTS_CREATE | Root.FLAG_SUPPORTS_IS_CHILD);
-        row.add(Root.COLUMN_TITLE, "TEST-Create");
-        row.add(Root.COLUMN_DOCUMENT_ID, "doc:create");
-
-        return result;
-    }
-
-    private Map<String, Doc> mDocs = new HashMap<>();
-
-    private Doc mLocalRoot;
-    private Doc mCreateRoot;
-
-    private Doc buildDoc(String docId, String displayName, String mimeType) {
-        final Doc doc = new Doc();
-        doc.docId = docId;
-        doc.displayName = displayName;
-        doc.mimeType = mimeType;
-        mDocs.put(doc.docId, doc);
-        return doc;
-    }
-
-    public void resetRoots() {
-        Log.d(TAG, "resetRoots()");
-
-        mDocs.clear();
-
-        mLocalRoot = buildDoc("doc:local", null, Document.MIME_TYPE_DIR);
-
-        mCreateRoot = buildDoc("doc:create", null, Document.MIME_TYPE_DIR);
-        mCreateRoot.flags = Document.FLAG_DIR_SUPPORTS_CREATE;
-
-        {
-            Doc file1 = buildDoc("doc:file1", "FILE1", "mime1/file1");
-            file1.contents = "fileone".getBytes();
-            file1.flags = Document.FLAG_SUPPORTS_WRITE;
-            mLocalRoot.children.add(file1);
-            mCreateRoot.children.add(file1);
-        }
-
-        {
-            Doc file2 = buildDoc("doc:file2", "FILE2", "mime2/file2");
-            file2.contents = "filetwo".getBytes();
-            file2.flags = Document.FLAG_SUPPORTS_WRITE;
-            mLocalRoot.children.add(file2);
-            mCreateRoot.children.add(file2);
-        }
-
-        Doc dir1 = buildDoc("doc:dir1", "DIR1", Document.MIME_TYPE_DIR);
-        mLocalRoot.children.add(dir1);
-
-        {
-            Doc file3 = buildDoc("doc:file3", "FILE3", "mime3/file3");
-            file3.contents = "filethree".getBytes();
-            file3.flags = Document.FLAG_SUPPORTS_WRITE;
-            dir1.children.add(file3);
-        }
-
-        Doc dir2 = buildDoc("doc:dir2", "DIR2", Document.MIME_TYPE_DIR);
-        mCreateRoot.children.add(dir2);
-
-        {
-            Doc file4 = buildDoc("doc:file4", "FILE4", "mime4/file4");
-            file4.contents = "filefour".getBytes();
-            file4.flags = Document.FLAG_SUPPORTS_WRITE;
-            dir2.children.add(file4);
-        }
-    }
-
-    private static class Doc {
-        public String docId;
-        public int flags;
-        public String displayName;
-        public long size;
-        public String mimeType;
-        public long lastModified;
-        public byte[] contents;
-        public List<Doc> children = new ArrayList<>();
-
-        public void include(MatrixCursor result) {
-            final RowBuilder row = result.newRow();
-            row.add(Document.COLUMN_DOCUMENT_ID, docId);
-            row.add(Document.COLUMN_DISPLAY_NAME, displayName);
-            row.add(Document.COLUMN_SIZE, size);
-            row.add(Document.COLUMN_MIME_TYPE, mimeType);
-            row.add(Document.COLUMN_FLAGS, flags);
-            row.add(Document.COLUMN_LAST_MODIFIED, lastModified);
-        }
-    }
-
-    @Override
-    public boolean isChildDocument(String parentDocumentId, String documentId) {
-        for (Doc doc : mDocs.get(parentDocumentId).children) {
-            if (doc.docId.equals(documentId)) {
-                return true;
-            }
-            if (Document.MIME_TYPE_DIR.equals(doc.mimeType)) {
-                return isChildDocument(doc.docId, documentId);
-            }
-        }
-        return false;
-    }
-
-    @Override
-    public String createDocument(String parentDocumentId, String mimeType, String displayName)
-            throws FileNotFoundException {
-        final String docId = "doc:" + System.currentTimeMillis();
-        final Doc doc = buildDoc(docId, displayName, mimeType);
-        doc.flags = Document.FLAG_SUPPORTS_WRITE | Document.FLAG_SUPPORTS_RENAME;
-        mDocs.get(parentDocumentId).children.add(doc);
-        return docId;
-    }
-
-    @Override
-    public String renameDocument(String documentId, String displayName)
-            throws FileNotFoundException {
-        mDocs.get(documentId).displayName = displayName;
-        return null;
-    }
-
-    @Override
-    public void deleteDocument(String documentId) throws FileNotFoundException {
-        mDocs.remove(documentId);
-        for (Doc doc : mDocs.values()) {
-            doc.children.remove(documentId);
-        }
-    }
-
-    @Override
-    public Cursor queryDocument(String documentId, String[] projection)
-            throws FileNotFoundException {
-        final MatrixCursor result = new MatrixCursor(resolveDocumentProjection(projection));
-        mDocs.get(documentId).include(result);
-        return result;
-    }
-
-    @Override
-    public Cursor queryChildDocuments(String parentDocumentId, String[] projection,
-            String sortOrder) throws FileNotFoundException {
-        final MatrixCursor result = new MatrixCursor(resolveDocumentProjection(projection));
-        for (Doc doc : mDocs.get(parentDocumentId).children) {
-            doc.include(result);
-        }
-        return result;
-    }
-
-    @Override
-    public ParcelFileDescriptor openDocument(String documentId, String mode,
-            CancellationSignal signal) throws FileNotFoundException {
-        final Doc doc = mDocs.get(documentId);
-        if (doc == null) {
-            throw new FileNotFoundException();
-        }
-        final ParcelFileDescriptor[] pipe;
-        try {
-            pipe = ParcelFileDescriptor.createPipe();
-        } catch (IOException e) {
-            throw new IllegalStateException(e);
-        }
-        if (mode.contains("w")) {
-            new AsyncTask<Void, Void, Void>() {
-                @Override
-                protected Void doInBackground(Void... params) {
-                    synchronized (doc) {
-                        try {
-                            final InputStream is = new ParcelFileDescriptor.AutoCloseInputStream(
-                                    pipe[0]);
-                            doc.contents = readFullyNoClose(is);
-                            is.close();
-                            doc.notifyAll();
-                        } catch (IOException e) {
-                            Log.w(TAG, "Failed to stream", e);
-                        }
-                    }
-                    return null;
-                }
-            }.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);
-            return pipe[1];
-        } else {
-            new AsyncTask<Void, Void, Void>() {
-                @Override
-                protected Void doInBackground(Void... params) {
-                    synchronized (doc) {
-                        try {
-                            final OutputStream os = new ParcelFileDescriptor.AutoCloseOutputStream(
-                                    pipe[1]);
-                            while (doc.contents == null) {
-                                doc.wait();
-                            }
-                            os.write(doc.contents);
-                            os.close();
-                        } catch (IOException e) {
-                            Log.w(TAG, "Failed to stream", e);
-                        } catch (InterruptedException e) {
-                            Log.w(TAG, "Interuppted", e);
-                        }
-                    }
-                    return null;
-                }
-            }.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);
-            return pipe[0];
-        }
-    }
-
-    private static byte[] readFullyNoClose(InputStream in) throws IOException {
-        ByteArrayOutputStream bytes = new ByteArrayOutputStream();
-        byte[] buffer = new byte[1024];
-        int count;
-        while ((count = in.read(buffer)) != -1) {
-            bytes.write(buffer, 0, count);
-        }
-        return bytes.toByteArray();
-    }
-}
diff --git a/packages/DocumentsUI/tests/Android.mk b/packages/DocumentsUI/tests/Android.mk
index cf486b1..2a540d4 100644
--- a/packages/DocumentsUI/tests/Android.mk
+++ b/packages/DocumentsUI/tests/Android.mk
@@ -17,4 +17,3 @@
 
 include $(BUILD_PACKAGE)
 
-include $(LOCAL_PATH)/../testing/TestDocumentsProvider/Android.mk
diff --git a/packages/InputDevices/res/values-am/strings.xml b/packages/InputDevices/res/values-am/strings.xml
index efabbbf..3186add 100644
--- a/packages/InputDevices/res/values-am/strings.xml
+++ b/packages/InputDevices/res/values-am/strings.xml
@@ -8,8 +8,7 @@
     <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"እንግሊዘኛ (ዩ. ኤስ.)፣ አለም አቀፍ ቅጥ"</string>
     <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"እንግሊዘኛ (ዩ. ኤስ.)፣ የኮልማርክ ቅጥ"</string>
     <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"እንግሊዘኛ (ዩ. ኤስ.)፣ የድቮራክ ቅጥ"</string>
-    <!-- no translation found for keyboard_layout_english_us_workman_label (2944541595262173111) -->
-    <skip />
+    <string name="keyboard_layout_english_us_workman_label" msgid="2944541595262173111">"እንግሊዝኛ (አሜሪካ)፣ የሥራሰው ቅጥ"</string>
     <string name="keyboard_layout_german_label" msgid="8451565865467909999">"ጀርመን"</string>
     <string name="keyboard_layout_french_label" msgid="813450119589383723">"ፈረንሳይኛ"</string>
     <string name="keyboard_layout_french_ca_label" msgid="365352601060604832">"ፈረንሳይኛ (ካናዳ)"</string>
diff --git a/packages/InputDevices/res/values-bn-rBD/strings.xml b/packages/InputDevices/res/values-bn-rBD/strings.xml
index bfbf3d3..a0ce313 100644
--- a/packages/InputDevices/res/values-bn-rBD/strings.xml
+++ b/packages/InputDevices/res/values-bn-rBD/strings.xml
@@ -8,8 +8,7 @@
     <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"ইংরেজি (US), আন্তর্জাতিক শৈলী"</string>
     <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"ইংরেজি (US), কোলেম্যাক শৈলী"</string>
     <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"ইংরেজি (US), ডিভোরাক শৈলী"</string>
-    <!-- no translation found for keyboard_layout_english_us_workman_label (2944541595262173111) -->
-    <skip />
+    <string name="keyboard_layout_english_us_workman_label" msgid="2944541595262173111">"ইংরেজি (US), ওয়ার্কম্যান শৈলী"</string>
     <string name="keyboard_layout_german_label" msgid="8451565865467909999">"জার্মান"</string>
     <string name="keyboard_layout_french_label" msgid="813450119589383723">"ফরাসী"</string>
     <string name="keyboard_layout_french_ca_label" msgid="365352601060604832">"ফরাসী (কানাডা)"</string>
diff --git a/packages/InputDevices/res/values-cs/strings.xml b/packages/InputDevices/res/values-cs/strings.xml
index 614ba56..3e7b9c8 100644
--- a/packages/InputDevices/res/values-cs/strings.xml
+++ b/packages/InputDevices/res/values-cs/strings.xml
@@ -8,8 +8,7 @@
     <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"anglické (USA), mezinárodní"</string>
     <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"anglické (USA), styl Colemak"</string>
     <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"anglické (USA), styl Dvorak"</string>
-    <!-- no translation found for keyboard_layout_english_us_workman_label (2944541595262173111) -->
-    <skip />
+    <string name="keyboard_layout_english_us_workman_label" msgid="2944541595262173111">"anglické (USA), styl Workman"</string>
     <string name="keyboard_layout_german_label" msgid="8451565865467909999">"německé"</string>
     <string name="keyboard_layout_french_label" msgid="813450119589383723">"francouzské"</string>
     <string name="keyboard_layout_french_ca_label" msgid="365352601060604832">"francouzské (Kanada)"</string>
diff --git a/packages/InputDevices/res/values-de/strings.xml b/packages/InputDevices/res/values-de/strings.xml
index ce25623..6af0030 100644
--- a/packages/InputDevices/res/values-de/strings.xml
+++ b/packages/InputDevices/res/values-de/strings.xml
@@ -8,8 +8,7 @@
     <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"Englisch (USA), international"</string>
     <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"Englisch (USA), Colemak"</string>
     <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"Englisch (USA), Dvorak"</string>
-    <!-- no translation found for keyboard_layout_english_us_workman_label (2944541595262173111) -->
-    <skip />
+    <string name="keyboard_layout_english_us_workman_label" msgid="2944541595262173111">"Englisch (USA), Workman"</string>
     <string name="keyboard_layout_german_label" msgid="8451565865467909999">"Deutsch"</string>
     <string name="keyboard_layout_french_label" msgid="813450119589383723">"Französisch"</string>
     <string name="keyboard_layout_french_ca_label" msgid="365352601060604832">"Französisch (Kanada)"</string>
diff --git a/packages/InputDevices/res/values-el/strings.xml b/packages/InputDevices/res/values-el/strings.xml
index 0a99dbb..da6dca2 100644
--- a/packages/InputDevices/res/values-el/strings.xml
+++ b/packages/InputDevices/res/values-el/strings.xml
@@ -8,8 +8,7 @@
     <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"Αγγλικά (ΗΠΑ), τύπου International"</string>
     <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"Αγγλικά (ΗΠΑ), τύπου Colemak"</string>
     <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"Αγγλικά (ΗΠΑ), τύπου Dvorak"</string>
-    <!-- no translation found for keyboard_layout_english_us_workman_label (2944541595262173111) -->
-    <skip />
+    <string name="keyboard_layout_english_us_workman_label" msgid="2944541595262173111">"Αγγλικά (ΗΠΑ), στυλ Workman"</string>
     <string name="keyboard_layout_german_label" msgid="8451565865467909999">"Γερμανικά"</string>
     <string name="keyboard_layout_french_label" msgid="813450119589383723">"Γαλλικά"</string>
     <string name="keyboard_layout_french_ca_label" msgid="365352601060604832">"Γαλλικά (Καναδά)"</string>
diff --git a/packages/InputDevices/res/values-es-rUS/strings.xml b/packages/InputDevices/res/values-es-rUS/strings.xml
index 20d677b..6acf07b 100644
--- a/packages/InputDevices/res/values-es-rUS/strings.xml
+++ b/packages/InputDevices/res/values-es-rUS/strings.xml
@@ -8,8 +8,7 @@
     <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"Inglés (EE. UU.), internacional"</string>
     <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"Inglés (EE. UU.), Colemak"</string>
     <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"Inglés (EE. UU.), Dvorak"</string>
-    <!-- no translation found for keyboard_layout_english_us_workman_label (2944541595262173111) -->
-    <skip />
+    <string name="keyboard_layout_english_us_workman_label" msgid="2944541595262173111">"Inglés (EE. UU.), Workman"</string>
     <string name="keyboard_layout_german_label" msgid="8451565865467909999">"Alemán"</string>
     <string name="keyboard_layout_french_label" msgid="813450119589383723">"Francés"</string>
     <string name="keyboard_layout_french_ca_label" msgid="365352601060604832">"Francés (Canadá)"</string>
diff --git a/packages/InputDevices/res/values-fa/strings.xml b/packages/InputDevices/res/values-fa/strings.xml
index a05d071..f2848a9 100644
--- a/packages/InputDevices/res/values-fa/strings.xml
+++ b/packages/InputDevices/res/values-fa/strings.xml
@@ -8,8 +8,7 @@
     <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"انگلیسی (ایالات متحده)، سبک بین‌المللی"</string>
     <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"‏انگلیسی (ایالات متحده)، سبک Colemak"</string>
     <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"‏انگلیسی (ایالات متحده)، سبک Dvorak"</string>
-    <!-- no translation found for keyboard_layout_english_us_workman_label (2944541595262173111) -->
-    <skip />
+    <string name="keyboard_layout_english_us_workman_label" msgid="2944541595262173111">"انگلیسی (ایالات متحده)، سبک ورک‌من"</string>
     <string name="keyboard_layout_german_label" msgid="8451565865467909999">"آلمانی"</string>
     <string name="keyboard_layout_french_label" msgid="813450119589383723">"فرانسوی"</string>
     <string name="keyboard_layout_french_ca_label" msgid="365352601060604832">"فرانسوی (کانادا)‏"</string>
diff --git a/packages/InputDevices/res/values-fi/strings.xml b/packages/InputDevices/res/values-fi/strings.xml
index 250333c..284efc8 100644
--- a/packages/InputDevices/res/values-fi/strings.xml
+++ b/packages/InputDevices/res/values-fi/strings.xml
@@ -8,8 +8,7 @@
     <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"englanti (Yhdysvallat), kansainvälinen"</string>
     <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"englanti (Yhdysvallat), Colemak"</string>
     <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"englanti (Yhdysvallat), Dvorak"</string>
-    <!-- no translation found for keyboard_layout_english_us_workman_label (2944541595262173111) -->
-    <skip />
+    <string name="keyboard_layout_english_us_workman_label" msgid="2944541595262173111">"englanti (Yhdysvallat), Workman"</string>
     <string name="keyboard_layout_german_label" msgid="8451565865467909999">"saksa"</string>
     <string name="keyboard_layout_french_label" msgid="813450119589383723">"ranska"</string>
     <string name="keyboard_layout_french_ca_label" msgid="365352601060604832">"ranska (Kanada)"</string>
diff --git a/packages/InputDevices/res/values-fr-rCA/strings.xml b/packages/InputDevices/res/values-fr-rCA/strings.xml
index 3842584..b26a0ea 100644
--- a/packages/InputDevices/res/values-fr-rCA/strings.xml
+++ b/packages/InputDevices/res/values-fr-rCA/strings.xml
@@ -8,8 +8,7 @@
     <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"Anglais (États-Unis), international"</string>
     <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"Anglais (États-Unis), type Colemak"</string>
     <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"Anglais (États-Unis), type Dvorak"</string>
-    <!-- no translation found for keyboard_layout_english_us_workman_label (2944541595262173111) -->
-    <skip />
+    <string name="keyboard_layout_english_us_workman_label" msgid="2944541595262173111">"Anglais (États-Unis), style Workman"</string>
     <string name="keyboard_layout_german_label" msgid="8451565865467909999">"Allemand"</string>
     <string name="keyboard_layout_french_label" msgid="813450119589383723">"Français"</string>
     <string name="keyboard_layout_french_ca_label" msgid="365352601060604832">"Français (Canada)"</string>
diff --git a/packages/InputDevices/res/values-fr/strings.xml b/packages/InputDevices/res/values-fr/strings.xml
index 679dba9..a428a23 100644
--- a/packages/InputDevices/res/values-fr/strings.xml
+++ b/packages/InputDevices/res/values-fr/strings.xml
@@ -8,8 +8,7 @@
     <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"Anglais (États-Unis), international"</string>
     <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"Anglais (États-Unis), type Colemak"</string>
     <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"Anglais (États-Unis), type Dvorak"</string>
-    <!-- no translation found for keyboard_layout_english_us_workman_label (2944541595262173111) -->
-    <skip />
+    <string name="keyboard_layout_english_us_workman_label" msgid="2944541595262173111">"Anglais (États-Unis), style Workman"</string>
     <string name="keyboard_layout_german_label" msgid="8451565865467909999">"Allemand"</string>
     <string name="keyboard_layout_french_label" msgid="813450119589383723">"Français"</string>
     <string name="keyboard_layout_french_ca_label" msgid="365352601060604832">"Français (Canada)"</string>
diff --git a/packages/InputDevices/res/values-gl-rES/strings.xml b/packages/InputDevices/res/values-gl-rES/strings.xml
index ab76a14..bb0f2a0 100644
--- a/packages/InputDevices/res/values-gl-rES/strings.xml
+++ b/packages/InputDevices/res/values-gl-rES/strings.xml
@@ -8,8 +8,7 @@
     <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"Inglés (EUA), estilo internacional"</string>
     <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"Inglés (EUA), estilo Colemak"</string>
     <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"Inglés (EUA), estilo Dvorak"</string>
-    <!-- no translation found for keyboard_layout_english_us_workman_label (2944541595262173111) -->
-    <skip />
+    <string name="keyboard_layout_english_us_workman_label" msgid="2944541595262173111">"Inglés (EUA), estilo Workman"</string>
     <string name="keyboard_layout_german_label" msgid="8451565865467909999">"Alemán"</string>
     <string name="keyboard_layout_french_label" msgid="813450119589383723">"Francés"</string>
     <string name="keyboard_layout_french_ca_label" msgid="365352601060604832">"Francés (Canadá)"</string>
diff --git a/packages/InputDevices/res/values-gu-rIN/strings.xml b/packages/InputDevices/res/values-gu-rIN/strings.xml
index 63c3874..e83b0ca 100644
--- a/packages/InputDevices/res/values-gu-rIN/strings.xml
+++ b/packages/InputDevices/res/values-gu-rIN/strings.xml
@@ -8,8 +8,7 @@
     <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"અંગ્રેજી (યુએસ), આંતરરાષ્ટ્રીય શૈલી"</string>
     <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"અંગ્રેજી (યુએસ), કોલેમેક શૈલી"</string>
     <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"અંગ્રેજી (યુએસ), ડ્વોરક શૈલી"</string>
-    <!-- no translation found for keyboard_layout_english_us_workman_label (2944541595262173111) -->
-    <skip />
+    <string name="keyboard_layout_english_us_workman_label" msgid="2944541595262173111">"અંગ્રેજી (યુએસ), વર્કમૅન શૈલી"</string>
     <string name="keyboard_layout_german_label" msgid="8451565865467909999">"જર્મન"</string>
     <string name="keyboard_layout_french_label" msgid="813450119589383723">"ફ્રેન્ચ"</string>
     <string name="keyboard_layout_french_ca_label" msgid="365352601060604832">"ફ્રેન્ચ (કેનેડા)"</string>
diff --git a/packages/InputDevices/res/values-hr/strings.xml b/packages/InputDevices/res/values-hr/strings.xml
index 829f817..27066ad 100644
--- a/packages/InputDevices/res/values-hr/strings.xml
+++ b/packages/InputDevices/res/values-hr/strings.xml
@@ -8,8 +8,7 @@
     <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"engleska (SAD), međunarodna"</string>
     <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"engleska (SAD), Colemakov raspored"</string>
     <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"engleska (SAD), Dvorakov raspored"</string>
-    <!-- no translation found for keyboard_layout_english_us_workman_label (2944541595262173111) -->
-    <skip />
+    <string name="keyboard_layout_english_us_workman_label" msgid="2944541595262173111">"Engleska (SAD), raspored Workman"</string>
     <string name="keyboard_layout_german_label" msgid="8451565865467909999">"njemačka"</string>
     <string name="keyboard_layout_french_label" msgid="813450119589383723">"francuska"</string>
     <string name="keyboard_layout_french_ca_label" msgid="365352601060604832">"francuska (Kanada)"</string>
diff --git a/packages/InputDevices/res/values-hy-rAM/strings.xml b/packages/InputDevices/res/values-hy-rAM/strings.xml
index f47aba2..0d11645 100644
--- a/packages/InputDevices/res/values-hy-rAM/strings.xml
+++ b/packages/InputDevices/res/values-hy-rAM/strings.xml
@@ -8,8 +8,7 @@
     <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"Անգլերեն (ԱՄՆ), միջազգային տեսակ"</string>
     <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"Անգլերեն (ԱՄՆ), Colemak տեսակ"</string>
     <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"Անգլերեն (ԱՄՆ), Dvorak տեսակ"</string>
-    <!-- no translation found for keyboard_layout_english_us_workman_label (2944541595262173111) -->
-    <skip />
+    <string name="keyboard_layout_english_us_workman_label" msgid="2944541595262173111">"Անգլերեն (ԱՄՆ), Workman տեսակ"</string>
     <string name="keyboard_layout_german_label" msgid="8451565865467909999">"Գերմաներեն"</string>
     <string name="keyboard_layout_french_label" msgid="813450119589383723">"Ֆրանսերեն"</string>
     <string name="keyboard_layout_french_ca_label" msgid="365352601060604832">"Ֆրանսերեն (Կանադա)"</string>
diff --git a/packages/InputDevices/res/values-is-rIS/strings.xml b/packages/InputDevices/res/values-is-rIS/strings.xml
index 35a5a17..de91275 100644
--- a/packages/InputDevices/res/values-is-rIS/strings.xml
+++ b/packages/InputDevices/res/values-is-rIS/strings.xml
@@ -8,8 +8,7 @@
     <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"Enskt (Bandaríkin), alþjóðlegt"</string>
     <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"Enskt (Bandaríkin), Colemak-stíll"</string>
     <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"Enskt (Bandaríkin), Dvorak-stíll"</string>
-    <!-- no translation found for keyboard_layout_english_us_workman_label (2944541595262173111) -->
-    <skip />
+    <string name="keyboard_layout_english_us_workman_label" msgid="2944541595262173111">"Enska (Bandaríkin), Workman-stíll"</string>
     <string name="keyboard_layout_german_label" msgid="8451565865467909999">"Þýskt"</string>
     <string name="keyboard_layout_french_label" msgid="813450119589383723">"Franskt"</string>
     <string name="keyboard_layout_french_ca_label" msgid="365352601060604832">"Franskt (Kanada)"</string>
diff --git a/packages/InputDevices/res/values-iw/strings.xml b/packages/InputDevices/res/values-iw/strings.xml
index 0c8b4e9..b3bd576 100644
--- a/packages/InputDevices/res/values-iw/strings.xml
+++ b/packages/InputDevices/res/values-iw/strings.xml
@@ -8,8 +8,7 @@
     <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"אנגלית (ארה\"ב), סגנון בינ\"ל"</string>
     <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"‏אנגלית (ארה\"ב), סגנון Colemak"</string>
     <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"‏אנגלית (ארה\"ב), סגנון Dvorak"</string>
-    <!-- no translation found for keyboard_layout_english_us_workman_label (2944541595262173111) -->
-    <skip />
+    <string name="keyboard_layout_english_us_workman_label" msgid="2944541595262173111">"‏אנגלית (ארה\"ב), סגנון Workman"</string>
     <string name="keyboard_layout_german_label" msgid="8451565865467909999">"גרמנית"</string>
     <string name="keyboard_layout_french_label" msgid="813450119589383723">"צרפתית"</string>
     <string name="keyboard_layout_french_ca_label" msgid="365352601060604832">"צרפתית (קנדה)"</string>
diff --git a/packages/InputDevices/res/values-ja/strings.xml b/packages/InputDevices/res/values-ja/strings.xml
index 7fbddd7..2b3daf5 100644
--- a/packages/InputDevices/res/values-ja/strings.xml
+++ b/packages/InputDevices/res/values-ja/strings.xml
@@ -8,8 +8,7 @@
     <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"英語(アメリカ)、インターナショナル配列"</string>
     <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"英語(アメリカ)、Colemak配列"</string>
     <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"英語(アメリカ)、Dvorak配列"</string>
-    <!-- no translation found for keyboard_layout_english_us_workman_label (2944541595262173111) -->
-    <skip />
+    <string name="keyboard_layout_english_us_workman_label" msgid="2944541595262173111">"英語(アメリカ)、Workman配列"</string>
     <string name="keyboard_layout_german_label" msgid="8451565865467909999">"ドイツ語"</string>
     <string name="keyboard_layout_french_label" msgid="813450119589383723">"フランス語"</string>
     <string name="keyboard_layout_french_ca_label" msgid="365352601060604832">"フランス語(カナダ)"</string>
diff --git a/packages/InputDevices/res/values-ka-rGE/strings.xml b/packages/InputDevices/res/values-ka-rGE/strings.xml
index 56bd3e3..66d147e 100644
--- a/packages/InputDevices/res/values-ka-rGE/strings.xml
+++ b/packages/InputDevices/res/values-ka-rGE/strings.xml
@@ -8,8 +8,7 @@
     <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"ინგლისური (აშშ), საერთაშორისო სტილი"</string>
     <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"ინგლისური (აშშ), Colemak სტილი"</string>
     <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"ინგლისური (აშშ), Dvorak სტილი"</string>
-    <!-- no translation found for keyboard_layout_english_us_workman_label (2944541595262173111) -->
-    <skip />
+    <string name="keyboard_layout_english_us_workman_label" msgid="2944541595262173111">"ინგლისური (აშშ), Workman სტილი"</string>
     <string name="keyboard_layout_german_label" msgid="8451565865467909999">"გერმანული"</string>
     <string name="keyboard_layout_french_label" msgid="813450119589383723">"ფრანგული"</string>
     <string name="keyboard_layout_french_ca_label" msgid="365352601060604832">"ფრანგული (კანადა)"</string>
diff --git a/packages/InputDevices/res/values-kk-rKZ/strings.xml b/packages/InputDevices/res/values-kk-rKZ/strings.xml
index df2da88..d253542 100644
--- a/packages/InputDevices/res/values-kk-rKZ/strings.xml
+++ b/packages/InputDevices/res/values-kk-rKZ/strings.xml
@@ -8,8 +8,7 @@
     <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"Ағылшын (АҚШ), Халықаралық стилі"</string>
     <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"Ағылшын (АҚШ), Colemak стилі"</string>
     <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"Ағылшын (АҚШ), Dvorak стилі"</string>
-    <!-- no translation found for keyboard_layout_english_us_workman_label (2944541595262173111) -->
-    <skip />
+    <string name="keyboard_layout_english_us_workman_label" msgid="2944541595262173111">"Ағылшын (АҚШ), Workman стилі"</string>
     <string name="keyboard_layout_german_label" msgid="8451565865467909999">"Неміс"</string>
     <string name="keyboard_layout_french_label" msgid="813450119589383723">"Француз"</string>
     <string name="keyboard_layout_french_ca_label" msgid="365352601060604832">"Француз (Канада)"</string>
diff --git a/packages/InputDevices/res/values-kn-rIN/strings.xml b/packages/InputDevices/res/values-kn-rIN/strings.xml
index f88076c..243e6597 100644
--- a/packages/InputDevices/res/values-kn-rIN/strings.xml
+++ b/packages/InputDevices/res/values-kn-rIN/strings.xml
@@ -8,8 +8,7 @@
     <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"ಇಂಗ್ಲಿಷ್ (US), ಅಂತರರಾಷ್ಟ್ರೀಯ ಶೈಲಿ"</string>
     <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"ಇಂಗ್ಲಿಷ್ (US), ಕೋಲ್ಮಾರ್ಕ್ ಶೈಲಿ"</string>
     <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"ಇಂಗ್ಲಿಷ್ (US), ಡಿವೊರಾಕ್ ಶೈಲಿ"</string>
-    <!-- no translation found for keyboard_layout_english_us_workman_label (2944541595262173111) -->
-    <skip />
+    <string name="keyboard_layout_english_us_workman_label" msgid="2944541595262173111">"ಇಂಗ್ಲೀಷ್ (US), ವರ್ಕ್‌ಮನ್ ಶೈಲಿ"</string>
     <string name="keyboard_layout_german_label" msgid="8451565865467909999">"ಜರ್ಮನ್"</string>
     <string name="keyboard_layout_french_label" msgid="813450119589383723">"ಫ್ರೆಂಚ್"</string>
     <string name="keyboard_layout_french_ca_label" msgid="365352601060604832">"ಫ್ರೆಂಚ್‌ (ಕೆನಡಾ)"</string>
diff --git a/packages/InputDevices/res/values-ko/strings.xml b/packages/InputDevices/res/values-ko/strings.xml
index d215375..7758210 100644
--- a/packages/InputDevices/res/values-ko/strings.xml
+++ b/packages/InputDevices/res/values-ko/strings.xml
@@ -8,8 +8,7 @@
     <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"영어(미국), 글로벌 스타일"</string>
     <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"영어(미국), 콜맥 스타일"</string>
     <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"영어(미국), 드보락 스타일"</string>
-    <!-- no translation found for keyboard_layout_english_us_workman_label (2944541595262173111) -->
-    <skip />
+    <string name="keyboard_layout_english_us_workman_label" msgid="2944541595262173111">"영어(미국), 워크맨 스타일"</string>
     <string name="keyboard_layout_german_label" msgid="8451565865467909999">"독일어"</string>
     <string name="keyboard_layout_french_label" msgid="813450119589383723">"프랑스어"</string>
     <string name="keyboard_layout_french_ca_label" msgid="365352601060604832">"프랑스어(캐나다)"</string>
diff --git a/packages/InputDevices/res/values-ky-rKG/strings.xml b/packages/InputDevices/res/values-ky-rKG/strings.xml
index ee9cc5a..aa74733 100644
--- a/packages/InputDevices/res/values-ky-rKG/strings.xml
+++ b/packages/InputDevices/res/values-ky-rKG/strings.xml
@@ -8,8 +8,7 @@
     <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"Англис (АКШ), эл аралык"</string>
     <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"Англис (АКШ), Colemak стили"</string>
     <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"Англис (АКШ), Dvorak стили"</string>
-    <!-- no translation found for keyboard_layout_english_us_workman_label (2944541595262173111) -->
-    <skip />
+    <string name="keyboard_layout_english_us_workman_label" msgid="2944541595262173111">"Англисче (АКШ), Workman стили"</string>
     <string name="keyboard_layout_german_label" msgid="8451565865467909999">"Немис"</string>
     <string name="keyboard_layout_french_label" msgid="813450119589383723">"Француз"</string>
     <string name="keyboard_layout_french_ca_label" msgid="365352601060604832">"Француз (Канада)"</string>
diff --git a/packages/InputDevices/res/values-lo-rLA/strings.xml b/packages/InputDevices/res/values-lo-rLA/strings.xml
index 33c9f61..05b1b83 100644
--- a/packages/InputDevices/res/values-lo-rLA/strings.xml
+++ b/packages/InputDevices/res/values-lo-rLA/strings.xml
@@ -8,8 +8,7 @@
     <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"ອັງກິດ (ສະຫະລັດຯ), ແບບສາກົນ"</string>
     <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"ອັງກິດ (ສະຫະລັດຯ), ແບບ Colemak"</string>
     <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"ອັງກິດ (ສະຫະລັດຯ), ແບບ Dvorak"</string>
-    <!-- no translation found for keyboard_layout_english_us_workman_label (2944541595262173111) -->
-    <skip />
+    <string name="keyboard_layout_english_us_workman_label" msgid="2944541595262173111">"ອັງກິດ (ສະຫະລັດ), ແບບຄົນ​ເຮັດ​ວຽກ"</string>
     <string name="keyboard_layout_german_label" msgid="8451565865467909999">"ເຢຍລະມັນ"</string>
     <string name="keyboard_layout_french_label" msgid="813450119589383723">"ຝຣັ່ງ"</string>
     <string name="keyboard_layout_french_ca_label" msgid="365352601060604832">"ຝຣັ່ງ (ຄານາດາ)"</string>
diff --git a/packages/InputDevices/res/values-ml-rIN/strings.xml b/packages/InputDevices/res/values-ml-rIN/strings.xml
index b42bdb7..0faa40e 100644
--- a/packages/InputDevices/res/values-ml-rIN/strings.xml
+++ b/packages/InputDevices/res/values-ml-rIN/strings.xml
@@ -8,8 +8,7 @@
     <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"ഇംഗ്ലീഷ് (യു.എസ്), അന്തർദ്ദേശീയ ശൈലി"</string>
     <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"ഇംഗ്ലീഷ് (യു.എസ്), കോൽമാക് ശൈലി"</string>
     <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"ഇംഗ്ലീഷ് (യു.എസ്), ദ്വരോക്ക് ശൈലി"</string>
-    <!-- no translation found for keyboard_layout_english_us_workman_label (2944541595262173111) -->
-    <skip />
+    <string name="keyboard_layout_english_us_workman_label" msgid="2944541595262173111">"ഇംഗ്ലീഷ് (യുഎസ്), വർക്ക്‌മാൻ ശൈലി"</string>
     <string name="keyboard_layout_german_label" msgid="8451565865467909999">"ജര്‍‌മ്മന്‍‌"</string>
     <string name="keyboard_layout_french_label" msgid="813450119589383723">"ഫ്രഞ്ച്"</string>
     <string name="keyboard_layout_french_ca_label" msgid="365352601060604832">"ഫ്രഞ്ച് (കാനഡ)"</string>
diff --git a/packages/InputDevices/res/values-nb/strings.xml b/packages/InputDevices/res/values-nb/strings.xml
index 378cdc1..37604e3 100644
--- a/packages/InputDevices/res/values-nb/strings.xml
+++ b/packages/InputDevices/res/values-nb/strings.xml
@@ -8,8 +8,7 @@
     <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"Engelsk (USA), internasjonal stil"</string>
     <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"Engelsk (USA), Colemak-stil"</string>
     <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"Engelsk (USA), Dvorak-stil"</string>
-    <!-- no translation found for keyboard_layout_english_us_workman_label (2944541595262173111) -->
-    <skip />
+    <string name="keyboard_layout_english_us_workman_label" msgid="2944541595262173111">"Engelsk (USA), workman-stil"</string>
     <string name="keyboard_layout_german_label" msgid="8451565865467909999">"Tysk"</string>
     <string name="keyboard_layout_french_label" msgid="813450119589383723">"Fransk"</string>
     <string name="keyboard_layout_french_ca_label" msgid="365352601060604832">"Fransk (Canada)"</string>
diff --git a/packages/InputDevices/res/values-ne-rNP/strings.xml b/packages/InputDevices/res/values-ne-rNP/strings.xml
index 571d717..4c3dec3 100644
--- a/packages/InputDevices/res/values-ne-rNP/strings.xml
+++ b/packages/InputDevices/res/values-ne-rNP/strings.xml
@@ -8,8 +8,7 @@
     <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"अङ्ग्रेजी (अमेरिकी), अन्तर्राष्ट्रिय शैली"</string>
     <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"अङ्ग्रेजी (अमेरिकी), कोलमाक शैली"</string>
     <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"अङ्ग्रेजी (अमेरिकी), डेभोर्याक शैली"</string>
-    <!-- no translation found for keyboard_layout_english_us_workman_label (2944541595262173111) -->
-    <skip />
+    <string name="keyboard_layout_english_us_workman_label" msgid="2944541595262173111">"अंग्रेजी (अमेरिका), वर्कम्यान शैली"</string>
     <string name="keyboard_layout_german_label" msgid="8451565865467909999">"जर्मन"</string>
     <string name="keyboard_layout_french_label" msgid="813450119589383723">"फ्रान्सेली"</string>
     <string name="keyboard_layout_french_ca_label" msgid="365352601060604832">"फ्रेंच (क्यानाडा)"</string>
diff --git a/packages/InputDevices/res/values-pl/strings.xml b/packages/InputDevices/res/values-pl/strings.xml
index 7175705..2ae815e32 100644
--- a/packages/InputDevices/res/values-pl/strings.xml
+++ b/packages/InputDevices/res/values-pl/strings.xml
@@ -8,8 +8,7 @@
     <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"Angielski (USA), międzynarodowy"</string>
     <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"Angielski (USA), Colemak"</string>
     <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"Angielski (USA), Dvorak"</string>
-    <!-- no translation found for keyboard_layout_english_us_workman_label (2944541595262173111) -->
-    <skip />
+    <string name="keyboard_layout_english_us_workman_label" msgid="2944541595262173111">"Angielski (USA), Workman"</string>
     <string name="keyboard_layout_german_label" msgid="8451565865467909999">"Niemiecki"</string>
     <string name="keyboard_layout_french_label" msgid="813450119589383723">"Francuski"</string>
     <string name="keyboard_layout_french_ca_label" msgid="365352601060604832">"Francuski (Kanada)"</string>
diff --git a/packages/InputDevices/res/values-pt-rBR/strings.xml b/packages/InputDevices/res/values-pt-rBR/strings.xml
index 15c2d37..a1503a4 100644
--- a/packages/InputDevices/res/values-pt-rBR/strings.xml
+++ b/packages/InputDevices/res/values-pt-rBR/strings.xml
@@ -8,8 +8,7 @@
     <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"Inglês (EUA), estilo internacional"</string>
     <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"Inglês (EUA), estilo Colemak"</string>
     <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"Inglês (EUA), estilo Dvorak"</string>
-    <!-- no translation found for keyboard_layout_english_us_workman_label (2944541595262173111) -->
-    <skip />
+    <string name="keyboard_layout_english_us_workman_label" msgid="2944541595262173111">"Inglês (EUA), estilo Workman"</string>
     <string name="keyboard_layout_german_label" msgid="8451565865467909999">"Alemão"</string>
     <string name="keyboard_layout_french_label" msgid="813450119589383723">"Francês"</string>
     <string name="keyboard_layout_french_ca_label" msgid="365352601060604832">"Francês (Canadá)"</string>
diff --git a/packages/InputDevices/res/values-pt/strings.xml b/packages/InputDevices/res/values-pt/strings.xml
index 15c2d37..a1503a4 100644
--- a/packages/InputDevices/res/values-pt/strings.xml
+++ b/packages/InputDevices/res/values-pt/strings.xml
@@ -8,8 +8,7 @@
     <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"Inglês (EUA), estilo internacional"</string>
     <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"Inglês (EUA), estilo Colemak"</string>
     <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"Inglês (EUA), estilo Dvorak"</string>
-    <!-- no translation found for keyboard_layout_english_us_workman_label (2944541595262173111) -->
-    <skip />
+    <string name="keyboard_layout_english_us_workman_label" msgid="2944541595262173111">"Inglês (EUA), estilo Workman"</string>
     <string name="keyboard_layout_german_label" msgid="8451565865467909999">"Alemão"</string>
     <string name="keyboard_layout_french_label" msgid="813450119589383723">"Francês"</string>
     <string name="keyboard_layout_french_ca_label" msgid="365352601060604832">"Francês (Canadá)"</string>
diff --git a/packages/InputDevices/res/values-ro/strings.xml b/packages/InputDevices/res/values-ro/strings.xml
index ccfe568..795e9a2 100644
--- a/packages/InputDevices/res/values-ro/strings.xml
+++ b/packages/InputDevices/res/values-ro/strings.xml
@@ -8,8 +8,7 @@
     <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"Engleză (SUA), stil internațional"</string>
     <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"Engleză (SUA), stil Colemak"</string>
     <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"Engleză (SUA), stil Dvorak"</string>
-    <!-- no translation found for keyboard_layout_english_us_workman_label (2944541595262173111) -->
-    <skip />
+    <string name="keyboard_layout_english_us_workman_label" msgid="2944541595262173111">"Engleză (SUA), stil Workman"</string>
     <string name="keyboard_layout_german_label" msgid="8451565865467909999">"Germană"</string>
     <string name="keyboard_layout_french_label" msgid="813450119589383723">"Franceză"</string>
     <string name="keyboard_layout_french_ca_label" msgid="365352601060604832">"Franceză (Canada)"</string>
diff --git a/packages/InputDevices/res/values-ru/strings.xml b/packages/InputDevices/res/values-ru/strings.xml
index 7d3038e..ac4c81b 100644
--- a/packages/InputDevices/res/values-ru/strings.xml
+++ b/packages/InputDevices/res/values-ru/strings.xml
@@ -8,8 +8,7 @@
     <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"английский (США, международная)"</string>
     <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"английский (США, Colemak)"</string>
     <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"английский (США, Dvorak)"</string>
-    <!-- no translation found for keyboard_layout_english_us_workman_label (2944541595262173111) -->
-    <skip />
+    <string name="keyboard_layout_english_us_workman_label" msgid="2944541595262173111">"английский (США, Workman)"</string>
     <string name="keyboard_layout_german_label" msgid="8451565865467909999">"немецкий"</string>
     <string name="keyboard_layout_french_label" msgid="813450119589383723">"французский"</string>
     <string name="keyboard_layout_french_ca_label" msgid="365352601060604832">"французский (Канада)"</string>
diff --git a/packages/InputDevices/res/values-sl/strings.xml b/packages/InputDevices/res/values-sl/strings.xml
index f9e4610..a643c8e 100644
--- a/packages/InputDevices/res/values-sl/strings.xml
+++ b/packages/InputDevices/res/values-sl/strings.xml
@@ -8,8 +8,7 @@
     <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"angleška (ZDA), mednarodni slog"</string>
     <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"angleška (ZDA), slog Colemak"</string>
     <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"angleška (ZDA), slog Dvorak"</string>
-    <!-- no translation found for keyboard_layout_english_us_workman_label (2944541595262173111) -->
-    <skip />
+    <string name="keyboard_layout_english_us_workman_label" msgid="2944541595262173111">"angleška (ZDA), slog Workman"</string>
     <string name="keyboard_layout_german_label" msgid="8451565865467909999">"nemška"</string>
     <string name="keyboard_layout_french_label" msgid="813450119589383723">"francoska"</string>
     <string name="keyboard_layout_french_ca_label" msgid="365352601060604832">"francoska (Kanada)"</string>
diff --git a/packages/InputDevices/res/values-sr/strings.xml b/packages/InputDevices/res/values-sr/strings.xml
index a216bc3..b06f6fc 100644
--- a/packages/InputDevices/res/values-sr/strings.xml
+++ b/packages/InputDevices/res/values-sr/strings.xml
@@ -8,8 +8,7 @@
     <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"енглеска (САД), међународни стил"</string>
     <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"енглеска (САД), Colemak стил"</string>
     <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"енглеска (САД), Dvorak стил"</string>
-    <!-- no translation found for keyboard_layout_english_us_workman_label (2944541595262173111) -->
-    <skip />
+    <string name="keyboard_layout_english_us_workman_label" msgid="2944541595262173111">"енглеска (САД), Workman стил"</string>
     <string name="keyboard_layout_german_label" msgid="8451565865467909999">"немачка"</string>
     <string name="keyboard_layout_french_label" msgid="813450119589383723">"француска"</string>
     <string name="keyboard_layout_french_ca_label" msgid="365352601060604832">"француска (Канада)"</string>
diff --git a/packages/InputDevices/res/values-sv/strings.xml b/packages/InputDevices/res/values-sv/strings.xml
index 23f2c98..89cb54e 100644
--- a/packages/InputDevices/res/values-sv/strings.xml
+++ b/packages/InputDevices/res/values-sv/strings.xml
@@ -8,8 +8,7 @@
     <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"Engelskt (USA), internationellt"</string>
     <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"Engelskt (USA), colemak"</string>
     <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"Engelskt (USA), dvorak"</string>
-    <!-- no translation found for keyboard_layout_english_us_workman_label (2944541595262173111) -->
-    <skip />
+    <string name="keyboard_layout_english_us_workman_label" msgid="2944541595262173111">"Engelskt (USA), workman"</string>
     <string name="keyboard_layout_german_label" msgid="8451565865467909999">"Tyskt"</string>
     <string name="keyboard_layout_french_label" msgid="813450119589383723">"Franskt"</string>
     <string name="keyboard_layout_french_ca_label" msgid="365352601060604832">"Franskt (Kanada)"</string>
diff --git a/packages/InputDevices/res/values-sw/strings.xml b/packages/InputDevices/res/values-sw/strings.xml
index 720d427..1f447b0 100644
--- a/packages/InputDevices/res/values-sw/strings.xml
+++ b/packages/InputDevices/res/values-sw/strings.xml
@@ -8,8 +8,7 @@
     <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"Kiingereza (Marekani), Muundo wa Kimataifa"</string>
     <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"Kiingereza (Marekani), Muundo wa Colemak"</string>
     <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"Kiingereza (Marekani), Muundo wa Dvorak"</string>
-    <!-- no translation found for keyboard_layout_english_us_workman_label (2944541595262173111) -->
-    <skip />
+    <string name="keyboard_layout_english_us_workman_label" msgid="2944541595262173111">"Kiingereza (US), mtindo wa Workman"</string>
     <string name="keyboard_layout_german_label" msgid="8451565865467909999">"Kijerumani"</string>
     <string name="keyboard_layout_french_label" msgid="813450119589383723">"Kifaransa"</string>
     <string name="keyboard_layout_french_ca_label" msgid="365352601060604832">"Kifaransa (Kanada)"</string>
diff --git a/packages/InputDevices/res/values-ta-rIN/strings.xml b/packages/InputDevices/res/values-ta-rIN/strings.xml
index 43d0bd1..32efe7b 100644
--- a/packages/InputDevices/res/values-ta-rIN/strings.xml
+++ b/packages/InputDevices/res/values-ta-rIN/strings.xml
@@ -8,8 +8,7 @@
     <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"ஆங்கிலம் (யூஎஸ்), சர்வதேச நடை"</string>
     <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"ஆங்கிலம் (யூஎஸ்), கோல்மாக் நடை"</string>
     <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"ஆங்கிலம் (யூஎஸ்), டிவாரக் நடை"</string>
-    <!-- no translation found for keyboard_layout_english_us_workman_label (2944541595262173111) -->
-    <skip />
+    <string name="keyboard_layout_english_us_workman_label" msgid="2944541595262173111">"ஆங்கிலம் (யூஎஸ்), வொர்க்மென் நடை"</string>
     <string name="keyboard_layout_german_label" msgid="8451565865467909999">"ஜெர்மன்"</string>
     <string name="keyboard_layout_french_label" msgid="813450119589383723">"ஃபிரெஞ்ச்"</string>
     <string name="keyboard_layout_french_ca_label" msgid="365352601060604832">"ஃபிரெஞ்ச் (கனடா)"</string>
diff --git a/packages/InputDevices/res/values-te-rIN/strings.xml b/packages/InputDevices/res/values-te-rIN/strings.xml
index d214ae6..e07d4c8 100644
--- a/packages/InputDevices/res/values-te-rIN/strings.xml
+++ b/packages/InputDevices/res/values-te-rIN/strings.xml
@@ -8,8 +8,7 @@
     <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"ఇంగ్లీష్ (US), అంతర్జాతీయ శైలి"</string>
     <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"ఇంగ్లీష్ (US), కొల్‌మాక్ శైలి"</string>
     <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"ఇంగ్లీష్ (US), ద్వోరక్ శైలి"</string>
-    <!-- no translation found for keyboard_layout_english_us_workman_label (2944541595262173111) -->
-    <skip />
+    <string name="keyboard_layout_english_us_workman_label" msgid="2944541595262173111">"ఆంగ్లం (US), వర్క్‌మాన్ శైలి"</string>
     <string name="keyboard_layout_german_label" msgid="8451565865467909999">"జర్మన్"</string>
     <string name="keyboard_layout_french_label" msgid="813450119589383723">"ఫ్రెంచ్"</string>
     <string name="keyboard_layout_french_ca_label" msgid="365352601060604832">"ఫ్రెంచ్ (కెనడా)"</string>
diff --git a/packages/InputDevices/res/values-tr/strings.xml b/packages/InputDevices/res/values-tr/strings.xml
index 3dd0d3b..a8d9a0f 100644
--- a/packages/InputDevices/res/values-tr/strings.xml
+++ b/packages/InputDevices/res/values-tr/strings.xml
@@ -8,8 +8,7 @@
     <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"İngilizce (ABD) Uluslararası stil"</string>
     <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"İngilizce (ABD) Colemak stili"</string>
     <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"İngilizce (ABD) Dvorak stili"</string>
-    <!-- no translation found for keyboard_layout_english_us_workman_label (2944541595262173111) -->
-    <skip />
+    <string name="keyboard_layout_english_us_workman_label" msgid="2944541595262173111">"İngilizce (ABD), Workman stili"</string>
     <string name="keyboard_layout_german_label" msgid="8451565865467909999">"Almanca"</string>
     <string name="keyboard_layout_french_label" msgid="813450119589383723">"Fransızca"</string>
     <string name="keyboard_layout_french_ca_label" msgid="365352601060604832">"Fransızca (Kanada)"</string>
diff --git a/packages/InputDevices/res/values-ur-rPK/strings.xml b/packages/InputDevices/res/values-ur-rPK/strings.xml
index 2c5a8b8..3d2f618 100644
--- a/packages/InputDevices/res/values-ur-rPK/strings.xml
+++ b/packages/InputDevices/res/values-ur-rPK/strings.xml
@@ -8,8 +8,7 @@
     <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"انگریزی (امریکہ)، انٹرنیشنل سٹائل"</string>
     <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"انگریزی (امریکہ)، کول مارک سٹائل"</string>
     <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"انگریزی (امریکہ)، ڈوراک سٹائل"</string>
-    <!-- no translation found for keyboard_layout_english_us_workman_label (2944541595262173111) -->
-    <skip />
+    <string name="keyboard_layout_english_us_workman_label" msgid="2944541595262173111">"‏انگریزی (US)، ورک مین اسٹائل"</string>
     <string name="keyboard_layout_german_label" msgid="8451565865467909999">"جرمن"</string>
     <string name="keyboard_layout_french_label" msgid="813450119589383723">"فرانسیسی"</string>
     <string name="keyboard_layout_french_ca_label" msgid="365352601060604832">"فرانسیسی (کینیڈا)"</string>
diff --git a/packages/InputDevices/res/values-uz-rUZ/strings.xml b/packages/InputDevices/res/values-uz-rUZ/strings.xml
index ee20328..9c55615 100644
--- a/packages/InputDevices/res/values-uz-rUZ/strings.xml
+++ b/packages/InputDevices/res/values-uz-rUZ/strings.xml
@@ -8,8 +8,7 @@
     <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"Inglizcha (AQSH), xalqaro uslubda"</string>
     <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"Inglizcha (AQSH), Kolemak uslubida"</string>
     <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"Inglizcha (AQSH), Dvorak uslubida"</string>
-    <!-- no translation found for keyboard_layout_english_us_workman_label (2944541595262173111) -->
-    <skip />
+    <string name="keyboard_layout_english_us_workman_label" msgid="2944541595262173111">"Ingliz (AQSH), ishchi uslubda"</string>
     <string name="keyboard_layout_german_label" msgid="8451565865467909999">"Nemischa"</string>
     <string name="keyboard_layout_french_label" msgid="813450119589383723">"Fransuzcha"</string>
     <string name="keyboard_layout_french_ca_label" msgid="365352601060604832">"Fransuzcha (Kanada)"</string>
diff --git a/packages/InputDevices/res/values-zh-rCN/strings.xml b/packages/InputDevices/res/values-zh-rCN/strings.xml
index 2ba2667..c61dccb 100644
--- a/packages/InputDevices/res/values-zh-rCN/strings.xml
+++ b/packages/InputDevices/res/values-zh-rCN/strings.xml
@@ -8,8 +8,7 @@
     <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"英语(美国),国际风格"</string>
     <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"英语(美国),Colemak 风格"</string>
     <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"英语(美国),Dvorak 风格"</string>
-    <!-- no translation found for keyboard_layout_english_us_workman_label (2944541595262173111) -->
-    <skip />
+    <string name="keyboard_layout_english_us_workman_label" msgid="2944541595262173111">"英语(美国),Workman 风格"</string>
     <string name="keyboard_layout_german_label" msgid="8451565865467909999">"德语"</string>
     <string name="keyboard_layout_french_label" msgid="813450119589383723">"法语"</string>
     <string name="keyboard_layout_french_ca_label" msgid="365352601060604832">"法语(加拿大)"</string>
diff --git a/packages/InputDevices/res/values-zu/strings.xml b/packages/InputDevices/res/values-zu/strings.xml
index 80899d0..0dcffb0 100644
--- a/packages/InputDevices/res/values-zu/strings.xml
+++ b/packages/InputDevices/res/values-zu/strings.xml
@@ -8,8 +8,7 @@
     <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"I-English (US), isitayela sakwamanye amazwe"</string>
     <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"I-English (US), isitayela se-Colemak"</string>
     <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"I-English (US), isitayela se-Dvorak"</string>
-    <!-- no translation found for keyboard_layout_english_us_workman_label (2944541595262173111) -->
-    <skip />
+    <string name="keyboard_layout_english_us_workman_label" msgid="2944541595262173111">"I-English (US), isitayela sokusebenza"</string>
     <string name="keyboard_layout_german_label" msgid="8451565865467909999">"Isi-German"</string>
     <string name="keyboard_layout_french_label" msgid="813450119589383723">"Isi-French"</string>
     <string name="keyboard_layout_french_ca_label" msgid="365352601060604832">"Isi-French (Canada)"</string>
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java
index 11e937b..df9d44a 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java
@@ -2,6 +2,7 @@
 
 import android.content.ContentValues;
 import android.content.Context;
+import android.content.res.Resources;
 import android.database.Cursor;
 import android.database.sqlite.SQLiteDatabase;
 import android.database.sqlite.SQLiteOpenHelper;
@@ -30,10 +31,9 @@
 
     private static final String TABLE_MTP_DOCUMENTS = "MtpDocuments";
 
-    static final String COLUMN_DEVICE_ID = "deviceId";
-    static final String COLUMN_STORAGE_ID = "storageId";
-    static final String COLUMN_OBJECT_HANDLE = "objectHandle";
-    static final String COLUMN_FULL_PATH = "fullPath";
+    static final String COLUMN_DEVICE_ID = "device_id";
+    static final String COLUMN_STORAGE_ID = "storage_id";
+    static final String COLUMN_OBJECT_HANDLE = "object_handle";
 
     private static class OpenHelper extends SQLiteOpenHelper {
         private static final String CREATE_TABLE_QUERY =
@@ -43,7 +43,6 @@
                 COLUMN_DEVICE_ID + " INTEGER NOT NULL," +
                 COLUMN_STORAGE_ID + " INTEGER NOT NULL," +
                 COLUMN_OBJECT_HANDLE + " INTEGER," +
-                COLUMN_FULL_PATH + " TEXT NOT NULL," +
                 DocumentsContract.Document.COLUMN_MIME_TYPE + " TEXT," +
                 DocumentsContract.Document.COLUMN_DISPLAY_NAME + " TEXT NOT NULL," +
                 DocumentsContract.Document.COLUMN_SUMMARY + " TEXT," +
@@ -86,17 +85,15 @@
     }
 
     @VisibleForTesting
-    void putRootDocument(MtpRoot root) throws Exception {
+    void putRootDocument(Resources resources, MtpRoot root) throws Exception {
         database.beginTransaction();
         try {
             final ContentValues values = new ContentValues();
             values.put(COLUMN_DEVICE_ID, root.mDeviceId);
             values.put(COLUMN_STORAGE_ID, root.mStorageId);
             values.putNull(COLUMN_OBJECT_HANDLE);
-            values.put(
-                    COLUMN_FULL_PATH, "/" + root.mDeviceId + "/" + escape(root.mDescription));
             values.put(Document.COLUMN_MIME_TYPE, DocumentsContract.Document.MIME_TYPE_DIR);
-            values.put(Document.COLUMN_DISPLAY_NAME, root.mDescription);
+            values.put(Document.COLUMN_DISPLAY_NAME, root.getRootName(resources));
             values.putNull(Document.COLUMN_SUMMARY);
             values.putNull(Document.COLUMN_LAST_MODIFIED);
             values.putNull(Document.COLUMN_ICON);
@@ -113,7 +110,7 @@
     }
 
     @VisibleForTesting
-    void putDocument(int deviceId, String parentFullPath, MtpObjectInfo info) throws Exception {
+    void putDocument(int deviceId, MtpObjectInfo info) throws Exception {
         database.beginTransaction();
         try {
             final String mimeType = CursorHelper.formatTypeToMimeType(info.getFormat());
@@ -134,9 +131,7 @@
             values.put(COLUMN_DEVICE_ID, deviceId);
             values.put(COLUMN_STORAGE_ID, info.getStorageId());
             values.put(COLUMN_OBJECT_HANDLE, info.getObjectHandle());
-            values.put(COLUMN_FULL_PATH, parentFullPath + "/" + escape(info.getName()));
-            values.put(
-                    Document.COLUMN_MIME_TYPE, CursorHelper.formatTypeToMimeType(info.getFormat()));
+            values.put(Document.COLUMN_MIME_TYPE, mimeType);
             values.put(Document.COLUMN_DISPLAY_NAME, info.getName());
             values.putNull(Document.COLUMN_SUMMARY);
             values.put(
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java
index 7ce32542..8e1335f 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java
@@ -1,6 +1,5 @@
 package com.android.mtp;
 
-
 import android.database.Cursor;
 import android.mtp.MtpConstants;
 import android.mtp.MtpObjectInfo;
@@ -15,7 +14,6 @@
         MtpDatabase.COLUMN_DEVICE_ID,
         MtpDatabase.COLUMN_STORAGE_ID,
         MtpDatabase.COLUMN_OBJECT_HANDLE,
-        MtpDatabase.COLUMN_FULL_PATH,
         DocumentsContract.Document.COLUMN_MIME_TYPE,
         DocumentsContract.Document.COLUMN_DISPLAY_NAME,
         DocumentsContract.Document.COLUMN_SUMMARY,
@@ -25,6 +23,8 @@
         DocumentsContract.Document.COLUMN_SIZE
     };
 
+    private final TestResources resources = new TestResources();
+
     @Override
     public void tearDown() {
         MtpDatabase.deleteDatabase(getContext());
@@ -32,35 +32,10 @@
 
     public void testPutRootDocument() throws Exception {
         final MtpDatabase database = new MtpDatabase(getContext());
-        final MtpRoot root = new MtpRoot(
-                0,
-                1,
-                "Device A",
-                "Storage",
-                1000,
-                2000,
-                "");
-        database.putRootDocument(root);
-
-        final MtpRoot duplicatedNameRoot = new MtpRoot(
-                0,
-                2,
-                "Device A",
-                "Storage",
-                1000,
-                2000,
-                "");
-        database.putRootDocument(duplicatedNameRoot);
-
-        final MtpRoot strangeNameRoot = new MtpRoot(
-                0,
-                3,
-                "Device A",
-                "/@#%&<>Storage",
-                1000,
-                2000,
-                "");
-        database.putRootDocument(strangeNameRoot);
+        database.putRootDocument(resources, new MtpRoot(0, 1, "Device", "Storage", 1000, 2000, ""));
+        database.putRootDocument(resources, new MtpRoot(0, 2, "Device", "Storage", 1000, 2000, ""));
+        database.putRootDocument(
+                resources, new MtpRoot(0, 3, "Device", "/@#%&<>Storage", 1000, 2000, ""));
 
         final Cursor cursor = database.queryChildDocuments(COLUMN_NAMES);
         assertEquals(3, cursor.getCount());
@@ -70,22 +45,23 @@
         assertEquals("deviceId", 0, cursor.getInt(1));
         assertEquals("storageId", 1, cursor.getInt(2));
         assertTrue("objectHandle", cursor.isNull(3));
-        assertEquals("fullPath", "/0/Storage", cursor.getString(4));
-        assertEquals("mimeType", DocumentsContract.Document.MIME_TYPE_DIR, cursor.getString(5));
-        assertEquals("displayName", "Storage", cursor.getString(6));
-        assertTrue("summary", cursor.isNull(7));
-        assertTrue("lastModified", cursor.isNull(8));
-        assertTrue("icon", cursor.isNull(9));
-        assertEquals("flag", 0, cursor.getInt(10));
-        assertEquals("size", 1000, cursor.getInt(11));
+        assertEquals("mimeType", DocumentsContract.Document.MIME_TYPE_DIR, cursor.getString(4));
+        assertEquals("displayName", "Device Storage", cursor.getString(5));
+        assertTrue("summary", cursor.isNull(6));
+        assertTrue("lastModified", cursor.isNull(7));
+        assertTrue("icon", cursor.isNull(8));
+        assertEquals("flag", 0, cursor.getInt(9));
+        assertEquals("size", 1000, cursor.getInt(10));
 
         cursor.moveToNext();
         assertEquals("documentId", 2, cursor.getInt(0));
-        assertEquals("fullPath", "/0/Storage", cursor.getString(4));
+        assertEquals("displayName", "Device Storage", cursor.getString(5));
 
         cursor.moveToNext();
         assertEquals("documentId", 3, cursor.getInt(0));
-        assertEquals("fullPath", "/0/%2F%40%23%25%26%3C%3EStorage", cursor.getString(4));
+        assertEquals("displayName", "Device /@#%&<>Storage", cursor.getString(5));
+
+        cursor.close();
     }
 
     public void testPutDocument() throws Exception {
@@ -96,7 +72,7 @@
         builder.setStorageId(5);
         builder.setFormat(MtpConstants.FORMAT_TEXT);
         builder.setCompressedSize(1000);
-        database.putDocument(0, "/0/Storage", builder.build());
+        database.putDocument(0, builder.build());
 
         final Cursor cursor = database.queryChildDocuments(COLUMN_NAMES);
         assertEquals(1, cursor.getCount());
@@ -105,17 +81,16 @@
         assertEquals("deviceId", 0, cursor.getInt(1));
         assertEquals("storageId", 5, cursor.getInt(2));
         assertEquals("objectHandle", 100, cursor.getInt(3));
-        assertEquals("fullPath", "/0/Storage/test.txt", cursor.getString(4));
-        assertEquals("mimeType", "text/plain", cursor.getString(5));
-        assertEquals("displayName", "test.txt", cursor.getString(6));
-        assertTrue("summary", cursor.isNull(7));
-        assertTrue("lastModified", cursor.isNull(8));
-        assertTrue("icon", cursor.isNull(9));
+        assertEquals("mimeType", "text/plain", cursor.getString(4));
+        assertEquals("displayName", "test.txt", cursor.getString(5));
+        assertTrue("summary", cursor.isNull(6));
+        assertTrue("lastModified", cursor.isNull(7));
+        assertTrue("icon", cursor.isNull(8));
         assertEquals(
                 "flag",
                 DocumentsContract.Document.FLAG_SUPPORTS_DELETE |
                 DocumentsContract.Document.FLAG_SUPPORTS_WRITE,
-                cursor.getInt(10));
-        assertEquals("size", 1000, cursor.getInt(11));
+                cursor.getInt(9));
+        assertEquals("size", 1000, cursor.getInt(10));
     }
 }
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
index 0c03814c..5765f0a 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
@@ -16,9 +16,6 @@
 
 package com.android.mtp;
 
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.content.res.Resources.NotFoundException;
 import android.database.Cursor;
 import android.mtp.MtpConstants;
 import android.mtp.MtpObjectInfo;
@@ -26,7 +23,6 @@
 import android.provider.DocumentsContract.Root;
 import android.provider.DocumentsContract;
 import android.test.AndroidTestCase;
-import android.test.mock.MockResources;
 import android.test.suitebuilder.annotation.SmallTest;
 
 import java.io.FileNotFoundException;
@@ -39,16 +35,7 @@
     private TestContentResolver mResolver;
     private MtpDocumentsProvider mProvider;
     private TestMtpManager mMtpManager;
-    private final MockResources mResources = new MockResources() {
-        @Override
-        public String getString(int id) throws NotFoundException {
-            switch (id) {
-                case R.string.root_name:
-                    return "%1$s %2$s";
-            }
-            throw new NotFoundException();
-        }
-    };
+    private final TestResources mResources = new TestResources();
 
     @Override
     public void setUp() throws IOException {
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestResources.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestResources.java
new file mode 100644
index 0000000..eb80e3b
--- /dev/null
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestResources.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.mtp;
+
+import android.test.mock.MockResources;
+
+class TestResources extends MockResources {
+    @Override
+    public String getString(int id) throws NotFoundException {
+        switch (id) {
+            case R.string.root_name:
+                return "%1$s %2$s";
+        }
+        throw new NotFoundException();
+    }
+}
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 41ed64c..0e31d8d 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -393,8 +393,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Vou uit"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Vou in"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"Skerm is vasgespeld"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"Dit hou dit in sig totdat jy dit ontspeld. Raak en hou Terug en Oorsig op dieselfde tyd om te ontspeld."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"Dit hou dit in sig totdat jy ontspeld. Raak en hou Oorsig om te ontspeld."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"Het dit"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"Nee, dankie"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Versteek <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 673710d..ec6ec93 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -393,8 +393,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"አስፋ"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"ሰብስብ"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"ማያ ገጽ ተሰክቷል"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"ይህ እስከሚነቅሉት ድረስ ድረስ በዕይታ ውስጥ እንዲቆይ ያደርገዋል። ለመንቀል በተመሳሳይ ጊዜ ተመለስን እና አጠቃላይ ዕይታን አንድ ላይ ነክተው ይያዙ።"</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"ይህ እስከሚነቅሉት ድረስ በዕይታ ውስጥ ያቆየዋል። እንዲነቀል ለማድረግ አጠቃላይ ዕይታን ነካ አድርገው ይያዙት።"</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"ገባኝ"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"አይ፣ አመሰግናለሁ"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> ይደበቅ?"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index c2c7e65..02fc3fe 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -397,8 +397,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"توسيع"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"تصغير"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"تم تثبيت الشاشة"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"يساعد هذا على استمرار العرض حتى يتم إلغاء التثبيت. ويمكنك لمس \"رجوع\" و\"عرض عام\" مع الاستمرار في وقت واحد لإلغاء التثبيت."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"يساعد هذا على استمرار العرض حتى يتم إلغاء التثبيت. ويمكنك لمس \"عرض عام\" مع الاستمرار في وقت واحد لإلغاء التثبيت."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"حسنًا"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"لا، شكرًا"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"هل تريد إخفاء <xliff:g id="TILE_LABEL">%1$s</xliff:g>؟"</string>
diff --git a/packages/SystemUI/res/values-az-rAZ/strings.xml b/packages/SystemUI/res/values-az-rAZ/strings.xml
index a949dbb..aba22f8 100644
--- a/packages/SystemUI/res/values-az-rAZ/strings.xml
+++ b/packages/SystemUI/res/values-az-rAZ/strings.xml
@@ -393,8 +393,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Genişləndirin"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Yığcamlaşdırın"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"Ekrana sancaq taxıldı"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"Sancaq götürülənə qədər bu, görünəcək. Sancağı götürmək üçün Geri və İcmal düymələrinə eyni vaxtda toxunun və saxlayın."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"Sancaq götürülənə qədər bu, görünəcək. Sancağı götürmək üçün Geri və İcmal düymələrinə toxunun və saxlayın."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"Anladım!"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"Yox, çox sağ olun"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> gizlədilsin?"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index a59f4c5..50ac61f 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -393,8 +393,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Разгъване"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Свиване"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"Екранът е фиксиран"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"Така екранът ще се показва, докато не го освободите. За да направите това, докоснете и задръжте бутона за връщане назад и този за общ преглед едновременно."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"Така екранът ще се показва, докато не го освободите. За да направите това, докоснете и задръжте бутона за общ преглед."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"Разбрах"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"Не, благодаря"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Да се скрие ли „<xliff:g id="TILE_LABEL">%1$s</xliff:g>“?"</string>
diff --git a/packages/SystemUI/res/values-bn-rBD/strings.xml b/packages/SystemUI/res/values-bn-rBD/strings.xml
index f4adc14..f32cfcc 100644
--- a/packages/SystemUI/res/values-bn-rBD/strings.xml
+++ b/packages/SystemUI/res/values-bn-rBD/strings.xml
@@ -393,8 +393,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"প্রসারিত করুন"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"সঙ্কুচিত করুন"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"স্ক্রীন পিন করা হয়েছে"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"এটি আপনার আনপিন না করা পর্যন্ত এটিকে দর্শনে রাখে৷ আনপিন করতে একই সময়ে ফিরুন এবং ওভারভিউ এ স্পর্শ করে ধরে রাখুন৷"</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"এটি আপনার আনপিন না করা পর্যন্ত এটিকে দর্শনে রাখে৷ আনপিন করতে ওভারভিউ এ স্পর্শ করে ধরে রাখুন৷"</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"বুঝেছি"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"না থাক"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> লুকাবেন?"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 00f96a7..429f70b 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -395,8 +395,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Amplia"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Replega"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"La pantalla està fixada"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"Continuarà a la visualització fins que n\'anul·lis la fixació. Per fer-ho, toca i mantén premuts els botons Enrere i Visió general a la vegada."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"Continuarà a la visualització fins que n\'anul·lis la fixació. Per fer-ho, toca i mantén premut el botó Visió general."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"D\'acord"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"No, gràcies"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Vols amagar <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index e429a06..ee77cf9 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -397,8 +397,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Rozbalit"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Sbalit"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"Obrazovka je připnuta"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"Obsah bude připnut v zobrazení, dokud jej neuvolníte. Chcete-li jej uvolnit, stiskněte a podržte současně tlačítka Zpět a Přehled."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"Obsah bude připnut v zobrazení, dokud jej neuvolníte. Uvolníte jej stisknutím a podržením tlačítka Přehled."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"Rozumím"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"Ne, děkuji"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Skrýt <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index e4436c8..f749756 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -393,8 +393,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Udvid"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Skjul"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"Skærmen er fastgjort"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"Dette fastholder den i visningen, indtil du frigør den. Tryk på Tilbage og Oversigt på samme tid, og hold dem nede for at frigøre denne skærm."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"Dette fastholder den i visningen, indtil du frigør den. Tryk på Oversigt, og hold den nede for at frigøre denne skærm."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"OK, det er forstået"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"Nej tak"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Vil du skjule <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index b113083..cfaecaf 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -395,8 +395,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Maximieren"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Minimieren"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"Bildschirm ist fixiert"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"Der Bildschirm wird solange angezeigt, bis Sie die Fixierung aufheben. Berühren und halten Sie \"Zurück\" und \"Übersicht\" gleichzeitig, um die Fixierung aufzuheben."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"Der Bildschirm wird solange angezeigt, bis Sie die Fixierung aufheben. Berühren und halten Sie \"Übersicht\", wenn Sie die Fixierung aufheben möchten."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"OK"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"Nein danke"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> ausblenden?"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 27a019c..6fc1b59 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -395,8 +395,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Ανάπτυξη"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Σύμπτυξη"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"Η οθόνη καρφιτσώθηκε"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"Με αυτόν τον τρόπο παραμένει σε προβολή έως ότου την ξεκαρφιτσώσετε. Αγγίξτε παρατεταμένα \"Επιστροφή\" και \"Επισκόπηση\" ταυτόχρονα για ξεκαρφίτσωμα."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"Με αυτόν τον τρόπο παραμένει σε προβολή έως ότου την ξεκαρφιτσώσετε. Αγγίξτε παρατεταμένα \"Επισκόπηση\" για ξεκαρφίτσωμα."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"Το κατάλαβα"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"Όχι"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Απόκρυψη <xliff:g id="TILE_LABEL">%1$s</xliff:g>;"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index b1f71a2..ffdc3af7 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -393,8 +393,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Expand"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Collapse"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"Screen is pinned"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"This keeps it in view until you unpin. Touch and hold Back and Overview at the same time to unpin."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"This keeps it in view until you unpin. Touch and hold Overview to unpin."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"Got it"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"No, thanks"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Hide <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index b1f71a2..ffdc3af7 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -393,8 +393,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Expand"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Collapse"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"Screen is pinned"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"This keeps it in view until you unpin. Touch and hold Back and Overview at the same time to unpin."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"This keeps it in view until you unpin. Touch and hold Overview to unpin."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"Got it"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"No, thanks"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Hide <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index b1f71a2..ffdc3af7 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -393,8 +393,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Expand"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Collapse"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"Screen is pinned"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"This keeps it in view until you unpin. Touch and hold Back and Overview at the same time to unpin."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"This keeps it in view until you unpin. Touch and hold Overview to unpin."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"Got it"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"No, thanks"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Hide <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index bca484a..d4bb0a6 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -395,8 +395,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Expandir"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Contraer"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"Pantalla fija"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"Esta función mantiene fija la vista de la pantalla hasta que la desactivas. Mantén presionados los botones Atrás y Recientes al mismo tiempo para anular la fijación."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"Esta función mantiene fija la vista de la pantalla hasta que la desactivas. Mantén presionado el botón Recientes para anular la fijación."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"Entendido"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"No, gracias"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"¿Ocultar <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 3c89db8..d3cae62 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -393,8 +393,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Mostrar"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Ocultar"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"Pantalla fijada"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"La pantalla se mantendrá visible hasta que dejes de fijarla. Para ello, mantén pulsados los botones de retroceso e información general."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"La pantalla se mantendrá visible hasta que dejes de fijarla. Para ello, mantén pulsado el botón de información general."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"Entendido"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"No, gracias"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"¿Ocultar <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
diff --git a/packages/SystemUI/res/values-et-rEE/strings.xml b/packages/SystemUI/res/values-et-rEE/strings.xml
index 01e5848..0dfbdfc 100644
--- a/packages/SystemUI/res/values-et-rEE/strings.xml
+++ b/packages/SystemUI/res/values-et-rEE/strings.xml
@@ -393,8 +393,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Laiendamine"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Ahendamine"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"Ekraan on kinnitatud"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"See hoiab selle kuval, kuni selle vabastate. Vabastamiseks puudutage ning hoidke korraga all nuppe Tagasi ja Ülevaade."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"See hoiab selle kuval, kuni selle vabastate. Vabastamiseks puudutage ja hoidke all nuppu Ülevaade."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"Selge"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"Tänan, ei"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Kas peita <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
diff --git a/packages/SystemUI/res/values-eu-rES/strings.xml b/packages/SystemUI/res/values-eu-rES/strings.xml
index 613b44a..769164d 100644
--- a/packages/SystemUI/res/values-eu-rES/strings.xml
+++ b/packages/SystemUI/res/values-eu-rES/strings.xml
@@ -393,8 +393,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Zabaldu"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Tolestu"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"Pantaila ainguratuta dago"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"Horrela, ikusgai mantenduko da aingura kendu arte. Aingura kentzeko, eduki ukituta aldi berean \"Atzera\" eta \"Ikuspegi orokorra\" botoiak."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"Horrela, ikusgai mantenduko da, aingura kendu arte. Aingura kentzeko, eduki ukituta \"Ikuspegi orokorra\" botoia."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"Ados"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"Ez, eskerrik asko"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> ezkutatu nahi duzu?"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 9967225..1c99a23 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -393,8 +393,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"بزرگ کردن"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"کوچک کردن"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"صفحه نمایش پین شد"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"تا زمانی که پین را بردارید، در نما نگه‌داشته می‌شود. برای برداشتن پین، برگشت و نمای کلی را به صورت هم‌زمان لمس کنید و نگه‌دارید."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"تا زمانی که پین را بردارید، در نما نگه‌داشته می‌شود. برای برداشتن پین، نمای کلی را لمس کنید و نگه‌دارید."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"متوجه شدم"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"نه سپاسگزارم"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> مخفی شود؟"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 2d138cb..79bf369 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -393,8 +393,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Laajenna."</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Tiivistä."</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"Näyttö on kiinnitetty"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"Tämä pitää sen näkyvissä, kunnes poistat kiinnityksen. Kosketa Edellinen- ja Viimeisimmät-kohtaa samanaikaisesti pitkään kiinnityksen poistamiseksi."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"Tämä pitää sen näkyvissä, kunnes poistat kiinnityksen. Kosketa Viimeisimmät-kohtaa pitkään kiinnityksen poistamiseksi."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"Selvä"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"Ei kiitos"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Piilotetaanko <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 979ee35..605e4c5 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -395,8 +395,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Développer"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Réduire"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"L\'écran est épinglé"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"Cet écran est épinglé jusqu\'à ce que vous annuliez l\'opération. Pour annuler l\'épinglage, maintenez un doigt simultanément sur « Retour » et « Aperçu »."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"Cet écran est épinglé jusqu\'à ce que vous annuliez l\'opération. Pour annuler l\'épinglage, maintenez le doigt sur « Aperçu »."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"OK"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"Non, merci"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Masquer <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 9ab6613..3fee28e 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -327,7 +327,7 @@
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Priorité\nuniquement"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Alarmes\nuniquement"</string>
     <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Charge en cours… (chargé à 100 %% dans <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
-    <string name="keyguard_indication_charging_time_fast" msgid="9018981952053914986">"Charge rapide… (chargé à 100 % dans <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time_fast" msgid="9018981952053914986">"Charge rapide… (chargé à 100 %% dans <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
     <string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Charge lente… (chargé à 100 % dans <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Changer d\'utilisateur"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Changer d\'utilisateur (utilisateur actuel : <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>)"</string>
@@ -395,8 +395,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Développer"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Réduire"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"Écran épinglé"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"Cet écran est épinglé jusqu\'à annulation de l\'opération. Pour annuler l\'épinglage, appuyez simultanément sur \"Retour\" et \"Aperçu\" de manière prolongée."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"Cet écran est épinglé jusqu\'à annulation de l\'opération. Pour annuler l\'épinglage, appuyez de manière prolongée sur \"Aperçu\"."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"OK"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"Non, merci"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Masquer <xliff:g id="TILE_LABEL">%1$s</xliff:g> ?"</string>
diff --git a/packages/SystemUI/res/values-gl-rES/strings.xml b/packages/SystemUI/res/values-gl-rES/strings.xml
index bc44150..9a66d87 100644
--- a/packages/SystemUI/res/values-gl-rES/strings.xml
+++ b/packages/SystemUI/res/values-gl-rES/strings.xml
@@ -395,8 +395,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Ampliar"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Contraer"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"A pantalla está fixada"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"A pantalla manterase visible ata que anules a fixación. Para facelo, mantén premido Atrás e Visión xeral ao mesmo tempo."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"A pantalla manterase visible ata que anules a fixación. Para facelo, mantén premido Visión xeral."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"De acordo"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"Non, grazas"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Queres ocultar <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
diff --git a/packages/SystemUI/res/values-gu-rIN/strings.xml b/packages/SystemUI/res/values-gu-rIN/strings.xml
index ba8c517..fe60448 100644
--- a/packages/SystemUI/res/values-gu-rIN/strings.xml
+++ b/packages/SystemUI/res/values-gu-rIN/strings.xml
@@ -393,8 +393,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"વિસ્તૃત કરો"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"સંકુચિત કરો"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"સ્ક્રીન પિન કરેલ છે"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"તમે જ્યાં સુધી અનપિન કરશો નહીં ત્યાં સુધી આ તેને દૃશ્યમાં રાખે છે. અનપિન કરવા માટે બેકને ટચ કરો અને પકડો અને તે જ સમયે વિહંગાવલોકન કરો."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"તમે જ્યાં સુધી અનપિન કરશો નહીં ત્યાં સુધી આ તેને દૃશ્યમાં રાખે છે. અનપિન કરવા માટે વિહંગાવલોકનને ટચ કરો અને પકડો."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"સમજાઈ ગયું"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"નહીં આભાર"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> ને છુપાવીએ?"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 669ce5a..a433ca5 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -393,8 +393,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"विस्तृत करें"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"संक्षिप्त करें"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"स्‍क्रीन पिन कर दी गई है"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"इससे वह तब तक दृश्‍य में रहता है जब तक कि आप उसे अनपिन नहीं कर देते. अनपिन करने के लिए वापस जाएं और अवलोकन करें को एक ही समय पर स्‍पर्श करके रखें."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"इससे वह तब तक दृश्‍य में बना रहता है जब तक कि आप उसे अनपिन नहीं कर देते. अनपिन करने के लिए अवलोकन करें को स्‍पर्श करके रखें."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"समझ लिया"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"नहीं, रहने दें"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> को छिपाएं?"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index e928cbc..b72ac3d 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -394,8 +394,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Proširivanje"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Sažimanje"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"Zaslon je prikvačen"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"Zaslon će tako ostati u prvom planu dok ga ne otkvačite. Istovremeno dodirnite i držite Natrag i Pregled da biste ga otkvačili."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"Zaslon će tako ostati u prvom planu dok ga ne otkvačite. Dodirnite i držite Pregled da biste ga otkvačili."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"Shvaćam"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"Ne, hvala"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Želite li sakriti pločicu <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index a347ede..d27813a 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -393,8 +393,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Kibontás"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Összecsukás"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"A képernyő rögzítve van"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"Megjelenítve tartja addig, amíg Ön fel nem oldja fel a rögzítést. A rögzítés feloldásához tartsa egyszerre lenyomva a Vissza és az Áttekintés lehetőséget."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"Megjelenítve tartja addig, amíg Ön fel nem oldja a rögzítést. A feloldáshoz tartsa lenyomva az Áttekintés lehetőséget."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"Értem"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"Nem, köszönöm"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Elrejti ezt: <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml
index 18f6c88..125b19d 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings.xml
+++ b/packages/SystemUI/res/values-hy-rAM/strings.xml
@@ -393,8 +393,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Ընդարձակել"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Կոծկել"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"Էկրանն ամրացված է"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"Էկրանը կմնա տեսադաշտում, մինչև այն ապամրացնեք: Ապամրացնելու համար միաժամանակ հպեք և պահեք Համատեսքի և Հետ կոճակները:"</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"Էկրանը կմնա տեսադաշտում, մինչև այն ապամրացնեք: Ապամրացնելու համար հպեք և պահեք Համատեսքի կոճակը:"</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"Հասկանալի է"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"Ոչ, շնորհակալություն"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Թաքցնե՞լ <xliff:g id="TILE_LABEL">%1$s</xliff:g>-ը:"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index afcac63..1370ef4 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -393,8 +393,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Luaskan"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Ciutkan"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"Layar dipasangi pin"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"Ini akan terus ditampilkan sampai Anda melepas pin. Sentuh dan tahan tombol Kembali dan Ringkasan secara bersamaan untuk melepas pin."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"Ini akan terus ditampilkan sampai Anda melepas pin. Sentuh dan tahan tombol Ringkasan untuk melepas pin."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"Mengerti"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"Lain kali"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Sembunyikan <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
diff --git a/packages/SystemUI/res/values-is-rIS/strings.xml b/packages/SystemUI/res/values-is-rIS/strings.xml
index 48d0d1a..a57e66c 100644
--- a/packages/SystemUI/res/values-is-rIS/strings.xml
+++ b/packages/SystemUI/res/values-is-rIS/strings.xml
@@ -393,8 +393,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Stækka"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Minnka"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"Skjárinn er festur"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"Þetta heldur þessu opnu þangað til þú losar. Haltu bakk- og yfirlitshnöppunum inni á sama tíma til að losa."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"Þetta heldur þessu opnu þangað til þú losar. Haltu yfirlitshnappinum inni til að losa."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"Ég skil"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"Nei, takk"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Fela <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index dea0330..77be017 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -395,8 +395,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Espandi"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Comprimi"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"La schermata è bloccata"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"La schermata rimane visibile finché la sblocchi. Tocca e tieni premuti contemporaneamente Indietro e Panoramica per sbloccare."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"La schermata rimane visibile finché la sblocchi. Tocca Panoramica e tieni premuto per sbloccare."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"OK"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"No, grazie"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Nascondere <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 772a3fa..20cb1ea 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -395,8 +395,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"הרחב"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"כווץ"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"המסך מוצמד"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"שומר בתצוגה עד לביטול ההצמדה. גע והחזק בו-זמנית ב\'הקודם\' ו\'סקירה\' כדי לבטל הצמדה."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"שומר בתצוגה עד לביטול ההצמדה. גע והחזק בו-זמנית ב\'הקודם\' ו\'סקירה\' כדי לבטל הצמדה."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"הבנתי"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"לא, תודה"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"להסתיר<xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 6e570e3..3d40c73 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -395,8 +395,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"展開"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"折りたたむ"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"画面が固定されました"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"固定を解除するまで画面が常に表示されるようになります。[戻る]と[最近]を同時に押し続けると固定が解除されます。"</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"固定を解除するまで画面が常に表示されるようになります。[最近]を押し続けると固定が解除されます。"</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"はい"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"いいえ"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g>を非表示にしますか?"</string>
diff --git a/packages/SystemUI/res/values-ka-rGE/strings.xml b/packages/SystemUI/res/values-ka-rGE/strings.xml
index 6f26123..8f42d5b 100644
--- a/packages/SystemUI/res/values-ka-rGE/strings.xml
+++ b/packages/SystemUI/res/values-ka-rGE/strings.xml
@@ -393,8 +393,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"გავრცობა"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"ჩაკეცვა"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"ეკრანი ჩამაგრებულია"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"ამით ის ხედში დარჩება, სანამ ჩამაგრებას არ გააუქმებთ. ჩამაგრების გასაუქმებლად შეეხეთ და დააყოვნეთ „დაბრუნება“-ზე და „მიმოხილვა“-ზე ერთდროულად."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"ამით ის ხედში დარჩება, სანამ ჩამაგრებას არ გააუქმებთ. ჩამაგრების გასაუქმებლად შეეხეთ და დააყოვნეთ „მიმოხილვა“-ზე."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"გასაგებია"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"არა, გმადლობთ"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"დაიმალოს <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
diff --git a/packages/SystemUI/res/values-kk-rKZ/strings.xml b/packages/SystemUI/res/values-kk-rKZ/strings.xml
index 2668de4..192518a 100644
--- a/packages/SystemUI/res/values-kk-rKZ/strings.xml
+++ b/packages/SystemUI/res/values-kk-rKZ/strings.xml
@@ -393,8 +393,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Жаю"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Жию"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"Экран түйрелді"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"Бұл сіз оны босатқанша оны көрсетіп тұрады. Босату үшін «Кері» және «Шолу» түймелерін бір уақытта басып тұрыңыз."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"Бұл сіз оны босатқанша оны көрсетіп тұрады. Босату үшін «Шолу» түймесін бір уақытта басып тұрыңыз."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"Түсіндім"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"Жоқ, рақмет"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> жасыру керек пе?"</string>
diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml
index 08d761f..284af53 100644
--- a/packages/SystemUI/res/values-km-rKH/strings.xml
+++ b/packages/SystemUI/res/values-km-rKH/strings.xml
@@ -393,8 +393,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"ពង្រីក"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"បង្រួម"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"អេក្រង់​ត្រូវ​បាន​ភ្ជាប់"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"រក្សាទុក​វា​ក្នុង​ទិដ្ឋភាព​រហូត​ដល់​អ្នក​ផ្ដាច់។ ប៉ះ ហើយ​សង្កត់​ថយក្រោយ និង​ទិដ្ឋភាព​នៅ​ពេល​តែ​មួយ​ដើម្បី​ផ្ដាច់។"</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"វា​រក្សាទុក​ក្នុង​ទិដ្ឋភាព​រហូត​ដល់​អ្នក​ផ្ដាច់។ ប៉ះ និង​សង្កត់​ទិដ្ឋភាព​ដើម្បី​ផ្ដាច់។"</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"យល់​ហើយ"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"ទេ អរគុណ"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"លាក់ <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
diff --git a/packages/SystemUI/res/values-kn-rIN/strings.xml b/packages/SystemUI/res/values-kn-rIN/strings.xml
index 2cf1697..484551b 100644
--- a/packages/SystemUI/res/values-kn-rIN/strings.xml
+++ b/packages/SystemUI/res/values-kn-rIN/strings.xml
@@ -393,8 +393,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"ವಿಸ್ತರಿಸು"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"ಸಂಕುಚಿಸು"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"ಪರದೆಯನ್ನು ಪಿನ್ ಮಾಡಲಾಗಿದೆ"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"ನೀವು ಅನ್‌ಪಿನ್ ಮಾಡುವವರೆಗೆ ಅದನ್ನು ವೀಕ್ಷಣೆಯಲ್ಲಿಡುತ್ತದೆ. ಅನ್‌ಪಿನ್ ಮಾಡಲು ಒಂದೇ ಸಮಯದಲ್ಲಿ ಸ್ಪರ್ಶಿಸಿ ಮತ್ತು ಒತ್ತಿ ಹಿಡಿದುಕೊಳ್ಳಿ ಹಾಗೂ ಅವಲೋಕಿಸಿ."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"ನೀವು ಅನ್‌ಪಿನ್ ಮಾಡುವವರೆಗೆ ಅದನ್ನು ವೀಕ್ಷಣೆಯಲ್ಲಿಡುತ್ತದೆ. ಅನ್‌ಪಿನ್ ಮಾಡಲು ಅವಲೋಕನವನ್ನು ಸ್ಪರ್ಶಿಸಿ ಮತ್ತು ಹಿಡಿದುಕೊಳ್ಳಿ."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"ತಿಳಿಯಿತು"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"ಧನ್ಯವಾದಗಳು"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> ಮರೆಮಾಡುವುದೇ?"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 4e8be28..c7f5489 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -393,8 +393,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"펼치기"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"접기"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"화면 고정됨"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"고정 해제하기 전까지 계속 표시됩니다. 고정 해제하려면 뒤로와 최근 사용을 동시에 길게 터치합니다."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"고정 해제하기 전까지 계속 표시됩니다. 고정 해제하려면 최근 사용을 길게 터치합니다."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"확인"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"거부"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g>을(를) 숨기시겠습니까?"</string>
diff --git a/packages/SystemUI/res/values-ky-rKG/strings.xml b/packages/SystemUI/res/values-ky-rKG/strings.xml
index fc6897f..f57c9fc 100644
--- a/packages/SystemUI/res/values-ky-rKG/strings.xml
+++ b/packages/SystemUI/res/values-ky-rKG/strings.xml
@@ -393,8 +393,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Жайып көрсөтүү"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Жыйнап коюу"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"Экран кадалган"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"Бул бошотулмайынча көрүнө берет. Бошотуу үчүн, бир убакта Артка жана Карап чыгууну коё бербей басып туруңуз."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"Бул бошотулмайынча көрүнө берет. Бошотуу үчүн, Карап чыгууну коё бербей басып туруңуз."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"Түшүндүм"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"Жок, рахмат"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> жашырылсынбы?"</string>
diff --git a/packages/SystemUI/res/values-lo-rLA/strings.xml b/packages/SystemUI/res/values-lo-rLA/strings.xml
index 6bb2043..18f3111 100644
--- a/packages/SystemUI/res/values-lo-rLA/strings.xml
+++ b/packages/SystemUI/res/values-lo-rLA/strings.xml
@@ -393,8 +393,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"ຂະຫຍາຍ"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"ຫຍໍ້ລົງ"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"ປັກ​ໝຸດໜ້າ​ຈໍ​ແລ້ວ"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"ມັນ​ຈະ​ຮັກ​ສາ​ໜ້າ​ຈໍ​ໄວ້​ໃນ​ມຸມມອງ​ຂອງ​ທ່ານ​ຈົນ​ກວ່າ​ທ່ານ​ຈະ​ຖອດ​ໝຸດ. ​ແຕະ​ປຸ່ມ ກັບ​ຄືນ ແລະ ພາບ​ຮວມ​ ຄ້າງ​ໄວ້​ພ້ອມ​ກັນ​ເພື່ອ​ຖອດ​ໝຸດ."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"ມັນ​ຈະ​ຮັກ​ສາ​ໜ້າ​ຈໍ​ໄວ້​ໃນ​ມຸມມອງ​ຂອງ​ທ່ານ​ຈົນ​ກວ່າ​ທ່ານ​ຈະ​ຖອດ​ໝຸດ. ​ແຕະ​ປຸ່ມ ພາບ​ຮວມ​ ຄ້າງ​ໄວ້​ເພື່ອ​ຖອດ​ໝຸດ."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"ເຂົ້າໃຈແລ້ວ"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"ບໍ່, ຂອບໃຈ"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"ເຊື່ອງ <xliff:g id="TILE_LABEL">%1$s</xliff:g> ຫຼື​ບໍ່?"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 8883cb6..307b7d9 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -395,8 +395,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Išskleisti"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Sutraukti"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"Ekranas prisegtas"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"Tai bus rodoma, kol atsegsite. Kad atsegtumėte, tuo pačiu metu palieskite ir laikykite „Atgal“ ir „Apžvalga“."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"Tai bus rodoma, kol atsegsite. Kad atsegtumėte, palieskite ir laikykite „Apžvalga“."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"Supratau"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"Ne, ačiū"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Slėpti „<xliff:g id="TILE_LABEL">%1$s</xliff:g>“?"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 47ca06a..3660cda 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -394,8 +394,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Izvērst"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Sakļaut"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"Ekrāns ir piesprausts"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"Šādi tas būs redzams līdz brīdim, kad to atspraudīsiet. Lai atspraustu, vienlaikus pieskarieties vienumiem “Atpakaļ” un “Pārskats” un turiet tos nospiestus."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"Šādi tas būs redzams līdz brīdim, kad to atspraudīsiet. Lai atspraustu, pieskarieties vienumam “Pārskats” un turiet to nospiestu."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"Sapratu!"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"Nē, paldies"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Vai paslēpt vienumu <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
diff --git a/packages/SystemUI/res/values-mk-rMK/strings.xml b/packages/SystemUI/res/values-mk-rMK/strings.xml
index 891ffd8..f8d0417 100644
--- a/packages/SystemUI/res/values-mk-rMK/strings.xml
+++ b/packages/SystemUI/res/values-mk-rMK/strings.xml
@@ -395,8 +395,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Прошири"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Собери"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"Екранот е прикачен"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"Ќе се гледа сè додека не го откачите. Допрете и држете Назад и Краток преглед истовремено за откачување."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"Ќе се гледа сè додека не го откачите. Допрете и држете Краток преглед за откачување."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"Сфатив"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"Не, фала"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Сокриј <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
diff --git a/packages/SystemUI/res/values-ml-rIN/strings.xml b/packages/SystemUI/res/values-ml-rIN/strings.xml
index 64d4184..516e846 100644
--- a/packages/SystemUI/res/values-ml-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ml-rIN/strings.xml
@@ -393,8 +393,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"വികസിപ്പിക്കുക"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"ചുരുക്കുക"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"സ്‌ക്രീൻ പിൻ ചെയ്‌തു"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"നിങ്ങൾ അൺപിൻ ചെയ്യുന്നതുവരെ ഇത് കാണുന്ന വിധത്തിൽ നിലനിർത്തുന്നു. അൺപിൻ ചെയ്യാൻ \'മടങ്ങുക\', \'ചുരുക്കവിവരണം\' എന്നിവ ഒരേ സമയം സ്‌പർശിച്ച് പിടിക്കുക."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"നിങ്ങൾ അൺപിൻ ചെയ്യുന്നതുവരെ ഇത് കാണുന്ന വിധത്തിൽ നിലനിർത്തുന്നു. അൺപിൻ ചെയ്യുന്നതിന് \'ചുരുക്കവിവരണം\' സ്‌പർശിച്ചുപിടിക്കുക."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"മനസ്സിലായി"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"വേണ്ട, നന്ദി"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> എന്നത് മറയ്‌ക്കണോ?"</string>
diff --git a/packages/SystemUI/res/values-mn-rMN/strings.xml b/packages/SystemUI/res/values-mn-rMN/strings.xml
index 740ee0d..8cb8df1 100644
--- a/packages/SystemUI/res/values-mn-rMN/strings.xml
+++ b/packages/SystemUI/res/values-mn-rMN/strings.xml
@@ -391,8 +391,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Дэлгэх"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Хураах"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"Дэлгэц эхэнд байрлуулагдсан"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"Таныг эхэнд нээхийг болиулах хүртэл харагдана. Хүрээд, Back дээр удаан дараад хаахдаа Overview-ийг дар"</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"Таныг эхэнд нээхийг болиулах хүртэл харагдана. Хаахын тулд хүрээдOverview-ийг дар"</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"Ойлголоо"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"Үгүй"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g>-ийг нуух уу?"</string>
diff --git a/packages/SystemUI/res/values-mr-rIN/strings.xml b/packages/SystemUI/res/values-mr-rIN/strings.xml
index 00d7bc8..cfa6b5f 100644
--- a/packages/SystemUI/res/values-mr-rIN/strings.xml
+++ b/packages/SystemUI/res/values-mr-rIN/strings.xml
@@ -393,8 +393,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"विस्तृत करा"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"संकुचित करा"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"स्क्रीन पिन केलेली आहे"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"हे आपण अनपिन करेपर्यंत दृश्यामध्ये ते ठेवते. अनपिन करण्यासाठी एकाच वेळी परत आणि अलीकडील ला स्पर्श करा आणि धरून ठेवा आणि विहंगावलोकन करा."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"हे आपण अनपिन करेपर्यंत दृश्यामध्ये ते ठेवते. अनपिन करण्यासाठी स्पर्श करा आणि धरून ठेवा."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"समजले"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"नाही धन्यवाद"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> लपवायचे?"</string>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml
index 10865dd..6ff9a61 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings.xml
@@ -393,8 +393,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Kembangkan"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Runtuhkan"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"Skrin telah disemat"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"Ini akan memastikan skrin kelihatan sehingga anda menyahsemat. Sentuh dan tahan Kembali dan Gambaran Keseluruhan pada masa yang sama untuk menyahsemat."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"Ini akan memastikan skrin kelihatan sehingga anda menyahsemat. Sentuh dan tahan Gambaran Keseluruhan untuk menyahsemat."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"Faham"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"Tidak"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Sembunyikan <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
diff --git a/packages/SystemUI/res/values-my-rMM/strings.xml b/packages/SystemUI/res/values-my-rMM/strings.xml
index 5cb6087..e4b3e54 100644
--- a/packages/SystemUI/res/values-my-rMM/strings.xml
+++ b/packages/SystemUI/res/values-my-rMM/strings.xml
@@ -393,8 +393,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"တိုးချဲ့ရန်"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"ခေါက်သိမ်းရန်..."</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"မျက်နှာပြင် ပင်ထိုးပြီးပါပြီ"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"သင်ပင်ဖြုတ်သည့် တိုင်အောင် ၎င်းအား မြင်ကွင်းတွင် ထားရှိပါမည်။ ပင်ဖြုတ်ရန် အနောက်နှင့် ခြုံငုံကြည့်ခြင်းကို ဖိ၍ နှိပ်ထားနိုင်သည်။"</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"သင်ပင်ဖြုတ်သည့် တိုင်အောင် ၎င်းအား မြင်ကွင်းတွင် ထားရှိပါမည်။ ပင်ဖြုတ်ရန် ခြုံငုံကြည့်ခြင်းကို ဖိ၍ နှိပ်ထားနိုင်သည်။"</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"အဲဒါ ရပြီ"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"မလို ကျေးဇူးပဲ"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> ဝှက်မည်လား?"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 39b404a..2882d7a 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -393,8 +393,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Utvid"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Skjul"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"Skjermen er låst"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"På denne måten blir skjermen synlig frem til du låser den opp. Trykk på og hold inne Tilbake og Oversikt samtidig for å låse opp."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"På denne måten blir skjermen synlig frem til du låser den opp. Trykk på og hold inne Tilbake og Oversikt for å låse opp."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"Skjønner"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"Nei takk"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Vil du skjule <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
diff --git a/packages/SystemUI/res/values-ne-rNP/strings.xml b/packages/SystemUI/res/values-ne-rNP/strings.xml
index 2a312f3..19d84ce 100644
--- a/packages/SystemUI/res/values-ne-rNP/strings.xml
+++ b/packages/SystemUI/res/values-ne-rNP/strings.xml
@@ -393,8 +393,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"विस्तार गर्नुहोस्"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"संक्षिप्त पार्नुहोस्"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"पर्दा राखेका छ"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"तपाईँ अनपिन सम्म यो दृश्य मा राख्छ। छुनुहोस् र अनपिन फिर्ता र सिंहावलोकन नै समय मा पकड।"</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"तपाईँ अनपिन सम्म यो दृश्य मा राख्छ। छुनुहोस् र अनपिन गर्न सिंहावलोकन पकड।"</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"बुझेँ"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"धन्यवाद पर्दैन"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"लुकाउनुहुन्छ <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
@@ -440,7 +440,7 @@
     <string name="qs_rearrange" msgid="8060918697551068765">"द्रुत सेटिङहरू पुनः व्यवस्थित गर्नुहोस्"</string>
     <string name="show_brightness" msgid="6613930842805942519">"द्रुत सेटिङहरूमा उज्यालो देखाउनुहोस्"</string>
     <string name="experimental" msgid="6198182315536726162">"प्रयोगात्मक"</string>
-    <string name="enable_bluetooth_title" msgid="5027037706500635269">"ब्लुटुथ सक्रिय पार्नुहुन्छ?"</string>
+    <string name="enable_bluetooth_title" msgid="5027037706500635269">"ब्लुटुथ सक्रिय पार्ने हो?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"आफ्नो ट्याब्लेटसँग किबोर्ड जोड्न, पहिले तपाईँले ब्लुटुथ सक्रिय गर्नुपर्छ।"</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"सक्रिय पार्नुहोस्"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 6bbb340..95ddeab 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -393,8 +393,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Uitvouwen"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Samenvouwen"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"Scherm is vastgezet"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"Het scherm blijft zichtbaar totdat u het u losmaakt. Houd \'Terug\' en \'Overzicht\' tegelijkertijd aangeraakt om het los te maken."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"Het scherm blijft zichtbaar totdat u het u losmaakt. Houd \'Overzicht\' aangeraakt om het los te maken."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"Ik snap het"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"Nee, bedankt"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> verbergen?"</string>
diff --git a/packages/SystemUI/res/values-pa-rIN/strings.xml b/packages/SystemUI/res/values-pa-rIN/strings.xml
index 61b68c1..6cb50b3 100644
--- a/packages/SystemUI/res/values-pa-rIN/strings.xml
+++ b/packages/SystemUI/res/values-pa-rIN/strings.xml
@@ -393,8 +393,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"ਵਿਸਤਾਰ ਕਰੋ"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"ਨਸ਼ਟ ਕਰੋ"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"ਸਕ੍ਰੀਨ ਪਿੰਨ ਕੀਤੀ"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"ਇਹ ਇਸਨੂੰ ਦ੍ਰਿਸ਼ ਵਿੱਚ ਰੱਖਦਾ ਹੈ ਜਦੋਂ ਤੱਕ ਤੁਸੀਂ ਅਨਪਿਨ ਨਹੀਂ ਕਰਦੇ। ਅਨਪਿਨ ਕਰਨ ਲਈ ਪਿੱਛੇ ਅਤੇ ਰੂਪ-ਰੇਖਾ ਨੂੰ ਇੱਕੋ ਸਮੇਂ ਛੋਹਵੋ ਅਤੇ ਹੋਲਡ ਕਰੋ।"</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"ਇਹ ਇਸਨੂੰ ਦ੍ਰਿਸ਼ ਵਿੱਚ ਰੱਖਦਾ ਹੈ ਜਦੋਂ ਤੱਕ ਤੁਸੀਂ ਅਨਪਿਨ ਨਹੀਂ ਕਰਦੇ। ਅਨਪਿਨ ਕਰਨ ਲਈ ਰੂਪ-ਰੇਖਾ ਨੂੰ ਛੋਹਵੋ ਅਤੇ ਹੋਲਡ ਕਰੋ।"</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"ਸਮਝ ਗਿਆ"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"ਨਹੀਂ ਧੰਨਵਾਦ"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"ਕੀ <xliff:g id="TILE_LABEL">%1$s</xliff:g> ਨੂੰ ਲੁਕਾਉਣਾ ਹੈ?"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index caa3081..1821cdd 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -395,8 +395,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Rozwiń"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Zwiń"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"Ekran jest przypięty"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"Ekran będzie widoczny, dopóki go nie odepniesz. Aby to zrobić, kliknij i przytrzymaj jednocześnie Wstecz i Przegląd."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"Ekran będzie widoczny, dopóki go nie odepniesz. Aby to zrobić, kliknij i przytrzymaj Przegląd."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"OK"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"Nie, dziękuję"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Ukryć <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index b82eb32..68ecfc8 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -395,8 +395,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Expandir"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Recolher"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"A tela está fixada"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"Ela é mantida à vista até que seja liberada. Toque em \"Voltar\" e \"Visão Geral\" e mantenha essas opções pressionadas ao mesmo tempo para liberar."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"Ela é mantida à vista até que seja liberada. Toque em \"Visão geral\" e mantenha essa opção pressionada para liberar."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"Entendi"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"Não, obrigado"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Esconder <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index c137908..61a76f9 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -393,8 +393,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Expandir"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Reduzir"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"O ecrã está fixado"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"Será mantido na vista até soltar. Toque sem soltar em Anterior e Vista geral em simultâneo para soltar."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"Será mantido na vista até soltar. Toque sem soltar em Vista geral para soltar."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"Compreendi"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"Não, obrigado"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Pretende ocultar <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index b82eb32..68ecfc8 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -395,8 +395,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Expandir"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Recolher"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"A tela está fixada"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"Ela é mantida à vista até que seja liberada. Toque em \"Voltar\" e \"Visão Geral\" e mantenha essas opções pressionadas ao mesmo tempo para liberar."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"Ela é mantida à vista até que seja liberada. Toque em \"Visão geral\" e mantenha essa opção pressionada para liberar."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"Entendi"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"Não, obrigado"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Esconder <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index b5819ea..3af273d 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -255,7 +255,7 @@
     <string name="quick_settings_location_off_label" msgid="7464544086507331459">"Localizarea este dezactivată"</string>
     <string name="quick_settings_media_device_label" msgid="1302906836372603762">"Dispozitiv media"</string>
     <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
-    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Numai apeluri de urgenţă"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Numai apeluri de urgență"</string>
     <string name="quick_settings_settings_label" msgid="5326556592578065401">"Setări"</string>
     <string name="quick_settings_time_label" msgid="4635969182239736408">"Ora"</string>
     <string name="quick_settings_user_label" msgid="5238995632130897840">"Eu"</string>
@@ -394,8 +394,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Extindeți"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Restrângeți"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"Ecranul este fixat"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"Ecranul este afișat până anulați fixarea. Apăsați lung pe Înapoi și pe Vizualizare generală simultan pentru a anula fixarea."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"Ecranul este afișat până anulați fixarea. Apăsați lung pe Vizualizare generală pentru a anula fixarea."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"Am înțeles"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"Nu, mulțumesc"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Ascundeți <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 0806684..296876c 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -397,8 +397,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Развернуть"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Свернуть"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"Блокировка в приложении включена"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"Это приложение останется активным, пока вы не отмените блокировку, одновременно нажав кнопки \"Назад\" и \"Обзор\"."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"Приложение останется активным, пока вы не отмените блокировку, одновременно нажав кнопки Назад и Обзор."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"ОК"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"Нет, спасибо"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Скрыть параметр \"<xliff:g id="TILE_LABEL">%1$s</xliff:g>\"?"</string>
diff --git a/packages/SystemUI/res/values-si-rLK/strings.xml b/packages/SystemUI/res/values-si-rLK/strings.xml
index 39147ff..e839aaa 100644
--- a/packages/SystemUI/res/values-si-rLK/strings.xml
+++ b/packages/SystemUI/res/values-si-rLK/strings.xml
@@ -393,8 +393,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"දිග හරින්න"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"හකුළන්න"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"තීරය අමුණන ලදි"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"ඔබ ගලවන තෙක් එය දර්ශනය තුළ මෙය තබයි. ගැලවීමට ආපසු සහ දළ විශ්ලේෂණය එකම වේලාවක ස්පර්ෂ කර අල්ලා සිටින්න."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"ඔබ ගලවන තෙක් එය දර්ශනය තුළ මෙය තබයි. ගැලවීමට දළ විශ්ලේෂණය ස්පර්ෂ කර අල්ලා සිටින්න."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"හරි, තේරුණා"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"එපා ස්තූතියි"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> සඟවන්නද?"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 86c8fe2..ebfd035 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -397,8 +397,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Rozbaliť"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Zbaliť"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"Obrazovka je pripnutá"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"Obsah bude pripnutý v zobrazení, dokým ho neuvoľníte. Ak ho chcete uvoľniť, stlačte a podržte súčasne tlačidlá Späť a Prehľad."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"Obsah bude pripnutý v zobrazení, dokým ho neuvoľníte. Uvoľníte ho stlačením a podržaním tlačidla Prehľad."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"Dobre"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"Nie, vďaka"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Skryť <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index c5dd188..d87b9a4 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -395,8 +395,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Razširi"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Strni"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"Zaslon je pripet"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"S tem ostane zaslon v pogledu, dokler ga ne odpnete. Hkrati pridržite tipko za nazaj in tipko za pregled, če ga želite odpeti."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"S tem ostane zaslon v pogledu, dokler ga ne odpnete. Pridržite tipko za pregled, če ga želite odpeti."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"Razumem"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"Ne, hvala"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Želite skriti <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
diff --git a/packages/SystemUI/res/values-sq-rAL/strings.xml b/packages/SystemUI/res/values-sq-rAL/strings.xml
index fcd65f7..5519e6b 100644
--- a/packages/SystemUI/res/values-sq-rAL/strings.xml
+++ b/packages/SystemUI/res/values-sq-rAL/strings.xml
@@ -393,8 +393,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Zgjeroje"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Mbylle"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"Ekrani u gozhdua"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"Kjo e ruan në pamje derisa e heq nga gozhdimi. Prek dhe mbaj shtypur njëkohësisht \"Prapa\" dhe \"Përmbledhje\" për ta hequr nga gozhdimi."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"Kjo e ruan në pamje derisa e heq nga gozhdimi. Prek dhe mbaj shtypur njëkohësisht \"Përmbledhje\" për ta hequr nga gozhdimi."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"E kuptova!"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"Jo, faleminderit!"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Të fshihet <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 2c55a5c..67959f5 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -394,8 +394,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Прошири"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Скупи"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"Екран је закачен"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"На овај начин ово остаје приказано док га не откачите. Истовремено додирните и задржите Назад и Преглед да бисте га откачили."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"На овај начин ово остаје приказано док га не откачите. Додирните и задржите Преглед да бисте га откачили."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"Важи"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"Не, хвала"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Желите ли да сакријете <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index e8b1765..48fe512 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -393,8 +393,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Utöka"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Komprimera"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"Skärmen har fästs"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"Med den här funktionen är skärmen synlig tills du lossar den. Tryck länge på Tillbaka och Översikt samtidigt om du vill lossa skärmen."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"Detta visar skärmen tills du lossar den. Tryck länge på Översikt om du vill lossa skärmen."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"OK"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"Nej tack"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Vill du dölja <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index bbe271d..2b65540 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -393,8 +393,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Panua"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Kunja"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"Skrini imebandikwa"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"Hii itaendelea kuonyesha hadi ubandue. Gusa na ushikilie Nyuma na Muhtasari kwa wakati mmoja ili ubandue."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"Hii itaendelea kuonyesha hadi uibandue. Gusa na ushikilie Muhtasari ili ubandue."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"Nimeelewa"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"Hapana, asante"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Ungependa kuficha <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
diff --git a/packages/SystemUI/res/values-ta-rIN/strings.xml b/packages/SystemUI/res/values-ta-rIN/strings.xml
index 08bef13..1f4a4a2 100644
--- a/packages/SystemUI/res/values-ta-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ta-rIN/strings.xml
@@ -393,8 +393,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"விரிவாக்கு"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"சுருக்கு"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"திரை பொருத்தப்பட்டது"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"பொருத்தியதை விலக்கும்வரை இதைக் காட்சியில் வைக்கும். விலக்க, பின் மற்றும் மேலோட்டப் பார்வையை ஒரே நேரத்தில் தொட்டுப் பிடிக்கவும்."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"பொருத்தியதை விலக்கும்வரை இதைக் காட்சியில் வைக்கும். விலக்க, மேலோட்டப் பார்வையைத் தொட்டுப் பிடிக்கவும்."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"புரிந்தது"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"வேண்டாம்"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g>ஐ மறைக்கவா?"</string>
diff --git a/packages/SystemUI/res/values-te-rIN/strings.xml b/packages/SystemUI/res/values-te-rIN/strings.xml
index 46bc704..d0b3439 100644
--- a/packages/SystemUI/res/values-te-rIN/strings.xml
+++ b/packages/SystemUI/res/values-te-rIN/strings.xml
@@ -393,8 +393,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"విస్తరింపజేయండి"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"కుదించండి"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"స్క్రీన్ పిన్ చేయబడింది"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"ఇది మీరు అన్‌పిన్ చేసే వరకు దీన్ని వీక్షణలో ఉంచుతుంది. అన్‌పిన్ చేయడానికి వెనుకకు మరియు స్థూలదృష్టిని ఒకేసారి తాకి, ఉంచండి."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"ఇది మీరు అన్‌పిన్ చేసే వరకు దీన్ని వీక్షణలో ఉంచుతుంది. అన్‌పిన్ చేయడానికి స్థూలదృష్టిని తాకి, ఉంచండి."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"అర్థమైంది"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"వద్దు, ధన్యవాదాలు"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g>ని దాచాలా?"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index f7e7be0..cb2921d 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -393,8 +393,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"ขยาย"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"ยุบ"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"ตรึงหน้าจอแล้ว"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"การดำเนินการนี้จะเปิดหน้าจอนี้ไว้เสมอจนกว่าคุณจะเลิกตรึง แตะ \"กลับ\" และ \"ภาพรวม\" พร้อมกันค้างไว้เพื่อเลิกตรึง"</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"การดำเนินการนี้จะเปิดหน้าจอนี้ไว้เสมอจนกว่าคุณจะเลิกตรึง แตะ \"ภาพรวม\" ค้างไว้เพื่อเลิกตรึง"</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"รับทราบ"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"ไม่เป็นไร ขอบคุณ"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"ซ่อน <xliff:g id="TILE_LABEL">%1$s</xliff:g> ไหม"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 92a6cdc..43969e9 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -393,8 +393,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Palawakin"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"I-collapse"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"Naka-pin ang screen"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"Pinapanatili nitong nasa view ito hanggang sa mag-unpin ka. Pindutin nang matagal ang Bumalik at Pangkalahatang-ideya nang sabay upang mag-unpin."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"Pinapanatili nitong nasa view ito hanggang sa mag-unpin ka. Pindutin nang matagal ang Pangkalahatang-ideya upang mag-unpin."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"Nakuha ko"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"Hindi, salamat na lang"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Itago ang <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 2b9d6da..7a044ef 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -393,8 +393,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Genişlet"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Daralt"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"Ekran sabitlendi"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"Böylece siz sabitlemesini kaldırana kadar görüntülenmeye devam eder. Sabitlemeyi kaldırmak için Geri ve Genel Bakış öğesine aynı anda dokunun ve basılı tutun."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"Böylece siz sabitlemesini kaldırana kadar görüntülenmeye devam eder. Sabitlemeyi kaldırmak için Genel Bakış\'a dokunun ve basılı tutun."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"Anladım"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"Hayır, teşekkürler"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> gizlensin mi?"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index c040439..37030ac 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -395,8 +395,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Розгорнути"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Згорнути"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"Екран закріплено"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"Закріпить екран, щоб ви могли постійно його бачити, доки не відкріпите. Щоб відкріпити, одночасно натисніть і втримуйте кнопки \"Назад\" і \"Огляд\"."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"Закріпить екран, щоб ви могли постійно його бачити, доки не відкріпите. Щоб відкріпити, натисніть і втримуйте кнопку \"Огляд\"."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"Зрозуміло"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"Ні, дякую"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Сховати <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
diff --git a/packages/SystemUI/res/values-ur-rPK/strings.xml b/packages/SystemUI/res/values-ur-rPK/strings.xml
index b0a5336..0712f98 100644
--- a/packages/SystemUI/res/values-ur-rPK/strings.xml
+++ b/packages/SystemUI/res/values-ur-rPK/strings.xml
@@ -393,8 +393,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"پھیلائیں"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"سکیڑیں"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"اسکرین پن کردہ ہے"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"یہ اس کو اس وقت تک منظر میں رکھتا ہے جب تک آپ اس سے پن نہیں ہٹا دیتے۔ پن ہٹانے کیلئے واپس اور عمومی جائزہ کو ایک ساتھ ٹچ کریں اور پکڑ کر رکھیں۔"</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"یہ اس کو اس وقت تک منظر میں رکھتا ہے جب تک آپ اس سے پن نہیں ہٹا دیتے۔ پن ہٹانے کیلئے عمومی جائزہ کو ٹچ کریں اور پکڑ کر رکھیں۔"</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"سمجھ آ گئی"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"نہیں شکریہ"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> کو چھپائیں؟"</string>
diff --git a/packages/SystemUI/res/values-uz-rUZ/strings.xml b/packages/SystemUI/res/values-uz-rUZ/strings.xml
index 9b9e2cd..ad3dcc7 100644
--- a/packages/SystemUI/res/values-uz-rUZ/strings.xml
+++ b/packages/SystemUI/res/values-uz-rUZ/strings.xml
@@ -393,8 +393,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Yoyish"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Yig‘ish"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"Ekran qadaldi"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"Ekran yechilmaguncha u qadalgan holatda qoladi. Uni yechish uchun “Orqaga” va “Umumiy nazar” tugmalarini bir vaqtda bosing va ushlab turing."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"Ekran yechilmaguncha u qadalgan holatda qoladi. Uni yechish uchun “Umumiy nazar” tugmasini bosing va ushlab turing."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"OK"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"Yo‘q, kerakmas"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> berkitilsinmi?"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index d4ed7a5..f13033b 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -393,8 +393,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Mở rộng"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Thu gọn"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"Màn hình được ghim"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"Thao tác này sẽ duy trì hiển thị màn hình cho đến khi bạn bỏ ghim. Chạm và giữ nút Quay lại và Tổng quan cùng một lúc để bỏ ghim."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"Thao tác này sẽ duy trì hiển thị màn hình cho đến khi bạn bỏ ghim. Chạm và giữ nút Quay lại để bỏ ghim."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"Ok"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"Không, cảm ơn"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Ẩn <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 05416ca..ade7636 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -395,8 +395,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"展开"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"收起"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"已固定屏幕"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"这将会固定显示此屏幕,直到您取消固定为止。触摸并同时按住“返回”和“概览”即可取消固定屏幕。"</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"这将会固定显示此屏幕,直到您取消固定为止。触摸并按住“概览”即可取消固定屏幕。"</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"知道了"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"不用了"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"要隐藏“<xliff:g id="TILE_LABEL">%1$s</xliff:g>”吗?"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index ba4d3cb..aa6e065c 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -395,8 +395,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"展開"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"收合"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"螢幕已固定"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"在您取消固定前,它會保持在檢視狀態。輕觸並同時按住 [返回] 和 [概覽],即可取消固定。"</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"在您取消固定前,它會保持在檢視狀態。輕觸並按住 [概覽] 即可取消固定。"</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"知道了"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"不用了,謝謝"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"隱藏 <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 6e0c852..ffaaefe 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -395,8 +395,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"展開"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"收合"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"螢幕已固定"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"這會讓目前的螢幕畫面保持顯示狀態,直到取消固定為止。同時按住返回按鈕和總覽按鈕即可取消固定。"</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"這會讓目前的螢幕畫面保持顯示狀態,直到取消固定為止。按住總覽按鈕即可取消固定。"</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"知道了"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"不用了,謝謝"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"隱藏<xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 147f6b6..f1df714 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -393,8 +393,8 @@
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Nweba"</string>
     <string name="accessibility_volume_collapse" msgid="3609549593031810875">"Goqa"</string>
     <string name="screen_pinning_title" msgid="3273740381976175811">"Isikrini siphiniwe"</string>
-    <string name="screen_pinning_description" msgid="1346522416878235405">"Lokhu kukugcina kubukeka uze ususe ukuphina. Thinta futhi ubambe u-Emuva no-Ukubuka konke ngesikhathi esisodwa ukuze ususe ukuphina."</string>
-    <string name="screen_pinning_description_accessible" msgid="8518446209564202557">"Lokhu kukugcina kubukeka uze ususe ukuphina. Thinta futhi ubambe u-Ukubuka konke ukuze ususe ukuphina."</string>
+    <!-- no translation found for screen_pinning_description (3577937698406151604) -->
+    <skip />
     <string name="screen_pinning_positive" msgid="3783985798366751226">"Ngiyitholile"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"Cha ngiyabonga"</string>
     <string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Fihla i-<xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index bae8017..07c59a9 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -136,7 +136,7 @@
     <integer name="touch_acceptance_delay">700</integer>
 
     <!-- The duration in seconds to wait before the dismiss buttons are shown. -->
-    <integer name="recents_task_bar_dismiss_delay_seconds">1</integer>
+    <integer name="recents_task_bar_dismiss_delay_seconds">1000</integer>
 
     <!-- The min animation duration for animating views that are currently visible. -->
     <integer name="recents_filter_animate_current_views_duration">250</integer>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 3a5680d..7c86f96 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -999,9 +999,7 @@
     <!-- Screen pinning dialog title. -->
     <string name="screen_pinning_title">Screen is pinned</string>
     <!-- Screen pinning dialog description. -->
-    <string name="screen_pinning_description">This keeps it in view until you unpin. Touch and hold Back and Overview at the same time to unpin.</string>
-    <!-- Screen pinning dialog description when in accessibility mode. -->
-    <string name="screen_pinning_description_accessible">This keeps it in view until you unpin. Touch and hold Overview to unpin.</string>
+    <string name="screen_pinning_description">This keeps it in view until you unpin. Touch and hold Back to unpin.</string>
     <!-- Screen pinning positive response. -->
     <string name="screen_pinning_positive">Got it</string>
     <!-- Screen pinning negative response. -->
diff --git a/packages/SystemUI/src/com/android/systemui/RecentsComponent.java b/packages/SystemUI/src/com/android/systemui/RecentsComponent.java
index 1d0bfe7..9a4cd93 100644
--- a/packages/SystemUI/src/com/android/systemui/RecentsComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/RecentsComponent.java
@@ -27,4 +27,9 @@
     void cancelPreloadingRecents();
     void showNextAffiliatedTask();
     void showPrevAffiliatedTask();
+
+    /**
+     * Docks the top-most task and opens recents.
+     */
+    void dockTopTask();
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Constants.java b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
index cdb6b93..6668df9 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Constants.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
@@ -37,6 +37,8 @@
             public static final boolean EnableTaskFiltering = false;
             // Enables dismiss-all
             public static final boolean EnableDismissAll = false;
+            // Enables fast-toggling
+            public static final boolean EnableFastToggleRecents = false;
             // Enables the thumbnail alpha on the front-most task
             public static final boolean EnableThumbnailAlphaOnFrontmost = false;
             // This disables the search bar integration
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
index c216f97..9400108 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
@@ -284,6 +284,11 @@
     }
 
     @Override
+    public void dockTopTask() {
+        mImpl.dockTopTask();
+    }
+
+    @Override
     public void showNextAffiliatedTask() {
         mImpl.showNextAffiliatedTask();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index c416967..0adad85 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -32,6 +32,7 @@
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.provider.Settings;
+import android.util.Log;
 import android.view.KeyEvent;
 import android.view.View;
 import android.view.ViewStub;
@@ -41,16 +42,21 @@
 import com.android.systemui.recents.events.activity.AppWidgetProviderChangedEvent;
 import com.android.systemui.recents.events.activity.EnterRecentsWindowAnimationStartedEvent;
 import com.android.systemui.recents.events.activity.HideRecentsEvent;
+import com.android.systemui.recents.events.activity.IterateRecentsEvent;
 import com.android.systemui.recents.events.activity.ToggleRecentsEvent;
 import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
 import com.android.systemui.recents.events.component.ScreenPinningRequestEvent;
-import com.android.systemui.recents.events.ui.DismissTaskEvent;
+import com.android.systemui.recents.events.ui.DismissTaskViewEvent;
 import com.android.systemui.recents.events.ui.ResizeTaskEvent;
 import com.android.systemui.recents.events.ui.ShowApplicationInfoEvent;
 import com.android.systemui.recents.events.ui.UserInteractionEvent;
 import com.android.systemui.recents.events.ui.dragndrop.DragEndEvent;
 import com.android.systemui.recents.events.ui.dragndrop.DragStartEvent;
+import com.android.systemui.recents.events.ui.focus.DismissFocusedTaskViewEvent;
+import com.android.systemui.recents.events.ui.focus.FocusNextTaskViewEvent;
+import com.android.systemui.recents.events.ui.focus.FocusPreviousTaskViewEvent;
 import com.android.systemui.recents.misc.Console;
+import com.android.systemui.recents.misc.DozeTrigger;
 import com.android.systemui.recents.misc.ReferenceCountedTrigger;
 import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.recents.model.RecentsPackageMonitor;
@@ -69,6 +75,9 @@
  */
 public class RecentsActivity extends Activity implements RecentsView.RecentsViewCallbacks {
 
+    private final static String TAG = "RecentsActivity";
+    private final static boolean DEBUG = false;
+
     public final static int EVENT_BUS_PRIORITY = Recents.EVENT_BUS_PRIORITY + 1;
 
     RecentsConfiguration mConfig;
@@ -96,6 +105,14 @@
     // Runnable to be executed after we paused ourselves
     Runnable mAfterPauseRunnable;
 
+    // The trigger to automatically launch the current task
+    DozeTrigger mIterateTrigger = new DozeTrigger(500, new Runnable() {
+        @Override
+        public void run() {
+            boolean dismissed = dismissRecentsToFocusedTask(false);
+        }
+    });
+
     /**
      * A common Runnable to finish Recents either by calling finish() (with a custom animation) or
      * launching Home with some ActivityOptions.  Generally we always launch home when we exit
@@ -244,7 +261,24 @@
         MetricsLogger.histogram(this, "overview_task_count", taskCount);
     }
 
-    /** Dismisses recents if we are already visible and the intent is to toggle the recents view */
+    /**
+     * Dismisses recents if we are already visible and the intent is to toggle the recents view.
+     */
+    boolean dismissRecentsToFocusedTask(boolean checkFilteredStackState) {
+        SystemServicesProxy ssp = Recents.getSystemServices();
+        if (ssp.isRecentsTopMost(ssp.getTopMostTask(), null)) {
+            // If we currently have filtered stacks, then unfilter those first
+            if (checkFilteredStackState &&
+                    mRecentsView.unfilterFilteredStacks()) return true;
+            // If we have a focused Task, launch that Task now
+            if (mRecentsView.launchFocusedTask()) return true;
+        }
+        return false;
+    }
+
+    /**
+     * Dismisses recents if we are already visible and the intent is to toggle the recents view.
+     */
     boolean dismissRecentsToFocusedTaskOrHome(boolean checkFilteredStackState) {
         RecentsActivityLaunchState launchState = mConfig.getLaunchState();
         SystemServicesProxy ssp = Recents.getSystemServices();
@@ -390,6 +424,11 @@
             mRecentsView.post(mAfterPauseRunnable);
             mAfterPauseRunnable = null;
         }
+
+        if (Constants.DebugFlags.App.EnableFastToggleRecents) {
+            // Stop the fast-toggle dozer
+            mIterateTrigger.stopDozing();
+        }
     }
 
     @Override
@@ -467,22 +506,27 @@
                 if (event.getRepeatCount() <= 0 || hasRepKeyTimeElapsed) {
                     // Focus the next task in the stack
                     final boolean backward = event.isShiftPressed();
-                    mRecentsView.focusNextTask(!backward);
+                    if (backward) {
+                        EventBus.getDefault().send(new FocusPreviousTaskViewEvent());
+                    } else {
+                        EventBus.getDefault().send(new FocusNextTaskViewEvent());
+                    }
                     mLastTabKeyEventTime = SystemClock.elapsedRealtime();
                 }
                 return true;
             }
             case KeyEvent.KEYCODE_DPAD_UP: {
-                mRecentsView.focusNextTask(true);
+                EventBus.getDefault().send(new FocusNextTaskViewEvent());
                 return true;
             }
             case KeyEvent.KEYCODE_DPAD_DOWN: {
-                mRecentsView.focusNextTask(false);
+                EventBus.getDefault().send(new FocusPreviousTaskViewEvent());
                 return true;
             }
             case KeyEvent.KEYCODE_DEL:
             case KeyEvent.KEYCODE_FORWARD_DEL: {
-                mRecentsView.dismissFocusedTask();
+                EventBus.getDefault().send(new DismissFocusedTaskViewEvent());
+
                 // Keep track of deletions by keyboard
                 MetricsLogger.histogram(this, "overview_task_dismissed_source",
                         Constants.Metrics.DismissSourceKeyboard);
@@ -542,6 +586,16 @@
         dismissRecentsToFocusedTaskOrHome(true /* checkFilteredStackState */);
     }
 
+    public final void onBusEvent(IterateRecentsEvent event) {
+        // Focus the next task
+        EventBus.getDefault().send(new FocusNextTaskViewEvent());
+        mIterateTrigger.poke();
+    }
+
+    public final void onBusEvent(UserInteractionEvent event) {
+        mIterateTrigger.stopDozing();
+    }
+
     public final void onBusEvent(HideRecentsEvent event) {
         if (event.triggeredFromAltTab) {
             // If we are hiding from releasing Alt-Tab, dismiss Recents to the focused app
@@ -558,7 +612,7 @@
         // Try and start the enter animation (or restart it on configuration changed)
         ReferenceCountedTrigger t = new ReferenceCountedTrigger(this, null, null, null);
         ViewAnimation.TaskViewEnterContext ctx = new ViewAnimation.TaskViewEnterContext(t);
-        mRecentsView.startEnterRecentsAnimation(ctx);
+        ctx.postAnimationTrigger.increment();
         if (mSearchWidgetInfo != null) {
             ctx.postAnimationTrigger.addLastDecrementRunnable(new Runnable() {
                 @Override
@@ -570,6 +624,20 @@
                 }
             });
         }
+        ctx.postAnimationTrigger.addLastDecrementRunnable(new Runnable() {
+            @Override
+            public void run() {
+                // If we are not launching with alt-tab and fast-toggle is enabled, then start
+                // the dozer now
+                RecentsActivityLaunchState launchState = mConfig.getLaunchState();
+                if (Constants.DebugFlags.App.EnableFastToggleRecents &&
+                        !launchState.launchedWithAltTab) {
+                    mIterateTrigger.startDozing();
+                }
+            }
+        });
+        mRecentsView.startEnterRecentsAnimation(ctx);
+        ctx.postAnimationTrigger.decrement();
     }
 
     public final void onBusEvent(AppWidgetProviderChangedEvent event) {
@@ -589,7 +657,7 @@
         MetricsLogger.count(this, "overview_app_info", 1);
     }
 
-    public final void onBusEvent(DismissTaskEvent event) {
+    public final void onBusEvent(DismissTaskViewEvent event) {
         // Remove any stored data from the loader
         RecentsTaskLoader loader = Recents.getTaskLoader();
         loader.deleteTaskData(event.task, false);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java
index e2e0e918..76b666f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java
@@ -56,7 +56,7 @@
 
     /** Returns whether the status bar scrim should be animated when shown for the first time. */
     public boolean shouldAnimateStatusBarScrim() {
-        return launchedFromHome;
+        return true;
     }
 
     /** Returns whether the status bar scrim should be visible. */
@@ -72,6 +72,6 @@
     /** Returns whether the nav bar scrim should be visible. */
     public boolean hasNavBarScrim() {
         // Only show the scrim if we have recent tasks, and if the nav bar is not transposed
-        return !launchedWithNoRecentTasks && mConfig.hasTransposedNavBar;
+        return !launchedWithNoRecentTasks && !mConfig.hasTransposedNavBar;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index 07c7897..b05e1fe 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -40,6 +40,7 @@
 import com.android.systemui.recents.events.EventBus;
 import com.android.systemui.recents.events.activity.EnterRecentsWindowAnimationStartedEvent;
 import com.android.systemui.recents.events.activity.HideRecentsEvent;
+import com.android.systemui.recents.events.activity.IterateRecentsEvent;
 import com.android.systemui.recents.events.activity.ToggleRecentsEvent;
 import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
 import com.android.systemui.recents.events.component.ScreenPinningRequestEvent;
@@ -265,26 +266,38 @@
         mTriggeredFromAltTab = false;
 
         try {
-            // If the user has toggled it too quickly, then just eat up the event here (it's better
-            // than showing a janky screenshot).
-            // NOTE: Ideally, the screenshot mechanism would take the window transform into account
-            if ((SystemClock.elapsedRealtime() - mLastToggleTime) < sMinToggleDelay) {
-                return;
-            }
-
-            // If Recents is the front most activity, then we should just communicate with it
-            // directly to launch the first task or dismiss itself
             SystemServicesProxy ssp = Recents.getSystemServices();
             ActivityManager.RunningTaskInfo topTask = ssp.getTopMostTask();
             MutableBoolean isTopTaskHome = new MutableBoolean(true);
             if (topTask != null && ssp.isRecentsTopMost(topTask, isTopTaskHome)) {
-                // Notify recents to toggle itself
-                EventBus.getDefault().post(new ToggleRecentsEvent());
-                mLastToggleTime = SystemClock.elapsedRealtime();
+                if (Constants.DebugFlags.App.EnableFastToggleRecents) {
+                    // Notify recents to move onto the next task
+                    EventBus.getDefault().post(new IterateRecentsEvent());
+                } else {
+                    // If the user has toggled it too quickly, then just eat up the event here (it's
+                    // better than showing a janky screenshot).
+                    // NOTE: Ideally, the screenshot mechanism would take the window transform into
+                    // account
+                    if ((SystemClock.elapsedRealtime() - mLastToggleTime) < sMinToggleDelay) {
+                        return;
+                    }
+
+                    EventBus.getDefault().post(new ToggleRecentsEvent());
+                    mLastToggleTime = SystemClock.elapsedRealtime();
+                }
                 return;
             } else {
+                // If the user has toggled it too quickly, then just eat up the event here (it's
+                // better than showing a janky screenshot).
+                // NOTE: Ideally, the screenshot mechanism would take the window transform into
+                // account
+                if ((SystemClock.elapsedRealtime() - mLastToggleTime) < sMinToggleDelay) {
+                    return;
+                }
+
                 // Otherwise, start the recents activity
                 startRecentsActivity(topTask, isTopTaskHome.value);
+                mLastToggleTime = SystemClock.elapsedRealtime();
             }
         } catch (ActivityNotFoundException e) {
             Console.logRawError("Failed to launch RecentAppsIntent", e);
@@ -333,7 +346,7 @@
         // Return early if there is no running task (can't determine affiliated tasks in this case)
         if (runningTask == null) return;
         // Return early if the running task is in the home stack (optimization)
-        if (ssp.isInHomeStack(runningTask.id)) return;
+        if (SystemServicesProxy.isHomeStack(runningTask.stackId)) return;
 
         // Find the task in the recents list
         ArrayList<Task> tasks = focusedStack.getTasks();
@@ -405,6 +418,16 @@
         showRelativeAffiliatedTask(false);
     }
 
+    public void dockTopTask() {
+        SystemServicesProxy ssp = Recents.getSystemServices();
+        ActivityManager.RunningTaskInfo topTask = ssp.getTopMostTask();
+        if (topTask != null && !SystemServicesProxy.isHomeStack(topTask.stackId)) {
+            ssp.startTaskInDockedMode(topTask.id,
+                    ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT);
+            showRecents(false /* triggeredFromAltTab */);
+        }
+    }
+
     /**
      * Returns the preloaded load plan and invalidates it.
      */
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsResizeTaskDialog.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsResizeTaskDialog.java
index 31ee8ad..28299d3 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsResizeTaskDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsResizeTaskDialog.java
@@ -234,14 +234,6 @@
         dismissAllowingStateLoss();
         mRecentsActivity.dismissRecentsToHomeWithoutTransitionAnimation();
 
-        // In debug mode, we force all task to be resizeable regardless of the
-        // current app configuration.
-        for (int i = additionalTasks; i >= 0; --i) {
-            if (mTasks[i] != null) {
-                ssp.setTaskResizeable(mTasks[i].key.id);
-            }
-        }
-
         // Show tasks as they might not be currently visible - beginning with the oldest so that
         // the focus ends on the selected one.
         for (int i = additionalTasks; i >= 0; --i) {
@@ -277,8 +269,7 @@
         if (mTasks[0].key.stackId != DOCKED_STACK_ID) {
             int taskId = mTasks[0].key.id;
             SystemServicesProxy ssp = Recents.getSystemServices();
-            ssp.setTaskResizeable(taskId);
-            ssp.dockTask(taskId, createMode);
+            ssp.startTaskInDockedMode(taskId, createMode);
             mRecentsView.launchTask(mTasks[0], null, DOCKED_STACK_ID);
         } else {
             Toast.makeText(getContext(), "Already docked", Toast.LENGTH_SHORT);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
index 231843e..10075bc 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
@@ -214,11 +214,8 @@
                         .setVisibility(View.INVISIBLE);
             }
 
-            final int description = mAccessibilityService.isEnabled()
-                    ? R.string.screen_pinning_description_accessible
-                    : R.string.screen_pinning_description;
             ((TextView) mLayout.findViewById(R.id.screen_pinning_description))
-                    .setText(description);
+                    .setText(R.string.screen_pinning_description);
             final int backBgVisibility =
                     mAccessibilityService.isEnabled() ? View.INVISIBLE : View.VISIBLE;
             mLayout.findViewById(R.id.screen_pinning_back_bg).setVisibility(backBgVisibility);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/EventBus.java b/packages/SystemUI/src/com/android/systemui/recents/events/EventBus.java
index fec0fc5..deae4c8 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/EventBus.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/EventBus.java
@@ -200,7 +200,8 @@
  */
 public class EventBus extends BroadcastReceiver {
 
-    public static final String TAG = "EventBus";
+    private static final String TAG = "EventBus";
+    private static final boolean DEBUG_TRACE_ALL = false;
 
     /**
      * An event super class that allows us to track internal event state across subscriber
@@ -277,9 +278,6 @@
     // The default priority of all subscribers
     private static final int DEFAULT_SUBSCRIBER_PRIORITY = 1;
 
-    // Used for debugging everything
-    private static final boolean DEBUG_TRACE_ALL = false;
-
     // Orders the handlers by priority and registration time
     private static final Comparator<EventHandler> EVENT_HANDLER_COMPARATOR = new Comparator<EventHandler>() {
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/IterateRecentsEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/IterateRecentsEvent.java
new file mode 100644
index 0000000..f7b2706
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/IterateRecentsEvent.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.recents.events.activity;
+
+import com.android.systemui.recents.events.EventBus;
+
+/**
+ * This is sent when the user taps on the Overview button to iterate to the next item in the
+ * Recents list.
+ */
+public class IterateRecentsEvent extends EventBus.Event {
+    // Simple event
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/DismissTaskEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/DismissTaskViewEvent.java
similarity index 89%
rename from packages/SystemUI/src/com/android/systemui/recents/events/ui/DismissTaskEvent.java
rename to packages/SystemUI/src/com/android/systemui/recents/events/ui/DismissTaskViewEvent.java
index 12e5d3d..968890a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/ui/DismissTaskEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/ui/DismissTaskViewEvent.java
@@ -23,12 +23,12 @@
 /**
  * This is sent when a {@link TaskView} has been dismissed.
  */
-public class DismissTaskEvent extends EventBus.Event {
+public class DismissTaskViewEvent extends EventBus.Event {
 
     public final Task task;
     public final TaskView taskView;
 
-    public DismissTaskEvent(Task task, TaskView taskView) {
+    public DismissTaskViewEvent(Task task, TaskView taskView) {
         this.task = task;
         this.taskView = taskView;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/focus/DismissFocusedTaskViewEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/focus/DismissFocusedTaskViewEvent.java
new file mode 100644
index 0000000..9f3e9d5
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/ui/focus/DismissFocusedTaskViewEvent.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.recents.events.ui.focus;
+
+import com.android.systemui.recents.events.EventBus;
+
+/**
+ * Dismisses the currently focused task view.
+ */
+public class DismissFocusedTaskViewEvent extends EventBus.Event {
+    // Simple event
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/focus/FocusNextTaskViewEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/focus/FocusNextTaskViewEvent.java
new file mode 100644
index 0000000..171ab5e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/ui/focus/FocusNextTaskViewEvent.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.recents.events.ui.focus;
+
+import com.android.systemui.recents.events.EventBus;
+
+/**
+ * Focuses the next task view in the stack.
+ */
+public class FocusNextTaskViewEvent extends EventBus.Event {
+    // Simple event
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/focus/FocusPreviousTaskViewEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/focus/FocusPreviousTaskViewEvent.java
new file mode 100644
index 0000000..22469e7
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/ui/focus/FocusPreviousTaskViewEvent.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.recents.events.ui.focus;
+
+import com.android.systemui.recents.events.EventBus;
+
+/**
+ * Focuses the previous task view in the stack.
+ */
+public class FocusPreviousTaskViewEvent extends EventBus.Event {
+    // Simple event
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/DozeTrigger.java b/packages/SystemUI/src/com/android/systemui/recents/misc/DozeTrigger.java
index 735f79f..336d2db 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/DozeTrigger.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/DozeTrigger.java
@@ -19,8 +19,8 @@
 import android.os.Handler;
 
 /**
- * A dozer is a class that fires a trigger after it falls asleep.  You can occasionally poke it to
- * wake it up, but it will fall asleep if left untouched.
+ * A dozer is a class that fires a trigger after it falls asleep.
+ * You can occasionally poke the trigger to wake it up, but it will fall asleep if left untouched.
  */
 public class DozeTrigger {
 
@@ -28,7 +28,7 @@
 
     boolean mIsDozing;
     boolean mHasTriggered;
-    int mDozeDurationSeconds;
+    int mDozeDurationMilliseconds;
     Runnable mSleepRunnable;
 
     // Sleep-runnable
@@ -41,9 +41,9 @@
         }
     };
 
-    public DozeTrigger(int dozeDurationSeconds, Runnable sleepRunnable) {
+    public DozeTrigger(int dozeDurationMilliseconds, Runnable sleepRunnable) {
         mHandler = new Handler();
-        mDozeDurationSeconds = dozeDurationSeconds;
+        mDozeDurationMilliseconds = dozeDurationMilliseconds;
         mSleepRunnable = sleepRunnable;
     }
 
@@ -69,7 +69,7 @@
     /** Poke this dozer to wake it up for a little bit. */
     void forcePoke() {
         mHandler.removeCallbacks(mDozeRunnable);
-        mHandler.postDelayed(mDozeRunnable, mDozeDurationSeconds * 1000);
+        mHandler.postDelayed(mDozeRunnable, mDozeDurationMilliseconds);
         mIsDozing = true;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index a51e475..141562c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -247,8 +247,10 @@
                 return true;
             }
 
+            // Note, this is only valid because we currently only allow the recents and home
+            // activities in the home stack
             if (isHomeTopMost != null) {
-                isHomeTopMost.value = isInHomeStack(topTask.id);
+                isHomeTopMost.value = SystemServicesProxy.isHomeStack(topTask.stackId);
             }
         }
         return false;
@@ -266,17 +268,6 @@
         return null;
     }
 
-    /** Allow a task to resize. */
-    public void setTaskResizeable(int taskId) {
-        if (mIam == null) return;
-
-        try {
-            mIam.setTaskResizeable(taskId, true);
-        } catch (RemoteException e) {
-            e.printStackTrace();
-        }
-    }
-
     /**
      * Resizes the given task to the new bounds.
      */
@@ -290,12 +281,14 @@
         }
     }
 
-    /** Docks a task to the side of the screen. */
-    public void dockTask(int taskId, int createMode) {
+    /** Docks a task to the side of the screen and starts it. */
+    public void startTaskInDockedMode(int taskId, int createMode) {
         if (mIam == null) return;
 
         try {
-            mIam.startActivityFromRecents(taskId, DOCKED_STACK_ID, null);
+            final ActivityOptions options = ActivityOptions.makeBasic();
+            options.setDockCreateMode(createMode);
+            mIam.startActivityFromRecents(taskId, DOCKED_STACK_ID, options.toBundle());
         } catch (RemoteException e) {
             e.printStackTrace();
         }
@@ -313,16 +306,18 @@
         }
     }
 
-    /** Returns whether the specified task is in the home stack */
-    public boolean isInHomeStack(int taskId) {
-        if (mAm == null) return false;
+    /**
+     * Returns whether the given stack id is the home stack id.
+     */
+    public static boolean isHomeStack(int stackId) {
+        return stackId == ActivityManager.HOME_STACK_ID;
+    }
 
-        // If we are mocking, then just return false
-        if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
-            return false;
-        }
-
-        return mAm.isInHomeStack(taskId);
+    /**
+     * Returns whether the given stack id is the freeform workspace stack id.
+     */
+    public static boolean isFreeformStack(int stackId) {
+        return stackId == ActivityManager.FREEFORM_WORKSPACE_STACK_ID;
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index 7f618e3..d5d0713 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -49,7 +49,7 @@
 import com.android.systemui.recents.events.EventBus;
 import com.android.systemui.recents.events.activity.DismissRecentsToHomeAnimationStarted;
 import com.android.systemui.recents.events.component.ScreenPinningRequestEvent;
-import com.android.systemui.recents.events.ui.DismissTaskEvent;
+import com.android.systemui.recents.events.ui.DismissTaskViewEvent;
 import com.android.systemui.recents.events.ui.dragndrop.DragDockStateChangedEvent;
 import com.android.systemui.recents.events.ui.dragndrop.DragEndEvent;
 import com.android.systemui.recents.events.ui.dragndrop.DragStartEvent;
@@ -69,6 +69,7 @@
 public class RecentsView extends FrameLayout implements TaskStackView.TaskStackViewCallbacks {
 
     private static final String TAG = "RecentsView";
+    private static final boolean DEBUG = false;
 
     private static final boolean ADD_HEADER_BITMAP = true;
 
@@ -404,22 +405,6 @@
         return super.verifyDrawable(who);
     }
 
-    /** Focuses the next task in the first stack view */
-    public void focusNextTask(boolean forward) {
-        // Get the first stack view
-        if (mTaskStackView != null) {
-            mTaskStackView.focusNextTask(forward, true);
-        }
-    }
-
-    /** Dismisses the focused task. */
-    public void dismissFocusedTask() {
-        // Get the first stack view
-        if (mTaskStackView != null) {
-            mTaskStackView.dismissFocusedTask();
-        }
-    }
-
     /** Unfilters any filtered stacks */
     public boolean unfilterFilteredStacks() {
         if (mStacks != null) {
@@ -562,7 +547,7 @@
         // Disable any focused state before we draw the header
         // Upfront the processing of the thumbnail
         if (tv.isFocusedTask()) {
-            tv.unsetFocusedTask();
+            tv.setFocusedState(false, false /* animated */, false /* requestViewFocus */);
         }
         TaskViewTransform transform = new TaskViewTransform();
         transform = stackView.getStackAlgorithm().getStackTransform(tv.mTask, stackScroll,
@@ -682,7 +667,7 @@
                     } else {
                         // Dismiss the task and return the user to home if we fail to
                         // launch the task
-                        EventBus.getDefault().send(new DismissTaskEvent(task, tv));
+                        EventBus.getDefault().send(new DismissTaskViewEvent(task, tv));
                         if (mCb != null) {
                             mCb.onTaskLaunchFailed();
                         }
@@ -800,8 +785,7 @@
                 // Dock the new task if we are hovering over a valid dock state
                 if (event.dockState != TaskStack.DockState.NONE) {
                     SystemServicesProxy ssp = Recents.getSystemServices();
-                    ssp.setTaskResizeable(event.task.key.id);
-                    ssp.dockTask(event.task.key.id, event.dockState.createMode);
+                    ssp.startTaskInDockedMode(event.task.key.id, event.dockState.createMode);
                     launchTask(event.task, null, INVALID_STACK_ID);
                 }
             }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java
index cf4c9cb..bf045f9 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java
@@ -34,14 +34,16 @@
  */
 class DockRegion {
     public static TaskStack.DockState[] PHONE_LANDSCAPE = {
+            // We only allow docking to the left for now on small devices
             TaskStack.DockState.LEFT
     };
     public static TaskStack.DockState[] PHONE_PORTRAIT = {
-            // We only allow docking to the top for now
+            // We only allow docking to the top for now on small devices
             TaskStack.DockState.TOP
     };
     public static TaskStack.DockState[] TABLET_LANDSCAPE = {
-            TaskStack.DockState.LEFT
+            TaskStack.DockState.LEFT,
+            TaskStack.DockState.RIGHT
     };
     public static TaskStack.DockState[] TABLET_PORTRAIT = PHONE_PORTRAIT;
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index 5928854..757e695 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -23,6 +23,8 @@
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.os.Bundle;
+import android.os.SystemService;
+import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
@@ -30,6 +32,7 @@
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.FrameLayout;
 import com.android.systemui.R;
+import com.android.systemui.recents.Constants;
 import com.android.systemui.recents.Recents;
 import com.android.systemui.recents.RecentsActivity;
 import com.android.systemui.recents.RecentsActivityLaunchState;
@@ -37,8 +40,11 @@
 import com.android.systemui.recents.events.EventBus;
 import com.android.systemui.recents.events.activity.PackagesChangedEvent;
 import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
-import com.android.systemui.recents.events.ui.DismissTaskEvent;
+import com.android.systemui.recents.events.ui.DismissTaskViewEvent;
 import com.android.systemui.recents.events.ui.UserInteractionEvent;
+import com.android.systemui.recents.events.ui.focus.DismissFocusedTaskViewEvent;
+import com.android.systemui.recents.events.ui.focus.FocusNextTaskViewEvent;
+import com.android.systemui.recents.events.ui.focus.FocusPreviousTaskViewEvent;
 import com.android.systemui.recents.misc.DozeTrigger;
 import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.recents.misc.Utilities;
@@ -60,6 +66,9 @@
         TaskView.TaskViewCallbacks, TaskStackViewScroller.TaskStackViewScrollerCallbacks,
         ViewPool.ViewPoolConsumer<TaskView, Task> {
 
+    private final static String TAG = "TaskStackView";
+    private final static boolean DEBUG = false;
+
     /** The TaskView callbacks */
     interface TaskStackViewCallbacks {
         public void onTaskViewClicked(TaskStackView stackView, TaskView tv, TaskStack stack, Task t,
@@ -80,14 +89,12 @@
     ArrayList<TaskViewTransform> mCurrentTaskTransforms = new ArrayList<>();
     DozeTrigger mUIDozeTrigger;
     int mFocusedTaskIndex = -1;
-    int mPrevAccessibilityFocusedIndex = -1;
     // Optimizations
     int mStackViewsAnimationDuration;
     boolean mStackViewsDirty = true;
     boolean mStackViewsClipDirty = true;
     boolean mAwaitingFirstLayout = true;
     boolean mStartEnterAnimationRequestedAfterLayout;
-    boolean mStartEnterAnimationCompleted;
     ViewAnimation.TaskViewEnterContext mStartEnterAnimationContext;
 
     Rect mTaskStackBounds = new Rect();
@@ -219,7 +226,6 @@
         mStackViewsDirty = true;
         mStackViewsClipDirty = true;
         mAwaitingFirstLayout = true;
-        mPrevAccessibilityFocusedIndex = -1;
         if (mUIDozeTrigger != null) {
             mUIDozeTrigger.stopDozing();
             mUIDozeTrigger.resetTrigger();
@@ -332,8 +338,6 @@
     /** Synchronizes the views with the model */
     boolean synchronizeStackViewsWithModel() {
         if (mStackViewsDirty) {
-            SystemServicesProxy ssp = Recents.getSystemServices();
-
             // Get all the task transforms
             ArrayList<Task> tasks = mStack.getTasks();
             float stackScroll = mStackScroller.getStackScroll();
@@ -344,8 +348,9 @@
             // Return all the invisible children to the pool
             mTmpTaskViewMap.clear();
             List<TaskView> taskViews = getTaskViews();
+            boolean wasLastFocusedTaskAnimated = false;
+            int lastFocusedTaskIndex = -1;
             int taskViewCount = taskViews.size();
-            boolean reaquireAccessibilityFocus = false;
             for (int i = taskViewCount - 1; i >= 0; i--) {
                 TaskView tv = taskViews.get(i);
                 Task task = tv.getTask();
@@ -353,8 +358,12 @@
                 if (visibleRange[1] <= taskIndex && taskIndex <= visibleRange[0]) {
                     mTmpTaskViewMap.put(task, tv);
                 } else {
+                    if (tv.isFocusedTask()) {
+                        wasLastFocusedTaskAnimated = tv.isFocusAnimated();
+                        lastFocusedTaskIndex = taskIndex;
+                        resetFocusedTask();
+                    }
                     mViewPool.returnViewToPool(tv);
-                    reaquireAccessibilityFocus |= (i == mPrevAccessibilityFocusedIndex);
                 }
             }
 
@@ -385,21 +394,14 @@
                 // Animate the task into place
                 tv.updateViewPropertiesToTaskTransform(mCurrentTaskTransforms.get(taskIndex),
                         mStackViewsAnimationDuration, mRequestUpdateClippingListener);
+            }
 
-                // Request accessibility focus on the next view if we removed the task
-                // that previously held accessibility focus
-                if (reaquireAccessibilityFocus) {
-                    taskViews = getTaskViews();
-                    taskViewCount = taskViews.size();
-                    if (taskViewCount > 0 && ssp.isTouchExplorationEnabled() &&
-                            mPrevAccessibilityFocusedIndex != -1) {
-                        TaskView atv = taskViews.get(taskViewCount - 1);
-                        int indexOfTask = mStack.indexOfTask(atv.getTask());
-                        if (mPrevAccessibilityFocusedIndex != indexOfTask) {
-                            tv.requestAccessibilityFocus();
-                            mPrevAccessibilityFocusedIndex = indexOfTask;
-                        }
-                    }
+            // Update the focus if the previous focused task was returned to the view pool
+            if (lastFocusedTaskIndex != -1) {
+                if (lastFocusedTaskIndex < visibleRange[1]) {
+                    setFocusedTask(visibleRange[1], false, wasLastFocusedTaskAnimated);
+                } else {
+                    setFocusedTask(visibleRange[0], false, wasLastFocusedTaskAnimated);
                 }
             }
 
@@ -473,118 +475,80 @@
         return mStackScroller;
     }
 
-    /** Focuses the task at the specified index in the stack */
-    void focusTask(int taskIndex, boolean scrollToNewPosition, final boolean animateFocusedState) {
-        // Return early if the task is already focused
-        if (taskIndex == mFocusedTaskIndex) return;
+    /**
+     * Sets the focused task to the provided (bounded taskIndex).
+     */
+    private void setFocusedTask(int taskIndex, boolean scrollToTask, final boolean animated) {
+        setFocusedTask(taskIndex, scrollToTask, animated, true);
+    }
 
-        if (0 <= taskIndex && taskIndex < mStack.getTaskCount()) {
-            mFocusedTaskIndex = taskIndex;
-            mPrevAccessibilityFocusedIndex = taskIndex;
+    /**
+     * Sets the focused task to the provided (bounded taskIndex).
+     */
+    private void setFocusedTask(int taskIndex, boolean scrollToTask, final boolean animated,
+                                final boolean requestViewFocus) {
+        // Find the next task to focus
+        int newFocusedTaskIndex = mStack.getTaskCount() > 0 ?
+                Math.max(0, Math.min(mStack.getTaskCount() - 1, taskIndex)) : -1;
+        final Task newFocusedTask = (newFocusedTaskIndex != -1) ?
+                mStack.getTasks().get(newFocusedTaskIndex) : null;
 
-            // Focus the view if possible, otherwise, focus the view after we scroll into position
-            final Task t = mStack.getTasks().get(mFocusedTaskIndex);
-            Runnable postScrollRunnable = new Runnable() {
+        // Reset the last focused task state if changed
+        if (mFocusedTaskIndex != -1) {
+            Task focusedTask = mStack.getTasks().get(mFocusedTaskIndex);
+            if (focusedTask != newFocusedTask) {
+                resetFocusedTask();
+            }
+        }
+
+        mFocusedTaskIndex = newFocusedTaskIndex;
+        if (mFocusedTaskIndex != -1) {
+            Runnable focusTaskRunnable = new Runnable() {
                 @Override
                 public void run() {
-                    TaskView tv = getChildViewForTask(t);
+                    TaskView tv = getChildViewForTask(newFocusedTask);
                     if (tv != null) {
-                        tv.setFocusedTask(animateFocusedState);
-                        tv.requestAccessibilityFocus();
+                        tv.setFocusedState(true, animated, requestViewFocus);
                     }
                 }
             };
 
-            // Scroll the view into position (just center it in the curve)
-            if (scrollToNewPosition) {
-                float newScroll = mLayoutAlgorithm.getStackScrollForTask(t) - 0.5f;
+            if (scrollToTask) {
+                // TODO: Center the newly focused task view
+                float newScroll = mLayoutAlgorithm.getStackScrollForTask(newFocusedTask) - 0.5f;
                 newScroll = mStackScroller.getBoundedStackScroll(newScroll);
-                mStackScroller.animateScroll(mStackScroller.getStackScroll(), newScroll, postScrollRunnable);
+                mStackScroller.animateScroll(mStackScroller.getStackScroll(), newScroll,
+                        focusTaskRunnable);
             } else {
-                if (postScrollRunnable != null) {
-                    postScrollRunnable.run();
-                }
+                focusTaskRunnable.run();
             }
-
         }
     }
 
     /**
-     * Ensures that there is a task focused, if nothing is focused, then we will use the task
-     * at the center of the visible stack.
+     * Sets the focused task relative to the currently focused task.
+     *
+     * @param animated determines whether to actually draw the highlight along with the change in
+     *                            focus.
      */
-    public boolean ensureFocusedTask(boolean findClosestToCenter) {
-        if (mFocusedTaskIndex < 0) {
-            List<TaskView> taskViews = getTaskViews();
-            int taskViewCount = taskViews.size();
-            if (findClosestToCenter) {
-                // If there is no task focused, then find the task that is closes to the center
-                // of the screen and use that as the currently focused task
-                int x = mLayoutAlgorithm.mStackRect.centerX();
-                int y = mLayoutAlgorithm.mStackRect.centerY();
-                for (int i = taskViewCount - 1; i >= 0; i--) {
-                    TaskView tv = taskViews.get(i);
-                    tv.getHitRect(mTmpRect);
-                    if (mTmpRect.contains(x, y)) {
-                        mFocusedTaskIndex = mStack.indexOfTask(tv.getTask());
-                        mPrevAccessibilityFocusedIndex = mFocusedTaskIndex;
-                        break;
-                    }
-                }
-            }
-            // If we can't find the center task, then use the front most index
-            if (mFocusedTaskIndex < 0 && taskViewCount > 0) {
-                TaskView tv = taskViews.get(taskViewCount - 1);
-                mFocusedTaskIndex = mStack.indexOfTask(tv.getTask());
-                mPrevAccessibilityFocusedIndex = mFocusedTaskIndex;
-            }
-        }
-        return mFocusedTaskIndex >= 0;
-    }
-
-    /**
-     * Focuses the next task in the stack.
-     * @param animateFocusedState determines whether to actually draw the highlight along with
-     *                            the change in focus, as well as whether to scroll to fit the
-     *                            task into view.
-     */
-    public void focusNextTask(boolean forward, boolean animateFocusedState) {
+    public void setRelativeFocusedTask(boolean forward, boolean animated) {
         // Find the next index to focus
-        int numTasks = mStack.getTaskCount();
-        if (numTasks == 0) return;
-
-        int direction = (forward ? -1 : 1);
-        int newIndex = mFocusedTaskIndex + direction;
-        if (newIndex >= 0 && newIndex <= (numTasks - 1)) {
-            newIndex = Math.max(0, Math.min(numTasks - 1, newIndex));
-            focusTask(newIndex, true, animateFocusedState);
-        }
+        int newIndex = mFocusedTaskIndex + (forward ? -1 : 1);
+        setFocusedTask(newIndex, true, animated);
     }
 
-    /** Dismisses the focused task. */
-    public void dismissFocusedTask() {
-        // Return early if the focused task index is invalid
-        if (mFocusedTaskIndex < 0 || mFocusedTaskIndex >= mStack.getTaskCount()) {
-            mFocusedTaskIndex = -1;
-            return;
-        }
-
-        Task t = mStack.getTasks().get(mFocusedTaskIndex);
-        TaskView tv = getChildViewForTask(t);
-        tv.dismissTask();
-    }
-
-    /** Resets the focused task. */
+    /**
+     * Resets the focused task.
+     */
     void resetFocusedTask() {
-        if ((0 <= mFocusedTaskIndex) && (mFocusedTaskIndex < mStack.getTaskCount())) {
+        if (mFocusedTaskIndex != -1) {
             Task t = mStack.getTasks().get(mFocusedTaskIndex);
             TaskView tv = getChildViewForTask(t);
             if (tv != null) {
-                tv.unsetFocusedTask();
+                tv.setFocusedState(false, false /* animated */, false /* requestViewFocus */);
             }
         }
         mFocusedTaskIndex = -1;
-        mPrevAccessibilityFocusedIndex = -1;
     }
 
     @Override
@@ -609,12 +573,12 @@
         super.onInitializeAccessibilityNodeInfo(info);
         List<TaskView> taskViews = getTaskViews();
         int taskViewCount = taskViews.size();
-        if (taskViewCount > 1 && mPrevAccessibilityFocusedIndex != -1) {
+        if (taskViewCount > 1 && mFocusedTaskIndex != -1) {
             info.setScrollable(true);
-            if (mPrevAccessibilityFocusedIndex > 0) {
+            if (mFocusedTaskIndex > 0) {
                 info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
             }
-            if (mPrevAccessibilityFocusedIndex < mStack.getTaskCount() - 1) {
+            if (mFocusedTaskIndex < mStack.getTaskCount() - 1) {
                 info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD);
             }
         }
@@ -630,22 +594,14 @@
         if (super.performAccessibilityAction(action, arguments)) {
             return true;
         }
-        if (ensureFocusedTask(false)) {
-            switch (action) {
-                case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: {
-                    if (mPrevAccessibilityFocusedIndex > 0) {
-                        focusNextTask(true, false);
-                        return true;
-                    }
-                }
-                break;
-                case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: {
-                    if (mPrevAccessibilityFocusedIndex < mStack.getTaskCount() - 1) {
-                        focusNextTask(false, false);
-                        return true;
-                    }
-                }
-                break;
+        switch (action) {
+            case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: {
+                setRelativeFocusedTask(true, false /* animated */);
+                return true;
+            }
+            case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: {
+                setRelativeFocusedTask(false, false /* animated */);
+                return true;
             }
         }
         return false;
@@ -678,7 +634,7 @@
 
     /** Computes the stack and task rects */
     public void computeRects(int windowWidth, int windowHeight, Rect taskStackBounds,
-            boolean launchedWithAltTab, boolean launchedFromHome) {
+                             boolean launchedWithAltTab, boolean launchedFromHome) {
         // Compute the rects in the stack algorithm
         mLayoutAlgorithm.computeRects(windowWidth, windowHeight, taskStackBounds);
 
@@ -741,12 +697,12 @@
                 mTmpRect.setEmpty();
             }
             tv.measure(
-                MeasureSpec.makeMeasureSpec(
-                        mLayoutAlgorithm.mTaskRect.width() + mTmpRect.left + mTmpRect.right,
-                        MeasureSpec.EXACTLY),
-                MeasureSpec.makeMeasureSpec(
-                        mLayoutAlgorithm.mTaskRect.height() + mTmpRect.top + mTmpRect.bottom,
-                        MeasureSpec.EXACTLY));
+                    MeasureSpec.makeMeasureSpec(
+                            mLayoutAlgorithm.mTaskRect.width() + mTmpRect.left + mTmpRect.right,
+                            MeasureSpec.EXACTLY),
+                    MeasureSpec.makeMeasureSpec(
+                            mLayoutAlgorithm.mTaskRect.height() + mTmpRect.top + mTmpRect.bottom,
+                            MeasureSpec.EXACTLY));
         }
 
         setMeasuredDimension(width, height);
@@ -815,17 +771,16 @@
             mStartEnterAnimationContext = null;
         }
 
-        // When Alt-Tabbing, focus the previous task (but leave the animation until we finish the
-        // enter animation).
-        RecentsActivityLaunchState launchState = mConfig.getLaunchState();
-        if (launchState.launchedWithAltTab) {
-            if (launchState.launchedFromAppWithThumbnail) {
-                focusTask(Math.max(0, mStack.getTaskCount() - 2), false,
-                        launchState.launchedHasConfigurationChanged);
-            } else {
-                focusTask(Math.max(0, mStack.getTaskCount() - 1), false,
-                        launchState.launchedHasConfigurationChanged);
-            }
+        // Set the task focused state without requesting view focus, and leave the focus animations
+        // until after the enter-animation
+        if (!Constants.DebugFlags.App.EnableFastToggleRecents && launchTargetTask != null) {
+            setFocusedTask(mStack.indexOfTask(launchTargetTask), false /* scrollToTask */,
+                    false /* animated */, false /* requestViewFocus */);
+        } else {
+            RecentsActivityLaunchState launchState = mConfig.getLaunchState();
+            int taskOffset = launchState.launchedFromHome ? -1 : -2;
+            setFocusedTask(mStack.getTaskCount() + taskOffset, false /* scrollToTask */,
+                    false /* animated */, false /* requestViewFocus */);
         }
 
         // Start dozing
@@ -874,32 +829,17 @@
             ctx.postAnimationTrigger.addLastDecrementRunnable(new Runnable() {
                 @Override
                 public void run() {
-                    mStartEnterAnimationCompleted = true;
                     // Poke the dozer to restart the trigger after the animation completes
                     mUIDozeTrigger.poke();
 
-                    SystemServicesProxy ssp = Recents.getSystemServices();
-                    List<TaskView> taskViews = getTaskViews();
-                    int taskViewCount = taskViews.size();
-                    if (taskViewCount > 0) {
-                        // Focus the first view if accessibility is enabled
-                        if (ssp.isTouchExplorationEnabled()) {
-                            TaskView tv = taskViews.get(taskViewCount - 1);
-                            tv.requestAccessibilityFocus();
-                            mPrevAccessibilityFocusedIndex = mStack.indexOfTask(tv.getTask());
-                        }
-                    }
-
-                    // Start the focus animation when alt-tabbing
-                    ArrayList<Task> tasks = mStack.getTasks();
-                    RecentsActivityLaunchState launchState = mConfig.getLaunchState();
-                    if (launchState.launchedWithAltTab &&
-                            !launchState.launchedHasConfigurationChanged &&
-                            0 <= mFocusedTaskIndex && mFocusedTaskIndex < tasks.size()) {
-                        TaskView tv = getChildViewForTask(tasks.get(mFocusedTaskIndex));
-                        if (tv != null) {
-                            tv.setFocusedTask(true);
-                        }
+                    // Update the focused state here -- since we only set the focused task without
+                    // requesting view focus in onFirstLayout(), actually request view focus and
+                    // animate the focused state if we are alt-tabbing now, after the window enter
+                    // animation is completed
+                    if (mFocusedTaskIndex != -1) {
+                        RecentsActivityLaunchState launchState = mConfig.getLaunchState();
+                        setFocusedTask(mFocusedTaskIndex, false /* scrollToTask */,
+                                launchState.launchedWithAltTab);
                     }
                 }
             });
@@ -1132,11 +1072,6 @@
     public void prepareViewToEnterPool(TaskView tv) {
         Task task = tv.getTask();
 
-        // Clear the accessibility focus for that view
-        if (tv.isAccessibilityFocused()) {
-            tv.clearAccessibilityFocus();
-        }
-
         // Report that this tasks's data is no longer being used
         Recents.getTaskLoader().unloadTaskData(task);
 
@@ -1167,11 +1102,6 @@
         // If the doze trigger has already fired, then update the state for this task view
         tv.setNoUserInteractionState();
 
-        // If we've finished the start animation, then ensure we always enable the focus animations
-        if (mStartEnterAnimationCompleted) {
-            tv.enableFocusAnimations();
-        }
-
         // Find the index where this task should be placed in the stack
         int insertIndex = -1;
         int taskIndex = mStack.indexOfTask(task);
@@ -1231,13 +1161,6 @@
         }
     }
 
-    @Override
-    public void onTaskViewFocusChanged(TaskView tv, boolean focused) {
-        if (focused) {
-            mFocusedTaskIndex = mStack.indexOfTask(tv.getTask());
-        }
-    }
-
     /**** TaskStackViewScroller.TaskStackViewScrollerCallbacks ****/
 
     @Override
@@ -1259,13 +1182,13 @@
         for (int i = tasks.size() - 1; i >= 0; i--) {
             final Task t = tasks.get(i);
             if (removedComponents.contains(t.key.getComponent())) {
-                TaskView tv = getChildViewForTask(t);
+                final TaskView tv = getChildViewForTask(t);
                 if (tv != null) {
                     // For visible children, defer removing the task until after the animation
                     tv.startDeleteTaskAnimation(new Runnable() {
                         @Override
                         public void run() {
-                            mStack.removeTask(t);
+                            removeTaskViewFromStack(tv);
                         }
                     }, 0);
                 } else {
@@ -1276,33 +1199,23 @@
         }
     }
 
-    public final void onBusEvent(DismissTaskEvent event) {
-        TaskView tv = event.taskView;
-        Task task = tv.getTask();
-        int taskIndex = mStack.indexOfTask(task);
-        boolean taskWasFocused = tv.isFocusedTask();
+    public final void onBusEvent(DismissTaskViewEvent event) {
+        removeTaskViewFromStack(event.taskView);
+    }
 
-        // Announce for accessibility
-        tv.announceForAccessibility(getContext().getString(R.string.accessibility_recents_item_dismissed,
-                tv.getTask().activityLabel));
+    public final void onBusEvent(FocusNextTaskViewEvent event) {
+        setRelativeFocusedTask(true, true);
+    }
 
-        // Remove the task from the view
-        mStack.removeTask(task);
+    public final void onBusEvent(FocusPreviousTaskViewEvent event) {
+        setRelativeFocusedTask(false, true);
+    }
 
-        // If the dismissed task was focused, then we should focus the new task in the same index
-        if (taskWasFocused) {
-            ArrayList<Task> tasks = mStack.getTasks();
-            int nextTaskIndex = Math.min(tasks.size() - 1, taskIndex - 1);
-            if (nextTaskIndex >= 0) {
-                Task nextTask = tasks.get(nextTaskIndex);
-                TaskView nextTv = getChildViewForTask(nextTask);
-                if (nextTv != null) {
-                    // Focus the next task, and only animate the visible state if we are launched
-                    // from Alt-Tab
-                    RecentsActivityLaunchState launchState = mConfig.getLaunchState();
-                    nextTv.setFocusedTask(launchState.launchedWithAltTab);
-                }
-            }
+    public final void onBusEvent(DismissFocusedTaskViewEvent event) {
+        if (mFocusedTaskIndex != -1) {
+            Task t = mStack.getTasks().get(mFocusedTaskIndex);
+            TaskView tv = getChildViewForTask(t);
+            tv.dismissTask();
         }
     }
 
@@ -1316,4 +1229,32 @@
             reset();
         }
     }
+
+    /**
+     * Removes the task from the stack, and updates the focus to the next task in the stack if the
+     * removed TaskView was focused.
+     */
+    private void removeTaskViewFromStack(TaskView tv) {
+        SystemServicesProxy ssp = Recents.getSystemServices();
+        Task task = tv.getTask();
+        int taskIndex = mStack.indexOfTask(task);
+        boolean taskWasFocused = tv.isFocusedTask();
+
+        // Reset the previously focused task before it is removed from the stack
+        resetFocusedTask();
+
+        // Announce for accessibility
+        tv.announceForAccessibility(getContext().getString(
+                R.string.accessibility_recents_item_dismissed, tv.getTask().activityLabel));
+
+        // Remove the task from the stack
+        mStack.removeTask(task);
+
+        if (taskWasFocused || ssp.isTouchExplorationEnabled()) {
+            // If the dismissed task was focused or if we are in touch exploration mode, then focus
+            // the next task
+            RecentsActivityLaunchState launchState = mConfig.getLaunchState();
+            setFocusedTask(taskIndex - 1, true /* scrollToTask */, launchState.launchedWithAltTab);
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
index 1274318..3a1a987 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
@@ -28,7 +28,7 @@
 import com.android.systemui.recents.Constants;
 import com.android.systemui.recents.events.EventBus;
 import com.android.systemui.recents.events.activity.HideRecentsEvent;
-import com.android.systemui.recents.events.ui.DismissTaskEvent;
+import com.android.systemui.recents.events.ui.DismissTaskViewEvent;
 
 import java.util.List;
 
@@ -408,13 +408,9 @@
                     // Find the front most task and scroll the next task to the front
                     float vScroll = ev.getAxisValue(MotionEvent.AXIS_VSCROLL);
                     if (vScroll > 0) {
-                        if (mSv.ensureFocusedTask(true)) {
-                            mSv.focusNextTask(true, false);
-                        }
+                        mSv.setRelativeFocusedTask(true, false /* animated */);
                     } else {
-                        if (mSv.ensureFocusedTask(true)) {
-                            mSv.focusNextTask(false, false);
-                        }
+                        mSv.setRelativeFocusedTask(false, false /* animated */);
                     }
                     return true;
             }
@@ -461,7 +457,7 @@
         // Re-enable touch events from this task view
         tv.setTouchEnabled(true);
         // Remove the task view from the stack
-        EventBus.getDefault().send(new DismissTaskEvent(tv.getTask(), tv));
+        EventBus.getDefault().send(new DismissTaskViewEvent(tv.getTask(), tv));
         // Keep track of deletions by keyboard
         MetricsLogger.histogram(tv.getContext(), "overview_task_dismissed_source",
                 Constants.Metrics.DismissSourceSwipeGesture);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index bab4da7..0a5ee79 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -29,8 +29,8 @@
 import android.graphics.Point;
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffColorFilter;
-import android.graphics.Rect;
 import android.util.AttributeSet;
+import android.util.Log;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewOutlineProvider;
@@ -40,13 +40,15 @@
 import android.widget.FrameLayout;
 import com.android.systemui.R;
 import com.android.systemui.recents.Constants;
+import com.android.systemui.recents.Recents;
 import com.android.systemui.recents.RecentsActivity;
 import com.android.systemui.recents.RecentsActivityLaunchState;
 import com.android.systemui.recents.RecentsConfiguration;
 import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.recents.events.ui.DismissTaskEvent;
+import com.android.systemui.recents.events.ui.DismissTaskViewEvent;
 import com.android.systemui.recents.events.ui.dragndrop.DragEndEvent;
 import com.android.systemui.recents.events.ui.dragndrop.DragStartEvent;
+import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.recents.misc.Utilities;
 import com.android.systemui.recents.model.Task;
 import com.android.systemui.statusbar.phone.PhoneStatusBar;
@@ -55,11 +57,13 @@
 public class TaskView extends FrameLayout implements Task.TaskCallbacks,
         View.OnClickListener, View.OnLongClickListener {
 
+    private final static String TAG = "TaskView";
+    private final static boolean DEBUG = false;
+
     /** The TaskView callbacks */
     interface TaskViewCallbacks {
         public void onTaskViewClicked(TaskView tv, Task task, boolean lockToTask);
         public void onTaskViewClipStateChanged(TaskView tv);
-        public void onTaskViewFocusChanged(TaskView tv, boolean focused);
     }
 
     RecentsConfiguration mConfig;
@@ -76,6 +80,7 @@
     Task mTask;
     boolean mTaskDataLoaded;
     boolean mIsFocused;
+    boolean mIsFocusAnimated;
     boolean mFocusAnimationsEnabled;
     boolean mClipViewInStack;
     AnimateableViewBounds mViewBounds;
@@ -397,15 +402,6 @@
             ctx.postAnimationTrigger.increment();
             startDelay = delay;
         }
-
-        // Enable the focus animations from this point onwards so that they aren't affected by the
-        // window transitions
-        postDelayed(new Runnable() {
-            @Override
-            public void run() {
-                enableFocusAnimations();
-            }
-        }, startDelay);
     }
 
     public void fadeInActionButton(int delay, int duration) {
@@ -547,7 +543,7 @@
         startDeleteTaskAnimation(new Runnable() {
             @Override
             public void run() {
-                EventBus.getDefault().send(new DismissTaskEvent(mTask, tv));
+                EventBus.getDefault().send(new DismissTaskViewEvent(mTask, tv));
             }
         }, 0);
     }
@@ -620,6 +616,8 @@
                 anim.addListener(postAnimRunnable);
             }
             anim.start();
+        } else {
+            postAnimRunnable.onAnimationEnd(null);
         }
     }
 
@@ -641,58 +639,32 @@
     /**** View focus state ****/
 
     /**
-     * Sets the focused task explicitly. We need a separate flag because requestFocus() won't happen
-     * if the view is not currently visible, or we are in touch state (where we still want to keep
-     * track of focus).
+     * Explicitly sets the focused state of this task.
      */
-    public void setFocusedTask(boolean animateFocusedState) {
-        mIsFocused = true;
-        if (mFocusAnimationsEnabled) {
-            // Focus the header bar
-            mHeaderView.onTaskViewFocusChanged(true, animateFocusedState);
-        }
-        // Update the thumbnail alpha with the focus
-        mThumbnailView.onFocusChanged(true);
-        // Call the callback
-        if (mCb != null) {
-            mCb.onTaskViewFocusChanged(this, true);
-        }
-        // Workaround, we don't always want it focusable in touch mode, but we want the first task
-        // to be focused after the enter-recents animation, which can be triggered from either touch
-        // or keyboard
-        setFocusableInTouchMode(true);
-        requestFocus();
-        setFocusableInTouchMode(false);
-        invalidate();
-    }
-
-    /**
-     * Unsets the focused task explicitly.
-     */
-    void unsetFocusedTask() {
-        mIsFocused = false;
-        if (mFocusAnimationsEnabled) {
-            // Un-focus the header bar
-            mHeaderView.onTaskViewFocusChanged(false, true);
+    public void setFocusedState(boolean isFocused, boolean animated, boolean requestViewFocus) {
+        if (DEBUG) {
+            Log.d(TAG, "setFocusedState: " + mTask.activityLabel + " focused: " + isFocused +
+                    " mIsFocused: " + mIsFocused + " animated: " + animated +
+                    " requestViewFocus: " + requestViewFocus + " isFocused(): " + isFocused() +
+                    " isAccessibilityFocused(): " + isAccessibilityFocused());
         }
 
-        // Update the thumbnail alpha with the focus
-        mThumbnailView.onFocusChanged(false);
-        // Call the callback
-        if (mCb != null) {
-            mCb.onTaskViewFocusChanged(this, false);
-        }
-        invalidate();
-    }
-
-    /**
-     * Updates the explicitly focused state when the view focus changes.
-     */
-    @Override
-    protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
-        super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
-        if (!gainFocus) {
-            unsetFocusedTask();
+        SystemServicesProxy ssp = Recents.getSystemServices();
+        mIsFocused = isFocused;
+        mIsFocusAnimated = animated;
+        mHeaderView.onTaskViewFocusChanged(isFocused, animated);
+        mThumbnailView.onFocusChanged(isFocused);
+        if (isFocused) {
+            if (requestViewFocus && !isFocused()) {
+                requestFocus();
+            }
+            if (requestViewFocus && !isAccessibilityFocused() && ssp.isTouchExplorationEnabled()) {
+                requestAccessibilityFocus();
+            }
+        } else {
+            if (isAccessibilityFocused() && ssp.isTouchExplorationEnabled()) {
+                clearAccessibilityFocus();
+            }
         }
     }
 
@@ -700,17 +672,14 @@
      * Returns whether we have explicitly been focused.
      */
     public boolean isFocusedTask() {
-        return mIsFocused || isFocused();
+        return mIsFocused;
     }
 
-    /** Enables all focus animations. */
-    void enableFocusAnimations() {
-        boolean wasFocusAnimationsEnabled = mFocusAnimationsEnabled;
-        mFocusAnimationsEnabled = true;
-        if (mIsFocused && !wasFocusAnimationsEnabled) {
-            // Re-notify the header if we were focused and animations were not previously enabled
-            mHeaderView.onTaskViewFocusChanged(true, true);
-        }
+    /**
+     * Returns whether this focused task is animated.
+     */
+    public boolean isFocusAnimated() {
+        return mIsFocusAnimated;
     }
 
     public void disableLayersForOneFrame() {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
index e1e07ef..f6353f8 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
@@ -39,7 +39,6 @@
 import android.util.AttributeSet;
 import android.view.View;
 import android.view.ViewOutlineProvider;
-import android.view.accessibility.AccessibilityManager;
 import android.view.animation.AnimationUtils;
 import android.view.animation.Interpolator;
 import android.widget.FrameLayout;
@@ -244,9 +243,8 @@
         mMoveTaskButton.setOnClickListener(this);
 
         // In accessibility, a single click on the focused app info button will show it
-        AccessibilityManager am = (AccessibilityManager) getContext().
-                getSystemService(Context.ACCESSIBILITY_SERVICE);
-        if (am != null && am.isEnabled()) {
+        SystemServicesProxy ssp = Recents.getSystemServices();
+        if (ssp.isTouchExplorationEnabled()) {
             mApplicationIcon.setOnClickListener(this);
         }
     }
@@ -369,9 +367,6 @@
 
     /** Notifies the associated TaskView has been focused. */
     void onTaskViewFocusChanged(boolean focused, boolean animateFocusedState) {
-        // If we are not animating the visible state, just return
-        if (!animateFocusedState) return;
-
         boolean isRunning = false;
         if (mFocusAnimator != null) {
             isRunning = mFocusAnimator.isRunning();
@@ -379,6 +374,9 @@
         }
 
         if (focused) {
+            // If we are not animating the visible state, just return
+            if (!animateFocusedState) return;
+
             int currentColor = mBackgroundColor;
             int secondaryColor = getSecondaryColor(mCurrentPrimaryColor, mCurrentPrimaryColorIsDark);
             int[][] states = new int[][] {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 8938669..2c16f81 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -217,7 +217,7 @@
 
     private boolean mDeviceProvisioned = false;
 
-    private RecentsComponent mRecents;
+    protected RecentsComponent mRecents;
 
     protected int mZenMode;
 
@@ -1275,20 +1275,22 @@
 
         int maxHeight = mRowMaxHeight;
         final StatusBarNotification sbn = entry.notification;
-        RemoteViews contentView = sbn.getNotification().contentView;
-        RemoteViews bigContentView = sbn.getNotification().bigContentView;
-        RemoteViews headsUpContentView = sbn.getNotification().headsUpContentView;
+        entry.cacheContentViews(mContext, null);
+
+        final RemoteViews contentView = entry.cachedContentView;
+        final RemoteViews bigContentView = entry.cachedBigContentView;
+        final RemoteViews headsUpContentView = entry.cachedHeadsUpContentView;
+        final RemoteViews publicContentView = entry.cachedPublicContentView;
 
         if (contentView == null) {
+            Log.v(TAG, "no contentView for: " + sbn.getNotification());
             return false;
         }
 
         if (DEBUG) {
-            Log.v(TAG, "publicNotification: " + sbn.getNotification().publicVersion);
+            Log.v(TAG, "publicContentView: " + publicContentView);
         }
 
-        Notification publicNotification = sbn.getNotification().publicVersion;
-
         ExpandableNotificationRow row;
 
         // Stash away previous user expansion state so we can restore it at
@@ -1377,9 +1379,9 @@
 
         // now the public version
         View publicViewLocal = null;
-        if (publicNotification != null) {
+        if (publicContentView != null) {
             try {
-                publicViewLocal = publicNotification.contentView.apply(
+                publicViewLocal = publicContentView.apply(
                         sbn.getPackageContext(mContext),
                         contentContainerPublic, mOnClickHandler);
 
@@ -1537,30 +1539,9 @@
             }
 
             if (viableAction != null) {
-                Notification stripped = n.clone();
-                Notification.Builder.stripForDelivery(stripped);
-                stripped.extras.putBoolean("android.rebuild", true);
-                stripped.actions = new Notification.Action[] { viableAction };
-                stripped.extras.putBoolean("android.rebuild.contentView", true);
-                stripped.contentView = null;
-                stripped.extras.putBoolean("android.rebuild.bigView", true);
-                stripped.bigContentView = null;
-                stripped.extras.putBoolean("android.rebuild.hudView", true);
-                stripped.headsUpContentView = null;
-
-                stripped.extras.putParcelable(Notification.EXTRA_LARGE_ICON,
-                        stripped.getLargeIcon());
-                if (SystemProperties.getBoolean("debug.strip_third_line", false)) {
-                    stripped.extras.putCharSequence(Notification.EXTRA_INFO_TEXT, null);
-                    stripped.extras.putCharSequence(Notification.EXTRA_SUMMARY_TEXT, null);
-                }
-
-                Notification rebuilt = Notification.Builder.rebuild(mContext, stripped);
-
-                n.actions = rebuilt.actions;
-                n.bigContentView = rebuilt.bigContentView;
-                n.headsUpContentView = rebuilt.headsUpContentView;
-                n.publicVersion = rebuilt.publicVersion;
+                Notification.Builder rebuilder = Notification.Builder.recoverBuilder(mContext, n);
+                rebuilder.setActions(viableAction);
+                rebuilder.build(); // will rewrite n
             }
         }
     }
@@ -2034,12 +2015,15 @@
         }
 
         Notification n = notification.getNotification();
-        if (DEBUG) {
-            logUpdate(entry, n);
-        }
-        boolean applyInPlace = shouldApplyInPlace(entry, n);
+
+        boolean applyInPlace = !entry.cacheContentViews(mContext, notification.getNotification());
         boolean shouldInterrupt = shouldInterrupt(entry, notification);
         boolean alertAgain = alertAgain(entry, n);
+        if (DEBUG) {
+            Log.d(TAG, "applyInPlace=" + applyInPlace
+                    + " shouldInterrupt=" + shouldInterrupt
+                    + " alertAgain=" + alertAgain);
+        }
 
         entry.notification = notification;
         mGroupManager.onEntryUpdated(entry, entry.notification);
@@ -2104,101 +2088,32 @@
     protected abstract void updateHeadsUp(String key, Entry entry, boolean shouldInterrupt,
             boolean alertAgain);
 
-    private void logUpdate(Entry oldEntry, Notification n) {
-        StatusBarNotification oldNotification = oldEntry.notification;
-        Log.d(TAG, "old notification: when=" + oldNotification.getNotification().when
-                + " ongoing=" + oldNotification.isOngoing()
-                + " expanded=" + oldEntry.getContentView()
-                + " contentView=" + oldNotification.getNotification().contentView
-                + " bigContentView=" + oldNotification.getNotification().bigContentView
-                + " publicView=" + oldNotification.getNotification().publicVersion
-                + " rowParent=" + oldEntry.row.getParent());
-        Log.d(TAG, "new notification: when=" + n.when
-                + " ongoing=" + oldNotification.isOngoing()
-                + " contentView=" + n.contentView
-                + " bigContentView=" + n.bigContentView
-                + " publicView=" + n.publicVersion);
-    }
-
-    /**
-     * @return whether we can just reapply the RemoteViews from a notification in-place when it is
-     * updated
-     */
-    private boolean shouldApplyInPlace(Entry entry, Notification n) {
-        StatusBarNotification oldNotification = entry.notification;
-        // XXX: modify when we do something more intelligent with the two content views
-        final RemoteViews oldContentView = oldNotification.getNotification().contentView;
-        final RemoteViews contentView = n.contentView;
-        final RemoteViews oldBigContentView = oldNotification.getNotification().bigContentView;
-        final RemoteViews bigContentView = n.bigContentView;
-        final RemoteViews oldHeadsUpContentView
-                = oldNotification.getNotification().headsUpContentView;
-        final RemoteViews headsUpContentView = n.headsUpContentView;
-        final Notification oldPublicNotification = oldNotification.getNotification().publicVersion;
-        final RemoteViews oldPublicContentView = oldPublicNotification != null
-                ? oldPublicNotification.contentView : null;
-        final Notification publicNotification = n.publicVersion;
-        final RemoteViews publicContentView = publicNotification != null
-                ? publicNotification.contentView : null;
-        boolean contentsUnchanged = entry.getContentView() != null
-                && contentView.getPackage() != null
-                && oldContentView.getPackage() != null
-                && oldContentView.getPackage().equals(contentView.getPackage())
-                && oldContentView.getLayoutId() == contentView.getLayoutId();
-        // large view may be null
-        boolean bigContentsUnchanged =
-                (entry.getExpandedContentView() == null && bigContentView == null)
-                || ((entry.getExpandedContentView() != null && bigContentView != null)
-                    && bigContentView.getPackage() != null
-                    && oldBigContentView.getPackage() != null
-                    && oldBigContentView.getPackage().equals(bigContentView.getPackage())
-                    && oldBigContentView.getLayoutId() == bigContentView.getLayoutId());
-        boolean headsUpContentsUnchanged =
-                (oldHeadsUpContentView == null && headsUpContentView == null)
-                || ((oldHeadsUpContentView != null && headsUpContentView != null)
-                    && headsUpContentView.getPackage() != null
-                    && oldHeadsUpContentView.getPackage() != null
-                    && oldHeadsUpContentView.getPackage().equals(headsUpContentView.getPackage())
-                    && oldHeadsUpContentView.getLayoutId() == headsUpContentView.getLayoutId());
-        boolean publicUnchanged  =
-                (oldPublicContentView == null && publicContentView == null)
-                || ((oldPublicContentView != null && publicContentView != null)
-                        && publicContentView.getPackage() != null
-                        && oldPublicContentView.getPackage() != null
-                        && oldPublicContentView.getPackage().equals(publicContentView.getPackage())
-                        && oldPublicContentView.getLayoutId() == publicContentView.getLayoutId());
-        return contentsUnchanged && bigContentsUnchanged && headsUpContentsUnchanged
-                && publicUnchanged;
-    }
-
-    private void updateNotificationViews(Entry entry, StatusBarNotification notification) {
-        final RemoteViews contentView = notification.getNotification().contentView;
-        final RemoteViews bigContentView = notification.getNotification().bigContentView;
-        final RemoteViews headsUpContentView = notification.getNotification().headsUpContentView;
-        final Notification publicVersion = notification.getNotification().publicVersion;
-        final RemoteViews publicContentView = publicVersion != null ? publicVersion.contentView
-                : null;
+    private void updateNotificationViews(Entry entry, StatusBarNotification sbn) {
+        final RemoteViews contentView = entry.cachedContentView;
+        final RemoteViews bigContentView = entry.cachedBigContentView;
+        final RemoteViews headsUpContentView = entry.cachedHeadsUpContentView;
+        final RemoteViews publicContentView = entry.cachedPublicContentView;
 
         // Reapply the RemoteViews
         contentView.reapply(mContext, entry.getContentView(), mOnClickHandler);
         if (bigContentView != null && entry.getExpandedContentView() != null) {
-            bigContentView.reapply(notification.getPackageContext(mContext),
+            bigContentView.reapply(sbn.getPackageContext(mContext),
                     entry.getExpandedContentView(),
                     mOnClickHandler);
         }
         View headsUpChild = entry.getHeadsUpContentView();
         if (headsUpContentView != null && headsUpChild != null) {
-            headsUpContentView.reapply(notification.getPackageContext(mContext),
+            headsUpContentView.reapply(sbn.getPackageContext(mContext),
                     headsUpChild, mOnClickHandler);
         }
         if (publicContentView != null && entry.getPublicContentView() != null) {
-            publicContentView.reapply(notification.getPackageContext(mContext),
+            publicContentView.reapply(sbn.getPackageContext(mContext),
                     entry.getPublicContentView(), mOnClickHandler);
         }
         // update the contentIntent
-        mNotificationClicker.register(entry.row, notification);
+        mNotificationClicker.register(entry.row, sbn);
 
-        entry.row.setStatusBarNotification(notification);
+        entry.row.setStatusBarNotification(sbn);
         entry.row.notifyContentUpdated();
         entry.row.resetHeight();
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
index aedae52..6a90d8e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
@@ -17,6 +17,7 @@
 package com.android.systemui.statusbar;
 
 import android.app.Notification;
+import android.content.Context;
 import android.os.SystemClock;
 import android.service.notification.NotificationListenerService;
 import android.service.notification.NotificationListenerService.Ranking;
@@ -24,6 +25,7 @@
 import android.service.notification.StatusBarNotification;
 import android.util.ArrayMap;
 import android.view.View;
+import android.widget.RemoteViews;
 
 import com.android.systemui.statusbar.phone.NotificationGroupManager;
 import com.android.systemui.statusbar.policy.HeadsUpManager;
@@ -53,6 +55,10 @@
         public boolean legacy; // whether the notification has a legacy, dark background
         public int targetSdk;
         private long lastFullScreenIntentLaunchTime = NOT_LAUNCHED_YET;
+        public RemoteViews cachedContentView;
+        public RemoteViews cachedBigContentView;
+        public RemoteViews cachedHeadsUpContentView;
+        public RemoteViews cachedPublicContentView;
 
         public Entry(StatusBarNotification n, StatusBarIconView ic) {
             this.key = n.getKey();
@@ -98,6 +104,67 @@
             return row.getPublicLayout().getContractedChild();
         }
 
+        public boolean cacheContentViews(Context ctx, Notification updatedNotification) {
+            boolean cached = false;
+            if (updatedNotification != null) {
+                final Notification.Builder updatedNotificationBuilder
+                        = Notification.Builder.recoverBuilder(ctx, updatedNotification);
+                final RemoteViews newContentView = updatedNotificationBuilder.makeContentView();
+                if (!compareRemoteViews(cachedContentView, newContentView)) {
+                    cachedContentView = newContentView;
+                    cached |= true;
+                }
+                final RemoteViews newBigContentView =
+                        updatedNotificationBuilder.makeBigContentView();
+                if (!compareRemoteViews(cachedBigContentView, newBigContentView)) {
+                    cachedBigContentView = newBigContentView;
+                    cached |= true;
+                }
+                final RemoteViews newHeadsUpContentView =
+                        updatedNotificationBuilder.makeHeadsUpContentView();
+                if (!compareRemoteViews(cachedHeadsUpContentView, newBigContentView)) {
+                    cachedHeadsUpContentView = newHeadsUpContentView;
+                    cached |= true;
+                }
+                final Notification updatedPublicNotification = updatedNotification.publicVersion;
+                final RemoteViews newPubContentView = (updatedPublicNotification != null)
+                        ? Notification.Builder.recoverBuilder(
+                                ctx, updatedPublicNotification).makeContentView()
+                        : null;
+                if (!compareRemoteViews(cachedPublicContentView, newPubContentView)) {
+                    cachedPublicContentView = newPubContentView;
+                    cached |= true;
+                }
+            } else {
+                final Notification.Builder builder
+                        = Notification.Builder.recoverBuilder(ctx, notification.getNotification());
+
+                cachedContentView = builder.makeContentView();
+                cachedBigContentView = builder.makeBigContentView();
+                cachedHeadsUpContentView = builder.makeHeadsUpContentView();
+
+                final Notification publicNotification =
+                        notification.getNotification().publicVersion;
+                if (publicNotification != null) {
+                    final Notification.Builder publicBuilder
+                            = Notification.Builder.recoverBuilder(ctx, publicNotification);
+                    cachedPublicContentView = publicBuilder.makeContentView();
+                }
+                cached = true;
+            }
+            return cached;
+        }
+
+        // Returns true if the RemoteViews are the same.
+        private boolean compareRemoteViews(final RemoteViews a, final RemoteViews b) {
+            return (a == null && b == null) ||
+                    (a != null && b != null
+                    && b.getPackage() != null
+                    && a.getPackage() != null
+                    && a.getPackage().equals(b.getPackage())
+                    && a.getLayoutId() == b.getLayoutId());
+        }
+
         public void notifyFullScreenIntentLaunched() {
             lastFullScreenIntentLaunchTime = SystemClock.elapsedRealtime();
         }
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 cfde791..cfdb01e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -88,7 +88,6 @@
 import android.view.ViewStub;
 import android.view.WindowManager;
 import android.view.WindowManagerGlobal;
-import android.view.accessibility.AccessibilityEvent;
 import android.view.animation.AccelerateDecelerateInterpolator;
 import android.view.animation.AccelerateInterpolator;
 import android.view.animation.Interpolator;
@@ -146,7 +145,6 @@
 import com.android.systemui.statusbar.policy.FullscreenUserSwitcher;
 import com.android.systemui.statusbar.policy.HeadsUpManager;
 import com.android.systemui.statusbar.policy.HotspotControllerImpl;
-import com.android.systemui.statusbar.policy.KeyButtonView;
 import com.android.systemui.statusbar.policy.KeyguardMonitor;
 import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
 import com.android.systemui.statusbar.policy.LocationControllerImpl;
@@ -1115,13 +1113,22 @@
         }
     };
 
-    private long mLastLockToAppLongPress;
-    private View.OnLongClickListener mLongPressBackRecentsListener =
-            new View.OnLongClickListener() {
+    private View.OnLongClickListener mLongPressBackListener = new View.OnLongClickListener() {
         @Override
         public boolean onLongClick(View v) {
-            handleLongPressBackRecents(v);
-            return true;
+            return handleLongPressBack();
+        }
+    };
+
+    private View.OnLongClickListener mRecentsLongClickListener = new View.OnLongClickListener() {
+
+        @Override
+        public boolean onLongClick(View v) {
+            if (mRecents != null) {
+                mRecents.dockTopTask();
+                return true;
+            }
+            return false;
         }
     };
 
@@ -1170,9 +1177,9 @@
         mNavigationBarView.getRecentsButton().setOnClickListener(mRecentsClickListener);
         mNavigationBarView.getRecentsButton().setOnTouchListener(mRecentsPreloadOnTouchListener);
         mNavigationBarView.getRecentsButton().setLongClickable(true);
-        mNavigationBarView.getRecentsButton().setOnLongClickListener(mLongPressBackRecentsListener);
+        mNavigationBarView.getRecentsButton().setOnLongClickListener(mRecentsLongClickListener);
         mNavigationBarView.getBackButton().setLongClickable(true);
-        mNavigationBarView.getBackButton().setOnLongClickListener(mLongPressBackRecentsListener);
+        mNavigationBarView.getBackButton().setOnLongClickListener(mLongPressBackListener);
         mNavigationBarView.getHomeButton().setOnTouchListener(mHomeActionListener);
         mNavigationBarView.getHomeButton().setOnLongClickListener(mLongPressHomeListener);
         mAssistManager.onConfigurationChanged();
@@ -4048,7 +4055,7 @@
 
     private void vibrateForCameraGesture() {
         // Make sure to pass -1 for repeat so VibratorService doesn't stop us when going to sleep.
-        mVibrator.vibrate(new long[] { 0, 750L }, -1 /* repeat */);
+        mVibrator.vibrate(new long[]{0, 750L}, -1 /* repeat */);
     }
 
     public void onScreenTurnedOn() {
@@ -4057,58 +4064,22 @@
     }
 
     /**
-     * This handles long-press of both back and recents.  They are
-     * handled together to capture them both being long-pressed
-     * at the same time to exit screen pinning (lock task).
-     *
-     * When accessibility mode is on, only a long-press from recents
-     * is required to exit.
-     *
-     * In all other circumstances we try to pass through long-press events
-     * for Back, so that apps can still use it.  Which can be from two things.
-     * 1) Not currently in screen pinning (lock task).
-     * 2) Back is long-pressed without recents.
+     * Handles long press for back button. This exits screen pinning.
      */
-    private void handleLongPressBackRecents(View v) {
+    private boolean handleLongPressBack() {
         try {
-            boolean sendBackLongPress = false;
             IActivityManager activityManager = ActivityManagerNative.getDefault();
-            boolean isAccessiblityEnabled = mAccessibilityManager.isEnabled();
-            if (activityManager.isInLockTaskMode() && !isAccessiblityEnabled) {
-                long time = System.currentTimeMillis();
-                // If we recently long-pressed the other button then they were
-                // long-pressed 'together'
-                if ((time - mLastLockToAppLongPress) < LOCK_TO_APP_GESTURE_TOLERENCE) {
-                    activityManager.stopLockTaskModeOnCurrent();
-                    // When exiting refresh disabled flags.
-                    mNavigationBarView.setDisabledFlags(mDisabled1, true);
-                } else if ((v.getId() == R.id.back)
-                        && !mNavigationBarView.getRecentsButton().isPressed()) {
-                    // If we aren't pressing recents right now then they presses
-                    // won't be together, so send the standard long-press action.
-                    sendBackLongPress = true;
-                }
-                mLastLockToAppLongPress = time;
-            } else {
-                // If this is back still need to handle sending the long-press event.
-                if (v.getId() == R.id.back) {
-                    sendBackLongPress = true;
-                } else if (isAccessiblityEnabled && activityManager.isInLockTaskMode()) {
-                    // When in accessibility mode a long press that is recents (not back)
-                    // should stop lock task.
-                    activityManager.stopLockTaskModeOnCurrent();
-                    // When exiting refresh disabled flags.
-                    mNavigationBarView.setDisabledFlags(mDisabled1, true);
-                }
-            }
-            if (sendBackLongPress) {
-                KeyButtonView keyButtonView = (KeyButtonView) v;
-                keyButtonView.sendEvent(KeyEvent.ACTION_DOWN, KeyEvent.FLAG_LONG_PRESS);
-                keyButtonView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
+            if (activityManager.isInLockTaskMode()) {
+                activityManager.stopLockTaskModeOnCurrent();
+
+                // When exiting refresh disabled flags.
+                mNavigationBarView.setDisabledFlags(mDisabled1, true);
+                return true;
             }
         } catch (RemoteException e) {
             Log.d(TAG, "Unable to reach activity manager", e);
         }
+        return false;
     }
 
     // Recents
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 08f0952..4f5fff4 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -178,7 +178,7 @@
         private static final long DEFAULT_MIN_FUTURITY = 5 * 1000;
         private static final long DEFAULT_MIN_INTERVAL = 60 * 1000;
         private static final long DEFAULT_ALLOW_WHILE_IDLE_SHORT_TIME = DEFAULT_MIN_FUTURITY;
-        private static final long DEFAULT_ALLOW_WHILE_IDLE_LONG_TIME = 15*60*1000;
+        private static final long DEFAULT_ALLOW_WHILE_IDLE_LONG_TIME = 9*60*1000;
         private static final long DEFAULT_ALLOW_WHILE_IDLE_WHITELIST_DURATION = 10*1000;
 
         // Minimum futurity of a new alarm
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 80cb4d0..dfe5751 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -75,6 +75,7 @@
 import android.os.storage.IMountService;
 import android.os.storage.MountServiceInternal;
 import android.os.storage.StorageManager;
+import android.provider.Settings.Global;
 import android.service.voice.IVoiceInteractionSession;
 import android.service.voice.VoiceInteractionSession;
 import android.util.ArrayMap;
@@ -1189,6 +1190,7 @@
     String mOrigDebugApp = null;
     boolean mOrigWaitForDebugger = false;
     boolean mAlwaysFinishActivities = false;
+    boolean mForceResizableActivites;
     IActivityController mController = null;
     String mProfileApp = null;
     ProcessRecord mProfileProc = null;
@@ -3842,8 +3844,8 @@
             Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
             int startFlags, ProfilerInfo profilerInfo, Bundle options) {
         return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
-            resultWho, requestCode, startFlags, profilerInfo, options,
-            UserHandle.getCallingUserId());
+                resultWho, requestCode, startFlags, profilerInfo, options,
+                UserHandle.getCallingUserId());
     }
 
     @Override
@@ -4150,7 +4152,12 @@
             Slog.w(TAG, msg);
             throw new SecurityException(msg);
         }
-        return startActivityFromRecentsInner(taskId, launchStackId, options);
+        final long origId = Binder.clearCallingIdentity();
+        try {
+            return startActivityFromRecentsInner(taskId, launchStackId, options);
+        } finally {
+            Binder.restoreCallingIdentity(origId);
+        }
     }
 
     final int startActivityFromRecentsInner(int taskId, int launchStackId, Bundle options) {
@@ -4172,8 +4179,12 @@
             }
 
             if (launchStackId != INVALID_STACK_ID && task.stack.mStackId != launchStackId) {
-                mStackSupervisor.moveTaskToStackUncheckedLocked(
-                        task, launchStackId, ON_TOP, FORCE_FOCUS, "startActivityFromRecents");
+                if (launchStackId == DOCKED_STACK_ID && options != null) {
+                    ActivityOptions activityOptions = new ActivityOptions(options);
+                    mWindowManager.setDockedStackCreateMode(activityOptions.getDockCreateMode());
+                }
+                mStackSupervisor.moveTaskToStackLocked(
+                        taskId, launchStackId, ON_TOP, FORCE_FOCUS, "startActivityFromRecents");
             }
 
             if (task.getRootActivity() != null) {
@@ -9027,7 +9038,8 @@
                 }
                 if (DEBUG_STACK) Slog.d(TAG_STACK, "moveActivityToStack: moving r=" + r
                         + " to stackId=" + stackId);
-                mStackSupervisor.moveTaskToStackLocked(r.task.taskId, stackId, ON_TOP, !FORCE_FOCUS);
+                mStackSupervisor.moveTaskToStackLocked(r.task.taskId, stackId, ON_TOP, !FORCE_FOCUS,
+                        "moveActivityToStack");
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
@@ -9047,7 +9059,8 @@
             try {
                 if (DEBUG_STACK) Slog.d(TAG_STACK, "moveTaskToStack: moving task=" + taskId
                         + " to stackId=" + stackId + " toTop=" + toTop);
-                mStackSupervisor.moveTaskToStackLocked(taskId, stackId, toTop, !FORCE_FOCUS);
+                mStackSupervisor.moveTaskToStackLocked(taskId, stackId, toTop, !FORCE_FOCUS,
+                        "moveTaskToStack");
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
@@ -9076,7 +9089,7 @@
                         + " to createMode=" + createMode + " toTop=" + toTop);
                 mWindowManager.setDockedStackCreateMode(createMode);
                 mStackSupervisor.moveTaskToStackLocked(
-                        taskId, DOCKED_STACK_ID, toTop, !FORCE_FOCUS);
+                        taskId, DOCKED_STACK_ID, toTop, !FORCE_FOCUS, "moveTaskToDockedStack");
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
@@ -11638,14 +11651,17 @@
 
     private void retrieveSettings() {
         final ContentResolver resolver = mContext.getContentResolver();
-        String debugApp = Settings.Global.getString(
-            resolver, Settings.Global.DEBUG_APP);
+        String debugApp = Settings.Global.getString(resolver, Settings.Global.DEBUG_APP);
         boolean waitForDebugger = Settings.Global.getInt(
             resolver, Settings.Global.WAIT_FOR_DEBUGGER, 0) != 0;
         boolean alwaysFinishActivities = Settings.Global.getInt(
             resolver, Settings.Global.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
         boolean forceRtl = Settings.Global.getInt(
                 resolver, Settings.Global.DEVELOPMENT_FORCE_RTL, 0) != 0;
+        int defaultForceResizable = Build.IS_DEBUGGABLE ? 1 : 0;
+        boolean forceResizable = Settings.Global.getInt(
+                resolver, Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES,
+                defaultForceResizable) != 0;
         // Transfer any global setting for forcing RTL layout, into a System Property
         SystemProperties.set(Settings.Global.DEVELOPMENT_FORCE_RTL, forceRtl ? "1":"0");
 
@@ -11660,6 +11676,7 @@
             mDebugApp = mOrigDebugApp = debugApp;
             mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
             mAlwaysFinishActivities = alwaysFinishActivities;
+            mForceResizableActivites = forceResizable;
             // This happens before any activities are started, so we can
             // change mConfiguration in-place.
             updateConfigurationLocked(configuration, null, true);
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 99539e4..1cd3758 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -21,6 +21,7 @@
 import static android.app.ActivityManager.FREEFORM_WORKSPACE_STACK_ID;
 import static android.app.ActivityManager.FULLSCREEN_WORKSPACE_STACK_ID;
 import static android.app.ActivityManager.HOME_STACK_ID;
+import static android.app.ActivityManager.INVALID_STACK_ID;
 import static android.app.ActivityManager.LAST_STATIC_STACK_ID;
 import static android.app.ActivityManager.PINNED_STACK_ID;
 import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
@@ -4375,6 +4376,7 @@
 
             RunningTaskInfo ci = new RunningTaskInfo();
             ci.id = task.taskId;
+            ci.stackId = (task.stack == null) ? INVALID_STACK_ID : task.stack.getStackId();
             ci.baseActivity = r.intent.getComponent();
             ci.topActivity = top.intent.getComponent();
             ci.lastActiveTime = task.lastActiveTime;
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 7e47006..3bf87d8 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -2749,8 +2749,7 @@
         boolean didSomething = false;
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
             final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
-            final int numStacks = stacks.size();
-            for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
+            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                 final ActivityStack stack = stacks.get(stackNdx);
                 if (stack.finishDisabledPackageActivitiesLocked(
                         packageName, filterByClasses, doit, evenPersistent, userId)) {
@@ -2992,84 +2991,87 @@
         }
 
         Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "am.resizeStack_" + stackId);
+        mWindowManager.deferSurfaceLayout();
+        try {
+            ActivityRecord r = stack.topRunningActivityLocked();
 
-        ActivityRecord r = stack.topRunningActivityLocked();
-
-        mTmpBounds.clear();
-        mTmpConfigs.clear();
-        ArrayList<TaskRecord> tasks = stack.getAllTasks();
-        for (int i = tasks.size() - 1; i >= 0; i--) {
-            TaskRecord task = tasks.get(i);
-            if (task.mResizeable) {
-                if (stack.mStackId == FREEFORM_WORKSPACE_STACK_ID) {
-                    // For freeform stack we don't adjust the size of the tasks to match that
-                    // of the stack, but we do try to make sure the tasks are still contained
-                    // with the bounds of the stack.
-                    tempRect2.set(task.mBounds);
-                    fitWithinBounds(tempRect2, bounds);
-                    task.updateOverrideConfiguration(tempRect2);
-                } else {
-                    task.updateOverrideConfiguration(bounds);
-                }
-            }
-
-            mTmpConfigs.put(task.taskId, task.mOverrideConfig);
-            mTmpBounds.put(task.taskId, task.mBounds);
-        }
-        stack.mFullscreen = mWindowManager.resizeStack(stackId, bounds, mTmpConfigs, mTmpBounds);
-        if (stack.mStackId == DOCKED_STACK_ID) {
-            // Dock stack funness...Yay!
-            if (stack.mFullscreen) {
-                // The dock stack went fullscreen which is kinda like dismissing it.
-                // In this case we make all other static stacks fullscreen and move all
-                // docked stack tasks to the fullscreen stack.
-                for (int i = FIRST_STATIC_STACK_ID; i <= LAST_STATIC_STACK_ID; i++) {
-                    if (i != DOCKED_STACK_ID && getStack(i) != null) {
-                        resizeStackLocked(i, null, preserveWindows, true);
+            mTmpBounds.clear();
+            mTmpConfigs.clear();
+            ArrayList<TaskRecord> tasks = stack.getAllTasks();
+            for (int i = tasks.size() - 1; i >= 0; i--) {
+                TaskRecord task = tasks.get(i);
+                if (task.mResizeable) {
+                    if (stack.mStackId == FREEFORM_WORKSPACE_STACK_ID) {
+                        // For freeform stack we don't adjust the size of the tasks to match that
+                        // of the stack, but we do try to make sure the tasks are still contained
+                        // with the bounds of the stack.
+                        tempRect2.set(task.mBounds);
+                        fitWithinBounds(tempRect2, bounds);
+                        task.updateOverrideConfiguration(tempRect2);
+                    } else {
+                        task.updateOverrideConfiguration(bounds);
                     }
                 }
 
-                final int count = tasks.size();
-                for (int i = 0; i < count; i++) {
-                    moveTaskToStackLocked(tasks.get(i).taskId,
-                            FULLSCREEN_WORKSPACE_STACK_ID, ON_TOP, FORCE_FOCUS);
-                }
+                mTmpConfigs.put(task.taskId, task.mOverrideConfig);
+                mTmpBounds.put(task.taskId, task.mBounds);
+            }
+            stack.mFullscreen = mWindowManager.resizeStack(stackId, bounds, mTmpConfigs, mTmpBounds);
+            if (stack.mStackId == DOCKED_STACK_ID) {
+                // Dock stack funness...Yay!
+                if (stack.mFullscreen) {
+                    // The dock stack went fullscreen which is kinda like dismissing it.
+                    // In this case we make all other static stacks fullscreen and move all
+                    // docked stack tasks to the fullscreen stack.
+                    for (int i = FIRST_STATIC_STACK_ID; i <= LAST_STATIC_STACK_ID; i++) {
+                        if (i != DOCKED_STACK_ID && getStack(i) != null) {
+                            resizeStackLocked(i, null, preserveWindows, true);
+                        }
+                    }
 
-                // stack shouldn't contain anymore activities, so nothing to resume.
-                r = null;
-            } else {
-                // Docked stacks occupy a dedicated region on screen so the size of all other
-                // static stacks need to be adjusted so they don't overlap with the docked stack.
-                // We get the bounds to use from window manager which has been adjusted for any
-                // screen controls and is also the same for all stacks.
-                mWindowManager.getStackDockedModeBounds(HOME_STACK_ID, tempRect);
+                    final int count = tasks.size();
+                    for (int i = 0; i < count; i++) {
+                        moveTaskToStackLocked(tasks.get(i).taskId,
+                                FULLSCREEN_WORKSPACE_STACK_ID, ON_TOP, FORCE_FOCUS, "resizeStack");
+                    }
 
-                for (int i = FIRST_STATIC_STACK_ID; i <= LAST_STATIC_STACK_ID; i++) {
-                    if (i != DOCKED_STACK_ID) {
-                        ActivityStack otherStack = getStack(i);
-                        if (otherStack != null) {
-                            resizeStackLocked(i, tempRect, PRESERVE_WINDOWS, true);
+                    // stack shouldn't contain anymore activities, so nothing to resume.
+                    r = null;
+                } else {
+                    // Docked stacks occupy a dedicated region on screen so the size of all other
+                    // static stacks need to be adjusted so they don't overlap with the docked stack.
+                    // We get the bounds to use from window manager which has been adjusted for any
+                    // screen controls and is also the same for all stacks.
+                    mWindowManager.getStackDockedModeBounds(HOME_STACK_ID, tempRect);
+
+                    for (int i = FIRST_STATIC_STACK_ID; i <= LAST_STATIC_STACK_ID; i++) {
+                        if (i != DOCKED_STACK_ID) {
+                            ActivityStack otherStack = getStack(i);
+                            if (otherStack != null) {
+                                resizeStackLocked(i, tempRect, PRESERVE_WINDOWS, true);
+                            }
                         }
                     }
                 }
+                // Since we are resizing the stack, all other operations should strive to preserve
+                // windows.
+                preserveWindows = true;
             }
-            // Since we are resizing the stack, all other operations should strive to preserve
-            // windows.
-            preserveWindows = true;
-        }
-        stack.setBounds(bounds);
+            stack.setBounds(bounds);
 
-        if (r != null) {
-            final boolean updated = stack.ensureActivityConfigurationLocked(r, 0, preserveWindows);
-            // And we need to make sure at this point that all other activities
-            // are made visible with the correct configuration.
-            ensureActivitiesVisibleLocked(r, 0, preserveWindows);
-            if (!updated) {
-                resumeTopActivitiesLocked(stack, null, null);
+            if (r != null) {
+                final boolean updated = stack.ensureActivityConfigurationLocked(r, 0, preserveWindows);
+                // And we need to make sure at this point that all other activities
+                // are made visible with the correct configuration.
+                ensureActivitiesVisibleLocked(r, 0, preserveWindows);
+                if (!updated) {
+                    resumeTopActivitiesLocked(stack, null, null);
+                }
             }
+        } finally {
+            mWindowManager.continueSurfaceLayout();
+            Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
         }
-
-        Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
     }
 
     void resizeTaskLocked(TaskRecord task, Rect bounds, int resizeMode, boolean preserveWindow) {
@@ -3265,13 +3267,13 @@
         return stack;
     }
 
-    void moveTaskToStackLocked(int taskId, int stackId, boolean toTop, boolean forceFocus) {
+    void moveTaskToStackLocked(int taskId, int stackId, boolean toTop, boolean forceFocus,
+            String reason) {
         final TaskRecord task = anyTaskForIdLocked(taskId);
         if (task == null) {
             Slog.w(TAG, "moveTaskToStack: no task for id=" + taskId);
             return;
         }
-        final String reason = "moveTaskToStack";
         if (stackId == DOCKED_STACK_ID || stackId == PINNED_STACK_ID
                 || stackId == FULLSCREEN_WORKSPACE_STACK_ID) {
             // We are about to relaunch the activity because its configuration changed due to
@@ -3284,7 +3286,8 @@
             mWindowManager.setReplacingWindow(r.appToken, true /* animate */);
         }
         final ActivityStack stack =
-                moveTaskToStackUncheckedLocked(task, stackId, toTop, forceFocus, reason);
+                moveTaskToStackUncheckedLocked(task, stackId, toTop, forceFocus,
+                        "moveTaskToStack:" + reason);
 
         // Make sure the task has the appropriate bounds/size for the stack it is in.
         if (stackId == FULLSCREEN_WORKSPACE_STACK_ID && task.mBounds != null) {
@@ -3330,7 +3333,8 @@
         if (task.mActivities.size() == 1) {
             // There is only one activity in the task. So, we can just move the task over to the
             // pinned stack without re-parenting the activity in a different task.
-            moveTaskToStackLocked(task.taskId, PINNED_STACK_ID, ON_TOP, FORCE_FOCUS);
+            moveTaskToStackLocked(task.taskId, PINNED_STACK_ID, ON_TOP, FORCE_FOCUS,
+                    "moveTopActivityToPinnedStack");
         } else {
             final ActivityStack pinnedStack = getStack(PINNED_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
             pinnedStack.moveActivityToStack(r);
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 090a342..120b40c 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -318,7 +318,7 @@
         mNextAffiliateTaskId = nextTaskId;
         mCallingUid = callingUid;
         mCallingPackage = callingPackage;
-        mResizeable = resizeable;
+        mResizeable = resizeable || mService.mForceResizableActivites;
         mPrivileged = privileged;
         ActivityInfo info = mActivities.get(0).info;
         mMinimalSize = info != null && info.layout != null ? info.layout.minimalSize : -1;
@@ -420,7 +420,7 @@
         } else {
             autoRemoveRecents = false;
         }
-        mResizeable = info.resizeable;
+        mResizeable = info.resizeable || mService.mForceResizableActivites;
         mLockTaskMode = info.lockTaskLaunchMode;
         mPrivileged = (info.applicationInfo.privateFlags & PRIVATE_FLAG_PRIVILEGED) != 0;
         setLockTaskAuth();
@@ -626,6 +626,9 @@
         // Only set this based on the first activity
         if (mActivities.isEmpty()) {
             taskType = r.mActivityType;
+            if (taskType == HOME_ACTIVITY_TYPE && mService.mForceResizableActivites) {
+                mResizeable = r.info.resizeable;
+            }
             isPersistable = r.isPersistable();
             mCallingUid = r.launchedFromUid;
             mCallingPackage = r.launchedFromPackage;
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index e8e46ef..361bbf9 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -2146,13 +2146,6 @@
                     + " id=" + id + " notification=" + notification);
         }
 
-        if (notification.getSmallIcon() != null) {
-            if (!notification.isValid()) {
-                throw new IllegalArgumentException("Invalid notification (): pkg=" + pkg
-                        + " id=" + id + " notification=" + notification);
-            }
-        }
-
         mHandler.post(new Runnable() {
             @Override
             public void run() {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index aed2f0b..e149616 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -1753,11 +1753,20 @@
 
         PermissionsState permissionsState = sb.getPermissionsState();
 
-        for (String permission : pkg.requestedPermissions) {
-            BasePermission bp = mSettings.mPermissions.get(permission);
-            if (bp != null && bp.isRuntime() && (grantedPermissions == null
-                    || ArrayUtils.contains(grantedPermissions, permission))) {
-                permissionsState.grantRuntimePermission(bp, userId);
+        final int immutableFlags = PackageManager.FLAG_PERMISSION_SYSTEM_FIXED
+                | PackageManager.FLAG_PERMISSION_POLICY_FIXED;
+
+        synchronized (mPackages) {
+            for (String permission : pkg.requestedPermissions) {
+                BasePermission bp = mSettings.mPermissions.get(permission);
+                if (bp != null && bp.isRuntime() && (grantedPermissions == null
+                        || ArrayUtils.contains(grantedPermissions, permission))) {
+                    final int flags = permissionsState.getPermissionFlags(permission, userId);
+                    // Installer cannot change immutable permissions.
+                    if ((flags & immutableFlags) == 0) {
+                        grantRuntimePermission(pkg.packageName, permission, userId);
+                    }
+                }
             }
         }
     }
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index b36a22e..4dd7388 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -16,14 +16,15 @@
 
 package com.android.server.pm;
 
-import android.accounts.Account;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.app.Activity;
 import android.app.ActivityManager;
 import android.app.ActivityManagerInternal;
 import android.app.ActivityManagerNative;
 import android.app.IStopUserCallback;
 import android.app.admin.DevicePolicyManager;
+import android.app.admin.DevicePolicyManagerInternal;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -46,6 +47,7 @@
 import android.os.ServiceManager;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.os.UserManagerInternal;
 import android.os.storage.StorageManager;
 import android.os.storage.VolumeInfo;
 import android.system.ErrnoException;
@@ -59,9 +61,11 @@
 import android.util.TimeUtils;
 import android.util.Xml;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.IAppOpsService;
 import com.android.internal.util.FastXmlSerializer;
+import com.android.internal.util.Preconditions;
 import com.android.internal.util.XmlUtils;
 import com.android.server.LocalServices;
 
@@ -83,11 +87,18 @@
 
 import libcore.io.IoUtils;
 
+/**
+ * Service for {@link UserManager}.
+ *
+ * Method naming convention:
+ * - Methods suffixed with "Locked" should be called within the {@code this} lock.
+ * - Methods suffixed with "RL" should be called within the {@link #mRestrictionsLock} lock.
+ */
 public class UserManagerService extends IUserManager.Stub {
 
     private static final String LOG_TAG = "UserManagerService";
 
-    private static final boolean DBG = false;
+    private static final boolean DBG = false; // DO NOT SUBMIT WITH TRUE
 
     private static final String TAG_NAME = "name";
     private static final String ATTR_FLAGS = "flags";
@@ -160,7 +171,38 @@
     private final File mUserListFile;
 
     private final SparseArray<UserInfo> mUsers = new SparseArray<UserInfo>();
-    private final SparseArray<Bundle> mUserRestrictions = new SparseArray<Bundle>();
+
+    private final Object mRestrictionsLock = new Object();
+
+    /**
+     * User restrictions set via UserManager.  This doesn't include restrictions set by
+     * device owner / profile owners.
+     *
+     * DO NOT Change existing {@link Bundle} in it.  When changing a restriction for a user,
+     * a new {@link Bundle} should always be created and set.  This is because a {@link Bundle}
+     * maybe shared between {@link #mBaseUserRestrictions} and
+     * {@link #mCachedEffectiveUserRestrictions}, but they should always updated separately.
+     * (Otherwise we won't be able to detect what restrictions have changed in
+     * {@link #updateUserRestrictionsInternalRL).
+     */
+    @GuardedBy("mRestrictionsLock")
+    private final SparseArray<Bundle> mBaseUserRestrictions = new SparseArray<>();
+
+    /**
+     * Cached user restrictions that are in effect -- i.e. {@link #mBaseUserRestrictions} combined
+     * with device / profile owner restrictions.  We'll initialize it lazily; use
+     * {@link #getEffectiveUserRestrictions} to access it.
+     *
+     * DO NOT Change existing {@link Bundle} in it.  When changing a restriction for a user,
+     * a new {@link Bundle} should always be created and set.  This is because a {@link Bundle}
+     * maybe shared between {@link #mBaseUserRestrictions} and
+     * {@link #mCachedEffectiveUserRestrictions}, but they should always updated separately.
+     * (Otherwise we won't be able to detect what restrictions have changed in
+     * {@link #updateUserRestrictionsInternalRL).
+     */
+    @GuardedBy("mRestrictionsLock")
+    private final SparseArray<Bundle> mCachedEffectiveUserRestrictions = new SparseArray<>();
+
     private final Bundle mGuestRestrictions = new Bundle();
 
     /**
@@ -176,6 +218,8 @@
 
     private IAppOpsService mAppOpsService;
 
+    private final LocalService mLocalService;
+
     private static UserManagerService sInstance;
 
     public static UserManagerService getInstance() {
@@ -231,6 +275,8 @@
                 sInstance = this;
             }
         }
+        mLocalService = new LocalService();
+        LocalServices.addService(UserManagerInternal.class, mLocalService);
     }
 
     void systemReady() {
@@ -258,8 +304,9 @@
         mAppOpsService = IAppOpsService.Stub.asInterface(
                 ServiceManager.getService(Context.APP_OPS_SERVICE));
         for (int i = 0; i < mUserIds.length; ++i) {
+            final int userId = mUserIds[i];
             try {
-                mAppOpsService.setUserRestrictions(mUserRestrictions.get(mUserIds[i]), mUserIds[i]);
+                mAppOpsService.setUserRestrictions(getEffectiveUserRestrictions(userId), userId);
             } catch (RemoteException e) {
                 Log.w(LOG_TAG, "Unable to notify AppOpsService of UserRestrictions");
             }
@@ -588,75 +635,171 @@
         }
     }
 
-    @Override
-    public boolean hasUserRestriction(String restrictionKey, int userId) {
-        synchronized (mPackagesLock) {
-            Bundle restrictions = mUserRestrictions.get(userId);
-            return restrictions != null && restrictions.getBoolean(restrictionKey);
+    @GuardedBy("mRestrictionsLock")
+    private Bundle computeEffectiveUserRestrictionsRL(int userId) {
+        final DevicePolicyManagerInternal dpmi =
+                LocalServices.getService(DevicePolicyManagerInternal.class);
+        final Bundle systemRestrictions = mBaseUserRestrictions.get(userId);
+
+        final Bundle effective;
+        if (dpmi == null) {
+            // TODO Make sure it's because DPMS is disabled and not because we called it too early.
+            effective = systemRestrictions;
+        } else {
+            effective = dpmi.getComposedUserRestrictions(userId, systemRestrictions);
+        }
+        return effective;
+    }
+
+    @GuardedBy("mRestrictionsLock")
+    private void invalidateEffectiveUserRestrictionsRL(int userId) {
+        if (DBG) {
+            Log.d(LOG_TAG, "invalidateEffectiveUserRestrictions userId=" + userId);
+        }
+        mCachedEffectiveUserRestrictions.remove(userId);
+    }
+
+    private Bundle getEffectiveUserRestrictions(int userId) {
+        synchronized (mRestrictionsLock) {
+            Bundle restrictions = mCachedEffectiveUserRestrictions.get(userId);
+            if (restrictions == null) {
+                restrictions = computeEffectiveUserRestrictionsRL(userId);
+                mCachedEffectiveUserRestrictions.put(userId, restrictions);
+            }
+            return restrictions;
         }
     }
 
+    /** @return a specific user restriction that's in effect currently. */
+    @Override
+    public boolean hasUserRestriction(String restrictionKey, int userId) {
+        Bundle restrictions = getEffectiveUserRestrictions(userId);
+        return restrictions != null && restrictions.getBoolean(restrictionKey);
+    }
+
+    /**
+     * @return UserRestrictions that are in effect currently.  This always returns a new
+     * {@link Bundle}.
+     */
     @Override
     public Bundle getUserRestrictions(int userId) {
-        synchronized (mPackagesLock) {
-            Bundle restrictions = mUserRestrictions.get(userId);
-            return restrictions != null ? new Bundle(restrictions) : new Bundle();
-        }
+        Bundle restrictions = getEffectiveUserRestrictions(userId);
+        return restrictions != null ? new Bundle(restrictions) : new Bundle();
     }
 
     @Override
     public void setUserRestriction(String key, boolean value, int userId) {
         checkManageUsersPermission("setUserRestriction");
-        synchronized (mPackagesLock) {
-            if (!UserRestrictionsUtils.SYSTEM_CONTROLLED_USER_RESTRICTIONS.contains(key)) {
-                Bundle restrictions = getUserRestrictions(userId);
-                restrictions.putBoolean(key, value);
-                setUserRestrictionsInternalLocked(restrictions, userId);
-            }
+        if (!UserRestrictionsUtils.SYSTEM_CONTROLLED_USER_RESTRICTIONS.contains(key)) {
+            setUserRestrictionNoCheck(key, value, userId);
         }
     }
 
     @Override
     public void setSystemControlledUserRestriction(String key, boolean value, int userId) {
         checkSystemOrRoot("setSystemControlledUserRestriction");
-        synchronized (mPackagesLock) {
-            Bundle restrictions = getUserRestrictions(userId);
-            restrictions.putBoolean(key, value);
-            setUserRestrictionsInternalLocked(restrictions, userId);
+        setUserRestrictionNoCheck(key, value, userId);
+    }
+
+    private void setUserRestrictionNoCheck(String key, boolean value, int userId) {
+        synchronized (mRestrictionsLock) {
+            // Note we can't modify Bundles stored in mBaseUserRestrictions directly, so create
+            // a copy.
+            final Bundle newRestrictions = new Bundle();
+            UserRestrictionsUtils.merge(newRestrictions, mBaseUserRestrictions.get(userId));
+            newRestrictions.putBoolean(key, value);
+
+            updateUserRestrictionsInternalRL(newRestrictions, userId);
         }
     }
 
-    @Override
-    public void setUserRestrictions(Bundle restrictions, int userId) {
-        checkManageUsersPermission("setUserRestrictions");
-        if (restrictions == null) return;
-
-        synchronized (mPackagesLock) {
-            final Bundle oldUserRestrictions = mUserRestrictions.get(userId);
-            // Restore the original state of system controlled restrictions from oldUserRestrictions
-            for (String key : UserRestrictionsUtils.SYSTEM_CONTROLLED_USER_RESTRICTIONS) {
-                restrictions.remove(key);
-                if (oldUserRestrictions.containsKey(key)) {
-                    restrictions.putBoolean(key, oldUserRestrictions.getBoolean(key));
-                }
-            }
-            setUserRestrictionsInternalLocked(restrictions, userId);
+    /**
+     * Optionally updating user restrictions, calculate the effective user restrictions by
+     * consulting {@link com.android.server.devicepolicy.DevicePolicyManagerService} and also
+     * apply it to {@link com.android.server.AppOpsService}.
+     * TODO applyUserRestrictionsLocked() should also apply to system settings.
+     *
+     * @param newRestrictions User restrictions to set.  If null, only the effective restrictions
+     *     will be updated.  Note don't pass an existing Bundle in {@link #mBaseUserRestrictions}
+     *     or {@link #mCachedEffectiveUserRestrictions}; that'll most likely cause a sub
+     * @param userId target user ID.
+     */
+    @GuardedBy("mRestrictionsLock")
+    private void updateUserRestrictionsInternalRL(
+            @Nullable Bundle newRestrictions, int userId) {
+        if (DBG) {
+            Log.d(LOG_TAG, "updateUserRestrictionsInternalLocked userId=" + userId
+                    + " bundle=" + newRestrictions);
         }
+        final Bundle prevRestrictions = getEffectiveUserRestrictions(userId);
+
+        // Update system restrictions.
+        if (newRestrictions != null) {
+            // If newRestrictions == the current one, it's probably a bug.
+            Preconditions.checkState(mBaseUserRestrictions.get(userId) != newRestrictions);
+            Preconditions.checkState(mCachedEffectiveUserRestrictions.get(userId)
+                    != newRestrictions);
+            mBaseUserRestrictions.put(userId, newRestrictions);
+        }
+
+        mCachedEffectiveUserRestrictions.put(
+                userId, computeEffectiveUserRestrictionsRL(userId));
+
+        applyUserRestrictionsRL(userId, mBaseUserRestrictions.get(userId), prevRestrictions);
     }
 
-    private void setUserRestrictionsInternalLocked(Bundle restrictions, int userId) {
-        final Bundle userRestrictions = mUserRestrictions.get(userId);
-        userRestrictions.clear();
-        userRestrictions.putAll(restrictions);
-        long token = Binder.clearCallingIdentity();
+    @GuardedBy("mRestrictionsLock")
+    private void applyUserRestrictionsRL(int userId,
+            Bundle newRestrictions, Bundle prevRestrictions) {
+        final long token = Binder.clearCallingIdentity();
         try {
-        mAppOpsService.setUserRestrictions(userRestrictions, userId);
+            mAppOpsService.setUserRestrictions(newRestrictions, userId);
         } catch (RemoteException e) {
             Log.w(LOG_TAG, "Unable to notify AppOpsService of UserRestrictions");
         } finally {
             Binder.restoreCallingIdentity(token);
         }
-        scheduleWriteUserLocked(mUsers.get(userId));
+
+        // TODO Move the code from DPMS.setUserRestriction().
+    }
+
+    @GuardedBy("mRestrictionsLock")
+    private void updateEffectiveUserRestrictionsRL(int userId) {
+        updateUserRestrictionsInternalRL(null, userId);
+    }
+
+    @GuardedBy("mRestrictionsLock")
+    private void updateEffectiveUserRestrictionsForAllUsersRL() {
+        // First, invalidate all cached values.
+        synchronized (mRestrictionsLock) {
+            mCachedEffectiveUserRestrictions.clear();
+        }
+        // We don't want to call into ActivityManagerNative while taking a lock, so we'll call
+        // it on a handler.
+        final Runnable r = new Runnable() {
+            @Override
+            public void run() {
+                // Then get the list of running users.
+                final int[] runningUsers;
+                try {
+                    runningUsers = ActivityManagerNative.getDefault().getRunningUserIds();
+                } catch (RemoteException e) {
+                    Log.w(LOG_TAG, "Unable to access ActivityManagerNative");
+                    return;
+                }
+                // Then re-calculate the effective restrictions and apply, only for running users.
+                // It's okay if a new user has started after the getRunningUserIds() call,
+                // because we'll do the same thing (re-calculate the restrictions and apply)
+                // when we start a user.
+                // TODO: "Apply restrictions upon user start hasn't been implemented.  Implement it.
+                synchronized (mRestrictionsLock) {
+                    for (int i = 0; i < runningUsers.length; i++) {
+                        updateUserRestrictionsInternalRL(null, runningUsers[i]);
+                    }
+                }
+            }
+        };
+        mHandler.post(r);
     }
 
     /**
@@ -926,7 +1069,9 @@
         mUserVersion = USER_VERSION;
 
         Bundle restrictions = new Bundle();
-        mUserRestrictions.append(UserHandle.USER_SYSTEM, restrictions);
+        synchronized (mRestrictionsLock) {
+            mBaseUserRestrictions.append(UserHandle.USER_SYSTEM, restrictions);
+        }
 
         updateUserIdsLocked();
         initDefaultGuestRestrictions();
@@ -989,9 +1134,13 @@
             serializer.startTag(null, TAG_NAME);
             serializer.text(userInfo.name);
             serializer.endTag(null, TAG_NAME);
-            Bundle restrictions = mUserRestrictions.get(userInfo.id);
+            Bundle restrictions;
+            synchronized (mRestrictionsLock) {
+                restrictions = mBaseUserRestrictions.get(userInfo.id);
+            }
             if (restrictions != null) {
-                UserRestrictionsUtils.writeRestrictions(serializer, restrictions, TAG_RESTRICTIONS);
+                UserRestrictionsUtils
+                        .writeRestrictions(serializer, restrictions, TAG_RESTRICTIONS);
             }
             serializer.endTag(null, TAG_USER);
 
@@ -1131,7 +1280,9 @@
             userInfo.guestToRemove = guestToRemove;
             userInfo.profileGroupId = profileGroupId;
             userInfo.restrictedProfileParentId = restrictedProfileParentId;
-            mUserRestrictions.append(id, restrictions);
+            synchronized (mRestrictionsLock) {
+                mBaseUserRestrictions.append(id, restrictions);
+            }
             return userInfo;
 
         } catch (IOException ioe) {
@@ -1333,7 +1484,9 @@
                     scheduleWriteUserLocked(userInfo);
                     updateUserIdsLocked();
                     Bundle restrictions = new Bundle();
-                    mUserRestrictions.append(userId, restrictions);
+                    synchronized (mRestrictionsLock) {
+                        mBaseUserRestrictions.append(userId, restrictions);
+                    }
                 }
             }
             mPm.newUserCreated(userId);
@@ -1616,25 +1769,6 @@
         }
     }
 
-    @Override
-    public void removeRestrictions() {
-        checkManageUsersPermission("remove restrictions");
-        final int userHandle = UserHandle.getCallingUserId();
-        removeRestrictionsForUser(userHandle, true);
-    }
-
-    private void removeRestrictionsForUser(final int userHandle, boolean unhideApps) {
-        synchronized (mPackagesLock) {
-            // Remove all user restrictions
-            setUserRestrictions(new Bundle(), userHandle);
-            // Remove any app restrictions
-            cleanAppRestrictions(userHandle);
-        }
-        if (unhideApps) {
-            unhideAllInstalledAppsForUser(userHandle);
-        }
-    }
-
     private void unhideAllInstalledAppsForUser(final int userHandle) {
         mHandler.post(new Runnable() {
             @Override
@@ -2062,7 +2196,10 @@
                 }
                 pw.println("    Restrictions:");
                 UserRestrictionsUtils.dumpRestrictions(
-                        pw, "      ", mUserRestrictions.get(user.id));
+                        pw, "      ", mBaseUserRestrictions.get(user.id));
+                pw.println("    Effective restrictions:");
+                UserRestrictionsUtils.dumpRestrictions(
+                        pw, "      ", mCachedEffectiveUserRestrictions.get(user.id));
             }
             pw.println();
             pw.println("Guest restrictions:");
@@ -2095,4 +2232,49 @@
     boolean isInitialized(int userId) {
         return (getUserInfo(userId).flags & UserInfo.FLAG_INITIALIZED) != 0;
     }
+
+    private class LocalService extends UserManagerInternal {
+
+        @Override
+        public Object getUserRestrictionsLock() {
+            return mRestrictionsLock;
+        }
+
+        @Override
+        @GuardedBy("mRestrictionsLock")
+        public void updateEffectiveUserRestrictionsRL(int userId) {
+            UserManagerService.this.updateEffectiveUserRestrictionsRL(userId);
+        }
+
+        @Override
+        @GuardedBy("mRestrictionsLock")
+        public void updateEffectiveUserRestrictionsForAllUsersRL() {
+            UserManagerService.this.updateEffectiveUserRestrictionsForAllUsersRL();
+        }
+
+        @Override
+        public Bundle getBaseUserRestrictions(int userId) {
+            synchronized (mRestrictionsLock) {
+                return mBaseUserRestrictions.get(userId);
+            }
+        }
+
+        @Override
+        public void setBaseUserRestrictionsByDpmsForMigration(
+                int userId, Bundle baseRestrictions) {
+            synchronized (mRestrictionsLock) {
+                mBaseUserRestrictions.put(userId, new Bundle(baseRestrictions));
+                invalidateEffectiveUserRestrictionsRL(userId);
+            }
+
+            synchronized (mPackagesLock) {
+                final UserInfo userInfo = mUsers.get(userId);
+                if (userInfo != null) {
+                    writeUserLocked(userInfo);
+                } else {
+                    Slog.w(LOG_TAG, "UserInfo not found for " + userId);
+                }
+            }
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
index db1fd2e..23e3b35 100644
--- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
+++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
@@ -86,7 +86,6 @@
             String tag) throws IOException {
         serializer.startTag(null, tag);
         for (String key : USER_RESTRICTIONS) {
-            //
             if (restrictions.getBoolean(key)
                     && !NON_PERSIST_USER_RESTRICTIONS.contains(key)) {
                 serializer.attribute(null, key, "true");
@@ -105,6 +104,17 @@
         }
     }
 
+    public static void merge(Bundle dest, Bundle in) {
+        if (in == null) {
+            return;
+        }
+        for (String key : in.keySet()) {
+            if (in.getBoolean(key, false)) {
+                dest.putBoolean(key, true);
+            }
+        }
+    }
+
     public static void dumpRestrictions(PrintWriter pw, String prefix, Bundle restrictions) {
         boolean noneSet = true;
         if (restrictions != null) {
@@ -114,9 +124,11 @@
                     noneSet = false;
                 }
             }
-        }
-        if (noneSet) {
-            pw.println(prefix + "none");
+            if (noneSet) {
+                pw.println(prefix + "none");
+            }
+        } else {
+            pw.println(prefix + "null");
         }
     }
 }
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index be86e2f..f4a4140 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -31,6 +31,7 @@
 
 import android.content.Context;
 import android.os.RemoteException;
+import android.os.Trace;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.TimeUtils;
@@ -731,8 +732,15 @@
             mWindowPlacerLocked.requestTraversal();
         }
 
+        if (mAnimating && !wasAnimating && Trace.isTagEnabled(Trace.TRACE_TAG_WINDOW_MANAGER)) {
+            Trace.asyncTraceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "animating", 0);
+        }
+
         if (!mAnimating && wasAnimating) {
             mWindowPlacerLocked.requestTraversal();
+            if (Trace.isTagEnabled(Trace.TRACE_TAG_WINDOW_MANAGER)) {
+                Trace.asyncTraceEnd(Trace.TRACE_TAG_WINDOW_MANAGER, "animating", 0);
+            }
         }
 
         mService.destroyPreservedSurfaceLocked();
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 8a2442a..62553cf 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -4679,7 +4679,7 @@
                 throw new IllegalArgumentException("resizeStack: stackId " + stackId
                         + " not found.");
             }
-            if (stack.setBounds(bounds, configs, taskBounds)) {
+            if (stack.setBounds(bounds, configs, taskBounds) && stack.isVisibleLocked()) {
                 stack.resizeWindows();
                 stack.getDisplayContent().layoutNeeded = true;
                 mWindowPlacerLocked.performSurfacePlacement();
@@ -4732,6 +4732,26 @@
         }
     }
 
+    /**
+     * Starts deferring layout passes. Useful when doing multiple changes but to optimize
+     * performance, only one layout pass should be done. This can be called multiple times, and
+     * layouting will be resumed once the last caller has called {@link #continueSurfaceLayout}
+     */
+    public void deferSurfaceLayout() {
+        synchronized (mWindowMap) {
+            mWindowPlacerLocked.deferLayout();
+        }
+    }
+
+    /**
+     * Resumes layout passes after deferring them. See {@link #deferSurfaceLayout()}
+     */
+    public void continueSurfaceLayout() {
+        synchronized (mWindowMap) {
+            mWindowPlacerLocked.continueLayout();
+        }
+    }
+
     public void getTaskBounds(int taskId, Rect bounds) {
         synchronized (mWindowMap) {
             Task task = mTaskIdToTask.get(taskId);
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index e2f4dd9..b267860 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -112,13 +112,34 @@
     private int mPreferredModeId = 0;
 
     private boolean mTraversalScheduled;
+    private int mDeferDepth = 0;
 
     public WindowSurfacePlacer(WindowManagerService service) {
         mService = service;
         mWallpaperControllerLocked = mService.mWallpaperControllerLocked;
     }
 
+    /**
+     * See {@link WindowManagerService#deferSurfaceLayout()}
+     */
+    void deferLayout() {
+        mDeferDepth++;
+    }
+
+    /**
+     * See {@link WindowManagerService#continueSurfaceLayout()}
+     */
+    void continueLayout() {
+        mDeferDepth--;
+        if (mDeferDepth <= 0) {
+            performSurfacePlacement();
+        }
+    }
+
     final void performSurfacePlacement() {
+        if (mDeferDepth > 0) {
+            return;
+        }
         int loopCount = 6;
         do {
             mTraversalScheduled = false;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 8385685..b4c8f96 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -16,6 +16,8 @@
 
 package com.android.server.devicepolicy;
 
+import com.google.android.collect.Sets;
+
 import static android.Manifest.permission.MANAGE_CA_CERTIFICATES;
 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
 import static android.app.admin.DevicePolicyManager.WIPE_EXTERNAL_STORAGE;
@@ -88,6 +90,7 @@
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.os.UserManagerInternal;
 import android.os.storage.StorageManager;
 import android.provider.ContactsContract.QuickContact;
 import android.provider.ContactsInternal;
@@ -183,8 +186,6 @@
     private static final int MONITORING_CERT_NOTIFICATION_ID = R.string.ssl_ca_cert_warning;
     private static final int PROFILE_WIPED_NOTIFICATION_ID = 1001;
 
-    private static final boolean DBG = false;
-
     private static final String ATTR_PERMISSION_PROVIDER = "permission-provider";
     private static final String ATTR_SETUP_COMPLETE = "setup-complete";
     private static final String ATTR_PERMISSION_POLICY = "permission-policy";
@@ -274,6 +275,7 @@
     final Injector mInjector;
     final IPackageManager mIPackageManager;
     final UserManager mUserManager;
+    final UserManagerInternal mUserManagerInternal;
 
     final LocalService mLocalService;
 
@@ -357,8 +359,10 @@
                     getSendingUserId());
             if (Intent.ACTION_BOOT_COMPLETED.equals(action)
                     || ACTION_EXPIRED_PASSWORD_NOTIFICATION.equals(action)) {
-                if (DBG) Slog.v(LOG_TAG, "Sending password expiration notifications for action "
-                        + action + " for user " + userHandle);
+                if (VERBOSE_LOG) {
+                    Slog.v(LOG_TAG, "Sending password expiration notifications for action "
+                            + action + " for user " + userHandle);
+                }
                 mHandler.post(new Runnable() {
                     @Override
                     public void run() {
@@ -1014,7 +1018,7 @@
 
     private void handlePackagesChanged(String packageName, int userHandle) {
         boolean removed = false;
-        if (DBG) Slog.d(LOG_TAG, "Handling package changes for user " + userHandle);
+        if (VERBOSE_LOG) Slog.d(LOG_TAG, "Handling package changes for user " + userHandle);
         DevicePolicyData policy = getUserData(userHandle);
         synchronized (this) {
             for (int i = policy.mAdminList.size() - 1; i >= 0; i--) {
@@ -1079,6 +1083,10 @@
             return UserManager.get(mContext);
         }
 
+        UserManagerInternal getUserManagerInternal() {
+            return LocalServices.getService(UserManagerInternal.class);
+        }
+
         NotificationManager getNotificationManager() {
             return mContext.getSystemService(NotificationManager.class);
         }
@@ -1233,6 +1241,7 @@
         mOwners = Preconditions.checkNotNull(injector.newOwners());
 
         mUserManager = Preconditions.checkNotNull(injector.getUserManager());
+        mUserManagerInternal = Preconditions.checkNotNull(injector.getUserManagerInternal());
         mIPackageManager = Preconditions.checkNotNull(injector.getIPackageManager());
 
         mLocalService = new LocalService();
@@ -1327,10 +1336,13 @@
         synchronized (this) {
             mOwners.load();
             findOwnerComponentIfNecessaryLocked();
+            migrateUserRestrictionsIfNecessaryLocked();
 
             // TODO PO may not have a class name either due to b/17652534.  Address that too.
 
             updateDeviceOwnerLocked();
+
+            // TODO Notify UM to update restrictions (?)
         }
     }
 
@@ -1350,14 +1362,113 @@
         if (doComponent == null) {
             Slog.e(LOG_TAG, "Device-owner isn't registered as device-admin");
         } else {
-            mOwners.setDeviceOwner(
+            mOwners.setDeviceOwnerWithRestrictionsMigrated(
                     doComponent,
                     mOwners.getDeviceOwnerName(),
-                    mOwners.getDeviceOwnerUserId());
+                    mOwners.getDeviceOwnerUserId(),
+                    !mOwners.getDeviceOwnerUserRestrictionsNeedsMigration());
             mOwners.writeDeviceOwner();
+            if (VERBOSE_LOG) {
+                Log.v(LOG_TAG, "Device owner component filled in");
+            }
         }
     }
 
+    /**
+     * We didn't use to persist user restrictions for each owners but only persisted in user
+     * manager.
+     */
+    private void migrateUserRestrictionsIfNecessaryLocked() {
+        boolean migrated = false;
+        // Migrate for the DO.  Basically all restrictions should be considered to be set by DO,
+        // except for the "system controlled" ones.
+        if (mOwners.getDeviceOwnerUserRestrictionsNeedsMigration()) {
+            if (VERBOSE_LOG) {
+                Log.v(LOG_TAG, "Migrating DO user restrictions");
+            }
+            migrated = true;
+
+            // Migrate user 0 restrictions to DO, except for "system" restrictions.
+            final ActiveAdmin deviceOwnerAdmin = getDeviceOwnerAdminLocked();
+
+            migrateUserRestrictionsForUser(UserHandle.SYSTEM, deviceOwnerAdmin,
+                    /* exceptionList =*/ UserRestrictionsUtils.SYSTEM_CONTROLLED_USER_RESTRICTIONS);
+
+            mOwners.setDeviceOwnerUserRestrictionsMigrated();
+        }
+
+        // Migrate for POs.  We have a few more exceptions.
+        final Set<String> normalExceptionList = Sets.newArraySet(
+                UserManager.DISALLOW_OUTGOING_CALLS,
+                UserManager.DISALLOW_SMS);
+        normalExceptionList.addAll(UserRestrictionsUtils.SYSTEM_CONTROLLED_USER_RESTRICTIONS);
+
+        final Set<String> managedExceptionList = new ArraySet<>(normalExceptionList.size() + 1);
+        managedExceptionList.addAll(normalExceptionList);
+        managedExceptionList.add(UserManager.DISALLOW_WALLPAPER);
+
+        for (UserInfo ui : mUserManager.getUsers()) {
+            final int userId = ui.id;
+            if (mOwners.getProfileOwnerUserRestrictionsNeedsMigration(userId)) {
+                if (userId != UserHandle.USER_SYSTEM) {
+                    if (VERBOSE_LOG) {
+                        Log.v(LOG_TAG, "Migrating PO user restrictions for user " + userId);
+                    }
+                    migrated = true;
+
+                    final ActiveAdmin profileOwnerAdmin = getProfileOwnerAdminLocked(userId);
+
+                    final Set<String> exceptionList =
+                            ui.isManagedProfile() ? managedExceptionList : normalExceptionList;
+
+                    migrateUserRestrictionsForUser(ui.getUserHandle(), profileOwnerAdmin,
+                            exceptionList);
+                }
+
+                mOwners.setProfileOwnerUserRestrictionsMigrated(userId);
+            }
+        }
+        if (VERBOSE_LOG && migrated) {
+            Log.v(LOG_TAG, "User restrictions migrated.");
+        }
+    }
+
+    private void migrateUserRestrictionsForUser(UserHandle user, ActiveAdmin admin,
+            Set<String> exceptionList) {
+        final Bundle origRestrictions = mUserManagerInternal.getBaseUserRestrictions(
+                user.getIdentifier());
+
+        final Bundle newSystemRestrictions = new Bundle();
+        final Bundle newOwnerRestrictions = new Bundle();
+
+        for (String key : origRestrictions.keySet()) {
+            if (!origRestrictions.getBoolean(key)) {
+                continue;
+            }
+            if (exceptionList.contains(key)) {
+                newSystemRestrictions.putBoolean(key, true);
+            } else {
+                newOwnerRestrictions.putBoolean(key, true);
+            }
+        }
+
+        if (VERBOSE_LOG) {
+            Log.v(LOG_TAG, "origRestrictions=" + origRestrictions);
+            Log.v(LOG_TAG, "newSystemRestrictions=" + newSystemRestrictions);
+            Log.v(LOG_TAG, "newOwnerRestrictions=" + newOwnerRestrictions);
+        }
+        mUserManagerInternal.setBaseUserRestrictionsByDpmsForMigration(user.getIdentifier(),
+                newSystemRestrictions);
+
+        if (admin != null) {
+            admin.ensureUserRestrictions().clear();
+            admin.ensureUserRestrictions().putAll(newOwnerRestrictions);
+        } else {
+            Slog.w(LOG_TAG, "ActiveAdmin for DO/PO not found. user=" + user.getIdentifier());
+        }
+        saveSettingsLocked(user.getIdentifier());
+    }
+
     private ComponentName findAdminComponentWithPackageLocked(String packageName, int userId) {
         final DevicePolicyData policy = getUserData(userId);
         final int n = policy.mAdminList.size();
@@ -1373,7 +1484,7 @@
                 nFound++;
             }
         }
-        if (nFound > 0) {
+        if (nFound > 1) {
             Slog.w(LOG_TAG, "Multiple DA found; assume the first one is DO.");
         }
         return found;
@@ -1636,6 +1747,9 @@
                 ? mInjector.getDevicePolicyFilePathForSystemUser() + DEVICE_POLICIES_XML
                 : new File(mInjector.environmentGetUserSystemDirectory(userHandle),
                         DEVICE_POLICIES_XML).getAbsolutePath();
+        if (VERBOSE_LOG) {
+            Log.v(LOG_TAG, "Opening " + base);
+        }
         return new JournaledFile(new File(base), new File(base + ".tmp"));
     }
 
@@ -1808,7 +1922,8 @@
                     try {
                         DeviceAdminInfo dai = findAdmin(
                                 ComponentName.unflattenFromString(name), userHandle);
-                        if (DBG && (UserHandle.getUserId(dai.getActivityInfo().applicationInfo.uid)
+                        if (VERBOSE_LOG
+                                && (UserHandle.getUserId(dai.getActivityInfo().applicationInfo.uid)
                                 != userHandle)) {
                             Slog.w(LOG_TAG, "findAdmin returned an incorrect uid "
                                     + dai.getActivityInfo().applicationInfo.uid + " for user "
@@ -1988,8 +2103,10 @@
             long token = mInjector.binderClearCallingIdentity();
             try {
                 String value = cameraDisabled ? "1" : "0";
-                if (DBG) Slog.v(LOG_TAG, "Change in camera state ["
-                        + cameraPropertyForUser + "] = " + value);
+                if (VERBOSE_LOG) {
+                    Slog.v(LOG_TAG, "Change in camera state ["
+                            + cameraPropertyForUser + "] = " + value);
+                }
                 mInjector.systemPropertiesSet(cameraPropertyForUser, value);
             } finally {
                 mInjector.binderRestoreCallingIdentity(token);
@@ -4513,8 +4630,10 @@
         }
         UserHandle callingUser = mInjector.binderGetCallingUserHandle();
         // Check if this is the profile owner who is calling
-        getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+        final ActiveAdmin admin =
+                getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
         synchronized (this) {
+            admin.userRestrictions = null;
             clearUserPoliciesLocked(callingUser);
             final int userId = callingUser.getIdentifier();
             mOwners.removeProfileOwner(userId);
@@ -4533,38 +4652,19 @@
 
         final long ident = mInjector.binderClearCallingIdentity();
         try {
-            clearUserRestrictions(userHandle);
             mIPackageManager.updatePermissionFlagsForAllApps(
                     PackageManager.FLAG_PERMISSION_POLICY_FIXED,
                     0  /* flagValues */, userHandle.getIdentifier());
+            // TODO This will not revert audio mute restrictions if they were set.  b/24981972
+            synchronized (mUserManagerInternal.getUserRestrictionsLock()) {
+                mUserManagerInternal.updateEffectiveUserRestrictionsRL(userHandle.getIdentifier());
+            }
         } catch (RemoteException re) {
         } finally {
             mInjector.binderRestoreCallingIdentity(ident);
         }
     }
 
-
-    private void clearUserRestrictions(UserHandle userHandle) {
-        Bundle userRestrictions = mUserManager.getUserRestrictions();
-        mUserManager.setUserRestrictions(new Bundle(), userHandle);
-        if (userRestrictions.getBoolean(UserManager.DISALLOW_ADJUST_VOLUME)) {
-            try {
-                mInjector.getIAudioService().setMasterMute(true, 0, mContext.getPackageName(),
-                        userHandle.getIdentifier());
-            } catch (RemoteException e) {
-                // Not much we can do here.
-            }
-        }
-        if (userRestrictions.getBoolean(UserManager.DISALLOW_UNMUTE_MICROPHONE)) {
-            try {
-                mInjector.getIAudioService().setMicrophoneMute(true, mContext.getPackageName(),
-                        userHandle.getIdentifier());
-            } catch (RemoteException e) {
-                // Not much we can do here.
-            }
-        }
-    }
-
     @Override
     public boolean hasUserSetupCompleted() {
         return hasUserSetupCompleted(UserHandle.getCallingUserId());
@@ -5503,95 +5603,123 @@
     }
 
     @Override
-    public void setUserRestriction(ComponentName who, String key, boolean enabled) {
+    public void setUserRestriction(ComponentName who, String key, boolean enabledFromThisOwner) {
         Preconditions.checkNotNull(who, "ComponentName is null");
         final int userHandle = mInjector.userHandleGetCallingUserId();
         final UserHandle user = new UserHandle(userHandle);
-        synchronized (this) {
-            ActiveAdmin activeAdmin =
-                    getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
-            boolean isDeviceOwner = isDeviceOwner(who);
-            if (!isDeviceOwner && userHandle != UserHandle.USER_SYSTEM
-                    && DEVICE_OWNER_USER_RESTRICTIONS.contains(key)) {
-                throw new SecurityException("Profile owners cannot set user restriction " + key);
-            }
-            if (IMMUTABLE_USER_RESTRICTIONS.contains(key)) {
-                throw new SecurityException("User restriction " + key + " cannot be changed");
-            }
-            boolean alreadyRestricted = mUserManager.hasUserRestriction(key, user);
+        synchronized (mUserManagerInternal.getUserRestrictionsLock()) {
+            synchronized (this) {
+                ActiveAdmin activeAdmin =
+                        getActiveAdminForCallerLocked(who,
+                                DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+                boolean isDeviceOwner = isDeviceOwner(who);
+                if (!isDeviceOwner && userHandle != UserHandle.USER_SYSTEM
+                        && DEVICE_OWNER_USER_RESTRICTIONS.contains(key)) {
+                    throw new SecurityException(
+                            "Profile owners cannot set user restriction " + key);
+                }
+                if (IMMUTABLE_USER_RESTRICTIONS.contains(key)) {
+                    throw new SecurityException("User restriction " + key + " cannot be changed");
+                }
 
-            long id = mInjector.binderClearCallingIdentity();
-            try {
-                if (enabled && !alreadyRestricted) {
-                    if (UserManager.DISALLOW_UNMUTE_MICROPHONE.equals(key)) {
-                        mInjector.getIAudioService()
-                                .setMicrophoneMute(true, mContext.getPackageName(), userHandle);
-                    } else if (UserManager.DISALLOW_ADJUST_VOLUME.equals(key)) {
-                        mInjector.getIAudioService()
-                                .setMasterMute(true, 0, mContext.getPackageName(), userHandle);
-                    } else if (UserManager.DISALLOW_CONFIG_WIFI.equals(key)) {
-                        mInjector.settingsSecurePutIntForUser(
-                                Settings.Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 0,
-                                userHandle);
-                    } else if (UserManager.DISALLOW_SHARE_LOCATION.equals(key)) {
-                        mInjector.settingsSecurePutIntForUser(
-                                Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF,
-                                userHandle);
-                        mInjector.settingsSecurePutStringForUser(
-                                Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "",
-                                userHandle);
-                    } else if (UserManager.DISALLOW_DEBUGGING_FEATURES.equals(key)) {
-                        // Only disable adb if changing for system user, since it is global
-                        // TODO: should this be admin user?
-                        if (userHandle == UserHandle.USER_SYSTEM) {
+                final long id = mInjector.binderClearCallingIdentity();
+                try {
+                    // Original value.
+                    final boolean alreadyRestricted = mUserManager.hasUserRestriction(key, user);
+
+                    // Save the restriction to ActiveAdmin.
+                    // TODO When DO sets a restriction, it'll always be treated as device-wide.
+                    // If there'll be a policy that can be set by both, we'll need scoping support,
+                    // and need to have another Bundle in DO active admin to hold restrictions as
+                    // PO.
+                    activeAdmin.ensureUserRestrictions().putBoolean(key, enabledFromThisOwner);
+                    saveSettingsLocked(userHandle);
+
+                    // Tell UserManager the new value.  Note this needs to be done before calling
+                    // into AudioService, because AS will check AppOps that'll be updated by UM.
+                    if (isDeviceOwner) {
+                        mUserManagerInternal.updateEffectiveUserRestrictionsForAllUsersRL();
+                    } else {
+                        mUserManagerInternal.updateEffectiveUserRestrictionsRL(userHandle);
+                    }
+
+                    // New value.
+                    final boolean enabled = mUserManager.hasUserRestriction(key, user);
+
+                    // TODO The rest of the code should move to UserManagerService.
+
+                    if (enabled && !alreadyRestricted) {
+                        if (UserManager.DISALLOW_UNMUTE_MICROPHONE.equals(key)) {
+                            mInjector.getIAudioService()
+                                    .setMicrophoneMute(true, mContext.getPackageName(), userHandle);
+                        } else if (UserManager.DISALLOW_ADJUST_VOLUME.equals(key)) {
+                            mInjector.getIAudioService()
+                                    .setMasterMute(true, 0, mContext.getPackageName(), userHandle);
+                        } else if (UserManager.DISALLOW_CONFIG_WIFI.equals(key)) {
+                            mInjector.settingsSecurePutIntForUser(
+                                    Settings.Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 0,
+                                    userHandle);
+                        } else if (UserManager.DISALLOW_SHARE_LOCATION.equals(key)) {
+                            mInjector.settingsSecurePutIntForUser(
+                                    Settings.Secure.LOCATION_MODE,
+                                    Settings.Secure.LOCATION_MODE_OFF,
+                                    userHandle);
+                            mInjector.settingsSecurePutStringForUser(
+                                    Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "",
+                                    userHandle);
+                        } else if (UserManager.DISALLOW_DEBUGGING_FEATURES.equals(key)) {
+                            // Only disable adb if changing for system user, since it is global
+                            // TODO: should this be admin user?
+                            if (userHandle == UserHandle.USER_SYSTEM) {
+                                mInjector.settingsGlobalPutStringForUser(
+                                        Settings.Global.ADB_ENABLED, "0", userHandle);
+                            }
+                        } else if (UserManager.ENSURE_VERIFY_APPS.equals(key)) {
                             mInjector.settingsGlobalPutStringForUser(
-                                    Settings.Global.ADB_ENABLED, "0", userHandle);
+                                    Settings.Global.PACKAGE_VERIFIER_ENABLE, "1",
+                                    userHandle);
+                            mInjector.settingsGlobalPutStringForUser(
+                                    Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB, "1",
+                                    userHandle);
+                        } else if (UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES.equals(key)) {
+                            mInjector.settingsSecurePutIntForUser(
+                                    Settings.Secure.INSTALL_NON_MARKET_APPS, 0,
+                                    userHandle);
                         }
-                    } else if (UserManager.ENSURE_VERIFY_APPS.equals(key)) {
-                        mInjector.settingsGlobalPutStringForUser(
-                                Settings.Global.PACKAGE_VERIFIER_ENABLE, "1",
-                                userHandle);
-                        mInjector.settingsGlobalPutStringForUser(
-                                Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB, "1",
-                                userHandle);
-                    } else if (UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES.equals(key)) {
-                        mInjector.settingsSecurePutIntForUser(
-                                Settings.Secure.INSTALL_NON_MARKET_APPS, 0,
-                                userHandle);
                     }
-                }
-                mUserManager.setUserRestriction(key, enabled, user);
-                activeAdmin.ensureUserRestrictions().putBoolean(key, enabled);
-                saveSettingsLocked(userHandle);
 
-                if (enabled != alreadyRestricted) {
-                    if (UserManager.DISALLOW_SHARE_LOCATION.equals(key)) {
-                        // Send out notifications however as some clients may want to reread the
-                        // value which actually changed due to a restriction having been applied.
-                        final String property = Settings.Secure.SYS_PROP_SETTING_VERSION;
-                        long version = mInjector.systemPropertiesGetLong(property, 0) + 1;
-                        mInjector.systemPropertiesSet(property, Long.toString(version));
+                    if (enabled != alreadyRestricted) {
+                        if (UserManager.DISALLOW_SHARE_LOCATION.equals(key)) {
+                            // Send out notifications however as some clients may want to reread the
+                            // value which actually changed due to a restriction having been
+                            // applied.
+                            final String property = Settings.Secure.SYS_PROP_SETTING_VERSION;
+                            long version = mInjector.systemPropertiesGetLong(property, 0) + 1;
+                            mInjector.systemPropertiesSet(property, Long.toString(version));
 
-                        final String name = Settings.Secure.LOCATION_PROVIDERS_ALLOWED;
-                        Uri url = Uri.withAppendedPath(Settings.Secure.CONTENT_URI, name);
-                        mContext.getContentResolver().notifyChange(url, null, true, userHandle);
+                            final String name = Settings.Secure.LOCATION_PROVIDERS_ALLOWED;
+                            Uri url = Uri.withAppendedPath(Settings.Secure.CONTENT_URI, name);
+                            mContext.getContentResolver().notifyChange(url, null, true, userHandle);
+                        }
                     }
-                }
-                if (!enabled && alreadyRestricted) {
-                    if (UserManager.DISALLOW_UNMUTE_MICROPHONE.equals(key)) {
-                        mInjector.getIAudioService()
-                                .setMicrophoneMute(false, mContext.getPackageName(), userHandle);
-                    } else if (UserManager.DISALLOW_ADJUST_VOLUME.equals(key)) {
-                        mInjector.getIAudioService()
-                                .setMasterMute(false, 0, mContext.getPackageName(), userHandle);
+                    if (!enabled && alreadyRestricted) {
+                        if (UserManager.DISALLOW_UNMUTE_MICROPHONE.equals(key)) {
+                            mInjector.getIAudioService()
+                                    .setMicrophoneMute(false, mContext.getPackageName(),
+                                            userHandle);
+                        } else if (UserManager.DISALLOW_ADJUST_VOLUME.equals(key)) {
+                            mInjector.getIAudioService()
+                                    .setMasterMute(false, 0, mContext.getPackageName(), userHandle);
+                        }
                     }
+                } catch (RemoteException re) {
+                    Slog.e(LOG_TAG, "Failed to talk to AudioService.", re);
+                } finally {
+                    mInjector.binderRestoreCallingIdentity(id);
                 }
-            } catch (RemoteException re) {
-                Slog.e(LOG_TAG, "Failed to talk to AudioService.", re);
-            } finally {
-                mInjector.binderRestoreCallingIdentity(id);
+
+                sendChangedNotification(userHandle);
             }
-            sendChangedNotification(userHandle);
         }
     }
 
@@ -5650,7 +5778,7 @@
             long id = mInjector.binderClearCallingIdentity();
 
             try {
-                if (DBG) {
+                if (VERBOSE_LOG) {
                     Slog.v(LOG_TAG, "installing " + packageName + " for "
                             + userId);
                 }
@@ -5705,7 +5833,9 @@
                         0, // no flags
                         primaryUser.id);
 
-                if (DBG) Slog.d(LOG_TAG, "Enabling system activities: " + activitiesToEnable);
+                if (VERBOSE_LOG) {
+                    Slog.d(LOG_TAG, "Enabling system activities: " + activitiesToEnable);
+                }
                 int numberOfAppsInstalled = 0;
                 if (activitiesToEnable != null) {
                     for (ResolveInfo info : activitiesToEnable) {
@@ -6275,7 +6405,8 @@
         }
     }
 
-    private final class LocalService extends DevicePolicyManagerInternal {
+    @VisibleForTesting
+    final class LocalService extends DevicePolicyManagerInternal {
         private List<OnCrossProfileWidgetProvidersChangeListener> mWidgetProviderListeners;
 
         @Override
@@ -6322,6 +6453,30 @@
             }
         }
 
+        @Override
+        public Bundle getComposedUserRestrictions(int userId, Bundle inBundle) {
+            synchronized (DevicePolicyManagerService.this) {
+                final ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked();
+                final ActiveAdmin profileOwner = getProfileOwnerAdminLocked(userId);
+
+                final Bundle deviceOwnerRestrictions =
+                        deviceOwner == null ? null : deviceOwner.userRestrictions;
+                final Bundle profileOwnerRestrictions =
+                        profileOwner == null ? null : profileOwner.userRestrictions;
+
+                if (deviceOwnerRestrictions == null && profileOwnerRestrictions == null) {
+                    // No restrictions to merge.
+                    return inBundle;
+                }
+
+                final Bundle composed = new Bundle(inBundle);
+                UserRestrictionsUtils.merge(composed, deviceOwnerRestrictions);
+                UserRestrictionsUtils.merge(composed, profileOwnerRestrictions);
+
+                return composed;
+            }
+        }
+
         private void notifyCrossProfileProvidersChanged(int userId, List<String> packages) {
             final List<OnCrossProfileWidgetProvidersChangeListener> listeners;
             synchronized (DevicePolicyManagerService.this) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java b/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
index 799267d..12b3775 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
@@ -30,7 +30,6 @@
 import android.util.Xml;
 
 import com.android.internal.util.FastXmlSerializer;
-import com.android.internal.util.Preconditions;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -75,6 +74,7 @@
     private static final String ATTR_PACKAGE = "package";
     private static final String ATTR_COMPONENT_NAME = "component";
     private static final String ATTR_USERID = "userId";
+    private static final String ATTR_USER_RESTRICTIONS_MIGRATED = "userRestrictionsMigrated";
 
     private static final String TAG_SYSTEM_UPDATE_POLICY = "system-update-policy";
 
@@ -155,7 +155,16 @@
             Slog.e(TAG, "Invalid user id for device owner user: " + userId);
             return;
         }
-        mDeviceOwner = new OwnerInfo(ownerName, admin);
+        // For a newly set DO, there's no need for migration.
+        setDeviceOwnerWithRestrictionsMigrated(admin, ownerName, userId,
+                /* userRestrictionsMigrated =*/ true);
+    }
+
+    // Note this should be only called during migration.  Normally when DO is set,
+    // userRestrictionsMigrated should always be true.
+    void setDeviceOwnerWithRestrictionsMigrated(ComponentName admin, String ownerName, int userId,
+            boolean userRestrictionsMigrated) {
+        mDeviceOwner = new OwnerInfo(ownerName, admin, userRestrictionsMigrated);
         mDeviceOwnerUserId = userId;
     }
 
@@ -165,7 +174,9 @@
     }
 
     void setProfileOwner(ComponentName admin, String ownerName, int userId) {
-        mProfileOwners.put(userId, new OwnerInfo(ownerName, admin));
+        // For a newly set PO, there's no need for migration.
+        mProfileOwners.put(userId, new OwnerInfo(ownerName, admin,
+                /* userRestrictionsMigrated =*/ true));
     }
 
     void removeProfileOwner(int userId) {
@@ -207,6 +218,38 @@
         return mDeviceOwner != null;
     }
 
+    /**
+     * @return true if user restrictions need to be migrated for DO.
+     */
+    boolean getDeviceOwnerUserRestrictionsNeedsMigration() {
+        return mDeviceOwner != null && !mDeviceOwner.userRestrictionsMigrated;
+    }
+
+    /**
+     * @return true if user restrictions need to be migrated for PO.
+     */
+    boolean getProfileOwnerUserRestrictionsNeedsMigration(int userId) {
+        OwnerInfo profileOwner = mProfileOwners.get(userId);
+        return profileOwner != null && !profileOwner.userRestrictionsMigrated;
+    }
+
+    /** Sets the user restrictions migrated flag, and also writes to the file. */
+    void setDeviceOwnerUserRestrictionsMigrated() {
+        if (mDeviceOwner != null) {
+            mDeviceOwner.userRestrictionsMigrated = true;
+        }
+        writeDeviceOwner();
+    }
+
+    /** Sets the user restrictions migrated flag, and also writes to the file.  */
+    void setProfileOwnerUserRestrictionsMigrated(int userId) {
+        OwnerInfo profileOwner = mProfileOwners.get(userId);
+        if (profileOwner != null) {
+            profileOwner.userRestrictionsMigrated = true;
+        }
+        writeProfileOwner(userId);
+    }
+
     private boolean readLegacyOwnerFile(File file) {
         if (!file.exists()) {
             // Already migrated or the device has no owners.
@@ -226,7 +269,8 @@
                 if (tag.equals(TAG_DEVICE_OWNER)) {
                     String name = parser.getAttributeValue(null, ATTR_NAME);
                     String packageName = parser.getAttributeValue(null, ATTR_PACKAGE);
-                    mDeviceOwner = new OwnerInfo(name, packageName);
+                    mDeviceOwner = new OwnerInfo(name, packageName,
+                            /* userRestrictionsMigrated =*/ false);
                     mDeviceOwnerUserId = UserHandle.USER_SYSTEM;
                 } else if (tag.equals(TAG_DEVICE_INITIALIZER)) {
                     // Deprecated tag
@@ -241,7 +285,8 @@
                         ComponentName admin = ComponentName.unflattenFromString(
                                 profileOwnerComponentStr);
                         if (admin != null) {
-                            profileOwnerInfo = new OwnerInfo(profileOwnerName, admin);
+                            profileOwnerInfo = new OwnerInfo(profileOwnerName, admin,
+                                /* userRestrictionsMigrated =*/ false);
                         } else {
                             // This shouldn't happen but switch from package name -> component name
                             // might have written bad device owner files. b/17652534
@@ -250,7 +295,8 @@
                         }
                     }
                     if (profileOwnerInfo == null) {
-                        profileOwnerInfo = new OwnerInfo(profileOwnerName, profileOwnerPackageName);
+                        profileOwnerInfo = new OwnerInfo(profileOwnerName, profileOwnerPackageName,
+                                /* userRestrictionsMigrated =*/ false);
                     }
                     mProfileOwners.put(userId, profileOwnerInfo);
                 } else if (TAG_SYSTEM_UPDATE_POLICY.equals(tag)) {
@@ -503,21 +549,24 @@
         }
     }
 
-    private static class OwnerInfo {
+    static class OwnerInfo {
         public final String name;
         public final String packageName;
         public final ComponentName admin;
+        public boolean userRestrictionsMigrated;
 
-        public OwnerInfo(String name, String packageName) {
+        public OwnerInfo(String name, String packageName, boolean userRestrictionsMigrated) {
             this.name = name;
             this.packageName = packageName;
             this.admin = new ComponentName(packageName, "");
+            this.userRestrictionsMigrated = userRestrictionsMigrated;
         }
 
-        public OwnerInfo(String name, ComponentName admin) {
+        public OwnerInfo(String name, ComponentName admin, boolean userRestrictionsMigrated) {
             this.name = name;
             this.admin = admin;
             this.packageName = admin.getPackageName();
+            this.userRestrictionsMigrated = userRestrictionsMigrated;
         }
 
         public void writeToXml(XmlSerializer out, String tag) throws IOException {
@@ -529,6 +578,8 @@
             if (admin != null) {
                 out.attribute(null, ATTR_COMPONENT_NAME, admin.flattenToString());
             }
+            out.attribute(null, ATTR_USER_RESTRICTIONS_MIGRATED,
+                    String.valueOf(userRestrictionsMigrated));
             out.endTag(null, tag);
         }
 
@@ -537,12 +588,16 @@
             final String name = parser.getAttributeValue(null, ATTR_NAME);
             final String componentName =
                     parser.getAttributeValue(null, ATTR_COMPONENT_NAME);
+            final String userRestrictionsMigratedStr =
+                    parser.getAttributeValue(null, ATTR_USER_RESTRICTIONS_MIGRATED);
+            final boolean userRestrictionsMigrated =
+                    ("true".equals(userRestrictionsMigratedStr));
 
             // Has component name?  If so, return [name, component]
             if (componentName != null) {
                 final ComponentName admin = ComponentName.unflattenFromString(componentName);
                 if (admin != null) {
-                    return new OwnerInfo(name, admin);
+                    return new OwnerInfo(name, admin, userRestrictionsMigrated);
                 } else {
                     // This shouldn't happen but switch from package name -> component name
                     // might have written bad device owner files. b/17652534
@@ -552,7 +607,7 @@
             }
 
             // Else, build with [name, package]
-            return new OwnerInfo(name, packageName);
+            return new OwnerInfo(name, packageName, userRestrictionsMigrated);
         }
 
         public void dump(String prefix, PrintWriter pw) {
diff --git a/services/net/java/android/net/ip/IpReachabilityMonitor.java b/services/net/java/android/net/ip/IpReachabilityMonitor.java
index 53f55cd..88155f7 100644
--- a/services/net/java/android/net/ip/IpReachabilityMonitor.java
+++ b/services/net/java/android/net/ip/IpReachabilityMonitor.java
@@ -403,7 +403,6 @@
 
     // TODO: simply the number of objects by making this extend Thread.
     private final class NetlinkSocketObserver implements Runnable {
-        private static final String TAG = "NetlinkSocketObserver";
         private NetlinkSocket mSocket;
 
         @Override
diff --git a/services/tests/servicestests/assets/DevicePolicyManagerServiceMigrationTest/legacy_device_owner.xml b/services/tests/servicestests/assets/DevicePolicyManagerServiceMigrationTest/legacy_device_owner.xml
new file mode 100644
index 0000000..9564969
--- /dev/null
+++ b/services/tests/servicestests/assets/DevicePolicyManagerServiceMigrationTest/legacy_device_owner.xml
@@ -0,0 +1,4 @@
+<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
+<device-owner package="com.android.frameworks.servicestests" />
+<profile-owner package="com.android.frameworks.servicestests" name="0" userId="10" component="com.android.frameworks.servicestests/com.android.server.devicepolicy.DummyDeviceAdmins$Admin2" />
+<profile-owner package="com.android.frameworks.servicestests" name="0" userId="11" component="com.android.frameworks.servicestests/com.android.server.devicepolicy.DummyDeviceAdmins$Admin3" />
diff --git a/services/tests/servicestests/assets/DevicePolicyManagerServiceMigrationTest/legacy_device_policies.xml b/services/tests/servicestests/assets/DevicePolicyManagerServiceMigrationTest/legacy_device_policies.xml
new file mode 100644
index 0000000..48cb814
--- /dev/null
+++ b/services/tests/servicestests/assets/DevicePolicyManagerServiceMigrationTest/legacy_device_policies.xml
@@ -0,0 +1,7 @@
+<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
+<policies setup-complete="true">
+    <admin name="com.google.android.gms/com.google.android.gms.mdm.receivers.MdmDeviceAdminReceiver">
+    </admin>
+    <admin name="com.android.frameworks.servicestests/com.android.server.devicepolicy.DummyDeviceAdmins$Admin1">
+    </admin>
+</policies>
diff --git a/services/tests/servicestests/assets/DevicePolicyManagerServiceMigrationTest/legacy_device_policies_10.xml b/services/tests/servicestests/assets/DevicePolicyManagerServiceMigrationTest/legacy_device_policies_10.xml
new file mode 100644
index 0000000..6b53840
--- /dev/null
+++ b/services/tests/servicestests/assets/DevicePolicyManagerServiceMigrationTest/legacy_device_policies_10.xml
@@ -0,0 +1,5 @@
+<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
+<policies setup-complete="true">
+    <admin name="com.android.frameworks.servicestests/com.android.server.devicepolicy.DummyDeviceAdmins$Admin2">
+    </admin>
+</policies>
diff --git a/services/tests/servicestests/assets/DevicePolicyManagerServiceMigrationTest/legacy_device_policies_11.xml b/services/tests/servicestests/assets/DevicePolicyManagerServiceMigrationTest/legacy_device_policies_11.xml
new file mode 100644
index 0000000..2bcc5d4
--- /dev/null
+++ b/services/tests/servicestests/assets/DevicePolicyManagerServiceMigrationTest/legacy_device_policies_11.xml
@@ -0,0 +1,5 @@
+<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
+<policies setup-complete="true">
+    <admin name="com.android.frameworks.servicestests/com.android.server.devicepolicy.DummyDeviceAdmins$Admin3">
+    </admin>
+</policies>
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java
new file mode 100644
index 0000000..dfa9f8f
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.devicepolicy;
+
+import com.android.server.LocalServices;
+import com.android.server.SystemService;
+import com.android.server.devicepolicy.DevicePolicyManagerServiceTestable.OwnersTestable;
+
+import android.app.admin.DevicePolicyManager;
+import android.app.admin.DevicePolicyManagerInternal;
+import android.content.pm.PackageManager;
+import android.content.pm.UserInfo;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.util.Pair;
+
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.when;
+
+public class DevicePolicyManagerServiceMigrationTest extends DpmTestBase {
+    private DpmMockContext mContext;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mContext = getContext();
+
+        when(mContext.packageManager.hasSystemFeature(eq(PackageManager.FEATURE_DEVICE_ADMIN)))
+                .thenReturn(true);
+    }
+
+    public void testMigration() throws Exception {
+        final File user10dir = mMockContext.addUser(10, 0);
+        final File user11dir = mMockContext.addUser(11, UserInfo.FLAG_MANAGED_PROFILE);
+        final File user12dir = mMockContext.addUser(12, 0);
+
+        setUpPackageManagerForAdmin(admin1, DpmMockContext.CALLER_SYSTEM_USER_UID);
+        setUpPackageManagerForAdmin(admin2, UserHandle.getUid(10, 123));
+        setUpPackageManagerForAdmin(admin3, UserHandle.getUid(11, 456));
+
+        // Create the legacy owners & policies file.
+        DpmTestUtils.writeToFile(
+                (new File(mContext.dataDir, OwnersTestable.LEGACY_FILE)).getAbsoluteFile(),
+                DpmTestUtils.readAsset(mRealTestContext,
+                        "DevicePolicyManagerServiceMigrationTest/legacy_device_owner.xml"));
+
+        DpmTestUtils.writeToFile(
+                (new File(mContext.systemUserDataDir, "device_policies.xml")).getAbsoluteFile(),
+                DpmTestUtils.readAsset(mRealTestContext,
+                        "DevicePolicyManagerServiceMigrationTest/legacy_device_policies.xml"));
+
+        DpmTestUtils.writeToFile(
+                (new File(user10dir, "device_policies.xml")).getAbsoluteFile(),
+                DpmTestUtils.readAsset(mRealTestContext,
+                        "DevicePolicyManagerServiceMigrationTest/legacy_device_policies_10.xml"));
+        DpmTestUtils.writeToFile(
+                (new File(user11dir, "device_policies.xml")).getAbsoluteFile(),
+                DpmTestUtils.readAsset(mRealTestContext,
+                        "DevicePolicyManagerServiceMigrationTest/legacy_device_policies_11.xml"));
+
+        // Set up UserManager
+        when(mMockContext.userManagerInternal.getBaseUserRestrictions(
+                eq(UserHandle.USER_SYSTEM))).thenReturn(DpmTestUtils.newRestrictions(
+                UserManager.DISALLOW_ADD_USER,
+                UserManager.DISALLOW_RECORD_AUDIO));
+
+        when(mMockContext.userManagerInternal.getBaseUserRestrictions(
+                eq(10))).thenReturn(DpmTestUtils.newRestrictions(
+                UserManager.DISALLOW_REMOVE_USER,
+                UserManager.DISALLOW_SMS,
+                UserManager.DISALLOW_OUTGOING_CALLS,
+                UserManager.DISALLOW_WALLPAPER,
+                UserManager.DISALLOW_RECORD_AUDIO));
+
+        when(mMockContext.userManagerInternal.getBaseUserRestrictions(
+                eq(11))).thenReturn(DpmTestUtils.newRestrictions(
+                UserManager.DISALLOW_REMOVE_USER,
+                UserManager.DISALLOW_SMS,
+                UserManager.DISALLOW_OUTGOING_CALLS,
+                UserManager.DISALLOW_WALLPAPER,
+                UserManager.DISALLOW_RECORD_AUDIO));
+
+        final Map<Integer, Bundle> newBaseRestrictions = new HashMap<>();
+
+        doAnswer(new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                Integer userId = (Integer) invocation.getArguments()[0];
+                Bundle bundle = (Bundle) invocation.getArguments()[1];
+
+                newBaseRestrictions.put(userId, bundle);
+
+                return null;
+            }
+        }).when(mContext.userManagerInternal).setBaseUserRestrictionsByDpmsForMigration(
+                anyInt(), any(Bundle.class));
+
+        // Initialize DPM/DPMS and let it migrate the persisted information.
+        // (Need clearCallingIdentity() to pass permission checks.)
+
+        final DevicePolicyManagerServiceTestable dpms;
+
+        final long ident = mContext.binder.clearCallingIdentity();
+        try {
+            LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class);
+
+            dpms = new DevicePolicyManagerServiceTestable(mContext, dataDir);
+
+            dpms.systemReady(SystemService.PHASE_LOCK_SETTINGS_READY);
+            dpms.systemReady(SystemService.PHASE_BOOT_COMPLETED);
+        } finally {
+            mContext.binder.restoreCallingIdentity(ident);
+        }
+
+        // Now all information should be migrated.
+        assertFalse(dpms.mOwners.getDeviceOwnerUserRestrictionsNeedsMigration());
+        assertFalse(dpms.mOwners.getProfileOwnerUserRestrictionsNeedsMigration(10));
+        assertFalse(dpms.mOwners.getProfileOwnerUserRestrictionsNeedsMigration(11));
+        assertFalse(dpms.mOwners.getProfileOwnerUserRestrictionsNeedsMigration(12));
+
+        // Check the new base restrictions.
+        DpmTestUtils.assertRestrictions(
+                DpmTestUtils.newRestrictions(
+                        UserManager.DISALLOW_RECORD_AUDIO
+                ),
+                newBaseRestrictions.get(UserHandle.USER_SYSTEM));
+
+        DpmTestUtils.assertRestrictions(
+                DpmTestUtils.newRestrictions(
+                        UserManager.DISALLOW_SMS,
+                        UserManager.DISALLOW_OUTGOING_CALLS,
+                        UserManager.DISALLOW_RECORD_AUDIO
+                ),
+                newBaseRestrictions.get(10));
+
+        DpmTestUtils.assertRestrictions(
+                DpmTestUtils.newRestrictions(
+                        UserManager.DISALLOW_SMS,
+                        UserManager.DISALLOW_OUTGOING_CALLS,
+                        UserManager.DISALLOW_WALLPAPER,
+                        UserManager.DISALLOW_RECORD_AUDIO
+                ),
+                newBaseRestrictions.get(11));
+
+        // Check the new owner restrictions.
+        DpmTestUtils.assertRestrictions(
+                DpmTestUtils.newRestrictions(
+                        UserManager.DISALLOW_ADD_USER
+                ),
+                dpms.getDeviceOwnerAdminLocked().ensureUserRestrictions());
+
+        DpmTestUtils.assertRestrictions(
+                DpmTestUtils.newRestrictions(
+                        UserManager.DISALLOW_REMOVE_USER,
+                        UserManager.DISALLOW_WALLPAPER
+                ),
+                dpms.getProfileOwnerAdminLocked(10).ensureUserRestrictions());
+
+        DpmTestUtils.assertRestrictions(
+                DpmTestUtils.newRestrictions(
+                        UserManager.DISALLOW_REMOVE_USER
+                ),
+                dpms.getProfileOwnerAdminLocked(11).ensureUserRestrictions());
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
index b109e7b..2c01b8a 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
@@ -27,6 +27,7 @@
 import android.os.PowerManagerInternal;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.os.UserManagerInternal;
 import android.view.IWindowManager;
 
 import java.io.File;
@@ -107,6 +108,11 @@
         }
 
         @Override
+        UserManagerInternal getUserManagerInternal() {
+            return context.userManagerInternal;
+        }
+
+        @Override
         PowerManagerInternal getPowerManagerInternal() {
             return context.powerManagerInternal;
         }
@@ -153,7 +159,7 @@
 
         @Override
         String getDevicePolicyFilePathForSystemUser() {
-            return context.systemUserDataDir.getAbsolutePath();
+            return context.systemUserDataDir.getAbsolutePath() + "/";
         }
 
         @Override
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index d6a60c7..727858b 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -27,7 +27,6 @@
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
-import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.os.Bundle;
@@ -70,9 +69,6 @@
     private DpmMockContext mContext;
     public DevicePolicyManager dpm;
     public DevicePolicyManagerServiceTestable dpms;
-    public ComponentName admin1;
-    public ComponentName admin2;
-    public ComponentName admin3;
 
     @Override
     protected void setUp() throws Exception {
@@ -85,10 +81,6 @@
 
         initializeDpms();
 
-        admin1 = new ComponentName(mRealTestContext, DummyDeviceAdmins.Admin1.class);
-        admin2 = new ComponentName(mRealTestContext, DummyDeviceAdmins.Admin2.class);
-        admin3 = new ComponentName(mRealTestContext, DummyDeviceAdmins.Admin3.class);
-
         setUpPackageManagerForAdmin(admin1, DpmMockContext.CALLER_UID);
         setUpPackageManagerForAdmin(admin2, DpmMockContext.CALLER_UID);
         setUpPackageManagerForAdmin(admin3, DpmMockContext.CALLER_UID);
@@ -113,67 +105,6 @@
         }
     }
 
-    private void setUpPackageManagerForAdmin(ComponentName admin, int packageUid) throws Exception {
-        setUpPackageManagerForAdmin(admin, packageUid,
-                PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED);
-    }
-
-    private void setUpPackageManagerForAdmin(ComponentName admin, int packageUid,
-            int enabledSetting) throws Exception {
-
-        // Set up queryBroadcastReceivers().
-
-        final Intent resolveIntent = new Intent();
-        resolveIntent.setComponent(admin);
-        final List<ResolveInfo> realResolveInfo =
-                mRealTestContext.getPackageManager().queryBroadcastReceivers(
-                        resolveIntent,
-                        PackageManager.GET_META_DATA);
-        assertNotNull(realResolveInfo);
-        assertEquals(1, realResolveInfo.size());
-
-        // We need to change AI, so set a clone.
-        realResolveInfo.set(0, DpmTestUtils.cloneParcelable(realResolveInfo.get(0)));
-
-        // We need to rewrite the UID in the activity info.
-        realResolveInfo.get(0).activityInfo.applicationInfo.uid = packageUid;
-
-        doReturn(realResolveInfo).when(mContext.packageManager).queryBroadcastReceivers(
-                MockUtils.checkIntentComponent(admin),
-                eq(PackageManager.GET_META_DATA
-                        | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS),
-                eq(UserHandle.getUserId(packageUid)));
-
-        // Set up getApplicationInfo().
-
-        final ApplicationInfo ai = DpmTestUtils.cloneParcelable(
-                mRealTestContext.getPackageManager().getApplicationInfo(
-                        admin1.getPackageName(),
-                        PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS));
-
-        ai.enabledSetting = enabledSetting;
-        ai.uid = packageUid;
-
-        doReturn(ai).when(mContext.ipackageManager).getApplicationInfo(
-                eq(admin1.getPackageName()),
-                eq(PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS),
-                eq(UserHandle.getUserId(packageUid)));
-
-        // Set up getPackageInfo().
-
-        final PackageInfo pi = DpmTestUtils.cloneParcelable(
-                mRealTestContext.getPackageManager().getPackageInfo(
-                        admin1.getPackageName(), 0));
-        assertTrue(pi.applicationInfo.flags != 0);
-
-        pi.applicationInfo.uid = packageUid;
-
-        doReturn(pi).when(mContext.ipackageManager).getPackageInfo(
-                eq(admin1.getPackageName()),
-                eq(0),
-                eq(UserHandle.getUserId(packageUid)));
-    }
-
     private void setUpUserManager() {
         // Emulate UserManager.set/getApplicationRestriction().
         final Map<Pair<String, UserHandle>, Bundle> appRestrictions = new HashMap<>();
@@ -220,7 +151,7 @@
         assertTrue(dpm.setProfileOwner(admin, "owner-name", DpmMockContext.CALLER_USER_HANDLE));
 
         // Check
-        assertEquals(admin1, dpm.getProfileOwnerAsUser(DpmMockContext.CALLER_USER_HANDLE));
+        assertEquals(admin, dpm.getProfileOwnerAsUser(DpmMockContext.CALLER_USER_HANDLE));
     }
 
     public void testHasNoFeature() throws Exception {
@@ -743,6 +674,8 @@
         assertEquals("", dpms.getDeviceOwner().getClassName());
 
         // Then create a new DPMS to have it load the settings from files.
+        when(mContext.userManager.getUserRestrictions(any(UserHandle.class)))
+                .thenReturn(new Bundle());
         initializeDpms();
 
         // Now the DO component name is a full name.
@@ -802,32 +735,33 @@
         assertTrue(dpm.setDeviceOwner(admin1, "owner-name",
                 UserHandle.USER_SYSTEM));
 
-        assertFalse(dpms.getDeviceOwnerAdminLocked().ensureUserRestrictions()
-                .getBoolean(UserManager.DISALLOW_SMS));
-        assertFalse(dpms.getDeviceOwnerAdminLocked().ensureUserRestrictions()
-                .getBoolean(UserManager.DISALLOW_OUTGOING_CALLS));
+        DpmTestUtils.assertRestrictions(
+                DpmTestUtils.newRestrictions(),
+                dpms.getDeviceOwnerAdminLocked().ensureUserRestrictions()
+        );
 
         dpm.addUserRestriction(admin1, UserManager.DISALLOW_SMS);
         dpm.addUserRestriction(admin1, UserManager.DISALLOW_OUTGOING_CALLS);
 
-        assertTrue(dpms.getDeviceOwnerAdminLocked().ensureUserRestrictions()
-                .getBoolean(UserManager.DISALLOW_SMS));
-        assertTrue(dpms.getDeviceOwnerAdminLocked().ensureUserRestrictions()
-                .getBoolean(UserManager.DISALLOW_OUTGOING_CALLS));
+        DpmTestUtils.assertRestrictions(
+                DpmTestUtils.newRestrictions(
+                        UserManager.DISALLOW_SMS, UserManager.DISALLOW_OUTGOING_CALLS),
+                dpms.getDeviceOwnerAdminLocked().ensureUserRestrictions()
+        );
 
         dpm.clearUserRestriction(admin1, UserManager.DISALLOW_SMS);
 
-        assertFalse(dpms.getDeviceOwnerAdminLocked().ensureUserRestrictions()
-                .getBoolean(UserManager.DISALLOW_SMS));
-        assertTrue(dpms.getDeviceOwnerAdminLocked().ensureUserRestrictions()
-                .getBoolean(UserManager.DISALLOW_OUTGOING_CALLS));
+        DpmTestUtils.assertRestrictions(
+                DpmTestUtils.newRestrictions(UserManager.DISALLOW_OUTGOING_CALLS),
+                dpms.getDeviceOwnerAdminLocked().ensureUserRestrictions()
+        );
 
         dpm.clearUserRestriction(admin1, UserManager.DISALLOW_OUTGOING_CALLS);
 
-        assertFalse(dpms.getDeviceOwnerAdminLocked().ensureUserRestrictions()
-                .getBoolean(UserManager.DISALLOW_SMS));
-        assertFalse(dpms.getDeviceOwnerAdminLocked().ensureUserRestrictions()
-                .getBoolean(UserManager.DISALLOW_OUTGOING_CALLS));
+        DpmTestUtils.assertRestrictions(
+                DpmTestUtils.newRestrictions(),
+                dpms.getDeviceOwnerAdminLocked().ensureUserRestrictions()
+        );
 
         // TODO Check inner calls.
         // TODO Make sure restrictions are written to the file.
@@ -836,42 +770,106 @@
     public void testSetUserRestriction_asPo() {
         setAsProfileOwner(admin1);
 
-        assertFalse(dpms.getProfileOwnerAdminLocked(DpmMockContext.CALLER_USER_HANDLE)
-                .ensureUserRestrictions()
-                .getBoolean(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES));
-        assertFalse(dpms.getProfileOwnerAdminLocked(DpmMockContext.CALLER_USER_HANDLE)
-                .ensureUserRestrictions()
-                .getBoolean(UserManager.DISALLOW_OUTGOING_CALLS));
+        DpmTestUtils.assertRestrictions(
+                DpmTestUtils.newRestrictions(),
+                dpms.getProfileOwnerAdminLocked(DpmMockContext.CALLER_USER_HANDLE)
+                        .ensureUserRestrictions()
+        );
 
         dpm.addUserRestriction(admin1, UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES);
         dpm.addUserRestriction(admin1, UserManager.DISALLOW_OUTGOING_CALLS);
 
-        assertTrue(dpms.getProfileOwnerAdminLocked(DpmMockContext.CALLER_USER_HANDLE)
-                .ensureUserRestrictions()
-                .getBoolean(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES));
-        assertTrue(dpms.getProfileOwnerAdminLocked(DpmMockContext.CALLER_USER_HANDLE)
-                .ensureUserRestrictions()
-                .getBoolean(UserManager.DISALLOW_OUTGOING_CALLS));
+        DpmTestUtils.assertRestrictions(
+                DpmTestUtils.newRestrictions(
+                        UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES,
+                        UserManager.DISALLOW_OUTGOING_CALLS
+                ),
+                dpms.getProfileOwnerAdminLocked(DpmMockContext.CALLER_USER_HANDLE)
+                        .ensureUserRestrictions()
+        );
 
         dpm.clearUserRestriction(admin1, UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES);
 
-        assertFalse(dpms.getProfileOwnerAdminLocked(DpmMockContext.CALLER_USER_HANDLE)
-                .ensureUserRestrictions()
-                .getBoolean(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES));
-        assertTrue(dpms.getProfileOwnerAdminLocked(DpmMockContext.CALLER_USER_HANDLE)
-                .ensureUserRestrictions()
-                .getBoolean(UserManager.DISALLOW_OUTGOING_CALLS));
+
+        DpmTestUtils.assertRestrictions(
+                DpmTestUtils.newRestrictions(
+                        UserManager.DISALLOW_OUTGOING_CALLS
+                ),
+                dpms.getProfileOwnerAdminLocked(DpmMockContext.CALLER_USER_HANDLE)
+                        .ensureUserRestrictions()
+        );
 
         dpm.clearUserRestriction(admin1, UserManager.DISALLOW_OUTGOING_CALLS);
 
-        assertFalse(dpms.getProfileOwnerAdminLocked(DpmMockContext.CALLER_USER_HANDLE)
-                .ensureUserRestrictions()
-                .getBoolean(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES));
-        assertFalse(dpms.getProfileOwnerAdminLocked(DpmMockContext.CALLER_USER_HANDLE)
-                .ensureUserRestrictions()
-                .getBoolean(UserManager.DISALLOW_OUTGOING_CALLS));
+        DpmTestUtils.assertRestrictions(
+                DpmTestUtils.newRestrictions(),
+                dpms.getProfileOwnerAdminLocked(DpmMockContext.CALLER_USER_HANDLE)
+                        .ensureUserRestrictions()
+        );
 
         // TODO Check inner calls.
         // TODO Make sure restrictions are written to the file.
     }
+
+    public void testGetComposedUserRestrictions_noDoNoPo() throws Exception {
+        final Bundle in = DpmTestUtils.newRestrictions(UserManager.DISALLOW_OUTGOING_CALLS);
+
+        Bundle actual = dpms.mLocalService.getComposedUserRestrictions(
+                UserHandle.USER_SYSTEM, in);
+        assertTrue(in == actual);
+
+        actual = dpms.mLocalService.getComposedUserRestrictions(
+                DpmMockContext.CALLER_USER_HANDLE, in);
+        assertTrue(in == actual);
+    }
+
+    public void testGetComposedUserRestrictions() throws Exception {
+        mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS);
+        mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
+        mContext.callerPermissions.add(permission.INTERACT_ACROSS_USERS_FULL);
+
+        // First, set DO.
+
+        // Call from a process on the system user.
+        mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
+
+        // Make sure admin1 is installed on system user.
+        setUpPackageManagerForAdmin(admin1, DpmMockContext.CALLER_SYSTEM_USER_UID);
+
+        // Call.
+        dpm.setActiveAdmin(admin1, /* replace =*/ false, UserHandle.USER_SYSTEM);
+        assertTrue(dpm.setDeviceOwner(admin1, "owner-name",
+                UserHandle.USER_SYSTEM));
+
+        dpm.addUserRestriction(admin1, "rest1");
+        dpm.addUserRestriction(admin1, "rest2");
+
+        // Set PO on CALLER_USER_HANDLE.
+        mContext.binder.callingUid = DpmMockContext.CALLER_UID;
+
+        setAsProfileOwner(admin2);
+
+        dpm.addUserRestriction(admin2, "restA");
+        dpm.addUserRestriction(admin2, "restB");
+
+        final Bundle in = DpmTestUtils.newRestrictions("abc");
+
+        Bundle actual = dpms.mLocalService.getComposedUserRestrictions(
+                UserHandle.USER_SYSTEM, in);
+        DpmTestUtils.assertRestrictions(
+                DpmTestUtils.newRestrictions("abc", "rest1", "rest2"),
+                actual);
+
+        actual = dpms.mLocalService.getComposedUserRestrictions(
+                DpmMockContext.CALLER_USER_HANDLE, in);
+        DpmTestUtils.assertRestrictions(
+                DpmTestUtils.newRestrictions("abc", "rest1", "rest2", "restA", "restB"),
+                actual);
+
+        actual = dpms.mLocalService.getComposedUserRestrictions(
+                DpmMockContext.CALLER_USER_HANDLE + 1, in);
+        DpmTestUtils.assertRestrictions(
+                DpmTestUtils.newRestrictions("abc", "rest1", "rest2"),
+                actual);
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
index d1b4835..cc337b0 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
@@ -36,6 +36,7 @@
 import android.os.PowerManagerInternal;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.os.UserManagerInternal;
 import android.test.mock.MockContentResolver;
 import android.test.mock.MockContext;
 import android.view.IWindowManager;
@@ -203,6 +204,7 @@
     public final EnvironmentForMock environment;
     public final SystemPropertiesForMock systemProperties;
     public final UserManager userManager;
+    public final UserManagerInternal userManagerInternal;
     public final UserManagerForMock userManagerForMock;
     public final PowerManagerForMock powerManager;
     public final PowerManagerInternal powerManagerInternal;
@@ -233,6 +235,7 @@
         environment = mock(EnvironmentForMock.class);
         systemProperties= mock(SystemPropertiesForMock.class);
         userManager = mock(UserManager.class);
+        userManagerInternal = mock(UserManagerInternal.class);
         userManagerForMock = mock(UserManagerForMock.class);
         powerManager = mock(PowerManagerForMock.class);
         powerManagerInternal = mock(PowerManagerInternal.class);
@@ -257,6 +260,9 @@
 
         // System user is always running.
         setUserRunning(UserHandle.USER_SYSTEM, true);
+
+        // This method must return an object.
+        when(userManagerInternal.getUserRestrictionsLock()).thenReturn(new Object());
     }
 
     public File addUser(int userId, int flags) {
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestBase.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestBase.java
index 63bf125..e11f3fb 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestBase.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestBase.java
@@ -16,10 +16,21 @@
 
 package com.android.server.devicepolicy;
 
+import android.content.ComponentName;
 import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.UserHandle;
 import android.test.AndroidTestCase;
 
 import java.io.File;
+import java.util.List;
+
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doReturn;
 
 public abstract class DpmTestBase extends AndroidTestCase {
     public static final String TAG = "DpmTest";
@@ -29,6 +40,10 @@
 
     public File dataDir;
 
+    public ComponentName admin1;
+    public ComponentName admin2;
+    public ComponentName admin3;
+
     @Override
     protected void setUp() throws Exception {
         super.setUp();
@@ -37,10 +52,77 @@
 
         mMockContext = new DpmMockContext(
                 mRealTestContext, new File(mRealTestContext.getCacheDir(), "test-data"));
+
+        admin1 = new ComponentName(mRealTestContext, DummyDeviceAdmins.Admin1.class);
+        admin2 = new ComponentName(mRealTestContext, DummyDeviceAdmins.Admin2.class);
+        admin3 = new ComponentName(mRealTestContext, DummyDeviceAdmins.Admin3.class);
     }
 
     @Override
     public DpmMockContext getContext() {
         return mMockContext;
     }
+
+
+    protected void setUpPackageManagerForAdmin(ComponentName admin, int packageUid)
+            throws Exception {
+        setUpPackageManagerForAdmin(admin, packageUid,
+                PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED);
+    }
+
+    protected void setUpPackageManagerForAdmin(ComponentName admin, int packageUid,
+            int enabledSetting) throws Exception {
+
+        // Set up queryBroadcastReceivers().
+
+        final Intent resolveIntent = new Intent();
+        resolveIntent.setComponent(admin);
+        final List<ResolveInfo> realResolveInfo =
+                mRealTestContext.getPackageManager().queryBroadcastReceivers(
+                        resolveIntent,
+                        PackageManager.GET_META_DATA);
+        assertNotNull(realResolveInfo);
+        assertEquals(1, realResolveInfo.size());
+
+        // We need to change AI, so set a clone.
+        realResolveInfo.set(0, DpmTestUtils.cloneParcelable(realResolveInfo.get(0)));
+
+        // We need to rewrite the UID in the activity info.
+        realResolveInfo.get(0).activityInfo.applicationInfo.uid = packageUid;
+
+        doReturn(realResolveInfo).when(mMockContext.packageManager).queryBroadcastReceivers(
+                MockUtils.checkIntentComponent(admin),
+                eq(PackageManager.GET_META_DATA
+                        | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS),
+                eq(UserHandle.getUserId(packageUid)));
+
+        // Set up getApplicationInfo().
+
+        final ApplicationInfo ai = DpmTestUtils.cloneParcelable(
+                mRealTestContext.getPackageManager().getApplicationInfo(
+                        admin.getPackageName(),
+                        PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS));
+
+        ai.enabledSetting = enabledSetting;
+        ai.uid = packageUid;
+
+        doReturn(ai).when(mMockContext.ipackageManager).getApplicationInfo(
+                eq(admin.getPackageName()),
+                eq(PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS),
+                eq(UserHandle.getUserId(packageUid)));
+
+        // Set up getPackageInfo().
+
+        final PackageInfo pi = DpmTestUtils.cloneParcelable(
+                mRealTestContext.getPackageManager().getPackageInfo(
+                        admin.getPackageName(), 0));
+        assertTrue(pi.applicationInfo.flags != 0);
+
+        pi.applicationInfo.uid = packageUid;
+
+        doReturn(pi).when(mMockContext.ipackageManager).getPackageInfo(
+                eq(admin.getPackageName()),
+                eq(0),
+                eq(UserHandle.getUserId(packageUid)));
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestUtils.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestUtils.java
index 7506273..cceb2d2 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestUtils.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestUtils.java
@@ -16,21 +16,35 @@
 
 package com.android.server.devicepolicy;
 
+import com.google.android.collect.Lists;
+import com.google.android.collect.Sets;
+
+import android.content.Context;
+import android.os.Bundle;
 import android.os.FileUtils;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.test.AndroidTestCase;
 import android.util.Log;
 import android.util.Printer;
 
 import org.junit.Assert;
 
+import java.io.BufferedReader;
 import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
+import java.util.Objects;
+import java.util.Set;
 
-public class DpmTestUtils {
-    private DpmTestUtils() {
-    }
+import junit.framework.AssertionFailedError;
 
+public class DpmTestUtils extends AndroidTestCase {
     public static void clearDir(File dir) {
         if (dir.exists()) {
             Assert.assertTrue("failed to delete dir", FileUtils.deleteContents(dir));
@@ -43,6 +57,44 @@
         return list == null ? 0 : list.size();
     }
 
+    public static Bundle newRestrictions(String... restrictions) {
+        final Bundle ret = new Bundle();
+        for (String restriction : restrictions) {
+            ret.putBoolean(restriction, true);
+        }
+        return ret;
+    }
+
+    public static void assertRestrictions(Bundle expected, Bundle actual) {
+        final ArrayList<String> elist;
+        if (expected == null) {
+            elist = null;
+        } else {
+            elist = Lists.newArrayList();
+            for (String key : expected.keySet()) {
+                if (expected.getBoolean(key)) {
+                    elist.add(key);
+                }
+            }
+            Collections.sort(elist);
+        }
+
+        final ArrayList<String> alist;
+        if (actual == null) {
+            alist = null;
+        } else {
+            alist = Lists.newArrayList();
+            for (String key : actual.keySet()) {
+                if (actual.getBoolean(key)) {
+                    alist.add(key);
+                }
+            }
+            Collections.sort(alist);
+        }
+
+        assertEquals(elist, alist);
+    }
+
     public static <T extends Parcelable> T cloneParcelable(T source) {
         Parcel p = Parcel.obtain();
         p.writeParcelable(source, 0);
@@ -58,4 +110,57 @@
             Log.i(DpmTestBase.TAG, x);
         }
     };
+
+    public static String readAsset(Context context, String assetPath) throws IOException {
+        final StringBuilder sb = new StringBuilder();
+        try (BufferedReader br = new BufferedReader(
+                new InputStreamReader(
+                        context.getResources().getAssets().open(assetPath)))) {
+            String line;
+            while ((line = br.readLine()) != null) {
+                sb.append(line);
+                sb.append(System.lineSeparator());
+            }
+        }
+        return sb.toString();
+    }
+
+    public static void writeToFile(File path, String content)
+            throws IOException {
+        path.getParentFile().mkdirs();
+
+        try (FileWriter writer = new FileWriter(path)) {
+            Log.i(DpmTestBase.TAG, "Writing to " + path);
+            Log.i(DpmTestBase.TAG, content);
+            writer.write(content);
+        }
+    }
+
+    private static boolean checkAssertRestrictions(Bundle a, Bundle b) {
+        try {
+            assertRestrictions(a, b);
+            return true;
+        } catch (AssertionFailedError e) {
+            return false;
+        }
+    }
+
+    public void testAssertRestrictions() {
+        final Bundle a = newRestrictions();
+        final Bundle b = newRestrictions("a");
+        final Bundle c = newRestrictions("a");
+        final Bundle d = newRestrictions("b", "c");
+        final Bundle e = newRestrictions("b", "c");
+
+        assertTrue(checkAssertRestrictions(null, null));
+        assertFalse(checkAssertRestrictions(null, a));
+        assertFalse(checkAssertRestrictions(a, null));
+        assertTrue(checkAssertRestrictions(a, a));
+
+        assertFalse(checkAssertRestrictions(a, b));
+        assertTrue(checkAssertRestrictions(b, c));
+
+        assertFalse(checkAssertRestrictions(c, d));
+        assertTrue(checkAssertRestrictions(d, e));
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/OwnersTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/OwnersTest.java
index 79845d2..4e11762 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/OwnersTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/OwnersTest.java
@@ -47,31 +47,6 @@
  (mmma frameworks/base/services/tests/servicestests/ for non-ninja build)
  */
 public class OwnersTest extends DpmTestBase {
-    private String readAsset(String assetPath) throws IOException {
-        final StringBuilder sb = new StringBuilder();
-        try (BufferedReader br = new BufferedReader(
-                new InputStreamReader(
-                        mRealTestContext.getResources().getAssets().open(assetPath)))) {
-            String line;
-            while ((line = br.readLine()) != null) {
-                sb.append(line);
-                sb.append(System.lineSeparator());
-            }
-        }
-        return sb.toString();
-    }
-
-    private void createLegacyFile(File path, String content)
-            throws IOException {
-        path.getParentFile().mkdirs();
-
-        try (FileWriter writer = new FileWriter(path)) {
-            Log.i(TAG, "Writing to " + path);
-            Log.i(TAG, content);
-            writer.write(content);
-        }
-    }
-
     public void testUpgrade01() throws Exception {
         getContext().addUsers(10, 11, 20, 21);
 
@@ -79,8 +54,8 @@
         {
             final OwnersTestable owners = new OwnersTestable(getContext());
 
-            createLegacyFile(owners.getLegacyConfigFileWithTestOverride(),
-                    readAsset("OwnersTest/test01/input.xml"));
+            DpmTestUtils.writeToFile(owners.getLegacyConfigFileWithTestOverride(),
+                    DpmTestUtils.readAsset(mRealTestContext, "OwnersTest/test01/input.xml"));
 
             owners.load();
 
@@ -99,6 +74,12 @@
             assertEquals(UserHandle.USER_NULL, owners.getDeviceOwnerUserId());
             assertNull(owners.getSystemUpdatePolicy());
             assertEquals(0, owners.getProfileOwnerKeys().size());
+
+            assertFalse(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
+            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
+            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
+            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
+            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
         }
 
         // Then re-read and check.
@@ -110,6 +91,12 @@
             assertEquals(UserHandle.USER_NULL, owners.getDeviceOwnerUserId());
             assertNull(owners.getSystemUpdatePolicy());
             assertEquals(0, owners.getProfileOwnerKeys().size());
+
+            assertFalse(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
+            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
+            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
+            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
+            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
         }
     }
 
@@ -120,8 +107,8 @@
         {
             final OwnersTestable owners = new OwnersTestable(getContext());
 
-            createLegacyFile(owners.getLegacyConfigFileWithTestOverride(),
-                    readAsset("OwnersTest/test02/input.xml"));
+            DpmTestUtils.writeToFile(owners.getLegacyConfigFileWithTestOverride(),
+                    DpmTestUtils.readAsset(mRealTestContext, "OwnersTest/test02/input.xml"));
 
             owners.load();
 
@@ -142,6 +129,12 @@
 
             assertNull(owners.getSystemUpdatePolicy());
             assertEquals(0, owners.getProfileOwnerKeys().size());
+
+            assertTrue(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
+            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
+            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
+            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
+            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
         }
 
         // Then re-read and check.
@@ -156,6 +149,12 @@
 
             assertNull(owners.getSystemUpdatePolicy());
             assertEquals(0, owners.getProfileOwnerKeys().size());
+
+            assertTrue(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
+            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
+            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
+            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
+            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
         }
     }
 
@@ -166,8 +165,8 @@
         {
             final OwnersTestable owners = new OwnersTestable(getContext());
 
-            createLegacyFile(owners.getLegacyConfigFileWithTestOverride(),
-                    readAsset("OwnersTest/test03/input.xml"));
+            DpmTestUtils.writeToFile(owners.getLegacyConfigFileWithTestOverride(),
+                    DpmTestUtils.readAsset(mRealTestContext, "OwnersTest/test03/input.xml"));
 
             owners.load();
 
@@ -196,6 +195,12 @@
                     owners.getProfileOwnerComponent(11));
             assertEquals("1", owners.getProfileOwnerName(11));
             assertEquals("com.google.android.testdpc1", owners.getProfileOwnerPackage(11));
+
+            assertFalse(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
+            assertTrue(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
+            assertTrue(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
+            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
+            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
         }
 
         // Then re-read and check.
@@ -218,9 +223,19 @@
                     owners.getProfileOwnerComponent(11));
             assertEquals("1", owners.getProfileOwnerName(11));
             assertEquals("com.google.android.testdpc1", owners.getProfileOwnerPackage(11));
+
+            assertFalse(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
+            assertTrue(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
+            assertTrue(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
+            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
+            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
         }
     }
 
+    /**
+     * Note this also tests {@link Owners#setDeviceOwnerUserRestrictionsMigrated()}
+     * and {@link  Owners#setProfileOwnerUserRestrictionsMigrated(int)}.
+     */
     public void testUpgrade04() throws Exception {
         getContext().addUsers(10, 11, 20, 21);
 
@@ -228,8 +243,8 @@
         {
             final OwnersTestable owners = new OwnersTestable(getContext());
 
-            createLegacyFile(owners.getLegacyConfigFileWithTestOverride(),
-                    readAsset("OwnersTest/test04/input.xml"));
+            DpmTestUtils.writeToFile(owners.getLegacyConfigFileWithTestOverride(),
+                    DpmTestUtils.readAsset(mRealTestContext, "OwnersTest/test04/input.xml"));
 
             owners.load();
 
@@ -262,6 +277,12 @@
                     owners.getProfileOwnerComponent(11));
             assertEquals("1", owners.getProfileOwnerName(11));
             assertEquals("com.google.android.testdpc1", owners.getProfileOwnerPackage(11));
+
+            assertTrue(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
+            assertTrue(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
+            assertTrue(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
+            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
+            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
         }
 
         // Then re-read and check.
@@ -288,6 +309,40 @@
                     owners.getProfileOwnerComponent(11));
             assertEquals("1", owners.getProfileOwnerName(11));
             assertEquals("com.google.android.testdpc1", owners.getProfileOwnerPackage(11));
+
+            assertTrue(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
+            assertTrue(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
+            assertTrue(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
+            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
+            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
+
+            owners.setDeviceOwnerUserRestrictionsMigrated();
+        }
+
+        {
+            final OwnersTestable owners = new OwnersTestable(getContext());
+            owners.load();
+
+            assertFalse(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
+            assertTrue(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
+            assertTrue(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
+            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
+            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
+
+            owners.setProfileOwnerUserRestrictionsMigrated(11);
+        }
+
+        {
+            final OwnersTestable owners = new OwnersTestable(getContext());
+            owners.load();
+
+            assertFalse(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
+            assertTrue(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
+            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
+            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
+            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
+
+            owners.setProfileOwnerUserRestrictionsMigrated(11);
         }
     }
 
@@ -298,8 +353,8 @@
         {
             final OwnersTestable owners = new OwnersTestable(getContext());
 
-            createLegacyFile(owners.getLegacyConfigFileWithTestOverride(),
-                    readAsset("OwnersTest/test05/input.xml"));
+            DpmTestUtils.writeToFile(owners.getLegacyConfigFileWithTestOverride(),
+                    DpmTestUtils.readAsset(mRealTestContext, "OwnersTest/test05/input.xml"));
 
             owners.load();
 
@@ -319,6 +374,12 @@
 
             assertNull(owners.getSystemUpdatePolicy());
             assertEquals(0, owners.getProfileOwnerKeys().size());
+
+            assertFalse(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
+            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
+            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
+            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
+            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
         }
 
         // Then re-read and check.
@@ -332,6 +393,12 @@
 
             assertNull(owners.getSystemUpdatePolicy());
             assertEquals(0, owners.getProfileOwnerKeys().size());
+
+            assertFalse(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
+            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
+            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
+            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
+            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
         }
     }
 
@@ -342,8 +409,8 @@
         {
             final OwnersTestable owners = new OwnersTestable(getContext());
 
-            createLegacyFile(owners.getLegacyConfigFileWithTestOverride(),
-                    readAsset("OwnersTest/test06/input.xml"));
+            DpmTestUtils.writeToFile(owners.getLegacyConfigFileWithTestOverride(),
+                    DpmTestUtils.readAsset(mRealTestContext, "OwnersTest/test06/input.xml"));
 
             owners.load();
 
@@ -362,6 +429,12 @@
 
             assertNotNull(owners.getSystemUpdatePolicy());
             assertEquals(5, owners.getSystemUpdatePolicy().getPolicyType());
+
+            assertFalse(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
+            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
+            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
+            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
+            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
         }
 
         // Then re-read and check.
@@ -375,6 +448,12 @@
 
             assertNotNull(owners.getSystemUpdatePolicy());
             assertEquals(5, owners.getSystemUpdatePolicy().getPolicyType());
+
+            assertFalse(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
+            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
+            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
+            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
+            assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
         }
     }
 
@@ -384,8 +463,8 @@
         final OwnersTestable owners = new OwnersTestable(getContext());
 
         // First, migrate to create new-style config files.
-        createLegacyFile(owners.getLegacyConfigFileWithTestOverride(),
-                readAsset("OwnersTest/test04/input.xml"));
+        DpmTestUtils.writeToFile(owners.getLegacyConfigFileWithTestOverride(),
+                DpmTestUtils.readAsset(mRealTestContext, "OwnersTest/test04/input.xml"));
 
         owners.load();
 
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 86f5ed7..66c7dbb 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
@@ -211,11 +211,14 @@
 
     public void testRestrictions() {
         UserInfo testUser = createUser("User 1", 0);
-        Bundle restrictions = new Bundle();
-        restrictions.putBoolean(UserManager.DISALLOW_INSTALL_APPS, true);
-        restrictions.putBoolean(UserManager.DISALLOW_CONFIG_WIFI, false);
-        mUserManager.setUserRestrictions(restrictions, new UserHandle(testUser.id));
+
+        mUserManager.setUserRestriction(
+                UserManager.DISALLOW_INSTALL_APPS, true, new UserHandle(testUser.id));
+        mUserManager.setUserRestriction(
+                UserManager.DISALLOW_CONFIG_WIFI, false, new UserHandle(testUser.id));
+
         Bundle stored = mUserManager.getUserRestrictions(new UserHandle(testUser.id));
+        // Note this will fail if DO already sets those restrictions.
         assertEquals(stored.getBoolean(UserManager.DISALLOW_CONFIG_WIFI), false);
         assertEquals(stored.getBoolean(UserManager.DISALLOW_UNINSTALL_APPS), false);
         assertEquals(stored.getBoolean(UserManager.DISALLOW_INSTALL_APPS), true);