Merge "Performe save when ENTER is pressed."
diff --git a/api/current.txt b/api/current.txt
index ef18bf9..9fe6857 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -2876,6 +2876,7 @@
     method public android.animation.TimeInterpolator getInterpolator();
     method public java.util.ArrayList<android.animation.Animator.AnimatorListener> getListeners();
     method public abstract long getStartDelay();
+    method public long getTotalDuration();
     method public boolean isPaused();
     method public abstract boolean isRunning();
     method public boolean isStarted();
@@ -2891,6 +2892,7 @@
     method public void setupEndValues();
     method public void setupStartValues();
     method public void start();
+    field public static final long DURATION_INFINITE = -1L; // 0xffffffffffffffffL
   }
 
   public static abstract interface Animator.AnimatorListener {
@@ -18173,6 +18175,24 @@
   public class MtpEvent {
     ctor public MtpEvent();
     method public int getEventCode();
+    field public static final int EVENT_CANCEL_TRANSACTION = 16385; // 0x4001
+    field public static final int EVENT_CAPTURE_COMPLETE = 16397; // 0x400d
+    field public static final int EVENT_DEVICE_INFO_CHANGED = 16392; // 0x4008
+    field public static final int EVENT_DEVICE_PROP_CHANGED = 16390; // 0x4006
+    field public static final int EVENT_DEVICE_RESET = 16395; // 0x400b
+    field public static final int EVENT_OBJECT_ADDED = 16386; // 0x4002
+    field public static final int EVENT_OBJECT_INFO_CHANGED = 16391; // 0x4007
+    field public static final int EVENT_OBJECT_PROP_CHANGED = 51201; // 0xc801
+    field public static final int EVENT_OBJECT_PROP_DESC_CHANGED = 51202; // 0xc802
+    field public static final int EVENT_OBJECT_REFERENCES_CHANGED = 51203; // 0xc803
+    field public static final int EVENT_OBJECT_REMOVED = 16387; // 0x4003
+    field public static final int EVENT_REQUEST_OBJECT_TRANSFER = 16393; // 0x4009
+    field public static final int EVENT_STORAGE_INFO_CHANGED = 16396; // 0x400c
+    field public static final int EVENT_STORE_ADDED = 16388; // 0x4004
+    field public static final int EVENT_STORE_FULL = 16394; // 0x400a
+    field public static final int EVENT_STORE_REMOVED = 16389; // 0x4005
+    field public static final int EVENT_UNDEFINED = 16384; // 0x4000
+    field public static final int EVENT_UNREPORTED_STATUS = 16398; // 0x400e
   }
 
   public final class MtpObjectInfo {
diff --git a/api/system-current.txt b/api/system-current.txt
index 0b216bdd..5e1aa41 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -2975,6 +2975,7 @@
     method public android.animation.TimeInterpolator getInterpolator();
     method public java.util.ArrayList<android.animation.Animator.AnimatorListener> getListeners();
     method public abstract long getStartDelay();
+    method public long getTotalDuration();
     method public boolean isPaused();
     method public abstract boolean isRunning();
     method public boolean isStarted();
@@ -2990,6 +2991,7 @@
     method public void setupEndValues();
     method public void setupStartValues();
     method public void start();
+    field public static final long DURATION_INFINITE = -1L; // 0xffffffffffffffffL
   }
 
   public static abstract interface Animator.AnimatorListener {
@@ -19685,6 +19687,24 @@
   public class MtpEvent {
     ctor public MtpEvent();
     method public int getEventCode();
+    field public static final int EVENT_CANCEL_TRANSACTION = 16385; // 0x4001
+    field public static final int EVENT_CAPTURE_COMPLETE = 16397; // 0x400d
+    field public static final int EVENT_DEVICE_INFO_CHANGED = 16392; // 0x4008
+    field public static final int EVENT_DEVICE_PROP_CHANGED = 16390; // 0x4006
+    field public static final int EVENT_DEVICE_RESET = 16395; // 0x400b
+    field public static final int EVENT_OBJECT_ADDED = 16386; // 0x4002
+    field public static final int EVENT_OBJECT_INFO_CHANGED = 16391; // 0x4007
+    field public static final int EVENT_OBJECT_PROP_CHANGED = 51201; // 0xc801
+    field public static final int EVENT_OBJECT_PROP_DESC_CHANGED = 51202; // 0xc802
+    field public static final int EVENT_OBJECT_REFERENCES_CHANGED = 51203; // 0xc803
+    field public static final int EVENT_OBJECT_REMOVED = 16387; // 0x4003
+    field public static final int EVENT_REQUEST_OBJECT_TRANSFER = 16393; // 0x4009
+    field public static final int EVENT_STORAGE_INFO_CHANGED = 16396; // 0x400c
+    field public static final int EVENT_STORE_ADDED = 16388; // 0x4004
+    field public static final int EVENT_STORE_FULL = 16394; // 0x400a
+    field public static final int EVENT_STORE_REMOVED = 16389; // 0x4005
+    field public static final int EVENT_UNDEFINED = 16384; // 0x4000
+    field public static final int EVENT_UNREPORTED_STATUS = 16398; // 0x400e
   }
 
   public final class MtpObjectInfo {
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index 393956f..3f8e311 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]);
+                    return displayPackageFilePath(args[1], UserHandle.USER_OWNER);
                 }
             }
             return 1;
@@ -767,12 +767,25 @@
     }
 
     private int runPath() {
+        int userId = UserHandle.USER_OWNER;
+        String option = nextOption();
+        if (option != null && option.equals("--user")) {
+            String optionData = nextOptionData();
+            if (optionData == null || !isNumber(optionData)) {
+                System.err.println("Error: no USER_ID specified");
+                showUsage();
+                return 1;
+            } else {
+                userId = Integer.parseInt(optionData);
+            }
+        }
+
         String pkg = nextArg();
         if (pkg == null) {
             System.err.println("Error: no package specified");
             return 1;
         }
-        return displayPackageFilePath(pkg);
+        return displayPackageFilePath(pkg, userId);
     }
 
     private int runDump() {
@@ -1637,7 +1650,7 @@
     }
 
     private int runClear() {
-        int userId = 0;
+        int userId = UserHandle.USER_OWNER;
         String option = nextOption();
         if (option != null && option.equals("--user")) {
             String optionData = nextOptionData();
@@ -1709,7 +1722,7 @@
     }
 
     private int runSetEnabledSetting(int state) {
-        int userId = 0;
+        int userId = UserHandle.USER_OWNER;
         String option = nextOption();
         if (option != null && option.equals("--user")) {
             String optionData = nextOptionData();
@@ -1758,7 +1771,7 @@
     }
 
     private int runSetHiddenSetting(boolean state) {
-        int userId = 0;
+        int userId = UserHandle.USER_OWNER;
         String option = nextOption();
         if (option != null && option.equals("--user")) {
             String optionData = nextOptionData();
@@ -1963,9 +1976,9 @@
      * Displays the package file for a package.
      * @param pckg
      */
-    private int displayPackageFilePath(String pckg) {
+    private int displayPackageFilePath(String pckg, int userId) {
         try {
-            PackageInfo info = mPm.getPackageInfo(pckg, 0, 0);
+            PackageInfo info = mPm.getPackageInfo(pckg, 0, userId);
             if (info != null && info.applicationInfo != null) {
                 System.out.print("package:");
                 System.out.println(info.applicationInfo.sourceDir);
@@ -2104,7 +2117,7 @@
         System.err.println("       pm list features");
         System.err.println("       pm list libraries");
         System.err.println("       pm list users");
-        System.err.println("       pm path PACKAGE");
+        System.err.println("       pm path [--user USER_ID] PACKAGE");
         System.err.println("       pm dump PACKAGE");
         System.err.println("       pm install [-lrtsfd] [-i PACKAGE] [--user USER_ID] [PATH]");
         System.err.println("       pm install-create [-lrtsfdp] [-i PACKAGE] [-S BYTES]");
diff --git a/core/java/android/animation/Animator.java b/core/java/android/animation/Animator.java
index d331c2a..844063c 100644
--- a/core/java/android/animation/Animator.java
+++ b/core/java/android/animation/Animator.java
@@ -28,7 +28,6 @@
 
     /**
      * The value used to indicate infinite duration (e.g. when Animators repeat infinitely).
-     * @hide
      */
     public static final long DURATION_INFINITE = -1;
     /**
@@ -191,11 +190,18 @@
     /**
      * Gets the total duration of the animation, accounting for animation sequences, start delay,
      * and repeating. Return {@link #DURATION_INFINITE} if the duration is infinite.
-     * @hide
-     * TODO: Unhide
+     *
+     * @return  Total time an animation takes to finish, starting from the time {@link #start()}
+     *          is called. {@link #DURATION_INFINITE} will be returned if the animation or any
+     *          child animation repeats infinite times.
      */
     public long getTotalDuration() {
-        return getStartDelay() + getDuration();
+        long duration = getDuration();
+        if (duration == DURATION_INFINITE) {
+            return DURATION_INFINITE;
+        } else {
+            return getStartDelay() + duration;
+        }
     }
 
     /**
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java
index d444638..1ab55dd 100644
--- a/core/java/android/animation/AnimatorSet.java
+++ b/core/java/android/animation/AnimatorSet.java
@@ -1030,9 +1030,6 @@
         }
     }
 
-    /**
-     * @hide
-     */
     @Override
     public long getTotalDuration() {
         updateAnimatorsDuration();
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index 4b3df30..6f65889 100644
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -536,9 +536,6 @@
         return mDuration;
     }
 
-    /**
-     * @hide
-     */
     @Override
     public long getTotalDuration() {
         if (mRepeatCount == INFINITE) {
diff --git a/core/java/android/hardware/input/IInputManager.aidl b/core/java/android/hardware/input/IInputManager.aidl
index c8b45c7..c6ae14e 100644
--- a/core/java/android/hardware/input/IInputManager.aidl
+++ b/core/java/android/hardware/input/IInputManager.aidl
@@ -67,4 +67,6 @@
     // Input device vibrator control.
     void vibrate(int deviceId, in long[] pattern, int repeat, IBinder token);
     void cancelVibrate(int deviceId, IBinder token);
+
+    void setPointerIconShape(int shapeId);
 }
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index bae5757..3949d97 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -757,6 +757,22 @@
         }
     }
 
+    /**
+     * Changes the mouse pointer's icon shape into the specified id.
+     *
+     * @param iconId The id of the pointer graphic, as a value between
+     * {@link PointerIcon.STYLE_ARROW} and {@link PointerIcon.STYLE_GRABBING}.
+     *
+     * @hide
+     */
+    public void setPointerIconShape(int iconId) {
+        try {
+            mIm.setPointerIconShape(iconId);
+        } catch (RemoteException ex) {
+            // Do nothing.
+        }
+    }
+
     private void populateInputDevicesLocked() {
         if (mInputDevicesChangedListener == null) {
             final InputDevicesChangedListener listener = new InputDevicesChangedListener();
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 85041ad..f7c8662 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -577,7 +577,7 @@
         public static final int KITKAT = 19;
 
         /**
-         * Android 4.4W: KitKat for watches, snacks on the run.
+         * June 2014: Android 4.4W. KitKat for watches, snacks on the run.
          *
          * <p>Applications targeting this or a later release will get these
          * new changes in behavior:</p>
@@ -595,7 +595,7 @@
         public static final int L = 21;
 
         /**
-         * Lollipop.  A flat one with beautiful shadows.  But still tasty.
+         * November 2014: Lollipop.  A flat one with beautiful shadows.  But still tasty.
          *
          * <p>Applications targeting this or a later release will get these
          * new changes in behavior:</p>
@@ -626,12 +626,38 @@
         public static final int LOLLIPOP = 21;
 
         /**
-         * Lollipop with an extra sugar coating on the outside!
+         * March 2015: Lollipop with an extra sugar coating on the outside!
          */
         public static final int LOLLIPOP_MR1 = 22;
 
         /**
-         * M comes after L.
+         * M is for Marshmallow!
+         *
+         * <p>Applications targeting this or a later release will get these
+         * new changes in behavior:</p>
+         * <ul>
+         * <li> Runtime permissions.  Dangerous permissions are no longer granted at
+         * install time, but must be requested by the application at runtime through
+         * {@link android.app.Activity#requestPermissions}.</li>
+         * <li> Bluetooth and Wi-Fi scanning now requires holding the location permission.</li>
+         * <li> {@link android.app.AlarmManager#setTimeZone AlarmManager.setTimeZone} will fail if
+         * the given timezone is non-Olson.</li>
+         * <li> Activity transitions will only return shared
+         * elements mapped in the returned view hierarchy back to the calling activity.</li>
+         * <li> {@link android.view.View} allows a number of behaviors that may break
+         * existing apps: Canvas throws an exception if restore() is called too many times,
+         * widgets may return a hint size when returning UNSPECIFIED measure specs, and it
+         * will respect the attributes {@link android.R.attr#foreground},
+         * {@link android.R.attr#foregroundGravity}, {@link android.R.attr#foregroundTint}, and
+         * {@link android.R.attr#foregroundTintMode}.</li>
+         * <li> {@link android.view.MotionEvent#getButtonState MotionEvent.getButtonState}
+         * will no longer report {@link android.view.MotionEvent#BUTTON_PRIMARY}
+         * and {@link android.view.MotionEvent#BUTTON_SECONDARY} as synonyms for
+         * {@link android.view.MotionEvent#BUTTON_STYLUS_PRIMARY} and
+         * {@link android.view.MotionEvent#BUTTON_STYLUS_SECONDARY}.</li>
+         * <li> {@link android.widget.ScrollView} now respects the layout param margins
+         * when measuring.</li>
+         * </ul>
          */
         public static final int M = 23;
 
diff --git a/core/java/android/preference/SeekBarVolumizer.java b/core/java/android/preference/SeekBarVolumizer.java
index 979c828..2445bc2 100644
--- a/core/java/android/preference/SeekBarVolumizer.java
+++ b/core/java/android/preference/SeekBarVolumizer.java
@@ -383,6 +383,7 @@
                 final IntentFilter filter = new IntentFilter(AudioManager.VOLUME_CHANGED_ACTION);
                 filter.addAction(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION);
                 filter.addAction(NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED);
+                filter.addAction(AudioManager.STREAM_DEVICES_CHANGED_ACTION);
                 mContext.registerReceiver(this, filter);
             } else {
                 mContext.unregisterReceiver(this);
@@ -395,13 +396,7 @@
             if (AudioManager.VOLUME_CHANGED_ACTION.equals(action)) {
                 int streamType = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1);
                 int streamValue = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, -1);
-                final boolean streamMatch = mNotificationOrRing ? isNotificationOrRing(streamType)
-                        : (streamType == mStreamType);
-                if (mSeekBar != null && streamMatch && streamValue != -1) {
-                    final boolean muted = mAudioManager.isStreamMute(mStreamType)
-                            || streamValue == 0;
-                    mUiHandler.postUpdateSlider(streamValue, mLastAudibleStreamVolume, muted);
-                }
+                updateVolumeSlider(streamType, streamValue);
             } else if (AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION.equals(action)) {
                 if (mNotificationOrRing) {
                     mRingerMode = mAudioManager.getRingerModeInternal();
@@ -409,10 +404,24 @@
                 if (mAffectedByRingerMode) {
                     updateSlider();
                 }
+            } else if (AudioManager.STREAM_DEVICES_CHANGED_ACTION.equals(action)) {
+                int streamType = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1);
+                int streamVolume = mAudioManager.getStreamVolume(streamType);
+                updateVolumeSlider(streamType, streamVolume);
             } else if (NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED.equals(action)) {
                 mZenMode = mNotificationManager.getZenMode();
                 updateSlider();
             }
         }
+
+        private void updateVolumeSlider(int streamType, int streamValue) {
+            final boolean streamMatch = mNotificationOrRing ? isNotificationOrRing(streamType)
+                    : (streamType == mStreamType);
+            if (mSeekBar != null && streamMatch && streamValue != -1) {
+                final boolean muted = mAudioManager.isStreamMute(mStreamType)
+                        || streamValue == 0;
+                mUiHandler.postUpdateSlider(streamValue, mLastAudibleStreamVolume, muted);
+            }
+        }
     }
 }
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index e054a61..2c49d16 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -68,6 +68,7 @@
     public static final int[] MINUTE_BUCKETS = generateMinuteBuckets();
     private static final int SECONDS_MS = 1000;
     private static final int MINUTES_MS = 60 * SECONDS_MS;
+    private static final int DAY_MINUTES = 24 * 60;
     private static final int ZERO_VALUE_MS = 10 * SECONDS_MS;
 
     private static final boolean DEFAULT_ALLOW_CALLS = true;
@@ -561,14 +562,6 @@
         return tryParseLong(val, defValue);
     }
 
-    public ArraySet<String> getAutomaticRuleNames() {
-        final ArraySet<String> rt = new ArraySet<String>();
-        for (int i = 0; i < automaticRules.size(); i++) {
-            rt.add(automaticRules.valueAt(i).name);
-        }
-        return rt;
-    }
-
     @Override
     public int describeContents() {
         return 0;
@@ -661,40 +654,65 @@
             boolean shortVersion) {
         final long now = System.currentTimeMillis();
         final long millis = minutesFromNow == 0 ? ZERO_VALUE_MS : minutesFromNow * MINUTES_MS;
-        return toTimeCondition(context, now + millis, minutesFromNow, now, userHandle,
-                shortVersion);
+        return toTimeCondition(context, now + millis, minutesFromNow, userHandle, shortVersion);
     }
 
-    public static Condition toTimeCondition(Context context, long time, int minutes, long now,
+    public static Condition toTimeCondition(Context context, long time, int minutes,
             int userHandle, boolean shortVersion) {
-        final int num, summaryResId, line1ResId;
+        final int num;
+        String summary, line1, line2;
+        final CharSequence formattedTime = getFormattedTime(context, time, minutes, userHandle);
+        final Resources res = context.getResources();
         if (minutes < 60) {
             // display as minutes
             num = minutes;
-            summaryResId = shortVersion ? R.plurals.zen_mode_duration_minutes_summary_short
+            int summaryResId = shortVersion ? R.plurals.zen_mode_duration_minutes_summary_short
                     : R.plurals.zen_mode_duration_minutes_summary;
-            line1ResId = shortVersion ? R.plurals.zen_mode_duration_minutes_short
+            summary = res.getQuantityString(summaryResId, num, num, formattedTime);
+            int line1ResId = shortVersion ? R.plurals.zen_mode_duration_minutes_short
                     : R.plurals.zen_mode_duration_minutes;
-        } else {
+            line1 = res.getQuantityString(line1ResId, num, num, formattedTime);
+            line2 = res.getString(R.string.zen_mode_until, formattedTime);
+        } else if (minutes < DAY_MINUTES) {
             // display as hours
             num =  Math.round(minutes / 60f);
-            summaryResId = shortVersion ? R.plurals.zen_mode_duration_hours_summary_short
+            int summaryResId = shortVersion ? R.plurals.zen_mode_duration_hours_summary_short
                     : R.plurals.zen_mode_duration_hours_summary;
-            line1ResId = shortVersion ? R.plurals.zen_mode_duration_hours_short
+            summary = res.getQuantityString(summaryResId, num, num, formattedTime);
+            int line1ResId = shortVersion ? R.plurals.zen_mode_duration_hours_short
                     : R.plurals.zen_mode_duration_hours;
+            line1 = res.getQuantityString(line1ResId, num, num, formattedTime);
+            line2 = res.getString(R.string.zen_mode_until, formattedTime);
+        } else {
+            // display as day/time
+            summary = line1 = line2 = res.getString(R.string.zen_mode_until, formattedTime);
         }
-        final String skeleton = DateFormat.is24HourFormat(context, userHandle) ? "Hm" : "hma";
-        final String pattern = DateFormat.getBestDateTimePattern(Locale.getDefault(), skeleton);
-        final CharSequence formattedTime = DateFormat.format(pattern, time);
-        final Resources res = context.getResources();
-        final String summary = res.getQuantityString(summaryResId, num, num, formattedTime);
-        final String line1 = res.getQuantityString(line1ResId, num, num, formattedTime);
-        final String line2 = res.getString(R.string.zen_mode_until, formattedTime);
         final Uri id = toCountdownConditionId(time);
         return new Condition(id, summary, line1, line2, 0, Condition.STATE_TRUE,
                 Condition.FLAG_RELEVANT_NOW);
     }
 
+    public static Condition toNextAlarmCondition(Context context, long now, long alarm,
+            int userHandle) {
+        int minutes = Math.round((alarm-now) / (float) MINUTES_MS);
+        final CharSequence formattedTime = getFormattedTime(context, alarm, minutes, userHandle);
+        final Resources res = context.getResources();
+        final String line1 = res.getString(R.string.zen_mode_alarm, formattedTime);
+        final Uri id = toCountdownConditionId(alarm);
+        return new Condition(id, "", line1, "", 0, Condition.STATE_TRUE,
+                Condition.FLAG_RELEVANT_NOW);
+    }
+
+    private static CharSequence getFormattedTime(Context context, long time, int minutes,
+            int userHandle) {
+        String skeleton = DateFormat.is24HourFormat(context, userHandle) ? "Hm" : "hma";
+        if (minutes > DAY_MINUTES) {
+            skeleton = "EEE " + (DateFormat.is24HourFormat(context, userHandle) ? "Hm" : "hma");
+        }
+        final String pattern = DateFormat.getBestDateTimePattern(Locale.getDefault(), skeleton);
+        return DateFormat.format(pattern, time);
+    }
+
     // ==== Built-in system conditions ====
 
     public static final String SYSTEM_AUTHORITY = "android";
@@ -900,11 +918,6 @@
         return UUID.randomUUID().toString().replace("-", "");
     }
 
-    public static String getConditionLine1(Context context, ZenModeConfig config,
-            int userHandle, boolean shortVersion) {
-        return getConditionLine(context, config, userHandle, true /*useLine1*/, shortVersion);
-    }
-
     public static String getConditionSummary(Context context, ZenModeConfig config,
             int userHandle, boolean shortVersion) {
         return getConditionLine(context, config, userHandle, false /*useLine1*/, shortVersion);
@@ -923,8 +936,8 @@
             if (time > 0) {
                 final long now = System.currentTimeMillis();
                 final long span = time - now;
-                c = toTimeCondition(context,
-                        time, Math.round(span / (float) MINUTES_MS), now, userHandle, shortVersion);
+                c = toTimeCondition(context, time, Math.round(span / (float) MINUTES_MS),
+                        userHandle, shortVersion);
             }
             final String rt = c == null ? "" : useLine1 ? c.line1 : c.summary;
             return TextUtils.isEmpty(rt) ? "" : rt;
diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java
index cc4598d..bae51d3 100644
--- a/core/java/android/view/InputDevice.java
+++ b/core/java/android/view/InputDevice.java
@@ -766,6 +766,15 @@
     }
 
     /**
+     * Sets the current pointer shape.
+     * @param pointerShape the id of the pointer icon.
+     * @hide
+     */
+    public void setPointerShape(int pointerShape) {
+        InputManager.getInstance().setPointerIconShape(pointerShape);
+    }
+
+    /**
      * Provides information about the range of values for a particular {@link MotionEvent} axis.
      *
      * @see InputDevice#getMotionRange(int)
diff --git a/core/java/android/view/PointerIcon.java b/core/java/android/view/PointerIcon.java
index cf35ce5..88e9a95 100644
--- a/core/java/android/view/PointerIcon.java
+++ b/core/java/android/view/PointerIcon.java
@@ -48,6 +48,12 @@
     /** Style constant: Null icon.  It has no bitmap. */
     public static final int STYLE_NULL = 0;
 
+    /** Style constant: no icons are specified. If all views uses this, then falls back
+     * to the default style, but this is helpful to distinguish a view explicitly want
+     * to have the default icon.
+     */
+    public static final int STYLE_NOT_SPECIFIED = 1;
+
     /** Style constant: Arrow icon.  (Default mouse pointer) */
     public static final int STYLE_ARROW = 1000;
 
@@ -60,12 +66,74 @@
     /** {@hide} Style constant: Spot anchor icon for touchpads. */
     public static final int STYLE_SPOT_ANCHOR = 2002;
 
+    // Style constants for additional predefined icons for mice.
+    /** Style constant: context-menu. */
+    public static final int STYLE_CONTEXT_MENU = 1001;
+
+    /** Style constant: hand. */
+    public static final int STYLE_HAND = 1002;
+
+    /** Style constant: help. */
+    public static final int STYLE_HELP = 1003;
+
+    /** Style constant: wait. */
+    public static final int STYLE_WAIT = 1004;
+
+    /** Style constant: cell. */
+    public static final int STYLE_CELL = 1006;
+
+    /** Style constant: crosshair. */
+    public static final int STYLE_CROSSHAIR = 1007;
+
+    /** Style constant: text. */
+    public static final int STYLE_TEXT = 1008;
+
+    /** Style constant: vertical-text. */
+    public static final int STYLE_VERTICAL_TEXT = 1009;
+
+    /** Style constant: alias (indicating an alias of/shortcut to something is
+      * to be created. */
+    public static final int STYLE_ALIAS = 1010;
+
+    /** Style constant: copy. */
+    public static final int STYLE_COPY = 1011;
+
+    /** Style constant: no-drop. */
+    public static final int STYLE_NO_DROP = 1012;
+
+    /** Style constant: all-scroll. */
+    public static final int STYLE_ALL_SCROLL = 1013;
+
+    /** Style constant: horizontal double arrow mainly for resizing. */
+    public static final int STYLE_HORIZONTAL_DOUBLE_ARROW = 1014;
+
+    /** Style constant: vertical double arrow mainly for resizing. */
+    public static final int STYLE_VERTICAL_DOUBLE_ARROW = 1015;
+
+    /** Style constant: diagonal double arrow -- top-right to bottom-left. */
+    public static final int STYLE_TOP_RIGHT_DIAGONAL_DOUBLE_ARROW = 1016;
+
+    /** Style constant: diagonal double arrow -- top-left to bottom-right. */
+    public static final int STYLE_TOP_LEFT_DIAGONAL_DOUBLE_ARROW = 1017;
+
+    /** Style constant: zoom-in. */
+    public static final int STYLE_ZOOM_IN = 1018;
+
+    /** Style constant: zoom-out. */
+    public static final int STYLE_ZOOM_OUT = 1019;
+
+    /** Style constant: grab. */
+    public static final int STYLE_GRAB = 1020;
+
+    /** Style constant: grabbing. */
+    public static final int STYLE_GRABBING = 1021;
+
     // OEM private styles should be defined starting at this range to avoid
     // conflicts with any system styles that may be defined in the future.
     private static final int STYLE_OEM_FIRST = 10000;
 
-    // The default pointer icon.
-    private static final int STYLE_DEFAULT = STYLE_ARROW;
+    /** {@hide} The default pointer icon. */
+    public static final int STYLE_DEFAULT = STYLE_ARROW;
 
     private static final PointerIcon gNullIcon = new PointerIcon(STYLE_NULL);
 
@@ -434,6 +502,49 @@
                 return com.android.internal.R.styleable.Pointer_pointerIconSpotTouch;
             case STYLE_SPOT_ANCHOR:
                 return com.android.internal.R.styleable.Pointer_pointerIconSpotAnchor;
+            case STYLE_HAND:
+                return com.android.internal.R.styleable.Pointer_pointerIconHand;
+            case STYLE_CONTEXT_MENU:
+                return com.android.internal.R.styleable.Pointer_pointerIconContextMenu;
+            case STYLE_HELP:
+                return com.android.internal.R.styleable.Pointer_pointerIconHelp;
+            case STYLE_WAIT:
+                // falls back to the default icon because no animation support.
+                return com.android.internal.R.styleable.Pointer_pointerIconArrow;
+            case STYLE_CELL:
+                return com.android.internal.R.styleable.Pointer_pointerIconCell;
+            case STYLE_CROSSHAIR:
+                return com.android.internal.R.styleable.Pointer_pointerIconCrosshair;
+            case STYLE_TEXT:
+                return com.android.internal.R.styleable.Pointer_pointerIconText;
+            case STYLE_VERTICAL_TEXT:
+                return com.android.internal.R.styleable.Pointer_pointerIconVerticalText;
+            case STYLE_ALIAS:
+                return com.android.internal.R.styleable.Pointer_pointerIconAlias;
+            case STYLE_COPY:
+                return com.android.internal.R.styleable.Pointer_pointerIconCopy;
+            case STYLE_ALL_SCROLL:
+                return com.android.internal.R.styleable.Pointer_pointerIconAllScroll;
+            case STYLE_NO_DROP:
+                return com.android.internal.R.styleable.Pointer_pointerIconNodrop;
+            case STYLE_HORIZONTAL_DOUBLE_ARROW:
+                return com.android.internal.R.styleable.Pointer_pointerIconHorizontalDoubleArrow;
+            case STYLE_VERTICAL_DOUBLE_ARROW:
+                return com.android.internal.R.styleable.Pointer_pointerIconVerticalDoubleArrow;
+            case STYLE_TOP_RIGHT_DIAGONAL_DOUBLE_ARROW:
+                return com.android.internal.R.styleable.
+                        Pointer_pointerIconTopRightDiagonalDoubleArrow;
+            case STYLE_TOP_LEFT_DIAGONAL_DOUBLE_ARROW:
+                return com.android.internal.R.styleable.
+                        Pointer_pointerIconTopLeftDiagonalDoubleArrow;
+            case STYLE_ZOOM_IN:
+                return com.android.internal.R.styleable.Pointer_pointerIconZoomIn;
+            case STYLE_ZOOM_OUT:
+                return com.android.internal.R.styleable.Pointer_pointerIconZoomOut;
+            case STYLE_GRAB:
+                return com.android.internal.R.styleable.Pointer_pointerIconGrab;
+            case STYLE_GRABBING:
+                return com.android.internal.R.styleable.Pointer_pointerIconGrabbing;
             default:
                 return 0;
         }
diff --git a/core/java/android/view/RenderNodeAnimator.java b/core/java/android/view/RenderNodeAnimator.java
index 2a3756d..7747580 100644
--- a/core/java/android/view/RenderNodeAnimator.java
+++ b/core/java/android/view/RenderNodeAnimator.java
@@ -336,9 +336,6 @@
         return mUnscaledDuration;
     }
 
-    /**
-     * @hide
-     */
     @Override
     public long getTotalDuration() {
         return mUnscaledDuration + mUnscaledStartDelay;
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 7752ed8..4bc2112 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -20995,6 +20995,11 @@
         }
     }
 
+    /** @hide */
+    public int getPointerShape(MotionEvent event, float x, float y) {
+        return PointerIcon.STYLE_NOT_SPECIFIED;
+    }
+
     //
     // Properties
     //
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 475ce2f..7c7ad91 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -1715,6 +1715,36 @@
         return false;
     }
 
+    /** @hide */
+    @Override
+    public int getPointerShape(MotionEvent event, float x, float y) {
+        // Check what the child under the pointer says about the pointer.
+        final int childrenCount = mChildrenCount;
+        if (childrenCount != 0) {
+            final ArrayList<View> preorderedList = buildOrderedChildList();
+            final boolean customOrder = preorderedList == null
+                    && isChildrenDrawingOrderEnabled();
+            final View[] children = mChildren;
+            for (int i = childrenCount - 1; i >= 0; i--) {
+                final int childIndex = customOrder ? getChildDrawingOrder(childrenCount, i) : i;
+                final View child = (preorderedList == null)
+                        ? children[childIndex] : preorderedList.get(childIndex);
+                PointF point = getLocalPoint();
+                if (isTransformedTouchPointInView(x, y, child, point)) {
+                    final int pointerShape = child.getPointerShape(event, point.x, point.y);
+                    if (pointerShape != PointerIcon.STYLE_NOT_SPECIFIED) {
+                        return pointerShape;
+                    }
+                    break;
+                }
+            }
+        }
+
+        // The pointer is not a child or the child has no preferences, returning the default
+        // implementation.
+        return super.getPointerShape(event, x, y);
+    }
+
     /**
      * {@inheritDoc}
      */
@@ -4606,7 +4636,6 @@
     }
 
     private void removeViewInternal(int index, View view) {
-
         if (mTransition != null) {
             mTransition.removeChild(this, view);
         }
@@ -4699,12 +4728,17 @@
     }
 
     private void removeViewsInternal(int start, int count) {
+        final int end = start + count;
+
+        if (start < 0 || count < 0 || end > mChildrenCount) {
+            throw new IndexOutOfBoundsException();
+        }
+
         final View focused = mFocused;
         final boolean detach = mAttachInfo != null;
         boolean clearChildFocus = false;
 
         final View[] children = mChildren;
-        final int end = start + count;
 
         for (int i = start; i < end; i++) {
             final View view = children[i];
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 3d10289..13b6a42 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -37,6 +37,7 @@
 import android.graphics.drawable.Drawable;
 import android.hardware.display.DisplayManager;
 import android.hardware.display.DisplayManager.DisplayListener;
+import android.hardware.input.InputManager;
 import android.media.AudioManager;
 import android.os.Binder;
 import android.os.Build;
@@ -324,6 +325,8 @@
     private long mFpsPrevTime = -1;
     private int mFpsNumFrames;
 
+    private int mPointerIconShape = PointerIcon.STYLE_NOT_SPECIFIED;
+
     /**
      * see {@link #playSoundEffect(int)}
      */
@@ -4168,6 +4171,30 @@
         private int processPointerEvent(QueuedInputEvent q) {
             final MotionEvent event = (MotionEvent)q.mEvent;
 
+            if (event.getPointerCount() == 1
+                    && event.isFromSource(InputDevice.SOURCE_MOUSE)) {
+                if (event.getActionMasked() == MotionEvent.ACTION_HOVER_ENTER
+                        || event.getActionMasked() == MotionEvent.ACTION_HOVER_EXIT) {
+                    // Other apps or the window manager may change the icon shape outside of
+                    // this app, therefore the icon shape has to be reset on enter/exit event.
+                    mPointerIconShape = PointerIcon.STYLE_NOT_SPECIFIED;
+                }
+
+                final float x = event.getX();
+                final float y = event.getY();
+                if (x >= 0 && x < mView.getWidth() && y >= 0 && y < mView.getHeight()) {
+                    int pointerShape = mView.getPointerShape(event, x, y);
+                    if (pointerShape == PointerIcon.STYLE_NOT_SPECIFIED) {
+                        pointerShape = PointerIcon.STYLE_DEFAULT;
+                    }
+
+                    if (mPointerIconShape != pointerShape) {
+                        mPointerIconShape = pointerShape;
+                        event.getDevice().setPointerShape(pointerShape);
+                    }
+                }
+            }
+
             mAttachInfo.mUnbufferedDispatchRequested = false;
             boolean handled = mView.dispatchPointerEvent(event);
             if (mAttachInfo.mUnbufferedDispatchRequested && !mUnbufferedInputDispatch) {
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index aaf6052..d20c729 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -22,6 +22,7 @@
 import android.content.pm.ActivityInfo;
 import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
+import android.graphics.Point;
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.os.Bundle;
@@ -38,7 +39,7 @@
  * instance of it is created by the window manager when it starts up, and allows
  * customization of window layering, special window types, key dispatching, and
  * layout.
- * 
+ *
  * <p>Because this provides deep interaction with the system window manager,
  * specific methods on this interface can be called from a variety of contexts
  * with various restrictions on what they can do.  These are encoded through
@@ -47,9 +48,9 @@
  * is attached to a method, then it is not called with any locks and may be
  * called from the main window manager thread or another thread calling into
  * the window manager.
- * 
+ *
  * <p>The current suffixes are:
- * 
+ *
  * <dl>
  * <dt> Ti <dd> Called from the input thread.  This is the thread that
  * collects pending input events and dispatches them to the appropriate window.
@@ -71,7 +72,7 @@
  * acquired by the window manager while it holds the window lock, so this is
  * even more restrictive than <var>Lw</var>.
  * </dl>
- * 
+ *
  * @hide
  */
 public interface WindowManagerPolicy {
@@ -138,7 +139,7 @@
          * Perform standard frame computation.  The result can be obtained with
          * getFrame() if so desired.  Must be called with the window manager
          * lock held.
-         * 
+         *
          * @param parentFrame The frame of the parent container this window
          * is in, used for computing its basic position.
          * @param displayFrame The frame of the overall display in which this
@@ -168,18 +169,18 @@
         /**
          * Retrieve the current frame of the window that has been assigned by
          * the window manager.  Must be called with the window manager lock held.
-         * 
+         *
          * @return Rect The rectangle holding the window frame.
          */
         public Rect getFrameLw();
 
         /**
-         * Retrieve the current frame of the window that is actually shown.
+         * Retrieve the current position of the window that is actually shown.
          * Must be called with the window manager lock held.
-         * 
-         * @return Rect The rectangle holding the shown window frame.
+         *
+         * @return Point The point holding the shown window position.
          */
-        public RectF getShownFrameLw();
+        public Point getShownPositionLw();
 
         /**
          * Retrieve the frame of the display that this window was last
@@ -206,7 +207,7 @@
          * account for screen decorations such as a status bar or soft
          * keyboard.  Must be called with the
          * window manager lock held.
-         * 
+         *
          * @return Rect The rectangle holding the content frame.
          */
         public Rect getContentFrameLw();
@@ -218,7 +219,7 @@
          * content frame to account for transient UI elements blocking it
          * such as an input method's candidates UI.  Must be called with the
          * window manager lock held.
-         * 
+         *
          * @return Rect The rectangle holding the visible frame.
          */
         public Rect getVisibleFrameLw();
@@ -229,12 +230,12 @@
          * layout of other windows.
          */
         public boolean getGivenInsetsPendingLw();
-        
+
         /**
          * Retrieve the insets given by this window's client for the content
          * area of windows behind it.  Must be called with the
          * window manager lock held.
-         * 
+         *
          * @return Rect The left, top, right, and bottom insets, relative
          * to the window's frame, of the actual contents.
          */
@@ -244,7 +245,7 @@
          * Retrieve the insets given by this window's client for the visible
          * area of windows behind it.  Must be called with the
          * window manager lock held.
-         * 
+         *
          * @return Rect The left, top, right, and bottom insets, relative
          * to the window's frame, of the actual visible area.
          */
@@ -252,7 +253,7 @@
 
         /**
          * Retrieve the current LayoutParams of the window.
-         * 
+         *
          * @return WindowManager.LayoutParams The window's internal LayoutParams
          *         instance.
          */
@@ -298,12 +299,12 @@
         public boolean isVoiceInteraction();
 
         /**
-         * Return true if, at any point, the application token associated with 
-         * this window has actually displayed any windows.  This is most useful 
-         * with the "starting up" window to determine if any windows were 
-         * displayed when it is closed. 
-         * 
-         * @return Returns true if one or more windows have been displayed, 
+         * Return true if, at any point, the application token associated with
+         * this window has actually displayed any windows.  This is most useful
+         * with the "starting up" window to determine if any windows were
+         * displayed when it is closed.
+         *
+         * @return Returns true if one or more windows have been displayed,
          *         else false.
          */
         public boolean hasAppShownWindows();
@@ -314,17 +315,17 @@
          * that will remove the surface.
          */
         boolean isVisibleLw();
-        
+
         /**
          * Like {@link #isVisibleLw}, but also counts a window that is currently
          * "hidden" behind the keyguard as visible.  This allows us to apply
          * things like window flags that impact the keyguard.
          */
         boolean isVisibleOrBehindKeyguardLw();
-        
+
         /**
-         * Is this window currently visible to the user on-screen?  It is 
-         * displayed either if it is visible or it is currently running an 
+         * Is this window currently visible to the user on-screen?  It is
+         * displayed either if it is visible or it is currently running an
          * animation before no longer being visible.  Must be called with the
          * window manager lock held.
          */
@@ -350,7 +351,7 @@
         boolean isDrawnLw();
 
         /**
-         * Returns true if this window has been shown on screen at some time in 
+         * Returns true if this window has been shown on screen at some time in
          * the past.  Must be called with the window manager lock held.
          */
         public boolean hasDrawnLw();
@@ -362,7 +363,7 @@
          * Returns true if {@link #showLw} was last called for the window.
          */
         public boolean hideLw(boolean doAnimation);
-        
+
         /**
          * Can be called to undo the effect of {@link #hideLw}, allowing a
          * window to be shown as long as the window manager and client would
@@ -479,7 +480,7 @@
 
     // NOTE: screen off reasons are in order of significance, with more
     // important ones lower than less important ones.
-    
+
     /** Screen turned off because of a device admin */
     public final int OFF_BECAUSE_OF_ADMIN = 1;
     /** Screen turned off because of power button */
@@ -498,10 +499,10 @@
     /** When not otherwise specified by the activity's screenOrientation, rotation is set by
      * the user. */
     public final int USER_ROTATION_LOCKED = 1;
-    
+
     /**
      * Perform initialization of the policy.
-     * 
+     *
      * @param context The system context we are running in.
      */
     public void init(Context context, IWindowManager windowManager,
@@ -526,11 +527,11 @@
 
     /**
      * Check permissions when adding a window.
-     * 
+     *
      * @param attrs The window's LayoutParams.
      * @param outAppOp First element will be filled with the app op corresponding to
      *                 this window, or OP_NONE.
-     *  
+     *
      * @return {@link WindowManagerGlobal#ADD_OKAY} if the add can proceed;
      *      else an error code, usually
      *      {@link WindowManagerGlobal#ADD_PERMISSION_DENIED}, to abort the add.
@@ -551,21 +552,21 @@
      * Sanitize the layout parameters coming from a client.  Allows the policy
      * to do things like ensure that windows of a specific type can't take
      * input focus.
-     * 
+     *
      * @param attrs The window layout parameters to be modified.  These values
      * are modified in-place.
      */
     public void adjustWindowParamsLw(WindowManager.LayoutParams attrs);
-    
+
     /**
      * After the window manager has computed the current configuration based
      * on its knowledge of the display and input devices, it gives the policy
      * a chance to adjust the information contained in it.  If you want to
      * leave it as-is, simply do nothing.
-     * 
+     *
      * <p>This method may be called by any thread in the window manager, but
      * no internal locks in the window manager will be held.
-     * 
+     *
      * @param config The Configuration being computed, for you to change as
      * desired.
      * @param keyboardPresence Flags that indicate whether internal or external
@@ -575,13 +576,13 @@
      */
     public void adjustConfigurationLw(Configuration config, int keyboardPresence,
             int navigationPresence);
-    
+
     /**
      * Assign a window type to a layer.  Allows you to control how different
      * kinds of windows are ordered on-screen.
-     * 
+     *
      * @param type The type of window being assigned.
-     * 
+     *
      * @return int An arbitrary integer used to order windows, with lower
      *         numbers below higher ones.
      */
@@ -591,9 +592,9 @@
      * Return how to Z-order sub-windows in relation to the window they are
      * attached to.  Return positive to have them ordered in front, negative for
      * behind.
-     * 
+     *
      * @param type The sub-window type code.
-     * 
+     *
      * @return int Layer in relation to the attached window, where positive is
      *         above and negative is below.
      */
@@ -669,19 +670,19 @@
      * manager (using the normal window manager APIs) that will be shown until
      * the application displays its own window.  This is called without the
      * window manager locked so that you can call back into it.
-     * 
+     *
      * @param appToken Token of the application being started.
-     * @param packageName The name of the application package being started. 
+     * @param packageName The name of the application package being started.
      * @param theme Resource defining the application's overall visual theme.
      * @param nonLocalizedLabel The default title label of the application if
      *        no data is found in the resource.
      * @param labelRes The resource ID the application would like to use as its name.
      * @param icon The resource ID the application would like to use as its icon.
      * @param windowFlags Window layout flags.
-     * 
+     *
      * @return Optionally you can return the View that was used to create the
      *         window, for easy removal in removeStartingWindow.
-     * 
+     *
      * @see #removeStartingWindow
      */
     public View addStartingWindow(IBinder appToken, String packageName,
@@ -694,15 +695,15 @@
      * that application.  You should at this point remove the window from the
      * window manager.  This is called without the window manager locked so
      * that you can call back into it.
-     * 
+     *
      * <p>Note: due to the nature of these functions not being called with the
      * window manager locked, you must be prepared for this function to be
      * called multiple times and/or an initial time with a null View window
      * even if you previously returned one.
-     * 
+     *
      * @param appToken Token of the application that has started.
      * @param window Window View that was returned by createStartingWindow.
-     * 
+     *
      * @see #addStartingWindow
      */
     public void removeStartingWindow(IBinder appToken, View window);
@@ -711,10 +712,10 @@
      * Prepare for a window being added to the window manager.  You can throw an
      * exception here to prevent the window being added, or do whatever setup
      * you need to keep track of the window.
-     * 
+     *
      * @param win The window being added.
-     * @param attrs The window's LayoutParams. 
-     *  
+     * @param attrs The window's LayoutParams.
+     *
      * @return {@link WindowManagerGlobal#ADD_OKAY} if the add can proceed, else an
      *         error code to abort the add.
      */
@@ -724,7 +725,7 @@
     /**
      * Called when a window is being removed from a window manager.  Must not
      * throw an exception -- clean up as much as possible.
-     * 
+     *
      * @param win The window being removed.
      */
     public void removeWindowLw(WindowState win);
@@ -733,12 +734,12 @@
      * Control the animation to run when a window's state changes.  Return a
      * non-0 number to force the animation to a specific resource ID, or 0
      * to use the default animation.
-     * 
+     *
      * @param win The window that is changing.
      * @param transit What is happening to the window: {@link #TRANSIT_ENTER},
      *                {@link #TRANSIT_EXIT}, {@link #TRANSIT_SHOW}, or
      *                {@link #TRANSIT_HIDE}.
-     * 
+     *
      * @return Resource ID of the actual animation to use, or 0 for none.
      */
     public int selectAnimationLw(WindowState win, int transit);
@@ -747,8 +748,8 @@
      * Determine the animation to run for a rotation transition based on the
      * top fullscreen windows {@link WindowManager.LayoutParams#rotationAnimation}
      * and whether it is currently fullscreen and frontmost.
-     * 
-     * @param anim The exiting animation resource id is stored in anim[0], the 
+     *
+     * @param anim The exiting animation resource id is stored in anim[0], the
      * entering animation resource id is stored in anim[1].
      */
     public void selectRotationAnimationLw(int anim[]);
@@ -814,7 +815,7 @@
      * <p>Allows you to define
      * behavior for keys that can not be overridden by applications.
      * This method is called from the input thread, with no locks held.
-     * 
+     *
      * @param win The window that currently has focus.  This is where the key
      *            event will normally go.
      * @param event The key event.
@@ -832,7 +833,7 @@
      *
      * <p>Allows you to define default global behavior for keys that were not handled
      * by applications.  This method is called from the input thread, with no locks held.
-     * 
+     *
      * @param win The window that currently has focus.  This is where the key
      *            event will normally go.
      * @param event The key event.
@@ -844,7 +845,7 @@
 
     /**
      * Called when layout of the windows is about to start.
-     * 
+     *
      * @param isDefaultDisplay true if window is on {@link Display#DEFAULT_DISPLAY}.
      * @param displayWidth The current full width of the screen.
      * @param displayHeight The current full height of the screen.
@@ -872,7 +873,7 @@
      * Called for each window attached to the window manager as layout is
      * proceeding.  The implementation of this function must take care of
      * setting the window's frame, either here or in finishLayout().
-     * 
+     *
      * @param win The window being positioned.
      * @param attached For sub-windows, the window it is attached to; this
      *                 window will already have had layoutWindow() called on it
@@ -880,7 +881,7 @@
      */
     public void layoutWindowLw(WindowState win, WindowState attached);
 
-    
+
     /**
      * Return the insets for the areas covered by system windows. These values
      * are computed on the most recent layout, so they are not guaranteed to
@@ -912,10 +913,10 @@
     static final int FINISH_LAYOUT_REDO_WALLPAPER = 0x0004;
     /** Need to recompute animations */
     static final int FINISH_LAYOUT_REDO_ANIM = 0x0008;
-    
+
     /**
      * Called following layout of all windows before each window has policy applied.
-     * 
+     *
      * @param displayWidth The current full width of the screen.
      * @param displayHeight The current full height of the screen.
      */
@@ -936,7 +937,7 @@
      * to each window. If in this function you do
      * something that may have modified the animation state of another window,
      * be sure to return non-zero in order to perform another pass through layout.
-     *  
+     *
      * @return Return any bit set of {@link #FINISH_LAYOUT_REDO_LAYOUT},
      * {@link #FINISH_LAYOUT_REDO_CONFIG}, {@link #FINISH_LAYOUT_REDO_WALLPAPER},
      * or {@link #FINISH_LAYOUT_REDO_ANIM}.
@@ -1150,7 +1151,7 @@
      * the system should go into safe mode.
      */
     public void setSafeMode(boolean safeMode);
-    
+
     /**
      * Called when the system is mostly done booting.
      */
@@ -1184,14 +1185,14 @@
      * this point the display is active.
      */
     public void enableScreenAfterBoot();
-    
+
     public void setCurrentOrientationLw(@ActivityInfo.ScreenOrientation int newOrientation);
-    
+
     /**
      * Call from application to perform haptic feedback on its window.
      */
     public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always);
-    
+
     /**
      * Called when we have started keeping the screen on because a window
      * requesting this has become visible.
@@ -1205,21 +1206,21 @@
     public void keepScreenOnStoppedLw();
 
     /**
-     * Gets the current user rotation mode. 
+     * Gets the current user rotation mode.
      *
      * @return The rotation mode.
      *
      * @see WindowManagerPolicy#USER_ROTATION_LOCKED
-     * @see WindowManagerPolicy#USER_ROTATION_FREE 
+     * @see WindowManagerPolicy#USER_ROTATION_FREE
      */
     @UserRotationMode
     public int getUserRotationMode();
 
     /**
-     * Inform the policy that the user has chosen a preferred orientation ("rotation lock"). 
+     * Inform the policy that the user has chosen a preferred orientation ("rotation lock").
      *
      * @param mode One of {@link WindowManagerPolicy#USER_ROTATION_LOCKED} or
-     *             {@link WindowManagerPolicy#USER_ROTATION_FREE}. 
+     *             {@link WindowManagerPolicy#USER_ROTATION_FREE}.
      * @param rotation One of {@link Surface#ROTATION_0}, {@link Surface#ROTATION_90},
      *                 {@link Surface#ROTATION_180}, {@link Surface#ROTATION_270}.
      */
diff --git a/core/java/android/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java
index 11d0f4a..4ac547a 100644
--- a/core/java/android/view/inputmethod/InputMethodInfo.java
+++ b/core/java/android/view/inputmethod/InputMethodInfo.java
@@ -429,7 +429,8 @@
 
     public void dump(Printer pw, String prefix) {
         pw.println(prefix + "mId=" + mId
-                + " mSettingsActivityName=" + mSettingsActivityName);
+                + " mSettingsActivityName=" + mSettingsActivityName
+                + " mSupportsSwitchingToNextInputMethod=" + mSupportsSwitchingToNextInputMethod);
         pw.println(prefix + "mIsDefaultResId=0x"
                 + Integer.toHexString(mIsDefaultResId));
         pw.println(prefix + "Service:");
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 0712052..1aeb9c93 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -116,6 +116,7 @@
 import android.view.KeyCharacterMap;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
+import android.view.PointerIcon;
 import android.view.View;
 import android.view.ViewParent;
 import android.view.ViewStructure;
@@ -5905,6 +5906,17 @@
         return mLayout != null ? mLayout.getHeight() : 0;
     }
 
+    /**
+     * @hide
+     */
+    @Override
+    public int getPointerShape(MotionEvent event, float x, float y) {
+        if (isTextSelectable() || isTextEditable()) {
+            return PointerIcon.STYLE_TEXT;
+        }
+        return super.getPointerShape(event, x, y);
+    }
+
     @Override
     public boolean onKeyPreIme(int keyCode, KeyEvent event) {
         // Note: If the IME is in fullscreen mode and IMS#mExtractEditText is in text action mode,
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 255e23a..f462a47 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -1017,7 +1017,15 @@
                             final RowScale rs = new RowScale(ChooserRowAdapter.this, 0.f, 1.f)
                                     .setInterpolator(mInterpolator);
                             mServiceTargetScale[i] = rs;
-                            rs.startAnimation();
+                        }
+
+                        // Start the animations in a separate loop.
+                        // The process of starting animations will result in
+                        // binding views to set up initial values, and we must
+                        // have ALL of the new RowScale objects created above before
+                        // we get started.
+                        for (int i = oldRCount; i < rcount; i++) {
+                            mServiceTargetScale[i].startAnimation();
                         }
                     }
 
@@ -1097,17 +1105,19 @@
 
             for (int i = 0; i < mColumnCount; i++) {
                 final View v = mChooserListAdapter.createView(row);
+                final int column = i;
                 v.setOnClickListener(new OnClickListener() {
                     @Override
                     public void onClick(View v) {
-                        startSelected(holder.itemIndex, false, true);
+                        startSelected(holder.itemIndices[column], false, true);
                     }
                 });
                 v.setOnLongClickListener(new OnLongClickListener() {
                     @Override
                     public boolean onLongClick(View v) {
                         showAppDetails(
-                                mChooserListAdapter.resolveInfoForPosition(holder.itemIndex, true));
+                                mChooserListAdapter.resolveInfoForPosition(
+                                        holder.itemIndices[column], true));
                         return true;
                     }
                 });
@@ -1165,8 +1175,8 @@
                 final View v = holder.cells[i];
                 if (start + i <= end) {
                     v.setVisibility(View.VISIBLE);
-                    holder.itemIndex = start + i;
-                    mChooserListAdapter.bindView(holder.itemIndex, v);
+                    holder.itemIndices[i] = start + i;
+                    mChooserListAdapter.bindView(holder.itemIndices[i], v);
                 } else {
                     v.setVisibility(View.GONE);
                 }
@@ -1197,11 +1207,12 @@
         final View[] cells;
         final ViewGroup row;
         int measuredRowHeight;
-        int itemIndex;
+        int[] itemIndices;
 
         public RowViewHolder(ViewGroup row, int cellCount) {
             this.row = row;
             this.cells = new View[cellCount];
+            this.itemIndices = new int[cellCount];
         }
 
         public void measure() {
@@ -1389,7 +1400,7 @@
                 final View v = mChooserRowAdapter.getView(pos, mCachedView, mListView);
                 int height = ((RowViewHolder) (v.getTag())).measuredRowHeight;
 
-                offset += (int) (height * mChooserRowAdapter.getRowScale(pos) * chooserTargetRows);
+                offset += (int) (height * mChooserRowAdapter.getRowScale(pos));
 
                 if (vt >= 0) {
                     mCachedViewType = vt;
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index aaa89df..9a5cde6 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -70,6 +70,7 @@
     private static final String TAG = "Zygote";
 
     private static final String PROPERTY_DISABLE_OPENGL_PRELOADING = "ro.zygote.disable_gl_preload";
+    private static final String PROPERTY_RUNNING_IN_CONTAINER = "ro.boot.container";
 
     private static final String ANDROID_SOCKET_PREFIX = "ANDROID_SOCKET_";
 
@@ -503,7 +504,6 @@
     private static boolean startSystemServer(String abiList, String socketName)
             throws MethodAndArgsCaller, RuntimeException {
         long capabilities = posixCapabilitiesAsBits(
-            OsConstants.CAP_BLOCK_SUSPEND,
             OsConstants.CAP_KILL,
             OsConstants.CAP_NET_ADMIN,
             OsConstants.CAP_NET_BIND_SERVICE,
@@ -515,6 +515,10 @@
             OsConstants.CAP_SYS_TIME,
             OsConstants.CAP_SYS_TTY_CONFIG
         );
+        /* Containers run without this capability, so avoid setting it in that case */
+        if (!SystemProperties.getBoolean(PROPERTY_RUNNING_IN_CONTAINER, false)) {
+            capabilities |= posixCapabilitiesAsBits(OsConstants.CAP_BLOCK_SUSPEND);
+        }
         /* Hardcoded command line to start the system server */
         String args[] = {
             "--setuid=1000",
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index ab372d3..75ad916a 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -3705,13 +3705,14 @@
         }
 
         /**
-         * Returns true if the Window is free floating and has a shadow. Note that non overlapping
-         * windows do not have a shadow since it could not be seen anyways (a small screen / tablet
+         * Returns true if the Window is free floating and has a shadow (although at some times
+         * it might not be displaying it, e.g. during a resize). Note that non overlapping windows
+         * do not have a shadow since it could not be seen anyways (a small screen / tablet
          * "tiles" the windows side by side but does not overlap them).
          * @return Returns true when the window has a shadow created by the non client decor.
          **/
         private boolean windowHasShadow() {
-            return windowHasNonClientDecor() && getElevation() > 0;
+            return windowHasNonClientDecor() && nonClientDecorHasShadow(mWindow.mWorkspaceId);
         }
 
         void setWindow(PhoneWindow phoneWindow) {
@@ -5417,7 +5418,7 @@
      * @param workspaceId The Id of the workspace which contains this window.
      * @Return Returns true if the window should show a shadow.
      **/
-    private boolean nonClientDecorHasShadow(int workspaceId) {
+    private static boolean nonClientDecorHasShadow(int workspaceId) {
         return workspaceId == FREEFORM_WORKSPACE_STACK_ID;
     }
 
diff --git a/core/jni/android_view_PointerIcon.h b/core/jni/android_view_PointerIcon.h
index 3bfd645..86f288d 100644
--- a/core/jni/android_view_PointerIcon.h
+++ b/core/jni/android_view_PointerIcon.h
@@ -31,6 +31,27 @@
     POINTER_ICON_STYLE_CUSTOM = -1,
     POINTER_ICON_STYLE_NULL = 0,
     POINTER_ICON_STYLE_ARROW = 1000,
+    POINTER_ICON_STYLE_CONTEXT_MENU = 1001,
+    POINTER_ICON_STYLE_HAND = 1002,
+    POINTER_ICON_STYLE_HELP = 1003,
+    POINTER_ICON_STYLE_WAIT = 1004,
+    POINTER_ICON_STYLE_CELL = 1006,
+    POINTER_ICON_STYLE_CROSSHAIR = 1007,
+    POINTER_ICON_STYLE_TEXT = 1008,
+    POINTER_ICON_STYLE_VERTICAL_TEXT = 1009,
+    POINTER_ICON_STYLE_ALIAS = 1010,
+    POINTER_ICON_STYLE_COPY = 1011,
+    POINTER_ICON_STYLE_NO_DROP = 1012,
+    POINTER_ICON_STYLE_ALL_SCROLL = 1013,
+    POINTER_ICON_STYLE_HORIZONTAL_DOUBLE_ARROW = 1014,
+    POINTER_ICON_STYLE_VERTICAL_DOUBLE_ARROW = 1015,
+    POINTER_ICON_STYLE_TOP_RIGHT_DOUBLE_ARROW = 1016,
+    POINTER_ICON_STYLE_TOP_LEFT_DOUBLE_ARROW = 1017,
+    POINTER_ICON_STYLE_ZOOM_IN = 1018,
+    POINTER_ICON_STYLE_ZOOM_OUT = 1019,
+    POINTER_ICON_STYLE_GRAB = 1020,
+    POINTER_ICON_STYLE_GRABBING = 1021,
+
     POINTER_ICON_STYLE_SPOT_HOVER = 2000,
     POINTER_ICON_STYLE_SPOT_TOUCH = 2001,
     POINTER_ICON_STYLE_SPOT_ANCHOR = 2002,
diff --git a/core/res/res/drawable-mdpi/pointer_alias.png b/core/res/res/drawable-mdpi/pointer_alias.png
new file mode 100644
index 0000000..8f61a39
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_alias.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_all_scroll.png b/core/res/res/drawable-mdpi/pointer_all_scroll.png
new file mode 100644
index 0000000..a897ef4
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_all_scroll.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_cell.png b/core/res/res/drawable-mdpi/pointer_cell.png
new file mode 100644
index 0000000..b521389
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_cell.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_context_menu.png b/core/res/res/drawable-mdpi/pointer_context_menu.png
new file mode 100644
index 0000000..4e1ba4e
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_context_menu.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_copy.png b/core/res/res/drawable-mdpi/pointer_copy.png
new file mode 100644
index 0000000..7d41036
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_copy.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_crosshair.png b/core/res/res/drawable-mdpi/pointer_crosshair.png
new file mode 100644
index 0000000..8a06c77
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_crosshair.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_grab.png b/core/res/res/drawable-mdpi/pointer_grab.png
new file mode 100644
index 0000000..0e0ea2e
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_grab.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_grabbing.png b/core/res/res/drawable-mdpi/pointer_grabbing.png
new file mode 100644
index 0000000..9deb64c
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_grabbing.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_hand.png b/core/res/res/drawable-mdpi/pointer_hand.png
new file mode 100644
index 0000000..c614d9e
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_hand.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_help.png b/core/res/res/drawable-mdpi/pointer_help.png
new file mode 100644
index 0000000..d54b2b1
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_help.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_horizontal_double_arrow.png b/core/res/res/drawable-mdpi/pointer_horizontal_double_arrow.png
new file mode 100644
index 0000000..a2951a9
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_horizontal_double_arrow.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_nodrop.png b/core/res/res/drawable-mdpi/pointer_nodrop.png
new file mode 100644
index 0000000..ad13c66
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_nodrop.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_text.png b/core/res/res/drawable-mdpi/pointer_text.png
new file mode 100644
index 0000000..34d1698
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_text.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_top_left_diagonal_double_arrow.png b/core/res/res/drawable-mdpi/pointer_top_left_diagonal_double_arrow.png
new file mode 100644
index 0000000..b0cd92c
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_top_left_diagonal_double_arrow.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_top_right_diagonal_double_arrow.png b/core/res/res/drawable-mdpi/pointer_top_right_diagonal_double_arrow.png
new file mode 100644
index 0000000..f8d3527
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_top_right_diagonal_double_arrow.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_vertical_double_arrow.png b/core/res/res/drawable-mdpi/pointer_vertical_double_arrow.png
new file mode 100644
index 0000000..48c9379
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_vertical_double_arrow.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_vertical_text.png b/core/res/res/drawable-mdpi/pointer_vertical_text.png
new file mode 100644
index 0000000..9fcbcba
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_vertical_text.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_zoom_in.png b/core/res/res/drawable-mdpi/pointer_zoom_in.png
new file mode 100644
index 0000000..17c4e66
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_zoom_in.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_zoom_out.png b/core/res/res/drawable-mdpi/pointer_zoom_out.png
new file mode 100644
index 0000000..742f705
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_zoom_out.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_alias.png b/core/res/res/drawable-xhdpi/pointer_alias.png
new file mode 100644
index 0000000..fe0fd25
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_alias.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_all_scroll.png b/core/res/res/drawable-xhdpi/pointer_all_scroll.png
new file mode 100644
index 0000000..e2374ec
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_all_scroll.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_cell.png b/core/res/res/drawable-xhdpi/pointer_cell.png
new file mode 100644
index 0000000..4ca09e3
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_cell.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_context_menu.png b/core/res/res/drawable-xhdpi/pointer_context_menu.png
new file mode 100644
index 0000000..05a59f8
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_context_menu.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_copy.png b/core/res/res/drawable-xhdpi/pointer_copy.png
new file mode 100644
index 0000000..f28a3e9
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_copy.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_crosshair.png b/core/res/res/drawable-xhdpi/pointer_crosshair.png
new file mode 100644
index 0000000..86c649c
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_crosshair.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_grab.png b/core/res/res/drawable-xhdpi/pointer_grab.png
new file mode 100644
index 0000000..b5c28ba
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_grab.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_grabbing.png b/core/res/res/drawable-xhdpi/pointer_grabbing.png
new file mode 100644
index 0000000..6aba589
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_grabbing.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_hand.png b/core/res/res/drawable-xhdpi/pointer_hand.png
new file mode 100644
index 0000000..486cb24
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_hand.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_help.png b/core/res/res/drawable-xhdpi/pointer_help.png
new file mode 100644
index 0000000..98a6632
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_help.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_horizontal_double_arrow.png b/core/res/res/drawable-xhdpi/pointer_horizontal_double_arrow.png
new file mode 100644
index 0000000..299ae11
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_horizontal_double_arrow.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_nodrop.png b/core/res/res/drawable-xhdpi/pointer_nodrop.png
new file mode 100644
index 0000000..c56bfbb
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_nodrop.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_text.png b/core/res/res/drawable-xhdpi/pointer_text.png
new file mode 100644
index 0000000..0cebeae
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_text.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_top_left_diagonal_double_arrow.png b/core/res/res/drawable-xhdpi/pointer_top_left_diagonal_double_arrow.png
new file mode 100644
index 0000000..5454a8b
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_top_left_diagonal_double_arrow.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_top_right_diagonal_double_arrow.png b/core/res/res/drawable-xhdpi/pointer_top_right_diagonal_double_arrow.png
new file mode 100644
index 0000000..a4268e4
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_top_right_diagonal_double_arrow.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_vertical_double_arrow.png b/core/res/res/drawable-xhdpi/pointer_vertical_double_arrow.png
new file mode 100644
index 0000000..95ca954
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_vertical_double_arrow.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_vertical_text.png b/core/res/res/drawable-xhdpi/pointer_vertical_text.png
new file mode 100644
index 0000000..a07d091
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_vertical_text.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_zoom_in.png b/core/res/res/drawable-xhdpi/pointer_zoom_in.png
new file mode 100644
index 0000000..9c29fcb
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_zoom_in.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/pointer_zoom_out.png b/core/res/res/drawable-xhdpi/pointer_zoom_out.png
new file mode 100644
index 0000000..710552b
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/pointer_zoom_out.png
Binary files differ
diff --git a/core/res/res/drawable/pointer_alias_icon.xml b/core/res/res/drawable/pointer_alias_icon.xml
new file mode 100644
index 0000000..8ba9301
--- /dev/null
+++ b/core/res/res/drawable/pointer_alias_icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
+    android:bitmap="@drawable/pointer_alias"
+    android:hotSpotX="8dp"
+    android:hotSpotY="6dp" />
diff --git a/core/res/res/drawable/pointer_all_scroll_icon.xml b/core/res/res/drawable/pointer_all_scroll_icon.xml
new file mode 100644
index 0000000..e946948
--- /dev/null
+++ b/core/res/res/drawable/pointer_all_scroll_icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
+    android:bitmap="@drawable/pointer_all_scroll"
+    android:hotSpotX="11dp"
+    android:hotSpotY="11dp" />
diff --git a/core/res/res/drawable/pointer_cell_icon.xml b/core/res/res/drawable/pointer_cell_icon.xml
new file mode 100644
index 0000000..da1e320
--- /dev/null
+++ b/core/res/res/drawable/pointer_cell_icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
+    android:bitmap="@drawable/pointer_cell"
+    android:hotSpotX="11dp"
+    android:hotSpotY="11dp" />
diff --git a/core/res/res/drawable/pointer_context_menu_icon.xml b/core/res/res/drawable/pointer_context_menu_icon.xml
new file mode 100644
index 0000000..330b627
--- /dev/null
+++ b/core/res/res/drawable/pointer_context_menu_icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
+    android:bitmap="@drawable/pointer_context_menu"
+    android:hotSpotX="4dp"
+    android:hotSpotY="4dp" />
diff --git a/core/res/res/drawable/pointer_copy_icon.xml b/core/res/res/drawable/pointer_copy_icon.xml
new file mode 100644
index 0000000..e299db5
--- /dev/null
+++ b/core/res/res/drawable/pointer_copy_icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
+    android:bitmap="@drawable/pointer_copy"
+    android:hotSpotX="9dp"
+    android:hotSpotY="9dp" />
diff --git a/core/res/res/drawable/pointer_crosshair_icon.xml b/core/res/res/drawable/pointer_crosshair_icon.xml
new file mode 100644
index 0000000..3b96a8a
--- /dev/null
+++ b/core/res/res/drawable/pointer_crosshair_icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
+    android:bitmap="@drawable/pointer_crosshair"
+    android:hotSpotX="12dp"
+    android:hotSpotY="12dp" />
diff --git a/core/res/res/drawable/pointer_grab_icon.xml b/core/res/res/drawable/pointer_grab_icon.xml
new file mode 100644
index 0000000..d437b3a
--- /dev/null
+++ b/core/res/res/drawable/pointer_grab_icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
+    android:bitmap="@drawable/pointer_grab"
+    android:hotSpotX="8dp"
+    android:hotSpotY="5dp" />
diff --git a/core/res/res/drawable/pointer_grabbing_icon.xml b/core/res/res/drawable/pointer_grabbing_icon.xml
new file mode 100644
index 0000000..38f4c3a
--- /dev/null
+++ b/core/res/res/drawable/pointer_grabbing_icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
+    android:bitmap="@drawable/pointer_grabbing"
+    android:hotSpotX="9dp"
+    android:hotSpotY="9dp" />
diff --git a/core/res/res/drawable/pointer_hand_icon.xml b/core/res/res/drawable/pointer_hand_icon.xml
new file mode 100644
index 0000000..3d90b88
--- /dev/null
+++ b/core/res/res/drawable/pointer_hand_icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
+    android:bitmap="@drawable/pointer_hand"
+    android:hotSpotX="9dp"
+    android:hotSpotY="4dp" />
diff --git a/core/res/res/drawable/pointer_help_icon.xml b/core/res/res/drawable/pointer_help_icon.xml
new file mode 100644
index 0000000..49ae554
--- /dev/null
+++ b/core/res/res/drawable/pointer_help_icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
+    android:bitmap="@drawable/pointer_help"
+    android:hotSpotX="4dp"
+    android:hotSpotY="4dp" />
diff --git a/core/res/res/drawable/pointer_horizontal_double_arrow_icon.xml b/core/res/res/drawable/pointer_horizontal_double_arrow_icon.xml
new file mode 100644
index 0000000..5a5ad9e
--- /dev/null
+++ b/core/res/res/drawable/pointer_horizontal_double_arrow_icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
+    android:bitmap="@drawable/pointer_horizontal_double_arrow"
+    android:hotSpotX="11dp"
+    android:hotSpotY="12dp" />
diff --git a/core/res/res/drawable/pointer_nodrop_icon.xml b/core/res/res/drawable/pointer_nodrop_icon.xml
new file mode 100644
index 0000000..955b40f
--- /dev/null
+++ b/core/res/res/drawable/pointer_nodrop_icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
+    android:bitmap="@drawable/pointer_nodrop"
+    android:hotSpotX="9dp"
+    android:hotSpotY="9dp" />
diff --git a/core/res/res/drawable/pointer_text_icon.xml b/core/res/res/drawable/pointer_text_icon.xml
new file mode 100644
index 0000000..d948c89
--- /dev/null
+++ b/core/res/res/drawable/pointer_text_icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
+    android:bitmap="@drawable/pointer_text"
+    android:hotSpotX="12dp"
+    android:hotSpotY="12dp" />
diff --git a/core/res/res/drawable/pointer_top_left_diagonal_double_arrow_icon.xml b/core/res/res/drawable/pointer_top_left_diagonal_double_arrow_icon.xml
new file mode 100644
index 0000000..de5efe2
--- /dev/null
+++ b/core/res/res/drawable/pointer_top_left_diagonal_double_arrow_icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
+    android:bitmap="@drawable/pointer_top_left_diagonal_double_arrow"
+    android:hotSpotX="11dp"
+    android:hotSpotY="11dp" />
diff --git a/core/res/res/drawable/pointer_top_right_diagonal_double_arrow_icon.xml b/core/res/res/drawable/pointer_top_right_diagonal_double_arrow_icon.xml
new file mode 100644
index 0000000..e87b526
--- /dev/null
+++ b/core/res/res/drawable/pointer_top_right_diagonal_double_arrow_icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
+    android:bitmap="@drawable/pointer_top_right_diagonal_double_arrow"
+    android:hotSpotX="12dp"
+    android:hotSpotY="11dp" />
diff --git a/core/res/res/drawable/pointer_vertical_double_arrow_icon.xml b/core/res/res/drawable/pointer_vertical_double_arrow_icon.xml
new file mode 100644
index 0000000..5759079
--- /dev/null
+++ b/core/res/res/drawable/pointer_vertical_double_arrow_icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
+    android:bitmap="@drawable/pointer_vertical_double_arrow"
+    android:hotSpotX="11dp"
+    android:hotSpotY="12dp" />
diff --git a/core/res/res/drawable/pointer_vertical_text_icon.xml b/core/res/res/drawable/pointer_vertical_text_icon.xml
new file mode 100644
index 0000000..3b48dc8
--- /dev/null
+++ b/core/res/res/drawable/pointer_vertical_text_icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
+    android:bitmap="@drawable/pointer_vertical_text"
+    android:hotSpotX="12dp"
+    android:hotSpotY="11dp" />
diff --git a/core/res/res/drawable/pointer_zoom_in_icon.xml b/core/res/res/drawable/pointer_zoom_in_icon.xml
new file mode 100644
index 0000000..e2dcb49
--- /dev/null
+++ b/core/res/res/drawable/pointer_zoom_in_icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
+    android:bitmap="@drawable/pointer_zoom_in"
+    android:hotSpotX="10dp"
+    android:hotSpotY="10dp" />
diff --git a/core/res/res/drawable/pointer_zoom_out_icon.xml b/core/res/res/drawable/pointer_zoom_out_icon.xml
new file mode 100644
index 0000000..b805df3
--- /dev/null
+++ b/core/res/res/drawable/pointer_zoom_out_icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
+    android:bitmap="@drawable/pointer_zoom_out"
+    android:hotSpotX="10dp"
+    android:hotSpotY="10dp" />
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 60f0502..9c420c2 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -143,7 +143,7 @@
     <string name="fcError" msgid="3327560126588500777">"Forbindelsesproblemer eller ugyldig funktionskode."</string>
     <string name="httpErrorOk" msgid="1191919378083472204">"OK"</string>
     <string name="httpError" msgid="7956392511146698522">"Der opstod en netværksfejl."</string>
-    <string name="httpErrorLookup" msgid="4711687456111963163">"Webadressen kunne ikke findes."</string>
+    <string name="httpErrorLookup" msgid="4711687456111963163">"Webadressen blev ikke fundet."</string>
     <string name="httpErrorUnsupportedAuthScheme" msgid="6299980280442076799">"Ordningen for webstedsgodkendelse understøttes ikke."</string>
     <string name="httpErrorAuth" msgid="1435065629438044534">"Der kunne ikke godkendes."</string>
     <string name="httpErrorProxyAuth" msgid="1788207010559081331">"Godkendelse via proxyserveren mislykkedes."</string>
@@ -155,7 +155,7 @@
     <string name="httpErrorFailedSslHandshake" msgid="96549606000658641">"Der kunne ikke oprettes en sikker forbindelse."</string>
     <string name="httpErrorBadUrl" msgid="3636929722728881972">"Siden kunne ikke åbnes, fordi webadressen er ugyldig."</string>
     <string name="httpErrorFile" msgid="2170788515052558676">"Der kunne ikke fås adgang til filen."</string>
-    <string name="httpErrorFileNotFound" msgid="6203856612042655084">"Den ønskede fil kunne ikke findes."</string>
+    <string name="httpErrorFileNotFound" msgid="6203856612042655084">"Den ønskede fil blev ikke fundet."</string>
     <string name="httpErrorTooManyRequests" msgid="1235396927087188253">"Der behandles for mange anmodninger. Prøv igen senere."</string>
     <string name="notification_title" msgid="8967710025036163822">"Loginfejl for <xliff:g id="ACCOUNT">%1$s</xliff:g>"</string>
     <string name="contentServiceSync" msgid="8353523060269335667">"Synkroniser"</string>
@@ -248,7 +248,7 @@
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"undersøge indholdet i et vindue, du interagerer med."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"aktivere Udforsk ved berøring"</string>
     <string name="capability_desc_canRequestTouchExploration" msgid="5800552516779249356">"De emner, der trykkes på, læses højt, og skærmen kan udforskes ved hjælp af bevægelser."</string>
-    <string name="capability_title_canRequestEnhancedWebAccessibility" msgid="1739881766522594073">"aktivere forbedrede webhjælpefunktioner"</string>
+    <string name="capability_title_canRequestEnhancedWebAccessibility" msgid="1739881766522594073">"Aktivér udvidede webhjælpefunktioner"</string>
     <string name="capability_desc_canRequestEnhancedWebAccessibility" msgid="7881063961507511765">"Der installeres muligvis scripts for at gøre appindhold mere tilgængeligt."</string>
     <string name="capability_title_canRequestFilterKeyEvents" msgid="2103440391902412174">"observere tekst, du skriver"</string>
     <string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Dette omfatter personlige data såsom kreditkortnumre og adgangskoder."</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index c13ef14..54100d5 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -223,7 +223,7 @@
     <string name="global_action_lockdown" msgid="8751542514724332873">"立即锁定"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"安全模式"</string>
-    <string name="android_system_label" msgid="6577375335728551336">"Android系统"</string>
+    <string name="android_system_label" msgid="6577375335728551336">"Android 系统"</string>
     <string name="user_owner_label" msgid="2804351898001038951">"个人"</string>
     <string name="managed_profile_label" msgid="6260850669674791528">"工作"</string>
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"通讯录"</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index a6eb68b..b818fe0 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -7605,6 +7605,44 @@
         <attr name="pointerIconSpotTouch" format="reference" />
         <!-- Reference to a pointer icon drawable with STYLE_SPOT_ANCHOR -->
         <attr name="pointerIconSpotAnchor" format="reference" />
+        <!-- Reference to a pointer drawable with STYLE_CONTEXT_MENU -->
+        <attr name="pointerIconContextMenu" format="reference"/>
+        <!-- Reference to a pointer drawable with STYLE_HAND -->
+        <attr name="pointerIconHand" format="reference"/>
+        <!-- Reference to a pointer drawable with STYLE_HELP -->
+        <attr name="pointerIconHelp" format="reference"/>
+        <!-- Reference to a pointer drawable with STYLE_CELL -->
+        <attr name="pointerIconCell" format="reference"/>
+        <!-- Reference to a pointer drawable with STYLE_CROSSHAIR -->
+        <attr name="pointerIconCrosshair" format="reference"/>
+        <!-- Reference to a pointer drawable with STYLE_TEXT -->
+        <attr name="pointerIconText" format="reference"/>
+        <!-- Reference to a pointer drawable with STYLE_VERTICAL_TEXT -->
+        <attr name="pointerIconVerticalText" format="reference"/>
+        <!-- Reference to a pointer drawable with STYLE_ALIAS -->
+        <attr name="pointerIconAlias" format="reference"/>
+        <!-- Reference to a pointer drawable with STYLE_COPY -->
+        <attr name="pointerIconCopy" format="reference"/>
+        <!-- Reference to a pointer drawable with STYLE_NODROP -->
+        <attr name="pointerIconNodrop" format="reference"/>
+        <!-- Reference to a pointer drawable with STYLE_ALL_SCROLL -->
+        <attr name="pointerIconAllScroll" format="reference"/>
+        <!-- Reference to a pointer drawable with STYLE_HORIZONTAL_DOUBLE_ARROW -->
+        <attr name="pointerIconHorizontalDoubleArrow" format="reference"/>
+        <!-- Reference to a pointer drawable with STYLE_VERTICAL_DOUBLE_ARROW -->
+        <attr name="pointerIconVerticalDoubleArrow" format="reference"/>
+        <!-- Reference to a pointer drawable with STYLE_TOP_RIGHT_DIAGONAL_DOUBLE_ARROW -->
+        <attr name="pointerIconTopRightDiagonalDoubleArrow" format="reference"/>
+        <!-- Reference to a pointer drawable with STYLE_TOP_LEFT_DIAGONAL_DOUBLE_ARROW -->
+        <attr name="pointerIconTopLeftDiagonalDoubleArrow" format="reference"/>
+        <!-- Reference to a pointer drawable with STYLE_ZOOM_IN -->
+        <attr name="pointerIconZoomIn" format="reference"/>
+        <!-- Reference to a pointer drawable with STYLE_ZOOM_OUT -->
+        <attr name="pointerIconZoomOut" format="reference"/>
+        <!-- Reference to a pointer drawable with STYLE_GRAB -->
+        <attr name="pointerIconGrab" format="reference"/>
+        <!-- Reference to a pointer drawable with STYLE_GRABBING -->
+        <attr name="pointerIconGrabbing" format="reference"/>
     </declare-styleable>
 
     <declare-styleable name="PointerIcon">
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 24d760f..6e956d7 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -938,6 +938,9 @@
     <!-- Is the device capable of hot swapping an UICC Card -->
     <bool name="config_hotswapCapable">false</bool>
 
+    <!-- Component name of the ICC hotswap prompt for restart dialog -->
+    <string name="config_iccHotswapPromptForRestartDialogComponent" translateable="false">@null</string>
+
     <!-- Enable puk unlockscreen by default.
          If unlock screen is disabled, the puk should be unlocked through Emergency Dialer -->
     <bool name="config_enable_puk_unlock_screen">true</bool>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index af5c74d..40cd097 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3993,6 +3993,9 @@
     <!-- Zen mode condition - line two: ending time. [CHAR LIMIT=NONE] -->
     <string name="zen_mode_until">Until <xliff:g id="formattedTime" example="10:00 PM">%1$s</xliff:g></string>
 
+    <!-- Zen mode condition - line one: Until next alarm. [CHAR LIMIT=NONE] -->
+    <string name="zen_mode_alarm">Until <xliff:g id="formattedTime" example="10:00 PM">%1$s</xliff:g> (next alarm)</string>
+
     <!-- Zen mode condition: no exit criteria. [CHAR LIMIT=NONE] -->
     <string name="zen_mode_forever">Until you turn this off</string>
 
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 11c4cc0..b831df8 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -1336,6 +1336,33 @@
         <item name="pointerIconSpotHover">@drawable/pointer_spot_hover_icon</item>
         <item name="pointerIconSpotTouch">@drawable/pointer_spot_touch_icon</item>
         <item name="pointerIconSpotAnchor">@drawable/pointer_spot_anchor_icon</item>
+        <item name="pointerIconHand">@drawable/pointer_hand_icon</item>
+        <item name="pointerIconContextMenu">@drawable/pointer_context_menu_icon</item>
+        <item name="pointerIconHelp">@drawable/pointer_help_icon</item>
+        <item name="pointerIconCell">@drawable/pointer_cell_icon</item>
+        <item name="pointerIconCrosshair">@drawable/pointer_crosshair_icon</item>
+        <item name="pointerIconText">@drawable/pointer_text_icon</item>
+        <item name="pointerIconVerticalText">@drawable/pointer_vertical_text_icon</item>
+        <item name="pointerIconAlias">@drawable/pointer_alias_icon</item>
+        <item name="pointerIconCopy">@drawable/pointer_copy_icon</item>
+        <item name="pointerIconAllScroll">@drawable/pointer_all_scroll_icon</item>
+        <item name="pointerIconNodrop">@drawable/pointer_nodrop_icon</item>
+        <item name="pointerIconHorizontalDoubleArrow">
+            @drawable/pointer_horizontal_double_arrow_icon
+        </item>
+        <item name="pointerIconVerticalDoubleArrow">
+            @drawable/pointer_vertical_double_arrow_icon
+        </item>
+        <item name="pointerIconTopRightDiagonalDoubleArrow">
+            @drawable/pointer_top_right_diagonal_double_arrow_icon
+        </item>
+        <item name="pointerIconTopLeftDiagonalDoubleArrow">
+            @drawable/pointer_top_left_diagonal_double_arrow_icon
+        </item>
+        <item name="pointerIconZoomIn">@drawable/pointer_zoom_in_icon</item>
+        <item name="pointerIconZoomOut">@drawable/pointer_zoom_out_icon</item>
+        <item name="pointerIconGrab">@drawable/pointer_grab_icon</item>
+        <item name="pointerIconGrabbing">@drawable/pointer_grabbing_icon</item>
     </style>
 
     <!-- Wifi dialog styles -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 06de81d..953b98f 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2078,6 +2078,7 @@
   <java-symbol type="string" name="zen_mode_default_events_name" />
   <java-symbol type="array" name="config_system_condition_providers" />
   <java-symbol type="string" name="muted_by" />
+  <java-symbol type="string" name="zen_mode_alarm" />
 
   <java-symbol type="string" name="select_day" />
   <java-symbol type="string" name="select_year" />
@@ -2326,4 +2327,6 @@
   <java-symbol type="bool" name="config_cameraDoubleTapPowerGestureEnabled" />
 
   <java-symbol type="drawable" name="platlogo_m" />
+
+  <java-symbol type="string" name="config_iccHotswapPromptForRestartDialogComponent" />
 </resources>
diff --git a/core/tests/coretests/src/android/animation/ValueAnimatorTests.java b/core/tests/coretests/src/android/animation/ValueAnimatorTests.java
index 049da2d..7164747 100644
--- a/core/tests/coretests/src/android/animation/ValueAnimatorTests.java
+++ b/core/tests/coretests/src/android/animation/ValueAnimatorTests.java
@@ -865,6 +865,47 @@
     }
 
     @SmallTest
+    public void testZeroScale() throws Throwable {
+        // Test whether animations would end properly when the scale is forced to be zero
+        float scale = ValueAnimator.getDurationScale();
+        ValueAnimator.setDurationScale(0f);
+
+        // Run two animators, one of which has a start delay, after setting the duration scale to 0
+        a1.setStartDelay(200);
+        final MyListener l1 =  new MyListener();
+        final MyListener l2 = new MyListener();
+        a1.addListener(l1);
+        a2.addListener(l2);
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                assertFalse(l1.startCalled);
+                assertFalse(l2.startCalled);
+                assertFalse(l1.endCalled);
+                assertFalse(l2.endCalled);
+
+                a1.start();
+                a2.start();
+            }
+        });
+        Thread.sleep(POLL_INTERVAL);
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                assertTrue(l1.startCalled);
+                assertTrue(l2.startCalled);
+                assertTrue(l1.endCalled);
+                assertTrue(l2.endCalled);
+            }
+        });
+
+        // Restore duration scale
+        ValueAnimator.setDurationScale(scale);
+    }
+
+    @SmallTest
     public void testReverse() throws Throwable {
         // Prolong animators duration so that we can do multiple checks during their run
         final ValueAnimator a3 = ValueAnimator.ofInt(0, 100);
diff --git a/docs/html/sdk/installing/index.jd b/docs/html/sdk/installing/index.jd
index dc258db..0375a2f 100644
--- a/docs/html/sdk/installing/index.jd
+++ b/docs/html/sdk/installing/index.jd
@@ -42,9 +42,9 @@
 JDK 6 or higher (the JRE alone is not sufficient)&mdash;JDK 7 is required when
 developing for Android 5.0 and higher. To check if you
 have JDK installed (and which version), open a terminal and type <code>javac -version</code>.
-If the JDK is not available or the version is lower than 6,
-<a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html" class="external-link"
->go download JDK</a>.</p>
+If the JDK is not available or the version is lower than version 6, download the 
+<a href="http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.html" class="external-link"
+>Java SE Development Kit 7</a>.</p>
 
 
 <div class="procedure-box">
diff --git a/graphics/java/android/graphics/Point.java b/graphics/java/android/graphics/Point.java
index e0d8ccc..3bd17fa 100644
--- a/graphics/java/android/graphics/Point.java
+++ b/graphics/java/android/graphics/Point.java
@@ -19,6 +19,8 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import java.io.PrintWriter;
+
 
 /**
  * Point holds two integer coordinates
@@ -95,6 +97,11 @@
         return "Point(" + x + ", " + y + ")";
     }
 
+    /** @hide */
+    public void printShortString(PrintWriter pw) {
+        pw.println("["); pw.print(x); pw.print(","); pw.print(y); pw.print("]");
+    }
+
     /**
      * Parcelable interface methods
      */
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 8011b59..6f548bc 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -2,6 +2,8 @@
 include $(CLEAR_VARS)
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 
+HWUI_NEW_OPS := false
+
 hwui_src_files := \
     font/CacheTexture.cpp \
     font/Font.cpp \
@@ -85,6 +87,17 @@
     -Wall -Wno-unused-parameter -Wunreachable-code \
     -ffast-math -O3 -Werror
 
+
+ifeq (true, $(HWUI_NEW_OPS))
+    hwui_src_files += \
+        BakedOpRenderer.cpp \
+        OpReorderer.cpp \
+        RecordingCanvas.cpp
+
+    hwui_cflags += -DHWUI_NEW_OPS
+
+endif
+
 ifndef HWUI_COMPILE_SYMBOLS
     hwui_cflags += -fvisibility=hidden
 endif
@@ -172,6 +185,13 @@
     unit_tests/LinearAllocatorTests.cpp \
     unit_tests/StringUtilsTests.cpp
 
+ifeq (true, $(HWUI_NEW_OPS))
+    LOCAL_SRC_FILES += \
+        unit_tests/BakedOpStateTests.cpp \
+        unit_tests/RecordingCanvasTests.cpp \
+        unit_tests/OpReordererTests.cpp
+endif
+
 include $(BUILD_NATIVE_TEST)
 
 # ------------------------
diff --git a/libs/hwui/BakedOpRenderer.cpp b/libs/hwui/BakedOpRenderer.cpp
new file mode 100644
index 0000000..4d9f9b4
--- /dev/null
+++ b/libs/hwui/BakedOpRenderer.cpp
@@ -0,0 +1,126 @@
+/*
+ * 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.
+ */
+
+#include "BakedOpRenderer.h"
+
+#include "Caches.h"
+#include "Glop.h"
+#include "GlopBuilder.h"
+#include "renderstate/RenderState.h"
+#include "utils/GLUtils.h"
+
+namespace android {
+namespace uirenderer {
+
+Texture* BakedOpRenderer::Info::getTexture(const SkBitmap* bitmap) {
+    Texture* texture = renderState.assetAtlas().getEntryTexture(bitmap);
+    if (!texture) {
+        return caches.textureCache.get(bitmap);
+    }
+    return texture;
+}
+
+void BakedOpRenderer::Info::renderGlop(const BakedOpState& state, const Glop& glop) {
+    bool useScissor = state.computedState.clipSideFlags != OpClipSideFlags::None;
+    renderState.scissor().setEnabled(useScissor);
+    if (useScissor) {
+        const Rect& clip = state.computedState.clipRect;
+        renderState.scissor().set(clip.left, viewportHeight - clip.bottom,
+            clip.getWidth(), clip.getHeight());
+    }
+    renderState.render(glop, orthoMatrix);
+    didDraw = true;
+}
+
+void BakedOpRenderer::startFrame(Info& info) {
+    info.renderState.setViewport(info.viewportWidth, info.viewportHeight);
+    info.renderState.blend().syncEnabled();
+    Caches::getInstance().clearGarbage();
+
+    if (!info.opaque) {
+        // TODO: partial invalidate!
+        info.renderState.scissor().setEnabled(false);
+        glClear(GL_COLOR_BUFFER_BIT);
+        info.didDraw = true;
+    }
+}
+void BakedOpRenderer::endFrame(Info& info) {
+    info.caches.pathCache.trim();
+    info.caches.tessellationCache.trim();
+
+#if DEBUG_OPENGL
+    GLUtils::dumpGLErrors();
+#endif
+
+#if DEBUG_MEMORY_USAGE
+    info.caches.dumpMemoryUsage();
+#else
+    if (Properties::debugLevel & kDebugMemory) {
+        info.caches.dumpMemoryUsage();
+    }
+#endif
+}
+
+void BakedOpRenderer::onRenderNodeOp(Info*, const RenderNodeOp&, const BakedOpState&) {
+    LOG_ALWAYS_FATAL("unsupported operation");
+}
+
+void BakedOpRenderer::onBitmapOp(Info* info, const BitmapOp& op, const BakedOpState& state) {
+    info->caches.textureState().activateTexture(0); // TODO: should this be automatic, and/or elsewhere?
+    Texture* texture = info->getTexture(op.bitmap);
+    if (!texture) return;
+    const AutoTexture autoCleanup(texture);
+
+    const int textureFillFlags = (op.bitmap->colorType() == kAlpha_8_SkColorType)
+            ? TextureFillFlags::IsAlphaMaskTexture : TextureFillFlags::None;
+    Glop glop;
+    GlopBuilder(info->renderState, info->caches, &glop)
+            .setRoundRectClipState(state.roundRectClipState)
+            .setMeshTexturedUnitQuad(texture->uvMapper)
+            .setFillTexturePaint(*texture, textureFillFlags, op.paint, state.alpha)
+            .setTransform(state.computedState.transform, TransformFlags::None)
+            .setModelViewMapUnitToRectSnap(Rect(0, 0, texture->width, texture->height))
+            .build();
+    info->renderGlop(state, glop);
+}
+
+void BakedOpRenderer::onRectOp(Info* info, const RectOp& op, const BakedOpState& state) {
+    Glop glop;
+    GlopBuilder(info->renderState, info->caches, &glop)
+            .setRoundRectClipState(state.roundRectClipState)
+            .setMeshUnitQuad()
+            .setFillPaint(*op.paint, state.alpha)
+            .setTransform(state.computedState.transform, TransformFlags::None)
+            .setModelViewMapUnitToRect(op.unmappedBounds)
+            .build();
+    info->renderGlop(state, glop);
+}
+
+void BakedOpRenderer::onSimpleRectsOp(Info* info, const SimpleRectsOp& op, const BakedOpState& state) {
+    Glop glop;
+    GlopBuilder(info->renderState, info->caches, &glop)
+            .setRoundRectClipState(state.roundRectClipState)
+            .setMeshIndexedQuads(&op.vertices[0], op.vertexCount / 4)
+            .setFillPaint(*op.paint, state.alpha)
+            .setTransform(state.computedState.transform, TransformFlags::None)
+            .setModelViewOffsetRect(0, 0, op.unmappedBounds)
+            .build();
+    info->renderGlop(state, glop);
+}
+
+
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/BakedOpRenderer.h b/libs/hwui/BakedOpRenderer.h
new file mode 100644
index 0000000..b8b4426
--- /dev/null
+++ b/libs/hwui/BakedOpRenderer.h
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HWUI_BAKED_OP_RENDERER_H
+#define ANDROID_HWUI_BAKED_OP_RENDERER_H
+
+#include "BakedOpState.h"
+#include "Matrix.h"
+
+namespace android {
+namespace uirenderer {
+
+class Caches;
+struct Glop;
+class RenderState;
+
+class BakedOpRenderer {
+public:
+    class Info {
+    public:
+        Info(Caches& caches, RenderState& renderState, int viewportWidth, int viewportHeight, bool opaque)
+                : renderState(renderState)
+                , caches(caches)
+                , opaque(opaque)
+                , viewportWidth(viewportWidth)
+                , viewportHeight(viewportHeight) {
+            orthoMatrix.loadOrtho(viewportWidth, viewportHeight);
+        }
+
+        Texture* getTexture(const SkBitmap* bitmap);
+
+        void renderGlop(const BakedOpState& state, const Glop& glop);
+        RenderState& renderState;
+        Caches& caches;
+
+        bool didDraw = false;
+        bool opaque;
+
+
+        // where should these live? layer state object?
+        int viewportWidth;
+        int viewportHeight;
+        Matrix4 orthoMatrix;
+    };
+
+    static void startFrame(Info& info);
+    static void endFrame(Info& info);
+
+    /**
+     * Declare all "onBitmapOp(...)" style function for every op type.
+     *
+     * These functions will perform the actual rendering of the individual operations in OpenGL,
+     * given the transform/clip and other state built into the BakedOpState object passed in.
+     */
+    #define BAKED_OP_RENDERER_METHOD(Type) static void on##Type(Info* info, const Type& op, const BakedOpState& state);
+    MAP_OPS(BAKED_OP_RENDERER_METHOD);
+};
+
+}; // namespace uirenderer
+}; // namespace android
+
+#endif // ANDROID_HWUI_BAKED_OP_RENDERER_H
diff --git a/libs/hwui/BakedOpState.h b/libs/hwui/BakedOpState.h
new file mode 100644
index 0000000..e2201ca
--- /dev/null
+++ b/libs/hwui/BakedOpState.h
@@ -0,0 +1,142 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HWUI_BAKED_OP_STATE_H
+#define ANDROID_HWUI_BAKED_OP_STATE_H
+
+#include "Matrix.h"
+#include "RecordedOp.h"
+#include "Rect.h"
+#include "Snapshot.h"
+
+namespace android {
+namespace uirenderer {
+
+namespace OpClipSideFlags {
+    enum {
+        None = 0x0,
+        Left = 0x1,
+        Top = 0x2,
+        Right = 0x4,
+        Bottom = 0x8,
+        Full = 0xF,
+        // ConservativeFull = 0x1F  needed?
+    };
+}
+
+/**
+ * Holds the resolved clip, transform, and bounds of a recordedOp, when replayed with a snapshot
+ */
+class ResolvedRenderState {
+public:
+    // TODO: remove the mapRects/matrix multiply when snapshot & recorded transforms are translates
+    ResolvedRenderState(const Snapshot& snapshot, const RecordedOp& recordedOp) {
+        /* TODO: benchmark a fast path for translate-only matrices, such as:
+        if (CC_LIKELY(snapshot.transform->getType() == Matrix4::kTypeTranslate
+                && recordedOp.localMatrix.getType() == Matrix4::kTypeTranslate)) {
+            float translateX = snapshot.transform->getTranslateX() + recordedOp.localMatrix.getTranslateX();
+            float translateY = snapshot.transform->getTranslateY() + recordedOp.localMatrix.getTranslateY();
+            transform.loadTranslate(translateX, translateY, 0);
+
+            // resolvedClipRect = intersect(parentMatrix * localClip, parentClip)
+            clipRect = recordedOp.localClipRect;
+            clipRect.translate(translateX, translateY);
+            clipRect.doIntersect(snapshot.getClipRect());
+            clipRect.snapToPixelBoundaries();
+
+            // resolvedClippedBounds = intersect(resolvedMatrix * opBounds, resolvedClipRect)
+            clippedBounds = recordedOp.unmappedBounds;
+            clippedBounds.translate(translateX, translateY);
+        } ... */
+
+        // resolvedMatrix = parentMatrix * localMatrix
+        transform.loadMultiply(*snapshot.transform, recordedOp.localMatrix);
+
+        // resolvedClipRect = intersect(parentMatrix * localClip, parentClip)
+        clipRect = recordedOp.localClipRect;
+        snapshot.transform->mapRect(clipRect);
+        clipRect.doIntersect(snapshot.getClipRect());
+        clipRect.snapToPixelBoundaries();
+
+        // resolvedClippedBounds = intersect(resolvedMatrix * opBounds, resolvedClipRect)
+        clippedBounds = recordedOp.unmappedBounds;
+        transform.mapRect(clippedBounds);
+
+        if (clipRect.left > clippedBounds.left) clipSideFlags |= OpClipSideFlags::Left;
+        if (clipRect.top > clippedBounds.top) clipSideFlags |= OpClipSideFlags::Top;
+        if (clipRect.right < clippedBounds.right) clipSideFlags |= OpClipSideFlags::Right;
+        if (clipRect.bottom < clippedBounds.bottom) clipSideFlags |= OpClipSideFlags::Bottom;
+        clippedBounds.doIntersect(clipRect);
+
+        /**
+         * TODO: once we support complex clips, we may want to reject to avoid that work where
+         * possible. Should we:
+         * 1 - quickreject based on clippedBounds, quick early (duplicating logic in resolvedOp)
+         * 2 - merge stuff into tryConstruct factory method, so it can handle quickRejection
+         *         and early return null in one place.
+         */
+    }
+    Matrix4 transform;
+    Rect clipRect;
+    int clipSideFlags = 0;
+    Rect clippedBounds;
+};
+
+/**
+ * Self-contained op wrapper, containing all resolved state required to draw the op.
+ *
+ * Stashed pointers within all point to longer lived objects, with no ownership implied.
+ */
+class BakedOpState {
+public:
+    static BakedOpState* tryConstruct(LinearAllocator& allocator,
+            const Snapshot& snapshot, const RecordedOp& recordedOp) {
+        BakedOpState* bakedOp = new (allocator) BakedOpState(
+                snapshot, recordedOp);
+        if (bakedOp->computedState.clippedBounds.isEmpty()) {
+            // bounds are empty, so op is rejected
+            allocator.rewindIfLastAlloc(bakedOp);
+            return nullptr;
+        }
+        return bakedOp;
+    }
+
+    static void* operator new(size_t size, LinearAllocator& allocator) {
+        return allocator.alloc(size);
+    }
+
+    // computed state:
+    const ResolvedRenderState computedState;
+
+    // simple state (straight pointer/value storage):
+    const float alpha;
+    const RoundRectClipState* roundRectClipState;
+    const ProjectionPathMask* projectionPathMask;
+    const RecordedOp* op;
+
+private:
+    BakedOpState(const Snapshot& snapshot, const RecordedOp& recordedOp)
+            : computedState(snapshot, recordedOp)
+            , alpha(snapshot.alpha)
+            , roundRectClipState(snapshot.roundRectClipState)
+            , projectionPathMask(snapshot.projectionPathMask)
+            , op(&recordedOp) {}
+};
+
+}; // namespace uirenderer
+}; // namespace android
+
+#endif // ANDROID_HWUI_BAKED_OP_STATE_H
diff --git a/libs/hwui/DeferredDisplayList.cpp b/libs/hwui/DeferredDisplayList.cpp
index 0c29a9e..a1825c5 100644
--- a/libs/hwui/DeferredDisplayList.cpp
+++ b/libs/hwui/DeferredDisplayList.cpp
@@ -528,7 +528,7 @@
     int insertBatchIndex = mBatches.size();
     if (!mBatches.empty()) {
         if (state->mBounds.isEmpty()) {
-            // don't know the bounds for op, so add to last batch and start from scratch on next op
+            // don't know the bounds for op, so create new batch and start from scratch on next op
             DrawBatch* b = new DrawBatch(deferInfo);
             b->add(op, state, deferInfo.opaqueOverBounds);
             mBatches.push_back(b);
diff --git a/libs/hwui/DeferredDisplayList.h b/libs/hwui/DeferredDisplayList.h
index 7873fbd..2d5979f 100644
--- a/libs/hwui/DeferredDisplayList.h
+++ b/libs/hwui/DeferredDisplayList.h
@@ -49,7 +49,7 @@
 
 class DeferredDisplayState {
 public:
-    /** static void* operator new(size_t size); PURPOSELY OMITTED **/
+    static void* operator new(size_t size) = delete;
     static void* operator new(size_t size, LinearAllocator& allocator) {
         return allocator.alloc(size);
     }
@@ -61,7 +61,6 @@
     bool mClipValid;
     Rect mClip;
     int mClipSideFlags; // specifies which sides of the bounds are clipped, unclipped if cleared
-    bool mClipped;
     mat4 mMatrix;
     float mAlpha;
     const RoundRectClipState* mRoundRectClipState;
diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp
index ee51da2..793d8c0 100644
--- a/libs/hwui/DisplayList.cpp
+++ b/libs/hwui/DisplayList.cpp
@@ -21,7 +21,13 @@
 
 #include "Debug.h"
 #include "DisplayList.h"
+#include "RenderNode.h"
+
+#if HWUI_NEW_OPS
+#include "RecordedOp.h"
+#else
 #include "DisplayListOp.h"
+#endif
 
 namespace android {
 namespace uirenderer {
@@ -61,8 +67,8 @@
     regions.clear();
 }
 
-size_t DisplayListData::addChild(DrawRenderNodeOp* op) {
-    mReferenceHolders.push_back(op->renderNode());
+size_t DisplayListData::addChild(NodeOpType* op) {
+    mReferenceHolders.push_back(op->renderNode);
     size_t index = mChildren.size();
     mChildren.push_back(op);
     return index;
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index 0bdb816..80ff96a 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -55,12 +55,19 @@
 class Rect;
 class Layer;
 
-class ClipRectOp;
-class SaveLayerOp;
-class SaveOp;
-class RestoreToCountOp;
+#if HWUI_NEW_OPS
+struct RecordedOp;
+struct RenderNodeOp;
+
+typedef RecordedOp BaseOpType;
+typedef RenderNodeOp NodeOpType;
+#else
 class DrawRenderNodeOp;
 
+typedef DisplayListOp BaseOpType;
+typedef DrawRenderNodeOp NodeOpType;
+#endif
+
 /**
  * Holds data used in the playback a tree of DisplayLists.
  */
@@ -107,6 +114,7 @@
  */
 class DisplayListData {
     friend class DisplayListCanvas;
+    friend class RecordingCanvas;
 public:
     struct Chunk {
         // range of included ops in DLD::displayListOps
@@ -139,11 +147,14 @@
     Vector<Functor*> functors;
 
     const std::vector<Chunk>& getChunks() const {
-        return chunks;
+            return chunks;
+    }
+    const std::vector<BaseOpType*>& getOps() const {
+        return ops;
     }
 
-    size_t addChild(DrawRenderNodeOp* childOp);
-    const std::vector<DrawRenderNodeOp*>& children() { return mChildren; }
+    size_t addChild(NodeOpType* childOp);
+    const std::vector<NodeOpType*>& children() { return mChildren; }
 
     void ref(VirtualLightRefBase* prop) {
         mReferenceHolders.push_back(prop);
@@ -157,10 +168,12 @@
     }
 
 private:
+    std::vector<BaseOpType*> ops;
+
     std::vector< sp<VirtualLightRefBase> > mReferenceHolders;
 
     // list of children display lists for quick, non-drawing traversal
-    std::vector<DrawRenderNodeOp*> mChildren;
+    std::vector<NodeOpType*> mChildren;
 
     std::vector<Chunk> chunks;
 
diff --git a/libs/hwui/DisplayListCanvas.cpp b/libs/hwui/DisplayListCanvas.cpp
index 77bde86..a1adb80 100644
--- a/libs/hwui/DisplayListCanvas.cpp
+++ b/libs/hwui/DisplayListCanvas.cpp
@@ -514,8 +514,12 @@
 }
 
 size_t DisplayListCanvas::addOpAndUpdateChunk(DisplayListOp* op) {
-    int insertIndex = mDisplayListData->displayListOps.size();
-    mDisplayListData->displayListOps.push_back(op);
+    int insertIndex = mDisplayListData->ops.size();
+#if HWUI_NEW_OPS
+    LOG_ALWAYS_FATAL("unsupported");
+#else
+    mDisplayListData->ops.push_back(op);
+#endif
     if (mDeferredBarrierType != kBarrier_None) {
         // op is first in new chunk
         mDisplayListData->chunks.emplace_back();
@@ -558,16 +562,18 @@
 
 size_t DisplayListCanvas::addRenderNodeOp(DrawRenderNodeOp* op) {
     int opIndex = addDrawOp(op);
+#if !HWUI_NEW_OPS
     int childIndex = mDisplayListData->addChild(op);
 
     // update the chunk's child indices
     DisplayListData::Chunk& chunk = mDisplayListData->chunks.back();
     chunk.endChildIndex = childIndex + 1;
 
-    if (op->renderNode()->stagingProperties().isProjectionReceiver()) {
+    if (op->renderNode->stagingProperties().isProjectionReceiver()) {
         // use staging property, since recording on UI thread
         mDisplayListData->projectionReceiveIndex = opIndex;
     }
+#endif
     return opIndex;
 }
 
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index ddfc533..1f6282d 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -1397,25 +1397,26 @@
 class DrawRenderNodeOp : public DrawBoundedOp {
     friend class RenderNode; // grant RenderNode access to info of child
     friend class DisplayListData; // grant DisplayListData access to info of child
+    friend class DisplayListCanvas;
 public:
     DrawRenderNodeOp(RenderNode* renderNode, const mat4& transformFromParent, bool clipIsSimple)
             : DrawBoundedOp(0, 0, renderNode->getWidth(), renderNode->getHeight(), nullptr)
-            , mRenderNode(renderNode)
+            , renderNode(renderNode)
             , mRecordedWithPotentialStencilClip(!clipIsSimple || !transformFromParent.isSimple())
             , mTransformFromParent(transformFromParent)
             , mSkipInOrderDraw(false) {}
 
     virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
             bool useQuickReject) override {
-        if (mRenderNode->isRenderable() && !mSkipInOrderDraw) {
-            mRenderNode->defer(deferStruct, level + 1);
+        if (renderNode->isRenderable() && !mSkipInOrderDraw) {
+            renderNode->defer(deferStruct, level + 1);
         }
     }
 
     virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
             bool useQuickReject) override {
-        if (mRenderNode->isRenderable() && !mSkipInOrderDraw) {
-            mRenderNode->replay(replayStruct, level + 1);
+        if (renderNode->isRenderable() && !mSkipInOrderDraw) {
+            renderNode->replay(replayStruct, level + 1);
         }
     }
 
@@ -1424,18 +1425,16 @@
     }
 
     virtual void output(int level, uint32_t logFlags) const override {
-        OP_LOG("Draw RenderNode %p %s", mRenderNode, mRenderNode->getName());
-        if (mRenderNode && (logFlags & kOpLogFlag_Recurse)) {
-            mRenderNode->output(level + 1);
+        OP_LOG("Draw RenderNode %p %s", renderNode, renderNode->getName());
+        if (renderNode && (logFlags & kOpLogFlag_Recurse)) {
+            renderNode->output(level + 1);
         }
     }
 
     virtual const char* name() override { return "DrawRenderNode"; }
 
-    RenderNode* renderNode() { return mRenderNode; }
-
 private:
-    RenderNode* mRenderNode;
+    RenderNode* renderNode;
 
     /**
      * This RenderNode was drawn into a DisplayList with the canvas in a state that will likely
diff --git a/libs/hwui/GlopBuilder.cpp b/libs/hwui/GlopBuilder.cpp
index fa166ae..d2da851 100644
--- a/libs/hwui/GlopBuilder.cpp
+++ b/libs/hwui/GlopBuilder.cpp
@@ -461,12 +461,12 @@
 // Transform
 ////////////////////////////////////////////////////////////////////////////////
 
-void GlopBuilder::setTransform(const Matrix4& canvas,
-        const int transformFlags) {
+GlopBuilder& GlopBuilder::setTransform(const Matrix4& canvas, const int transformFlags) {
     TRIGGER_STAGE(kTransformStage);
 
     mOutGlop->transform.canvas = canvas;
     mOutGlop->transform.transformFlags = transformFlags;
+    return *this;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -632,5 +632,42 @@
     mOutGlop->transform.meshTransform().mapRect(mOutGlop->bounds);
 }
 
+void GlopBuilder::dump(const Glop& glop) {
+    ALOGD("Glop Mesh");
+    const Glop::Mesh& mesh = glop.mesh;
+    ALOGD("    primitive mode: %d", mesh.primitiveMode);
+    ALOGD("    indices: buffer obj %x, indices %p", mesh.indices.bufferObject, mesh.indices.indices);
+
+    const Glop::Mesh::Vertices& vertices = glop.mesh.vertices;
+    ALOGD("    vertices: buffer obj %x, flags %x, pos %p, tex %p, clr %p, stride %d",
+            vertices.bufferObject, vertices.attribFlags,
+            vertices.position, vertices.texCoord, vertices.color, vertices.stride);
+    ALOGD("    element count: %d", mesh.elementCount);
+
+    ALOGD("Glop Fill");
+    const Glop::Fill& fill = glop.fill;
+    ALOGD("    program %p", fill.program);
+    if (fill.texture.texture) {
+        ALOGD("    texture %p, target %d, filter %d, clamp %d",
+                fill.texture.texture, fill.texture.target, fill.texture.filter, fill.texture.clamp);
+        if (fill.texture.textureTransform) {
+            fill.texture.textureTransform->dump("texture transform");
+        }
+    }
+    ALOGD_IF(fill.colorEnabled, "    color (argb) %.2f %.2f %.2f %.2f",
+            fill.color.a, fill.color.r, fill.color.g, fill.color.b);
+    ALOGD_IF(fill.filterMode != ProgramDescription::ColorFilterMode::None,
+            "    filterMode %d", (int)fill.filterMode);
+    ALOGD_IF(fill.skiaShaderData.skiaShaderType, "    shader type %d",
+            fill.skiaShaderData.skiaShaderType);
+
+    ALOGD("Glop transform");
+    glop.transform.modelView.dump("model view");
+    glop.transform.canvas.dump("canvas");
+
+    ALOGD("Glop blend %d %d", glop.blend.src, glop.blend.dst);
+    ALOGD("Glop bounds " RECT_STRING, RECT_ARGS(glop.bounds));
+}
+
 } /* namespace uirenderer */
 } /* namespace android */
diff --git a/libs/hwui/GlopBuilder.h b/libs/hwui/GlopBuilder.h
index 8d05570..6f5802e 100644
--- a/libs/hwui/GlopBuilder.h
+++ b/libs/hwui/GlopBuilder.h
@@ -71,9 +71,9 @@
     GlopBuilder& setFillTextureLayer(Layer& layer, float alpha);
 
     GlopBuilder& setTransform(const Snapshot& snapshot, const int transformFlags) {
-        setTransform(*snapshot.transform, transformFlags);
-        return *this;
+        return setTransform(*snapshot.transform, transformFlags);
     }
+    GlopBuilder& setTransform(const Matrix4& canvas, const int transformFlags);
 
     GlopBuilder& setModelViewMapUnitToRect(const Rect destination);
     GlopBuilder& setModelViewMapUnitToRectSnap(const Rect destination);
@@ -98,11 +98,12 @@
     GlopBuilder& setRoundRectClipState(const RoundRectClipState* roundRectClipState);
 
     void build();
+
+    static void dump(const Glop& glop);
 private:
     void setFill(int color, float alphaScale,
             SkXfermode::Mode mode, Blend::ModeOrderSwap modeUsage,
             const SkShader* shader, const SkColorFilter* colorFilter);
-    void setTransform(const Matrix4& canvas, const int transformFlags);
 
     enum StageFlags {
         kInitialStage = 0,
diff --git a/libs/hwui/Matrix.h b/libs/hwui/Matrix.h
index ed517ac..c017638 100644
--- a/libs/hwui/Matrix.h
+++ b/libs/hwui/Matrix.h
@@ -126,6 +126,9 @@
     void loadMultiply(const Matrix4& u, const Matrix4& v);
 
     void loadOrtho(float left, float right, float bottom, float top, float near, float far);
+    void loadOrtho(int width, int height) {
+        loadOrtho(0, width, height, 0, -1, 1);
+    }
 
     uint8_t getType() const;
 
diff --git a/libs/hwui/OpReorderer.cpp b/libs/hwui/OpReorderer.cpp
new file mode 100644
index 0000000..2e02306
--- /dev/null
+++ b/libs/hwui/OpReorderer.cpp
@@ -0,0 +1,405 @@
+/*
+ * 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.
+ */
+
+#include "OpReorderer.h"
+
+#include "utils/PaintUtils.h"
+#include "RenderNode.h"
+
+#include "SkCanvas.h"
+#include "utils/Trace.h"
+
+namespace android {
+namespace uirenderer {
+
+class BatchBase {
+
+public:
+    BatchBase(batchid_t batchId, BakedOpState* op, bool merging)
+        : mBatchId(batchId)
+        , mMerging(merging) {
+        mBounds = op->computedState.clippedBounds;
+        mOps.push_back(op);
+    }
+
+    bool intersects(const Rect& rect) const {
+        if (!rect.intersects(mBounds)) return false;
+
+        for (const BakedOpState* op : mOps) {
+            if (rect.intersects(op->computedState.clippedBounds)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    batchid_t getBatchId() const { return mBatchId; }
+    bool isMerging() const { return mMerging; }
+
+    const std::vector<BakedOpState*>& getOps() const { return mOps; }
+
+    void dump() const {
+        ALOGD("    Batch %p, merging %d, bounds " RECT_STRING, this, mMerging, RECT_ARGS(mBounds));
+    }
+protected:
+    batchid_t mBatchId;
+    Rect mBounds;
+    std::vector<BakedOpState*> mOps;
+    bool mMerging;
+};
+
+class OpBatch : public BatchBase {
+public:
+    static void* operator new(size_t size, LinearAllocator& allocator) {
+        return allocator.alloc(size);
+    }
+
+    OpBatch(batchid_t batchId, BakedOpState* op)
+            : BatchBase(batchId, op, false) {
+    }
+
+    void batchOp(BakedOpState* op) {
+        mBounds.unionWith(op->computedState.clippedBounds);
+        mOps.push_back(op);
+    }
+};
+
+class MergingOpBatch : public BatchBase {
+public:
+    static void* operator new(size_t size, LinearAllocator& allocator) {
+        return allocator.alloc(size);
+    }
+
+    MergingOpBatch(batchid_t batchId, BakedOpState* op)
+            : BatchBase(batchId, op, true) {
+    }
+
+    /*
+     * Helper for determining if a new op can merge with a MergingDrawBatch based on their bounds
+     * and clip side flags. Positive bounds delta means new bounds fit in old.
+     */
+    static inline bool checkSide(const int currentFlags, const int newFlags, const int side,
+            float boundsDelta) {
+        bool currentClipExists = currentFlags & side;
+        bool newClipExists = newFlags & side;
+
+        // if current is clipped, we must be able to fit new bounds in current
+        if (boundsDelta > 0 && currentClipExists) return false;
+
+        // if new is clipped, we must be able to fit current bounds in new
+        if (boundsDelta < 0 && newClipExists) return false;
+
+        return true;
+    }
+
+    static bool paintIsDefault(const SkPaint& paint) {
+        return paint.getAlpha() == 255
+                && paint.getColorFilter() == nullptr
+                && paint.getShader() == nullptr;
+    }
+
+    static bool paintsAreEquivalent(const SkPaint& a, const SkPaint& b) {
+        return a.getAlpha() == b.getAlpha()
+                && a.getColorFilter() == b.getColorFilter()
+                && a.getShader() == b.getShader();
+    }
+
+    /*
+     * Checks if a (mergeable) op can be merged into this batch
+     *
+     * If true, the op's multiDraw must be guaranteed to handle both ops simultaneously, so it is
+     * important to consider all paint attributes used in the draw calls in deciding both a) if an
+     * op tries to merge at all, and b) if the op can merge with another set of ops
+     *
+     * False positives can lead to information from the paints of subsequent merged operations being
+     * dropped, so we make simplifying qualifications on the ops that can merge, per op type.
+     */
+    bool canMergeWith(BakedOpState* op) const {
+        bool isTextBatch = getBatchId() == OpBatchType::Text
+                || getBatchId() == OpBatchType::ColorText;
+
+        // Overlapping other operations is only allowed for text without shadow. For other ops,
+        // multiDraw isn't guaranteed to overdraw correctly
+        if (!isTextBatch || PaintUtils::hasTextShadow(op->op->paint)) {
+            if (intersects(op->computedState.clippedBounds)) return false;
+        }
+
+        const BakedOpState* lhs = op;
+        const BakedOpState* rhs = mOps[0];
+
+        if (!MathUtils::areEqual(lhs->alpha, rhs->alpha)) return false;
+
+        // Identical round rect clip state means both ops will clip in the same way, or not at all.
+        // As the state objects are const, we can compare their pointers to determine mergeability
+        if (lhs->roundRectClipState != rhs->roundRectClipState) return false;
+        if (lhs->projectionPathMask != rhs->projectionPathMask) return false;
+
+        /* Clipping compatibility check
+         *
+         * Exploits the fact that if a op or batch is clipped on a side, its bounds will equal its
+         * clip for that side.
+         */
+        const int currentFlags = mClipSideFlags;
+        const int newFlags = op->computedState.clipSideFlags;
+        if (currentFlags != OpClipSideFlags::None || newFlags != OpClipSideFlags::None) {
+            const Rect& opBounds = op->computedState.clippedBounds;
+            float boundsDelta = mBounds.left - opBounds.left;
+            if (!checkSide(currentFlags, newFlags, OpClipSideFlags::Left, boundsDelta)) return false;
+            boundsDelta = mBounds.top - opBounds.top;
+            if (!checkSide(currentFlags, newFlags, OpClipSideFlags::Top, boundsDelta)) return false;
+
+            // right and bottom delta calculation reversed to account for direction
+            boundsDelta = opBounds.right - mBounds.right;
+            if (!checkSide(currentFlags, newFlags, OpClipSideFlags::Right, boundsDelta)) return false;
+            boundsDelta = opBounds.bottom - mBounds.bottom;
+            if (!checkSide(currentFlags, newFlags, OpClipSideFlags::Bottom, boundsDelta)) return false;
+        }
+
+        const SkPaint* newPaint = op->op->paint;
+        const SkPaint* oldPaint = mOps[0]->op->paint;
+
+        if (newPaint == oldPaint) {
+            // if paints are equal, then modifiers + paint attribs don't need to be compared
+            return true;
+        } else if (newPaint && !oldPaint) {
+            return paintIsDefault(*newPaint);
+        } else if (!newPaint && oldPaint) {
+            return paintIsDefault(*oldPaint);
+        }
+        return paintsAreEquivalent(*newPaint, *oldPaint);
+    }
+
+    void mergeOp(BakedOpState* op) {
+        mBounds.unionWith(op->computedState.clippedBounds);
+        mOps.push_back(op);
+
+        const int newClipSideFlags = op->computedState.clipSideFlags;
+        mClipSideFlags |= newClipSideFlags;
+
+        const Rect& opClip = op->computedState.clipRect;
+        if (newClipSideFlags & OpClipSideFlags::Left) mClipRect.left = opClip.left;
+        if (newClipSideFlags & OpClipSideFlags::Top) mClipRect.top = opClip.top;
+        if (newClipSideFlags & OpClipSideFlags::Right) mClipRect.right = opClip.right;
+        if (newClipSideFlags & OpClipSideFlags::Bottom) mClipRect.bottom = opClip.bottom;
+    }
+
+private:
+    int mClipSideFlags = 0;
+    Rect mClipRect;
+};
+
+class NullClient: public CanvasStateClient {
+    void onViewportInitialized() override {}
+    void onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) {}
+    GLuint getTargetFbo() const override { return 0; }
+};
+static NullClient sNullClient;
+
+OpReorderer::OpReorderer()
+        : mCanvasState(sNullClient) {
+}
+
+void OpReorderer::defer(const SkRect& clip, int viewportWidth, int viewportHeight,
+        const std::vector< sp<RenderNode> >& nodes) {
+    mCanvasState.initializeSaveStack(viewportWidth, viewportHeight,
+            clip.fLeft, clip.fTop, clip.fRight, clip.fBottom,
+            Vector3());
+    for (const sp<RenderNode>& node : nodes) {
+        if (node->nothingToDraw()) continue;
+
+        // TODO: dedupe this code with onRenderNode()
+        mCanvasState.save(SkCanvas::kClip_SaveFlag | SkCanvas::kMatrix_SaveFlag);
+        if (node->applyViewProperties(mCanvasState)) {
+            // not rejected do ops...
+            const DisplayListData& data = node->getDisplayListData();
+            deferImpl(data.getChunks(), data.getOps());
+        }
+        mCanvasState.restore();
+    }
+}
+
+void OpReorderer::defer(int viewportWidth, int viewportHeight,
+        const std::vector<DisplayListData::Chunk>& chunks, const std::vector<RecordedOp*>& ops) {
+    ATRACE_NAME("prepare drawing commands");
+    mCanvasState.initializeSaveStack(viewportWidth, viewportHeight,
+            0, 0, viewportWidth, viewportHeight, Vector3());
+    deferImpl(chunks, ops);
+}
+
+/**
+ * Used to define a list of lambdas referencing private OpReorderer::onXXXXOp() methods.
+ *
+ * This allows opIds embedded in the RecordedOps to be used for dispatching to these lambdas. E.g. a
+ * BitmapOp op then would be dispatched to OpReorderer::onBitmapOp(const BitmapOp&)
+ */
+#define OP_RECIEVER(Type) \
+        [](OpReorderer& reorderer, const RecordedOp& op) { reorderer.on##Type(static_cast<const Type&>(op)); },
+void OpReorderer::deferImpl(const std::vector<DisplayListData::Chunk>& chunks,
+        const std::vector<RecordedOp*>& ops) {
+    static std::function<void(OpReorderer& reorderer, const RecordedOp&)> receivers[] = {
+        MAP_OPS(OP_RECIEVER)
+    };
+    for (const DisplayListData::Chunk& chunk : chunks) {
+        for (size_t opIndex = chunk.beginOpIndex; opIndex < chunk.endOpIndex; opIndex++) {
+            const RecordedOp* op = ops[opIndex];
+            receivers[op->opId](*this, *op);
+        }
+    }
+}
+
+void OpReorderer::replayBakedOpsImpl(void* arg, BakedOpReceiver* receivers) {
+    ATRACE_NAME("flush drawing commands");
+    for (const BatchBase* batch : mBatches) {
+        // TODO: different behavior based on batch->isMerging()
+        for (const BakedOpState* op : batch->getOps()) {
+            receivers[op->op->opId](arg, *op->op, *op);
+        }
+    }
+}
+
+BakedOpState* OpReorderer::bakeOpState(const RecordedOp& recordedOp) {
+    return BakedOpState::tryConstruct(mAllocator, *mCanvasState.currentSnapshot(), recordedOp);
+}
+
+void OpReorderer::onRenderNodeOp(const RenderNodeOp& op) {
+    if (op.renderNode->nothingToDraw()) {
+        return;
+    }
+    mCanvasState.save(SkCanvas::kClip_SaveFlag | SkCanvas::kMatrix_SaveFlag);
+
+    // apply state from RecordedOp
+    mCanvasState.concatMatrix(op.localMatrix);
+    mCanvasState.clipRect(op.localClipRect.left, op.localClipRect.top,
+            op.localClipRect.right, op.localClipRect.bottom, SkRegion::kIntersect_Op);
+
+    // apply RenderProperties state
+    if (op.renderNode->applyViewProperties(mCanvasState)) {
+        // not rejected do ops...
+        const DisplayListData& data = op.renderNode->getDisplayListData();
+        deferImpl(data.getChunks(), data.getOps());
+    }
+    mCanvasState.restore();
+}
+
+static batchid_t tessellatedBatchId(const SkPaint& paint) {
+    return paint.getPathEffect()
+            ? OpBatchType::AlphaMaskTexture
+            : (paint.isAntiAlias() ? OpBatchType::AlphaVertices : OpBatchType::Vertices);
+}
+
+void OpReorderer::onBitmapOp(const BitmapOp& op) {
+    BakedOpState* bakedStateOp = bakeOpState(op);
+    if (!bakedStateOp) return; // quick rejected
+
+    mergeid_t mergeId = (mergeid_t) op.bitmap->getGenerationID();
+    // TODO: AssetAtlas
+
+    deferMergeableOp(bakedStateOp, OpBatchType::Bitmap, mergeId);
+}
+
+void OpReorderer::onRectOp(const RectOp& op) {
+    BakedOpState* bakedStateOp = bakeOpState(op);
+    if (!bakedStateOp) return; // quick rejected
+    deferUnmergeableOp(bakedStateOp, tessellatedBatchId(*op.paint));
+}
+
+void OpReorderer::onSimpleRectsOp(const SimpleRectsOp& op) {
+    BakedOpState* bakedStateOp = bakeOpState(op);
+    if (!bakedStateOp) return; // quick rejected
+    deferUnmergeableOp(bakedStateOp, OpBatchType::Vertices);
+}
+
+// iterate back toward target to see if anything drawn since should overlap the new op
+// if no target, merging ops still interate to find similar batch to insert after
+void OpReorderer::locateInsertIndex(int batchId, const Rect& clippedBounds,
+        BatchBase** targetBatch, size_t* insertBatchIndex) const {
+    for (int i = mBatches.size() - 1; i >= mEarliestBatchIndex; i--) {
+        BatchBase* overBatch = mBatches[i];
+
+        if (overBatch == *targetBatch) break;
+
+        // TODO: also consider shader shared between batch types
+        if (batchId == overBatch->getBatchId()) {
+            *insertBatchIndex = i + 1;
+            if (!*targetBatch) break; // found insert position, quit
+        }
+
+        if (overBatch->intersects(clippedBounds)) {
+            // NOTE: it may be possible to optimize for special cases where two operations
+            // of the same batch/paint could swap order, such as with a non-mergeable
+            // (clipped) and a mergeable text operation
+            *targetBatch = nullptr;
+            break;
+        }
+    }
+}
+
+void OpReorderer::deferUnmergeableOp(BakedOpState* op, batchid_t batchId) {
+    OpBatch* targetBatch = mBatchLookup[batchId];
+
+    size_t insertBatchIndex = mBatches.size();
+    if (targetBatch) {
+        locateInsertIndex(batchId, op->computedState.clippedBounds,
+                (BatchBase**)(&targetBatch), &insertBatchIndex);
+    }
+
+    if (targetBatch) {
+        targetBatch->batchOp(op);
+    } else  {
+        // new non-merging batch
+        targetBatch = new (mAllocator) OpBatch(batchId, op);
+        mBatchLookup[batchId] = targetBatch;
+        mBatches.insert(mBatches.begin() + insertBatchIndex, targetBatch);
+    }
+}
+
+// insertion point of a new batch, will hopefully be immediately after similar batch
+// (generally, should be similar shader)
+void OpReorderer::deferMergeableOp(BakedOpState* op, batchid_t batchId, mergeid_t mergeId) {
+    MergingOpBatch* targetBatch = nullptr;
+
+    // Try to merge with any existing batch with same mergeId
+    auto getResult = mMergingBatches[batchId].find(mergeId);
+    if (getResult != mMergingBatches[batchId].end()) {
+        targetBatch = getResult->second;
+        if (!targetBatch->canMergeWith(op)) {
+            targetBatch = nullptr;
+        }
+    }
+
+    size_t insertBatchIndex = mBatches.size();
+    locateInsertIndex(batchId, op->computedState.clippedBounds,
+            (BatchBase**)(&targetBatch), &insertBatchIndex);
+
+    if (targetBatch) {
+        targetBatch->mergeOp(op);
+    } else  {
+        // new merging batch
+        targetBatch = new (mAllocator) MergingOpBatch(batchId, op);
+        mMergingBatches[batchId].insert(std::make_pair(mergeId, targetBatch));
+
+        mBatches.insert(mBatches.begin() + insertBatchIndex, targetBatch);
+    }
+}
+
+void OpReorderer::dump() {
+    for (const BatchBase* batch : mBatches) {
+        batch->dump();
+    }
+}
+
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/OpReorderer.h b/libs/hwui/OpReorderer.h
new file mode 100644
index 0000000..395a1ba
--- /dev/null
+++ b/libs/hwui/OpReorderer.h
@@ -0,0 +1,145 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HWUI_OP_REORDERER_H
+#define ANDROID_HWUI_OP_REORDERER_H
+
+#include "BakedOpState.h"
+#include "CanvasState.h"
+#include "DisplayList.h"
+#include "RecordedOp.h"
+
+#include <vector>
+#include <unordered_map>
+
+struct SkRect;
+
+namespace android {
+namespace uirenderer {
+
+class BakedOpState;
+class BatchBase;
+class MergingOpBatch;
+class OpBatch;
+class Rect;
+
+typedef int batchid_t;
+typedef const void* mergeid_t;
+
+namespace OpBatchType {
+    enum {
+        None = 0, // Don't batch
+        Bitmap,
+        Patch,
+        AlphaVertices,
+        Vertices,
+        AlphaMaskTexture,
+        Text,
+        ColorText,
+
+        Count // must be last
+    };
+}
+
+class OpReorderer {
+public:
+    OpReorderer();
+
+    // TODO: not final, just presented this way for simplicity. Layers too?
+    void defer(const SkRect& clip, int viewportWidth, int viewportHeight,
+            const std::vector< sp<RenderNode> >& nodes);
+
+    void defer(int viewportWidth, int viewportHeight,
+            const std::vector<DisplayListData::Chunk>& chunks, const std::vector<RecordedOp*>& ops);
+    typedef std::function<void(void*, const RecordedOp&, const BakedOpState&)> BakedOpReceiver;
+
+    /**
+     * replayBakedOps() is templated based on what class will recieve ops being replayed.
+     *
+     * It constructs a lookup array of lambdas, which allows a recorded BakeOpState to use
+     * state->op->opId to lookup a receiver that will be called when the op is replayed.
+     *
+     * For example a BitmapOp would resolve, via the lambda lookup, to calling:
+     *
+     * StaticReceiver::onBitmapOp(Arg* arg, const BitmapOp& op, const BakedOpState& state);
+     */
+#define BAKED_OP_RECEIVER(Type) \
+    [](void* internalArg, const RecordedOp& op, const BakedOpState& state) { \
+        StaticReceiver::on##Type(static_cast<Arg*>(internalArg), static_cast<const Type&>(op), state); \
+    },
+    template <typename StaticReceiver, typename Arg>
+    void replayBakedOps(Arg* arg) {
+        static BakedOpReceiver receivers[] = {
+            MAP_OPS(BAKED_OP_RECEIVER)
+        };
+        StaticReceiver::startFrame(*arg);
+        replayBakedOpsImpl((void*)arg, receivers);
+        StaticReceiver::endFrame(*arg);
+    }
+private:
+    BakedOpState* bakeOpState(const RecordedOp& recordedOp);
+
+    void deferImpl(const std::vector<DisplayListData::Chunk>& chunks,
+            const std::vector<RecordedOp*>& ops);
+
+    void replayBakedOpsImpl(void* arg, BakedOpReceiver* receivers);
+
+    /**
+     * Declares all OpReorderer::onXXXXOp() methods for every RecordedOp type.
+     *
+     * These private methods are called from within deferImpl to defer each individual op
+     * type differently.
+     */
+#define INTERNAL_OP_HANDLER(Type) \
+    void on##Type(const Type& op);
+    MAP_OPS(INTERNAL_OP_HANDLER)
+
+    // iterate back toward target to see if anything drawn since should overlap the new op
+    // if no target, merging ops still iterate to find similar batch to insert after
+    void locateInsertIndex(int batchId, const Rect& clippedBounds,
+            BatchBase** targetBatch, size_t* insertBatchIndex) const;
+
+    void deferUnmergeableOp(BakedOpState* op, batchid_t batchId);
+
+    // insertion point of a new batch, will hopefully be immediately after similar batch
+    // (generally, should be similar shader)
+    void deferMergeableOp(BakedOpState* op, batchid_t batchId, mergeid_t mergeId);
+
+    void dump();
+
+    std::vector<BatchBase*> mBatches;
+
+    /**
+     * Maps the mergeid_t returned by an op's getMergeId() to the most recently seen
+     * MergingDrawBatch of that id. These ids are unique per draw type and guaranteed to not
+     * collide, which avoids the need to resolve mergeid collisions.
+     */
+    std::unordered_map<mergeid_t, MergingOpBatch*> mMergingBatches[OpBatchType::Count];
+
+    // Maps batch ids to the most recent *non-merging* batch of that id
+    OpBatch* mBatchLookup[OpBatchType::Count] = { nullptr };
+    CanvasState mCanvasState;
+
+    // contains ResolvedOps and Batches
+    LinearAllocator mAllocator;
+
+    int mEarliestBatchIndex = 0;
+};
+
+}; // namespace uirenderer
+}; // namespace android
+
+#endif // ANDROID_HWUI_OP_REORDERER_H
diff --git a/libs/hwui/RecordedOp.h b/libs/hwui/RecordedOp.h
new file mode 100644
index 0000000..a69f030
--- /dev/null
+++ b/libs/hwui/RecordedOp.h
@@ -0,0 +1,118 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HWUI_RECORDED_OP_H
+#define ANDROID_HWUI_RECORDED_OP_H
+
+#include "utils/LinearAllocator.h"
+#include "Rect.h"
+#include "Matrix.h"
+
+#include "SkXfermode.h"
+
+class SkBitmap;
+class SkPaint;
+
+namespace android {
+namespace uirenderer {
+
+class RenderNode;
+struct Vertex;
+
+/**
+ * The provided macro is executed for each op type in order, with the results separated by commas.
+ *
+ * This serves as the authoritative list of ops, used for generating ID enum, and ID based LUTs.
+ */
+#define MAP_OPS(OP_FN) \
+        OP_FN(BitmapOp) \
+        OP_FN(RectOp) \
+        OP_FN(RenderNodeOp) \
+        OP_FN(SimpleRectsOp)
+
+// Generate OpId enum
+#define IDENTITY_FN(Type) Type,
+namespace RecordedOpId {
+    enum {
+        MAP_OPS(IDENTITY_FN)
+        Count,
+    };
+}
+static_assert(RecordedOpId::BitmapOp == 0,
+        "First index must be zero for LUTs to work");
+
+#define BASE_PARAMS const Rect& unmappedBounds, const Matrix4& localMatrix, const Rect& localClipRect, const SkPaint* paint
+#define BASE_PARAMS_PAINTLESS const Rect& unmappedBounds, const Matrix4& localMatrix, const Rect& localClipRect
+#define SUPER(Type) RecordedOp(RecordedOpId::Type, unmappedBounds, localMatrix, localClipRect, paint)
+#define SUPER_PAINTLESS(Type) RecordedOp(RecordedOpId::Type, unmappedBounds, localMatrix, localClipRect, nullptr)
+
+struct RecordedOp {
+    /* ID from RecordedOpId - generally used for jumping into function tables */
+    const int opId;
+
+    /* bounds in *local* space, without accounting for DisplayList transformation */
+    const Rect unmappedBounds;
+
+    /* transform in recording space (vs DisplayList origin) */
+    const Matrix4 localMatrix;
+
+    /* clip in recording space */
+    const Rect localClipRect;
+
+    /* optional paint, stored in base object to simplify merging logic */
+    const SkPaint* paint;
+protected:
+    RecordedOp(unsigned int opId, BASE_PARAMS)
+            : opId(opId)
+            , unmappedBounds(unmappedBounds)
+            , localMatrix(localMatrix)
+            , localClipRect(localClipRect)
+            , paint(paint) {}
+};
+
+struct RenderNodeOp : RecordedOp {
+    RenderNodeOp(BASE_PARAMS_PAINTLESS, RenderNode* renderNode)
+            : SUPER_PAINTLESS(RenderNodeOp)
+            , renderNode(renderNode) {}
+    RenderNode * renderNode; // not const, since drawing modifies it (somehow...)
+};
+
+struct BitmapOp : RecordedOp {
+    BitmapOp(BASE_PARAMS, const SkBitmap* bitmap)
+            : SUPER(BitmapOp)
+            , bitmap(bitmap) {}
+    const SkBitmap* bitmap;
+    // TODO: asset atlas/texture id lookup?
+};
+
+struct RectOp : RecordedOp {
+    RectOp(BASE_PARAMS)
+            : SUPER(RectOp) {}
+};
+
+struct SimpleRectsOp : RecordedOp { // Filled, no AA (TODO: better name?)
+    SimpleRectsOp(BASE_PARAMS, Vertex* vertices, size_t vertexCount)
+            : SUPER(SimpleRectsOp)
+            , vertices(vertices)
+            , vertexCount(vertexCount) {}
+    Vertex* vertices;
+    const size_t vertexCount;
+};
+
+}; // namespace uirenderer
+}; // namespace android
+
+#endif // ANDROID_HWUI_RECORDED_OP_H
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
new file mode 100644
index 0000000..c4debd6
--- /dev/null
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -0,0 +1,402 @@
+/*
+ * 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.
+ */
+
+#include "RecordingCanvas.h"
+
+#include "RecordedOp.h"
+#include "RenderNode.h"
+
+namespace android {
+namespace uirenderer {
+
+RecordingCanvas::RecordingCanvas(size_t width, size_t height)
+        : mState(*this)
+        , mResourceCache(ResourceCache::getInstance()) {
+    reset(width, height);
+}
+
+RecordingCanvas::~RecordingCanvas() {
+    LOG_ALWAYS_FATAL_IF(mDisplayListData,
+            "Destroyed a RecordingCanvas during a record!");
+}
+
+void RecordingCanvas::reset(int width, int height) {
+    LOG_ALWAYS_FATAL_IF(mDisplayListData,
+            "prepareDirty called a second time during a recording!");
+    mDisplayListData = new DisplayListData();
+
+    mState.initializeSaveStack(width, height, 0, 0, width, height, Vector3());
+
+    mDeferredBarrierType = kBarrier_InOrder;
+    mState.setDirtyClip(false);
+    mRestoreSaveCount = -1;
+}
+
+DisplayListData* RecordingCanvas::finishRecording() {
+    mPaintMap.clear();
+    mRegionMap.clear();
+    mPathMap.clear();
+    DisplayListData* data = mDisplayListData;
+    mDisplayListData = nullptr;
+    mSkiaCanvasProxy.reset(nullptr);
+    return data;
+}
+
+SkCanvas* RecordingCanvas::asSkCanvas() {
+    LOG_ALWAYS_FATAL_IF(!mDisplayListData,
+            "attempting to get an SkCanvas when we are not recording!");
+    if (!mSkiaCanvasProxy) {
+        mSkiaCanvasProxy.reset(new SkiaCanvasProxy(this));
+    }
+
+    // SkCanvas instances default to identity transform, but should inherit
+    // the state of this Canvas; if this code was in the SkiaCanvasProxy
+    // constructor, we couldn't cache mSkiaCanvasProxy.
+    SkMatrix parentTransform;
+    getMatrix(&parentTransform);
+    mSkiaCanvasProxy.get()->setMatrix(parentTransform);
+
+    return mSkiaCanvasProxy.get();
+}
+
+// ----------------------------------------------------------------------------
+// android/graphics/Canvas state operations
+// ----------------------------------------------------------------------------
+// Save (layer)
+int RecordingCanvas::save(SkCanvas::SaveFlags flags) {
+    return mState.save((int) flags);
+}
+
+void RecordingCanvas::RecordingCanvas::restore() {
+    if (mRestoreSaveCount < 0) {
+        restoreToCount(getSaveCount() - 1);
+        return;
+    }
+
+    mRestoreSaveCount--;
+    mState.restore();
+}
+
+void RecordingCanvas::restoreToCount(int saveCount) {
+    mRestoreSaveCount = saveCount;
+    mState.restoreToCount(saveCount);
+}
+
+int RecordingCanvas::saveLayer(float left, float top, float right, float bottom, const SkPaint* paint,
+        SkCanvas::SaveFlags flags) {
+    LOG_ALWAYS_FATAL("TODO");
+    return 0;
+}
+
+// Matrix
+void RecordingCanvas::rotate(float degrees) {
+    if (degrees == 0) return;
+
+    mState.rotate(degrees);
+}
+
+void RecordingCanvas::scale(float sx, float sy) {
+    if (sx == 1 && sy == 1) return;
+
+    mState.scale(sx, sy);
+}
+
+void RecordingCanvas::skew(float sx, float sy) {
+    mState.skew(sx, sy);
+}
+
+void RecordingCanvas::translate(float dx, float dy) {
+    if (dx == 0 && dy == 0) return;
+
+    mState.translate(dx, dy, 0);
+}
+
+// Clip
+bool RecordingCanvas::getClipBounds(SkRect* outRect) const {
+    Rect bounds = mState.getLocalClipBounds();
+    *outRect = SkRect::MakeLTRB(bounds.left, bounds.top, bounds.right, bounds.bottom);
+    return !(outRect->isEmpty());
+}
+bool RecordingCanvas::quickRejectRect(float left, float top, float right, float bottom) const {
+    return mState.quickRejectConservative(left, top, right, bottom);
+}
+bool RecordingCanvas::quickRejectPath(const SkPath& path) const {
+    SkRect bounds = path.getBounds();
+    return mState.quickRejectConservative(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
+}
+bool RecordingCanvas::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) {
+    return mState.clipRect(left, top, right, bottom, op);
+}
+bool RecordingCanvas::clipPath(const SkPath* path, SkRegion::Op op) {
+    return mState.clipPath(path, op);
+}
+bool RecordingCanvas::clipRegion(const SkRegion* region, SkRegion::Op op) {
+    return mState.clipRegion(region, op);
+}
+
+// ----------------------------------------------------------------------------
+// android/graphics/Canvas draw operations
+// ----------------------------------------------------------------------------
+void RecordingCanvas::drawColor(int color, SkXfermode::Mode mode) {
+    SkPaint paint;
+    paint.setColor(color);
+    paint.setXfermodeMode(mode);
+    drawPaint(paint);
+}
+
+void RecordingCanvas::drawPaint(const SkPaint& paint) {
+    // TODO: more efficient recording?
+    Matrix4 identity;
+    identity.loadIdentity();
+
+    addOp(new (alloc()) RectOp(
+            mState.getRenderTargetClipBounds(),
+            identity,
+            mState.getRenderTargetClipBounds(),
+            refPaint(&paint)));
+}
+
+// Geometry
+void RecordingCanvas::drawPoints(const float* points, int count, const SkPaint& paint) {
+    LOG_ALWAYS_FATAL("TODO!");
+}
+void RecordingCanvas::drawLines(const float* points, int count, const SkPaint& paint) {
+    LOG_ALWAYS_FATAL("TODO!");
+}
+void RecordingCanvas::drawRect(float left, float top, float right, float bottom, const SkPaint& paint) {
+    addOp(new (alloc()) RectOp(
+            Rect(left, top, right, bottom),
+            *(mState.currentSnapshot()->transform),
+            mState.getRenderTargetClipBounds(),
+            refPaint(&paint)));
+}
+
+void RecordingCanvas::drawSimpleRects(const float* rects, int vertexCount, const SkPaint* paint) {
+    if (rects == nullptr) return;
+
+    Vertex* rectData = (Vertex*) mDisplayListData->allocator.alloc(vertexCount * sizeof(Vertex));
+    Vertex* vertex = rectData;
+
+    float left = FLT_MAX;
+    float top = FLT_MAX;
+    float right = FLT_MIN;
+    float bottom = FLT_MIN;
+    for (int index = 0; index < vertexCount; index += 4) {
+        float l = rects[index + 0];
+        float t = rects[index + 1];
+        float r = rects[index + 2];
+        float b = rects[index + 3];
+
+        Vertex::set(vertex++, l, t);
+        Vertex::set(vertex++, r, t);
+        Vertex::set(vertex++, l, b);
+        Vertex::set(vertex++, r, b);
+
+        left = std::min(left, l);
+        top = std::min(top, t);
+        right = std::max(right, r);
+        bottom = std::max(bottom, b);
+    }
+    addOp(new (alloc()) SimpleRectsOp(
+            Rect(left, top, right, bottom),
+            *(mState.currentSnapshot()->transform),
+            mState.getRenderTargetClipBounds(),
+            refPaint(paint), rectData, vertexCount));
+}
+
+void RecordingCanvas::drawRegion(const SkRegion& region, const SkPaint& paint) {
+    if (paint.getStyle() == SkPaint::kFill_Style
+            && (!paint.isAntiAlias() || mState.currentTransform()->isSimple())) {
+        int count = 0;
+        Vector<float> rects;
+        SkRegion::Iterator it(region);
+        while (!it.done()) {
+            const SkIRect& r = it.rect();
+            rects.push(r.fLeft);
+            rects.push(r.fTop);
+            rects.push(r.fRight);
+            rects.push(r.fBottom);
+            count += 4;
+            it.next();
+        }
+        drawSimpleRects(rects.array(), count, &paint);
+    } else {
+        SkRegion::Iterator it(region);
+        while (!it.done()) {
+            const SkIRect& r = it.rect();
+            drawRect(r.fLeft, r.fTop, r.fRight, r.fBottom, paint);
+            it.next();
+        }
+    }
+}
+void RecordingCanvas::drawRoundRect(float left, float top, float right, float bottom,
+            float rx, float ry, const SkPaint& paint) {
+    LOG_ALWAYS_FATAL("TODO!");
+}
+void RecordingCanvas::drawCircle(float x, float y, float radius, const SkPaint& paint) {
+    LOG_ALWAYS_FATAL("TODO!");
+}
+void RecordingCanvas::drawOval(float left, float top, float right, float bottom, const SkPaint& paint) {
+    LOG_ALWAYS_FATAL("TODO!");
+}
+void RecordingCanvas::drawArc(float left, float top, float right, float bottom,
+            float startAngle, float sweepAngle, bool useCenter, const SkPaint& paint) {
+    LOG_ALWAYS_FATAL("TODO!");
+}
+void RecordingCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
+    LOG_ALWAYS_FATAL("TODO!");
+}
+
+// Bitmap-based
+void RecordingCanvas::drawBitmap(const SkBitmap& bitmap, float left, float top, const SkPaint* paint) {
+    save(SkCanvas::kMatrix_SaveFlag);
+    translate(left, top);
+    drawBitmap(&bitmap, paint);
+    restore();
+}
+
+void RecordingCanvas::drawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix,
+                            const SkPaint* paint) {
+    if (matrix.isIdentity()) {
+        drawBitmap(&bitmap, paint);
+    } else if (!(matrix.getType() & ~(SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask))
+            && MathUtils::isPositive(matrix.getScaleX())
+            && MathUtils::isPositive(matrix.getScaleY())) {
+        // SkMatrix::isScaleTranslate() not available in L
+        SkRect src;
+        SkRect dst;
+        bitmap.getBounds(&src);
+        matrix.mapRect(&dst, src);
+        drawBitmap(bitmap, src.fLeft, src.fTop, src.fRight, src.fBottom,
+                   dst.fLeft, dst.fTop, dst.fRight, dst.fBottom, paint);
+    } else {
+        save(SkCanvas::kMatrix_SaveFlag);
+        concat(matrix);
+        drawBitmap(&bitmap, paint);
+        restore();
+    }
+}
+void RecordingCanvas::drawBitmap(const SkBitmap& bitmap, float srcLeft, float srcTop,
+            float srcRight, float srcBottom, float dstLeft, float dstTop,
+            float dstRight, float dstBottom, const SkPaint* paint) {
+    if (srcLeft == 0 && srcTop == 0
+            && srcRight == bitmap.width()
+            && srcBottom == bitmap.height()
+            && (srcBottom - srcTop == dstBottom - dstTop)
+            && (srcRight - srcLeft == dstRight - dstLeft)) {
+        // transform simple rect to rect drawing case into position bitmap ops, since they merge
+        save(SkCanvas::kMatrix_SaveFlag);
+        translate(dstLeft, dstTop);
+        drawBitmap(&bitmap, paint);
+        restore();
+    } else {
+        LOG_ALWAYS_FATAL("TODO!");
+    }
+}
+void RecordingCanvas::drawBitmapMesh(const SkBitmap& bitmap, int meshWidth, int meshHeight,
+            const float* vertices, const int* colors, const SkPaint* paint) {
+    LOG_ALWAYS_FATAL("TODO!");
+}
+void RecordingCanvas::drawNinePatch(const SkBitmap& bitmap, const android::Res_png_9patch& chunk,
+            float dstLeft, float dstTop, float dstRight, float dstBottom,
+            const SkPaint* paint) {
+    LOG_ALWAYS_FATAL("TODO!");
+}
+
+// Text
+void RecordingCanvas::drawText(const uint16_t* glyphs, const float* positions, int count,
+            const SkPaint& paint, float x, float y, float boundsLeft, float boundsTop,
+            float boundsRight, float boundsBottom, float totalAdvance) {
+    LOG_ALWAYS_FATAL("TODO!");
+}
+void RecordingCanvas::drawPosText(const uint16_t* text, const float* positions, int count,
+            int posCount, const SkPaint& paint) {
+    LOG_ALWAYS_FATAL("TODO!");
+}
+void RecordingCanvas::drawTextOnPath(const uint16_t* glyphs, int count, const SkPath& path,
+            float hOffset, float vOffset, const SkPaint& paint) {
+    LOG_ALWAYS_FATAL("TODO!");
+}
+
+void RecordingCanvas::drawBitmap(const SkBitmap* bitmap, const SkPaint* paint) {
+    addOp(new (alloc()) BitmapOp(
+            Rect(0, 0, bitmap->width(), bitmap->height()),
+            *(mState.currentSnapshot()->transform),
+            mState.getRenderTargetClipBounds(),
+            refPaint(paint), refBitmap(*bitmap)));
+}
+void RecordingCanvas::drawRenderNode(RenderNode* renderNode) {
+    RenderNodeOp* op = new (alloc()) RenderNodeOp(
+            Rect(0, 0, renderNode->getWidth(), renderNode->getHeight()), // are these safe? they're theoretically dynamic
+            *(mState.currentSnapshot()->transform),
+            mState.getRenderTargetClipBounds(),
+            renderNode);
+    int opIndex = addOp(op);
+    int childIndex = mDisplayListData->addChild(op);
+
+    // update the chunk's child indices
+    DisplayListData::Chunk& chunk = mDisplayListData->chunks.back();
+    chunk.endChildIndex = childIndex + 1;
+
+    if (renderNode->stagingProperties().isProjectionReceiver()) {
+        // use staging property, since recording on UI thread
+        mDisplayListData->projectionReceiveIndex = opIndex;
+    }
+}
+
+size_t RecordingCanvas::addOp(RecordedOp* op) {
+    // TODO: validate if "addDrawOp" quickrejection logic is useful before adding
+    int insertIndex = mDisplayListData->ops.size();
+    mDisplayListData->ops.push_back(op);
+    if (mDeferredBarrierType != kBarrier_None) {
+        // op is first in new chunk
+        mDisplayListData->chunks.emplace_back();
+        DisplayListData::Chunk& newChunk = mDisplayListData->chunks.back();
+        newChunk.beginOpIndex = insertIndex;
+        newChunk.endOpIndex = insertIndex + 1;
+        newChunk.reorderChildren = (mDeferredBarrierType == kBarrier_OutOfOrder);
+
+        int nextChildIndex = mDisplayListData->children().size();
+        newChunk.beginChildIndex = newChunk.endChildIndex = nextChildIndex;
+        mDeferredBarrierType = kBarrier_None;
+    } else {
+        // standard case - append to existing chunk
+        mDisplayListData->chunks.back().endOpIndex = insertIndex + 1;
+    }
+    return insertIndex;
+}
+
+void RecordingCanvas::refBitmapsInShader(const SkShader* shader) {
+    if (!shader) return;
+
+    // If this paint has an SkShader that has an SkBitmap add
+    // it to the bitmap pile
+    SkBitmap bitmap;
+    SkShader::TileMode xy[2];
+    if (shader->asABitmap(&bitmap, nullptr, xy) == SkShader::kDefault_BitmapType) {
+        refBitmap(bitmap);
+        return;
+    }
+    SkShader::ComposeRec rec;
+    if (shader->asACompose(&rec)) {
+        refBitmapsInShader(rec.fShaderA);
+        refBitmapsInShader(rec.fShaderB);
+        return;
+    }
+}
+
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h
new file mode 100644
index 0000000..ed299e5
--- /dev/null
+++ b/libs/hwui/RecordingCanvas.h
@@ -0,0 +1,300 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HWUI_RECORDING_CANVAS_H
+#define ANDROID_HWUI_RECORDING_CANVAS_H
+
+#include "Canvas.h"
+#include "CanvasState.h"
+#include "DisplayList.h"
+#include "utils/LinearAllocator.h"
+#include "utils/NinePatch.h"
+#include "ResourceCache.h"
+#include "SkiaCanvasProxy.h"
+#include "Snapshot.h"
+
+#include "SkDrawFilter.h"
+#include <vector>
+
+namespace android {
+namespace uirenderer {
+
+class OpReceiver;
+struct RecordedOp;
+
+class RecordingCanvas: public Canvas, public CanvasStateClient {
+public:
+    RecordingCanvas(size_t width, size_t height);
+    virtual ~RecordingCanvas();
+
+    void reset(int width, int height);
+    DisplayListData* finishRecording();
+
+// ----------------------------------------------------------------------------
+// MISC HWUI OPERATIONS - TODO: CATEGORIZE
+// ----------------------------------------------------------------------------
+    void insertReorderBarrier(bool enableReorder) {}
+    void drawRenderNode(RenderNode* renderNode);
+
+// ----------------------------------------------------------------------------
+// CanvasStateClient interface
+// ----------------------------------------------------------------------------
+    virtual void onViewportInitialized() override {}
+    virtual void onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) override {}
+    virtual GLuint getTargetFbo() const override { return -1; }
+
+// ----------------------------------------------------------------------------
+// android/graphics/Canvas interface
+// ----------------------------------------------------------------------------
+    virtual SkCanvas* asSkCanvas() override;
+
+    virtual void setBitmap(const SkBitmap& bitmap) override {
+        LOG_ALWAYS_FATAL("RecordingCanvas is not backed by a bitmap.");
+    }
+
+    virtual bool isOpaque() override { return false; }
+    virtual int width() override { return mState.getWidth(); }
+    virtual int height() override { return mState.getHeight(); }
+
+    virtual void setHighContrastText(bool highContrastText) override {
+        mHighContrastText = highContrastText;
+    }
+    virtual bool isHighContrastText() override { return mHighContrastText; }
+
+// ----------------------------------------------------------------------------
+// android/graphics/Canvas state operations
+// ----------------------------------------------------------------------------
+    // Save (layer)
+    virtual int getSaveCount() const override { return mState.getSaveCount(); }
+    virtual int save(SkCanvas::SaveFlags flags) override;
+    virtual void restore() override;
+    virtual void restoreToCount(int saveCount) override;
+
+    virtual int saveLayer(float left, float top, float right, float bottom, const SkPaint* paint,
+        SkCanvas::SaveFlags flags) override;
+    virtual int saveLayerAlpha(float left, float top, float right, float bottom,
+            int alpha, SkCanvas::SaveFlags flags) override {
+        SkPaint paint;
+        paint.setAlpha(alpha);
+        return saveLayer(left, top, right, bottom, &paint, flags);
+    }
+
+    // Matrix
+    virtual void getMatrix(SkMatrix* outMatrix) const override { mState.getMatrix(outMatrix); }
+    virtual void setMatrix(const SkMatrix& matrix) override { mState.setMatrix(matrix); }
+
+    virtual void concat(const SkMatrix& matrix) override { mState.concatMatrix(matrix); }
+    virtual void rotate(float degrees) override;
+    virtual void scale(float sx, float sy) override;
+    virtual void skew(float sx, float sy) override;
+    virtual void translate(float dx, float dy) override;
+
+    // Clip
+    virtual bool getClipBounds(SkRect* outRect) const override;
+    virtual bool quickRejectRect(float left, float top, float right, float bottom) const override;
+    virtual bool quickRejectPath(const SkPath& path) const override;
+
+    virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op) override;
+    virtual bool clipPath(const SkPath* path, SkRegion::Op op) override;
+    virtual bool clipRegion(const SkRegion* region, SkRegion::Op op) override;
+
+    // Misc
+    virtual SkDrawFilter* getDrawFilter() override { return mDrawFilter.get(); }
+    virtual void setDrawFilter(SkDrawFilter* filter) override {
+        mDrawFilter.reset(SkSafeRef(filter));
+    }
+
+// ----------------------------------------------------------------------------
+// android/graphics/Canvas draw operations
+// ----------------------------------------------------------------------------
+    virtual void drawColor(int color, SkXfermode::Mode mode) override;
+    virtual void drawPaint(const SkPaint& paint) override;
+
+    // Geometry
+    virtual void drawPoint(float x, float y, const SkPaint& paint) override {
+        float points[2] = { x, y };
+        drawPoints(points, 2, paint);
+    }
+    virtual void drawPoints(const float* points, int count, const SkPaint& paint) override;
+    virtual void drawLine(float startX, float startY, float stopX, float stopY,
+            const SkPaint& paint) override {
+        float points[4] = { startX, startY, stopX, stopY };
+        drawLines(points, 4, paint);
+    }
+    virtual void drawLines(const float* points, int count, const SkPaint& paint) override;
+    virtual void drawRect(float left, float top, float right, float bottom, const SkPaint& paint) override;
+    virtual void drawRegion(const SkRegion& region, const SkPaint& paint) override;
+    virtual void drawRoundRect(float left, float top, float right, float bottom,
+            float rx, float ry, const SkPaint& paint) override;
+    virtual void drawCircle(float x, float y, float radius, const SkPaint& paint) override;
+    virtual void drawOval(float left, float top, float right, float bottom, const SkPaint& paint) override;
+    virtual void drawArc(float left, float top, float right, float bottom,
+            float startAngle, float sweepAngle, bool useCenter, const SkPaint& paint) override;
+    virtual void drawPath(const SkPath& path, const SkPaint& paint) override;
+    virtual void drawVertices(SkCanvas::VertexMode vertexMode, int vertexCount,
+            const float* verts, const float* tex, const int* colors,
+            const uint16_t* indices, int indexCount, const SkPaint& paint) override
+        { /* RecordingCanvas does not support drawVertices(); ignore */ }
+
+    // Bitmap-based
+    virtual void drawBitmap(const SkBitmap& bitmap, float left, float top, const SkPaint* paint) override;
+    virtual void drawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix,
+                            const SkPaint* paint) override;
+    virtual void drawBitmap(const SkBitmap& bitmap, float srcLeft, float srcTop,
+            float srcRight, float srcBottom, float dstLeft, float dstTop,
+            float dstRight, float dstBottom, const SkPaint* paint) override;
+    virtual void drawBitmapMesh(const SkBitmap& bitmap, int meshWidth, int meshHeight,
+            const float* vertices, const int* colors, const SkPaint* paint) override;
+    virtual void drawNinePatch(const SkBitmap& bitmap, const android::Res_png_9patch& chunk,
+            float dstLeft, float dstTop, float dstRight, float dstBottom,
+            const SkPaint* paint) override;
+
+    // Text
+    virtual void drawText(const uint16_t* glyphs, const float* positions, int count,
+            const SkPaint& paint, float x, float y, float boundsLeft, float boundsTop,
+            float boundsRight, float boundsBottom, float totalAdvance) override;
+    virtual void drawPosText(const uint16_t* text, const float* positions, int count,
+            int posCount, const SkPaint& paint) override;
+    virtual void drawTextOnPath(const uint16_t* glyphs, int count, const SkPath& path,
+            float hOffset, float vOffset, const SkPaint& paint) override;
+    virtual bool drawTextAbsolutePos() const override { return false; }
+
+private:
+    enum DeferredBarrierType {
+        kBarrier_None,
+        kBarrier_InOrder,
+        kBarrier_OutOfOrder,
+    };
+
+    void drawBitmap(const SkBitmap* bitmap, const SkPaint* paint);
+    void drawSimpleRects(const float* rects, int vertexCount, const SkPaint* paint);
+
+
+    size_t addOp(RecordedOp* op);
+// ----------------------------------------------------------------------------
+// lazy object copy
+// ----------------------------------------------------------------------------
+    LinearAllocator& alloc() { return mDisplayListData->allocator; }
+
+    void refBitmapsInShader(const SkShader* shader);
+
+    template<class T>
+    inline const T* refBuffer(const T* srcBuffer, int32_t count) {
+        if (!srcBuffer) return nullptr;
+
+        T* dstBuffer = (T*) mDisplayListData->allocator.alloc(count * sizeof(T));
+        memcpy(dstBuffer, srcBuffer, count * sizeof(T));
+        return dstBuffer;
+    }
+
+    inline char* refText(const char* text, size_t byteLength) {
+        return (char*) refBuffer<uint8_t>((uint8_t*)text, byteLength);
+    }
+
+    inline const SkPath* refPath(const SkPath* path) {
+        if (!path) return nullptr;
+
+        // The points/verbs within the path are refcounted so this copy operation
+        // is inexpensive and maintains the generationID of the original path.
+        const SkPath* cachedPath = new SkPath(*path);
+        mDisplayListData->pathResources.push_back(cachedPath);
+        return cachedPath;
+    }
+
+    inline const SkPaint* refPaint(const SkPaint* paint) {
+        if (!paint) return nullptr;
+
+        // If there is a draw filter apply it here and store the modified paint
+        // so that we don't need to modify the paint every time we access it.
+        SkTLazy<SkPaint> filteredPaint;
+        if (mDrawFilter.get()) {
+            filteredPaint.set(*paint);
+            mDrawFilter->filter(filteredPaint.get(), SkDrawFilter::kPaint_Type);
+            paint = filteredPaint.get();
+        }
+
+        // compute the hash key for the paint and check the cache.
+        const uint32_t key = paint->getHash();
+        const SkPaint* cachedPaint = mPaintMap.valueFor(key);
+        // In the unlikely event that 2 unique paints have the same hash we do a
+        // object equality check to ensure we don't erroneously dedup them.
+        if (cachedPaint == nullptr || *cachedPaint != *paint) {
+            cachedPaint = new SkPaint(*paint);
+            std::unique_ptr<const SkPaint> copy(cachedPaint);
+            mDisplayListData->paints.push_back(std::move(copy));
+
+            // replaceValueFor() performs an add if the entry doesn't exist
+            mPaintMap.replaceValueFor(key, cachedPaint);
+            refBitmapsInShader(cachedPaint->getShader());
+        }
+
+        return cachedPaint;
+    }
+
+    inline const SkRegion* refRegion(const SkRegion* region) {
+        if (!region) {
+            return region;
+        }
+
+        const SkRegion* cachedRegion = mRegionMap.valueFor(region);
+        // TODO: Add generation ID to SkRegion
+        if (cachedRegion == nullptr) {
+            std::unique_ptr<const SkRegion> copy(new SkRegion(*region));
+            cachedRegion = copy.get();
+            mDisplayListData->regions.push_back(std::move(copy));
+
+            // replaceValueFor() performs an add if the entry doesn't exist
+            mRegionMap.replaceValueFor(region, cachedRegion);
+        }
+
+        return cachedRegion;
+    }
+
+    inline const SkBitmap* refBitmap(const SkBitmap& bitmap) {
+        // Note that this assumes the bitmap is immutable. There are cases this won't handle
+        // correctly, such as creating the bitmap from scratch, drawing with it, changing its
+        // contents, and drawing again. The only fix would be to always copy it the first time,
+        // which doesn't seem worth the extra cycles for this unlikely case.
+        SkBitmap* localBitmap = new (alloc()) SkBitmap(bitmap);
+        alloc().autoDestroy(localBitmap);
+        mDisplayListData->bitmapResources.push_back(localBitmap);
+        return localBitmap;
+    }
+
+    inline const Res_png_9patch* refPatch(const Res_png_9patch* patch) {
+        mDisplayListData->patchResources.push_back(patch);
+        mResourceCache.incrementRefcount(patch);
+        return patch;
+    }
+
+    DefaultKeyedVector<uint32_t, const SkPaint*> mPaintMap;
+    DefaultKeyedVector<const SkPath*, const SkPath*> mPathMap;
+    DefaultKeyedVector<const SkRegion*, const SkRegion*> mRegionMap;
+
+    CanvasState mState;
+    std::unique_ptr<SkiaCanvasProxy> mSkiaCanvasProxy;
+    ResourceCache& mResourceCache;
+    DeferredBarrierType mDeferredBarrierType = kBarrier_None;
+    DisplayListData* mDisplayListData = nullptr;
+    bool mHighContrastText = false;
+    SkAutoTUnref<SkDrawFilter> mDrawFilter;
+    int mRestoreSaveCount = -1;
+}; // class RecordingCanvas
+
+}; // namespace uirenderer
+}; // namespace android
+
+#endif // ANDROID_HWUI_RECORDING_CANVAS_H
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index bf1b4d0..28586fa 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -25,6 +25,9 @@
 
 #include "DamageAccumulator.h"
 #include "Debug.h"
+#if HWUI_NEW_OPS
+#include "RecordedOp.h"
+#endif
 #include "DisplayListOp.h"
 #include "LayerRenderer.h"
 #include "OpenGLRenderer.h"
@@ -46,8 +49,8 @@
                 mLayer->wasBuildLayered ? "true" : "false");
     }
     if (mDisplayListData) {
-        for (size_t i = 0; i < mDisplayListData->children().size(); i++) {
-            mDisplayListData->children()[i]->mRenderNode->debugDumpLayers(prefix);
+        for (auto&& child : mDisplayListData->children()) {
+            child->renderNode->debugDumpLayers(prefix);
         }
     }
 }
@@ -94,12 +97,16 @@
             SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
 
     properties().debugOutputProperties(level);
-    int flags = DisplayListOp::kOpLogFlag_Recurse;
+
     if (mDisplayListData) {
+#if HWUI_NEW_OPS
+        LOG_ALWAYS_FATAL("op dumping unsupported");
+#else
         // TODO: consider printing the chunk boundaries here
-        for (unsigned int i = 0; i < mDisplayListData->displayListOps.size(); i++) {
-            mDisplayListData->displayListOps[i]->output(level, flags);
+        for (auto&& op : mDisplayListData->getOps()) {
+            op->output(level, DisplayListOp::kOpLogFlag_Recurse);
         }
+#endif
     }
 
     ALOGD("%*sDone (%p, %s)", (level - 1) * 2, "", this, getName());
@@ -172,7 +179,7 @@
     pnode->clear_children();
     if (mDisplayListData) {
         for (auto&& child : mDisplayListData->children()) {
-            child->mRenderNode->copyTo(pnode->add_children());
+            child->renderNode->copyTo(pnode->add_children());
         }
     }
 }
@@ -332,6 +339,10 @@
     info.damageAccumulator->popTransform();
 }
 
+void RenderNode::syncProperties() {
+    mProperties = mStagingProperties;
+}
+
 void RenderNode::pushStagingPropertiesChanges(TreeInfo& info) {
     // Push the animators first so that setupStartValueIfNecessary() is called
     // before properties() is trampled by stagingProperties(), as they are
@@ -343,7 +354,7 @@
         mDirtyPropertyFields = 0;
         damageSelf(info);
         info.damageAccumulator->popTransform();
-        mProperties = mStagingProperties;
+        syncProperties();
         applyLayerPropertiesToLayer(info);
         // We could try to be clever and only re-damage if the matrix changed.
         // However, we don't need to worry about that. The cost of over-damaging
@@ -364,35 +375,39 @@
     mLayer->setBlend(props.needsBlending());
 }
 
+void RenderNode::syncDisplayList() {
+    // Make sure we inc first so that we don't fluctuate between 0 and 1,
+    // which would thrash the layer cache
+    if (mStagingDisplayListData) {
+        for (auto&& child : mStagingDisplayListData->children()) {
+            child->renderNode->incParentRefCount();
+        }
+    }
+    deleteDisplayListData();
+    mDisplayListData = mStagingDisplayListData;
+    mStagingDisplayListData = nullptr;
+    if (mDisplayListData) {
+        for (size_t i = 0; i < mDisplayListData->functors.size(); i++) {
+            (*mDisplayListData->functors[i])(DrawGlInfo::kModeSync, nullptr);
+        }
+    }
+}
+
 void RenderNode::pushStagingDisplayListChanges(TreeInfo& info) {
     if (mNeedsDisplayListDataSync) {
         mNeedsDisplayListDataSync = false;
-        // Make sure we inc first so that we don't fluctuate between 0 and 1,
-        // which would thrash the layer cache
-        if (mStagingDisplayListData) {
-            for (size_t i = 0; i < mStagingDisplayListData->children().size(); i++) {
-                mStagingDisplayListData->children()[i]->mRenderNode->incParentRefCount();
-            }
-        }
         // Damage with the old display list first then the new one to catch any
         // changes in isRenderable or, in the future, bounds
         damageSelf(info);
-        deleteDisplayListData();
-        mDisplayListData = mStagingDisplayListData;
-        mStagingDisplayListData = nullptr;
-        if (mDisplayListData) {
-            for (size_t i = 0; i < mDisplayListData->functors.size(); i++) {
-                (*mDisplayListData->functors[i])(DrawGlInfo::kModeSync, nullptr);
-            }
-        }
+        syncDisplayList();
         damageSelf(info);
     }
 }
 
 void RenderNode::deleteDisplayListData() {
     if (mDisplayListData) {
-        for (size_t i = 0; i < mDisplayListData->children().size(); i++) {
-            mDisplayListData->children()[i]->mRenderNode->decParentRefCount();
+        for (auto&& child : mDisplayListData->children()) {
+            child->renderNode->decParentRefCount();
         }
     }
     delete mDisplayListData;
@@ -407,13 +422,17 @@
             info.prepareTextures = cache.prefetchAndMarkInUse(
                     info.canvasContext, subtree->bitmapResources[i]);
         }
-        for (size_t i = 0; i < subtree->children().size(); i++) {
-            DrawRenderNodeOp* op = subtree->children()[i];
-            RenderNode* childNode = op->mRenderNode;
+        for (auto&& op : subtree->children()) {
+            RenderNode* childNode = op->renderNode;
+#if HWUI_NEW_OPS
+            info.damageAccumulator->pushTransform(&op->localMatrix);
+            bool childFunctorsNeedLayer = functorsNeedLayer; // TODO! || op->mRecordedWithPotentialStencilClip;
+#else
             info.damageAccumulator->pushTransform(&op->mTransformFromParent);
             bool childFunctorsNeedLayer = functorsNeedLayer
                     // Recorded with non-rect clip, or canvas-rotated by parent
                     || op->mRecordedWithPotentialStencilClip;
+#endif
             childNode->prepareTreeImpl(info, childFunctorsNeedLayer);
             info.damageAccumulator->popTransform();
         }
@@ -426,8 +445,8 @@
         mLayer = nullptr;
     }
     if (mDisplayListData) {
-        for (size_t i = 0; i < mDisplayListData->children().size(); i++) {
-            mDisplayListData->children()[i]->mRenderNode->destroyHardwareResources();
+        for (auto&& child : mDisplayListData->children()) {
+            child->renderNode->destroyHardwareResources();
         }
         if (mNeedsDisplayListDataSync) {
             // Next prepare tree we are going to push a new display list, so we can
@@ -449,6 +468,34 @@
     }
 }
 
+bool RenderNode::applyViewProperties(CanvasState& canvasState) const {
+    const Outline& outline = properties().getOutline();
+    if (properties().getAlpha() <= 0
+            || (outline.getShouldClip() && outline.isEmpty())
+            || properties().getScaleX() == 0
+            || properties().getScaleY() == 0) {
+        return false; // rejected
+    }
+
+    if (properties().getLeft() != 0 || properties().getTop() != 0) {
+        canvasState.translate(properties().getLeft(), properties().getTop());
+    }
+    if (properties().getStaticMatrix()) {
+        canvasState.concatMatrix(*properties().getStaticMatrix());
+    } else if (properties().getAnimationMatrix()) {
+        canvasState.concatMatrix(*properties().getAnimationMatrix());
+    }
+    if (properties().hasTransformMatrix()) {
+        if (properties().isTransformTranslateOnly()) {
+            canvasState.translate(properties().getTranslationX(), properties().getTranslationY());
+        } else {
+            canvasState.concatMatrix(*properties().getTransformMatrix());
+        }
+    }
+    return !canvasState.quickRejectConservative(
+            0, 0, properties().getWidth(), properties().getHeight());
+}
+
 /*
  * For property operations, we pass a savecount of 0, since the operations aren't part of the
  * displaylist, and thus don't have to compensate for the record-time/playback-time discrepancy in
@@ -580,6 +627,7 @@
  * which are flagged to not draw in the standard draw loop.
  */
 void RenderNode::computeOrdering() {
+#if !HWUI_NEW_OPS
     ATRACE_CALL();
     mProjectedNodes.clear();
 
@@ -588,14 +636,16 @@
     if (mDisplayListData == nullptr) return;
     for (unsigned int i = 0; i < mDisplayListData->children().size(); i++) {
         DrawRenderNodeOp* childOp = mDisplayListData->children()[i];
-        childOp->mRenderNode->computeOrderingImpl(childOp, &mProjectedNodes, &mat4::identity());
+        childOp->renderNode->computeOrderingImpl(childOp, &mProjectedNodes, &mat4::identity());
     }
+#endif
 }
 
 void RenderNode::computeOrderingImpl(
         DrawRenderNodeOp* opState,
         std::vector<DrawRenderNodeOp*>* compositedChildrenOfProjectionSurface,
         const mat4* transformFromProjectionSurface) {
+#if !HWUI_NEW_OPS
     mProjectedNodes.clear();
     if (mDisplayListData == nullptr || mDisplayListData->isEmpty()) return;
 
@@ -619,7 +669,7 @@
         bool haveAppliedPropertiesToProjection = false;
         for (unsigned int i = 0; i < mDisplayListData->children().size(); i++) {
             DrawRenderNodeOp* childOp = mDisplayListData->children()[i];
-            RenderNode* child = childOp->mRenderNode;
+            RenderNode* child = childOp->renderNode;
 
             std::vector<DrawRenderNodeOp*>* projectionChildren = nullptr;
             const mat4* projectionTransform = nullptr;
@@ -642,6 +692,7 @@
             child->computeOrderingImpl(childOp, projectionChildren, projectionTransform);
         }
     }
+#endif
 }
 
 class DeferOperationHandler {
@@ -701,11 +752,12 @@
 
 void RenderNode::buildZSortedChildList(const DisplayListData::Chunk& chunk,
         std::vector<ZDrawRenderNodeOpPair>& zTranslatedNodes) {
+#if !HWUI_NEW_OPS
     if (chunk.beginChildIndex == chunk.endChildIndex) return;
 
     for (unsigned int i = chunk.beginChildIndex; i < chunk.endChildIndex; i++) {
         DrawRenderNodeOp* childOp = mDisplayListData->children()[i];
-        RenderNode* child = childOp->mRenderNode;
+        RenderNode* child = childOp->renderNode;
         float childZ = child->properties().getZ();
 
         if (!MathUtils::isZero(childZ) && chunk.reorderChildren) {
@@ -719,6 +771,7 @@
 
     // Z sort any 3d children (stable-ness makes z compare fall back to standard drawing order)
     std::stable_sort(zTranslatedNodes.begin(), zTranslatedNodes.end());
+#endif
 }
 
 template <class T>
@@ -824,7 +877,7 @@
     while (shadowIndex < endIndex || drawIndex < endIndex) {
         if (shadowIndex < endIndex) {
             DrawRenderNodeOp* casterOp = zTranslatedNodes[shadowIndex].value;
-            RenderNode* caster = casterOp->mRenderNode;
+            RenderNode* caster = casterOp->renderNode;
             const float casterZ = zTranslatedNodes[shadowIndex].key;
             // attempt to render the shadow if the caster about to be drawn is its caster,
             // OR if its caster's Z value is similar to the previous potential caster
@@ -867,9 +920,14 @@
     // Transform renderer to match background we're projecting onto
     // (by offsetting canvas by translationX/Y of background rendernode, since only those are set)
     const DisplayListOp* op =
-            (mDisplayListData->displayListOps[mDisplayListData->projectionReceiveIndex]);
+#if HWUI_NEW_OPS
+            nullptr;
+    LOG_ALWAYS_FATAL("unsupported");
+#else
+            (mDisplayListData->getOps()[mDisplayListData->projectionReceiveIndex]);
+#endif
     const DrawRenderNodeOp* backgroundOp = reinterpret_cast<const DrawRenderNodeOp*>(op);
-    const RenderProperties& backgroundProps = backgroundOp->mRenderNode->properties();
+    const RenderProperties& backgroundProps = backgroundOp->renderNode->properties();
     renderer.translate(backgroundProps.getTranslationX(), backgroundProps.getTranslationY());
 
     // If the projection reciever has an outline, we mask projected content to it
@@ -948,6 +1006,9 @@
         setViewProperties<T>(renderer, handler);
     }
 
+#if HWUI_NEW_OPS
+    LOG_ALWAYS_FATAL("legacy op traversal not supported");
+#else
     bool quickRejected = properties().getClipToBounds()
             && renderer.quickRejectConservative(0, 0, properties().getWidth(), properties().getHeight());
     if (!quickRejected) {
@@ -969,9 +1030,8 @@
                 issueOperationsOf3dChildren(ChildrenSelectMode::NegativeZChildren,
                         initialTransform, zTranslatedNodes, renderer, handler);
 
-
                 for (size_t opIndex = chunk.beginOpIndex; opIndex < chunk.endOpIndex; opIndex++) {
-                    DisplayListOp *op = mDisplayListData->displayListOps[opIndex];
+                    DisplayListOp *op = mDisplayListData->getOps()[opIndex];
 #if DEBUG_DISPLAY_LIST
                     op->output(handler.level() + 1);
 #endif
@@ -988,6 +1048,7 @@
             }
         }
     }
+#endif
 
     DISPLAY_LIST_LOGD("%*sRestoreToCount %d", (handler.level() + 1) * 2, "", restoreTo);
     handler(new (alloc) RestoreToCountOp(restoreTo),
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index 88fc608..ff673ba 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -29,8 +29,8 @@
 
 #include "AnimatorManager.h"
 #include "Debug.h"
-#include "Matrix.h"
 #include "DisplayList.h"
+#include "Matrix.h"
 #include "RenderProperties.h"
 
 #include <vector>
@@ -43,6 +43,7 @@
 namespace android {
 namespace uirenderer {
 
+class CanvasState;
 class DisplayListOp;
 class DisplayListCanvas;
 class OpenGLRenderer;
@@ -74,6 +75,7 @@
  * attached.
  */
 class RenderNode : public VirtualLightRefBase {
+friend class TestUtils; // allow TestUtils to access syncDisplayList / syncProperties
 public:
     enum DirtyPropertyMask {
         GENERIC         = 1 << 1,
@@ -176,8 +178,25 @@
 
     AnimatorManager& animators() { return mAnimatorManager; }
 
+    // Returns false if the properties dictate the subtree contained in this RenderNode won't render
+    bool applyViewProperties(CanvasState& canvasState) const;
+
     void applyViewPropertyTransforms(mat4& matrix, bool true3dTransform = false) const;
 
+    bool nothingToDraw() const {
+        const Outline& outline = properties().getOutline();
+        return mDisplayListData == nullptr
+                || properties().getAlpha() <= 0
+                || (outline.getShouldClip() && outline.isEmpty())
+                || properties().getScaleX() == 0
+                || properties().getScaleY() == 0;
+    }
+
+    // Only call if RenderNode has DisplayListData...
+    const DisplayListData& getDisplayListData() const {
+        return *mDisplayListData;
+    }
+
 private:
     typedef key_value_pair_t<float, DrawRenderNodeOp*> ZDrawRenderNodeOpPair;
 
@@ -235,6 +254,10 @@
         const char* mText;
     };
 
+
+    void syncProperties();
+    void syncDisplayList();
+
     void prepareTreeImpl(TreeInfo& info, bool functorsNeedLayer);
     void pushStagingPropertiesChanges(TreeInfo& info);
     void pushStagingDisplayListChanges(TreeInfo& info);
diff --git a/libs/hwui/microbench/DisplayListCanvasBench.cpp b/libs/hwui/microbench/DisplayListCanvasBench.cpp
index 7b6be7a..fd42adb 100644
--- a/libs/hwui/microbench/DisplayListCanvasBench.cpp
+++ b/libs/hwui/microbench/DisplayListCanvasBench.cpp
@@ -18,12 +18,22 @@
 #include <utils/Singleton.h>
 
 #include "DisplayList.h"
+#if HWUI_NEW_OPS
+#include "RecordingCanvas.h"
+#else
 #include "DisplayListCanvas.h"
+#endif
 #include "microbench/MicroBench.h"
 
 using namespace android;
 using namespace android::uirenderer;
 
+#if HWUI_NEW_OPS
+typedef RecordingCanvas TestCanvas;
+#else
+typedef DisplayListCanvas TestCanvas;
+#endif
+
 BENCHMARK_NO_ARG(BM_DisplayListData_alloc);
 void BM_DisplayListData_alloc::Run(int iters) {
     StartBenchmarkTiming();
@@ -48,7 +58,7 @@
 
 BENCHMARK_NO_ARG(BM_DisplayListCanvas_record_empty);
 void BM_DisplayListCanvas_record_empty::Run(int iters) {
-    DisplayListCanvas canvas(100, 100);
+    TestCanvas canvas(100, 100);
     canvas.finishRecording();
 
     StartBenchmarkTiming();
@@ -62,7 +72,7 @@
 
 BENCHMARK_NO_ARG(BM_DisplayListCanvas_record_saverestore);
 void BM_DisplayListCanvas_record_saverestore::Run(int iters) {
-    DisplayListCanvas canvas(100, 100);
+    TestCanvas canvas(100, 100);
     canvas.finishRecording();
 
     StartBenchmarkTiming();
@@ -80,7 +90,7 @@
 
 BENCHMARK_NO_ARG(BM_DisplayListCanvas_record_translate);
 void BM_DisplayListCanvas_record_translate::Run(int iters) {
-    DisplayListCanvas canvas(100, 100);
+    TestCanvas canvas(100, 100);
     canvas.finishRecording();
 
     StartBenchmarkTiming();
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 38f6e53..238cf06 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -28,6 +28,11 @@
 #include "renderstate/Stencil.h"
 #include "protos/hwui.pb.h"
 
+#if HWUI_NEW_OPS
+#include "BakedOpRenderer.h"
+#include "OpReorderer.h"
+#endif
+
 #include <cutils/properties.h>
 #include <google/protobuf/io/zero_copy_stream_impl.h>
 #include <private/hwui/DrawGlInfo.h>
@@ -121,9 +126,11 @@
 
 bool CanvasContext::initialize(ANativeWindow* window) {
     setSurface(window);
+#if !HWUI_NEW_OPS
     if (mCanvas) return false;
     mCanvas = new OpenGLRenderer(mRenderThread.renderState());
     mCanvas->initProperties();
+#endif
     return true;
 }
 
@@ -162,11 +169,13 @@
 }
 
 void CanvasContext::processLayerUpdate(DeferredLayerUpdater* layerUpdater) {
+#if !HWUI_NEW_OPS
     bool success = layerUpdater->apply();
     LOG_ALWAYS_FATAL_IF(!success, "Failed to update layer!");
     if (layerUpdater->backingLayer()->deferredUpdateScheduled) {
         mCanvas->pushLayerUpdate(layerUpdater->backingLayer());
     }
+#endif
 }
 
 static bool wasSkipped(FrameInfo* info) {
@@ -239,8 +248,10 @@
 }
 
 void CanvasContext::draw() {
+#if !HWUI_NEW_OPS
     LOG_ALWAYS_FATAL_IF(!mCanvas || mEglSurface == EGL_NO_SURFACE,
             "drawRenderNode called on a context with no canvas or surface!");
+#endif
 
     SkRect dirty;
     mDamageAccumulator.finish(&dirty);
@@ -254,10 +265,12 @@
     mCurrentFrameInfo->markIssueDrawCommandsStart();
 
     Frame frame = mEglManager.beginFrame(mEglSurface);
-    if (frame.width() != mCanvas->getViewportWidth()
-            || frame.height() != mCanvas->getViewportHeight()) {
+
+    if (frame.width() != lastFrameWidth || frame.height() != lastFrameHeight) {
         // can't rely on prior content of window if viewport size changes
         dirty.setEmpty();
+        lastFrameWidth = frame.width();
+        lastFrameHeight = frame.height();
     } else if (mHaveNewSurface || frame.bufferAge() == 0) {
         // New surface needs a full draw
         dirty.setEmpty();
@@ -303,6 +316,18 @@
     mDamageHistory.next() = screenDirty;
 
     mEglManager.damageFrame(frame, dirty);
+
+#if HWUI_NEW_OPS
+    OpReorderer reorderer;
+    reorderer.defer(dirty, frame.width(), frame.height(), mRenderNodes);
+    BakedOpRenderer::Info info(Caches::getInstance(), mRenderThread.renderState(),
+            frame.width(), frame.height(), mOpaque);
+    // TODO: profiler().draw(mCanvas);
+    reorderer.replayBakedOps<BakedOpRenderer>(&info);
+
+    bool drew = info.didDraw;
+
+#else
     mCanvas->prepareDirty(frame.width(), frame.height(),
             dirty.fLeft, dirty.fTop, dirty.fRight, dirty.fBottom, mOpaque);
 
@@ -413,7 +438,7 @@
     profiler().draw(mCanvas);
 
     bool drew = mCanvas->finish();
-
+#endif
     // Even if we decided to cancel the frame, from the perspective of jank
     // metrics the frame was swapped at this point
     mCurrentFrameInfo->markSwapBuffers();
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index e0cbabd..16956e6 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -141,6 +141,9 @@
 
     void freePrefetechedLayers();
 
+    int lastFrameWidth = 0;
+    int lastFrameHeight = 0;
+
     RenderThread& mRenderThread;
     EglManager& mEglManager;
     sp<ANativeWindow> mNativeWindow;
diff --git a/libs/hwui/tests/TreeContentAnimation.cpp b/libs/hwui/tests/TreeContentAnimation.cpp
index a59261c..891af91 100644
--- a/libs/hwui/tests/TreeContentAnimation.cpp
+++ b/libs/hwui/tests/TreeContentAnimation.cpp
@@ -20,6 +20,7 @@
 
 #include <AnimationContext.h>
 #include <DisplayListCanvas.h>
+#include <RecordingCanvas.h>
 #include <RenderNode.h>
 #include <renderthread/RenderProxy.h>
 #include <renderthread/RenderTask.h>
@@ -39,6 +40,13 @@
 using namespace android::uirenderer::renderthread;
 using namespace android::uirenderer::test;
 
+#if HWUI_NEW_OPS
+typedef RecordingCanvas TestCanvas;
+#else
+typedef DisplayListCanvas TestCanvas;
+#endif
+
+
 class ContextFactory : public IContextFactory {
 public:
     virtual AnimationContext* createAnimationContext(renderthread::TimeLord& clock) override {
@@ -46,13 +54,13 @@
     }
 };
 
-static DisplayListCanvas* startRecording(RenderNode* node) {
-    DisplayListCanvas* renderer = new DisplayListCanvas(
+static TestCanvas* startRecording(RenderNode* node) {
+    TestCanvas* renderer = new TestCanvas(
             node->stagingProperties().getWidth(), node->stagingProperties().getHeight());
     return renderer;
 }
 
-static void endRecording(DisplayListCanvas* renderer, RenderNode* node) {
+static void endRecording(TestCanvas* renderer, RenderNode* node) {
     node->setStagingDisplayList(renderer->finishRecording());
     delete renderer;
 }
@@ -67,7 +75,7 @@
             frameCount = fc;
         }
     }
-    virtual void createContent(int width, int height, DisplayListCanvas* renderer) = 0;
+    virtual void createContent(int width, int height, TestCanvas* renderer) = 0;
     virtual void doFrame(int frameNr) = 0;
 
     template <class T>
@@ -102,7 +110,7 @@
 
         android::uirenderer::Rect DUMMY;
 
-        DisplayListCanvas* renderer = startRecording(rootNode);
+        TestCanvas* renderer = startRecording(rootNode);
         animation.createContent(width, height, renderer);
         endRecording(renderer, rootNode);
 
@@ -132,7 +140,7 @@
 class ShadowGridAnimation : public TreeContentAnimation {
 public:
     std::vector< sp<RenderNode> > cards;
-    void createContent(int width, int height, DisplayListCanvas* renderer) override {
+    void createContent(int width, int height, TestCanvas* renderer) override {
         renderer->drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode);
         renderer->insertReorderBarrier(true);
 
@@ -163,7 +171,7 @@
         node->mutateStagingProperties().mutableOutline().setShouldClip(true);
         node->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y | RenderNode::Z);
 
-        DisplayListCanvas* renderer = startRecording(node.get());
+        TestCanvas* renderer = startRecording(node.get());
         renderer->drawColor(0xFFEEEEEE, SkXfermode::kSrcOver_Mode);
         endRecording(renderer, node.get());
         return node;
@@ -179,7 +187,7 @@
 class ShadowGrid2Animation : public TreeContentAnimation {
 public:
     std::vector< sp<RenderNode> > cards;
-    void createContent(int width, int height, DisplayListCanvas* renderer) override {
+    void createContent(int width, int height, TestCanvas* renderer) override {
         renderer->drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode);
         renderer->insertReorderBarrier(true);
 
@@ -210,7 +218,7 @@
         node->mutateStagingProperties().mutableOutline().setShouldClip(true);
         node->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y | RenderNode::Z);
 
-        DisplayListCanvas* renderer = startRecording(node.get());
+        TestCanvas* renderer = startRecording(node.get());
         renderer->drawColor(0xFFEEEEEE, SkXfermode::kSrcOver_Mode);
         endRecording(renderer, node.get());
         return node;
@@ -226,7 +234,7 @@
 class RectGridAnimation : public TreeContentAnimation {
 public:
     sp<RenderNode> card;
-    void createContent(int width, int height, DisplayListCanvas* renderer) override {
+    void createContent(int width, int height, TestCanvas* renderer) override {
         renderer->drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode);
         renderer->insertReorderBarrier(true);
 
@@ -247,7 +255,7 @@
         node->mutateStagingProperties().setLeftTopRightBottom(x, y, x + width, y + height);
         node->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
 
-        DisplayListCanvas* renderer = startRecording(node.get());
+        TestCanvas* renderer = startRecording(node.get());
         renderer->drawColor(0xFFFF00FF, SkXfermode::kSrcOver_Mode);
 
         SkRegion region;
@@ -275,7 +283,7 @@
 class OvalAnimation : public TreeContentAnimation {
 public:
     sp<RenderNode> card;
-    void createContent(int width, int height, DisplayListCanvas* renderer) override {
+    void createContent(int width, int height, TestCanvas* renderer) override {
         renderer->drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode);
         renderer->insertReorderBarrier(true);
 
@@ -297,7 +305,7 @@
         node->mutateStagingProperties().setLeftTopRightBottom(x, y, x + width, y + height);
         node->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
 
-        DisplayListCanvas* renderer = startRecording(node.get());
+        TestCanvas* renderer = startRecording(node.get());
 
         SkPaint paint;
         paint.setAntiAlias(true);
@@ -317,7 +325,7 @@
 class PartialDamageTest : public TreeContentAnimation {
 public:
     std::vector< sp<RenderNode> > cards;
-    void createContent(int width, int height, DisplayListCanvas* renderer) override {
+    void createContent(int width, int height, TestCanvas* renderer) override {
         static SkColor COLORS[] = {
                 0xFFF44336,
                 0xFF9C27B0,
@@ -342,7 +350,7 @@
         cards[0]->mutateStagingProperties().setTranslationY(curFrame);
         cards[0]->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
 
-        DisplayListCanvas* renderer = startRecording(cards[0].get());
+        TestCanvas* renderer = startRecording(cards[0].get());
         renderer->drawColor(interpolateColor(curFrame / 150.0f, 0xFFF44336, 0xFFF8BBD0),
                 SkXfermode::kSrcOver_Mode);
         endRecording(renderer, cards[0].get());
@@ -370,7 +378,7 @@
         node->mutateStagingProperties().setLeftTopRightBottom(x, y, x + width, y + height);
         node->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
 
-        DisplayListCanvas* renderer = startRecording(node.get());
+        TestCanvas* renderer = startRecording(node.get());
         renderer->drawColor(color, SkXfermode::kSrcOver_Mode);
         endRecording(renderer, node.get());
         return node;
@@ -383,3 +391,43 @@
     "EGL_KHR_partial_update is supported by the device & are enabled in hwui.",
     TreeContentAnimation::run<PartialDamageTest>
 });
+
+
+class SimpleRectGridAnimation : public TreeContentAnimation {
+public:
+    sp<RenderNode> card;
+    void createContent(int width, int height, TestCanvas* renderer) override {
+        SkPaint paint;
+        paint.setColor(0xFF00FFFF);
+        renderer->drawRect(0, 0, width, height, paint);
+
+        card = createCard(40, 40, 200, 200);
+        renderer->drawRenderNode(card.get());
+    }
+    void doFrame(int frameNr) override {
+        int curFrame = frameNr % 150;
+        card->mutateStagingProperties().setTranslationX(curFrame);
+        card->mutateStagingProperties().setTranslationY(curFrame);
+        card->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
+    }
+private:
+    sp<RenderNode> createCard(int x, int y, int width, int height) {
+        sp<RenderNode> node = new RenderNode();
+        node->mutateStagingProperties().setLeftTopRightBottom(x, y, x + width, y + height);
+        node->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
+
+        TestCanvas* renderer = startRecording(node.get());
+        SkPaint paint;
+        paint.setColor(0xFFFF00FF);
+        renderer->drawRect(0, 0, width, height, paint);
+
+        endRecording(renderer, node.get());
+        return node;
+    }
+};
+static Benchmark _SimpleRectGrid(BenchmarkInfo{
+    "simplerectgrid",
+    "A simple collection of rects. "
+    "Low CPU/GPU load.",
+    TreeContentAnimation::run<SimpleRectGridAnimation>
+});
diff --git a/libs/hwui/unit_tests/BakedOpStateTests.cpp b/libs/hwui/unit_tests/BakedOpStateTests.cpp
new file mode 100644
index 0000000..82aebea
--- /dev/null
+++ b/libs/hwui/unit_tests/BakedOpStateTests.cpp
@@ -0,0 +1,97 @@
+/*
+ * 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.
+ */
+
+#include <gtest/gtest.h>
+
+#include <BakedOpState.h>
+#include <RecordedOp.h>
+#include <unit_tests/TestUtils.h>
+
+namespace android {
+namespace uirenderer {
+
+TEST(ResolvedRenderState, resolution) {
+    Matrix4 identity;
+    identity.loadIdentity();
+
+    Matrix4 translate10x20;
+    translate10x20.loadTranslate(10, 20, 0);
+
+    SkPaint paint;
+    RectOp recordedOp(Rect(30, 40, 100, 200), translate10x20, Rect(0, 0, 100, 200), &paint);
+    {
+        // recorded with transform, no parent transform
+        auto parentSnapshot = TestUtils::makeSnapshot(identity, Rect(0, 0, 100, 200));
+        ResolvedRenderState state(*parentSnapshot, recordedOp);
+        EXPECT_MATRIX_APPROX_EQ(state.transform, translate10x20);
+        EXPECT_EQ(state.clipRect, Rect(0, 0, 100, 200));
+        EXPECT_EQ(state.clippedBounds, Rect(40, 60, 100, 200)); // translated and also clipped
+    }
+    {
+        // recorded with transform and parent transform
+        auto parentSnapshot = TestUtils::makeSnapshot(translate10x20, Rect(0, 0, 100, 200));
+        ResolvedRenderState state(*parentSnapshot, recordedOp);
+
+        Matrix4 expectedTranslate;
+        expectedTranslate.loadTranslate(20, 40, 0);
+        EXPECT_MATRIX_APPROX_EQ(state.transform, expectedTranslate);
+
+        // intersection of parent & transformed child clip
+        EXPECT_EQ(state.clipRect, Rect(10, 20, 100, 200));
+
+        // translated and also clipped
+        EXPECT_EQ(state.clippedBounds, Rect(50, 80, 100, 200));
+    }
+}
+
+TEST(BakedOpState, constructAndReject) {
+    LinearAllocator allocator;
+
+    Matrix4 identity;
+    identity.loadIdentity();
+
+    Matrix4 translate100x0;
+    translate100x0.loadTranslate(100, 0, 0);
+
+    SkPaint paint;
+    {
+        RectOp rejectOp(Rect(30, 40, 100, 200), translate100x0, Rect(0, 0, 100, 200), &paint);
+        auto snapshot = TestUtils::makeSnapshot(identity, Rect(0, 0, 100, 200));
+        BakedOpState* bakedOp = BakedOpState::tryConstruct(allocator, *snapshot, rejectOp);
+
+        EXPECT_EQ(bakedOp, nullptr); // rejected by clip, so not constructed
+        EXPECT_LE(allocator.usedSize(), 8u); // no significant allocation space used for rejected op
+    }
+    {
+        RectOp successOp(Rect(30, 40, 100, 200), identity, Rect(0, 0, 100, 200), &paint);
+        auto snapshot = TestUtils::makeSnapshot(identity, Rect(0, 0, 100, 200));
+        BakedOpState* bakedOp = BakedOpState::tryConstruct(allocator, *snapshot, successOp);
+
+        EXPECT_NE(bakedOp, nullptr); // NOT rejected by clip, so will be constructed
+        EXPECT_GT(allocator.usedSize(), 64u); // relatively large alloc for non-rejected op
+    }
+}
+
+#define UNSUPPORTED_OP(Info, Type) \
+        static void on##Type(Info*, const Type&, const BakedOpState&) { FAIL(); }
+
+class Info {
+public:
+    int index = 0;
+};
+
+}
+}
diff --git a/libs/hwui/unit_tests/ClipAreaTests.cpp b/libs/hwui/unit_tests/ClipAreaTests.cpp
index 0c5e5e7..d6192df 100644
--- a/libs/hwui/unit_tests/ClipAreaTests.cpp
+++ b/libs/hwui/unit_tests/ClipAreaTests.cpp
@@ -101,10 +101,9 @@
     EXPECT_FALSE(area.isEmpty());
     EXPECT_FALSE(area.isSimple());
     EXPECT_FALSE(area.isRectangleList());
+
     Rect clipRect(area.getClipRect());
-    clipRect.dump("clipRect");
     Rect expected(0, 0, r * 2, r * 2);
-    expected.dump("expected");
     EXPECT_EQ(expected, clipRect);
     SkRegion clipRegion(area.getClipRegion());
     auto skRect(clipRegion.getBounds());
diff --git a/libs/hwui/unit_tests/OpReordererTests.cpp b/libs/hwui/unit_tests/OpReordererTests.cpp
new file mode 100644
index 0000000..cbfbb23
--- /dev/null
+++ b/libs/hwui/unit_tests/OpReordererTests.cpp
@@ -0,0 +1,189 @@
+/*
+ * 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.
+ */
+
+#include <gtest/gtest.h>
+
+#include <BakedOpState.h>
+#include <OpReorderer.h>
+#include <RecordedOp.h>
+#include <RecordingCanvas.h>
+#include <unit_tests/TestUtils.h>
+
+#include <unordered_map>
+
+namespace android {
+namespace uirenderer {
+
+#define UNSUPPORTED_OP(Info, Type) \
+        static void on##Type(Info*, const Type&, const BakedOpState&) { FAIL(); }
+
+class Info {
+public:
+    int index = 0;
+};
+
+class SimpleReceiver {
+public:
+    static void onBitmapOp(Info* info, const BitmapOp& op, const BakedOpState& state) {
+        EXPECT_EQ(1, info->index++);
+    }
+    static void onRectOp(Info* info, const RectOp& op, const BakedOpState& state) {
+        EXPECT_EQ(0, info->index++);
+    }
+    UNSUPPORTED_OP(Info, RenderNodeOp)
+    UNSUPPORTED_OP(Info, SimpleRectsOp)
+    static void startFrame(Info& info) {}
+    static void endFrame(Info& info) {}
+};
+TEST(OpReorderer, simple) {
+    auto dld = TestUtils::createDLD<RecordingCanvas>(100, 200, [](RecordingCanvas& canvas) {
+        SkBitmap bitmap = TestUtils::createSkBitmap(25, 25);
+        canvas.drawRect(0, 0, 100, 200, SkPaint());
+        canvas.drawBitmap(bitmap, 10, 10, nullptr);
+    });
+
+    OpReorderer reorderer;
+    reorderer.defer(200, 200, dld->getChunks(), dld->getOps());
+
+    Info info;
+    reorderer.replayBakedOps<SimpleReceiver>(&info);
+}
+
+
+static int SIMPLE_BATCHING_LOOPS = 5;
+class SimpleBatchingReceiver {
+public:
+    static void onBitmapOp(Info* info, const BitmapOp& op, const BakedOpState& state) {
+        EXPECT_TRUE(info->index++ >= SIMPLE_BATCHING_LOOPS);
+    }
+    static void onRectOp(Info* info, const RectOp& op, const BakedOpState& state) {
+        EXPECT_TRUE(info->index++ < SIMPLE_BATCHING_LOOPS);
+    }
+    UNSUPPORTED_OP(Info, RenderNodeOp)
+    UNSUPPORTED_OP(Info, SimpleRectsOp)
+    static void startFrame(Info& info) {}
+    static void endFrame(Info& info) {}
+};
+TEST(OpReorderer, simpleBatching) {
+    auto dld = TestUtils::createDLD<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
+        SkBitmap bitmap = TestUtils::createSkBitmap(10, 10);
+
+        // Alternate between drawing rects and bitmaps, with bitmaps overlapping rects.
+        // Rects don't overlap bitmaps, so bitmaps should be brought to front as a group.
+        canvas.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
+        for (int i = 0; i < SIMPLE_BATCHING_LOOPS; i++) {
+            canvas.translate(0, 10);
+            canvas.drawRect(0, 0, 10, 10, SkPaint());
+            canvas.drawBitmap(bitmap, 5, 0, nullptr);
+        }
+        canvas.restore();
+    });
+
+    OpReorderer reorderer;
+    reorderer.defer(200, 200, dld->getChunks(), dld->getOps());
+
+    Info info;
+    reorderer.replayBakedOps<SimpleBatchingReceiver>(&info);
+    EXPECT_EQ(2 * SIMPLE_BATCHING_LOOPS, info.index); // 2 x loops ops, because no merging (TODO: force no merging)
+}
+
+class RenderNodeReceiver {
+public:
+    UNSUPPORTED_OP(Info, BitmapOp)
+    static void onRectOp(Info* info, const RectOp& op, const BakedOpState& state) {
+        switch(info->index++) {
+        case 0:
+            EXPECT_EQ(Rect(0, 0, 200, 200), state.computedState.clippedBounds);
+            EXPECT_EQ(SK_ColorDKGRAY, op.paint->getColor());
+            break;
+        case 1:
+            EXPECT_EQ(Rect(50, 50, 150, 150), state.computedState.clippedBounds);
+            EXPECT_EQ(SK_ColorWHITE, op.paint->getColor());
+            break;
+        default:
+            FAIL();
+        }
+    }
+    UNSUPPORTED_OP(Info, RenderNodeOp)
+    UNSUPPORTED_OP(Info, SimpleRectsOp)
+    static void startFrame(Info& info) {}
+    static void endFrame(Info& info) {}
+};
+TEST(OpReorderer, renderNode) {
+    sp<RenderNode> child = TestUtils::createNode<RecordingCanvas>(10, 10, 110, 110, [](RecordingCanvas& canvas) {
+        SkPaint paint;
+        paint.setColor(SK_ColorWHITE);
+        canvas.drawRect(0, 0, 100, 100, paint);
+    });
+
+    RenderNode* childPtr = child.get();
+    sp<RenderNode> parent = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200, [childPtr](RecordingCanvas& canvas) {
+        SkPaint paint;
+        paint.setColor(SK_ColorDKGRAY);
+        canvas.drawRect(0, 0, 200, 200, paint);
+
+        canvas.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
+        canvas.translate(40, 40);
+        canvas.drawRenderNode(childPtr);
+        canvas.restore();
+    });
+
+    TestUtils::syncNodePropertiesAndDisplayList(child);
+    TestUtils::syncNodePropertiesAndDisplayList(parent);
+
+    std::vector< sp<RenderNode> > nodes;
+    nodes.push_back(parent.get());
+
+    OpReorderer reorderer;
+    reorderer.defer(SkRect::MakeWH(200, 200), 200, 200, nodes);
+
+    Info info;
+    reorderer.replayBakedOps<RenderNodeReceiver>(&info);
+}
+
+class ClippedReceiver {
+public:
+    static void onBitmapOp(Info* info, const BitmapOp& op, const BakedOpState& state) {
+        EXPECT_EQ(0, info->index++);
+        EXPECT_EQ(Rect(10, 20, 30, 40), state.computedState.clippedBounds);
+        EXPECT_EQ(Rect(10, 20, 30, 40), state.computedState.clipRect);
+        EXPECT_TRUE(state.computedState.transform.isIdentity());
+    }
+    UNSUPPORTED_OP(Info, RectOp)
+    UNSUPPORTED_OP(Info, RenderNodeOp)
+    UNSUPPORTED_OP(Info, SimpleRectsOp)
+    static void startFrame(Info& info) {}
+    static void endFrame(Info& info) {}
+};
+TEST(OpReorderer, clipped) {
+    sp<RenderNode> node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200, [](RecordingCanvas& canvas) {
+        SkBitmap bitmap = TestUtils::createSkBitmap(200, 200);
+        canvas.drawBitmap(bitmap, 0, 0, nullptr);
+    });
+    TestUtils::syncNodePropertiesAndDisplayList(node);
+    std::vector< sp<RenderNode> > nodes;
+    nodes.push_back(node.get());
+
+    OpReorderer reorderer;
+    reorderer.defer(SkRect::MakeLTRB(10, 20, 30, 40), // clip to small area, should see in receiver
+            200, 200, nodes);
+
+    Info info;
+    reorderer.replayBakedOps<ClippedReceiver>(&info);
+}
+
+}
+}
diff --git a/libs/hwui/unit_tests/RecordingCanvasTests.cpp b/libs/hwui/unit_tests/RecordingCanvasTests.cpp
new file mode 100644
index 0000000..c813833
--- /dev/null
+++ b/libs/hwui/unit_tests/RecordingCanvasTests.cpp
@@ -0,0 +1,112 @@
+/*
+ * 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.
+ */
+
+#include <gtest/gtest.h>
+
+#include <RecordedOp.h>
+#include <RecordingCanvas.h>
+#include <unit_tests/TestUtils.h>
+
+namespace android {
+namespace uirenderer {
+
+static void playbackOps(const std::vector<DisplayListData::Chunk>& chunks,
+        const std::vector<RecordedOp*>& ops, std::function<void(const RecordedOp&)> opReciever) {
+    for (const DisplayListData::Chunk& chunk : chunks) {
+        for (size_t opIndex = chunk.beginOpIndex; opIndex < chunk.endOpIndex; opIndex++) {
+            opReciever(*ops[opIndex]);
+        }
+    }
+}
+
+TEST(RecordingCanvas, emptyPlayback) {
+    auto dld = TestUtils::createDLD<RecordingCanvas>(100, 200, [](RecordingCanvas& canvas) {
+        canvas.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
+        canvas.restore();
+    });
+    playbackOps(dld->getChunks(), dld->getOps(), [](const RecordedOp& op) { FAIL(); });
+}
+
+TEST(RecordingCanvas, testSimpleRectRecord) {
+    auto dld = TestUtils::createDLD<RecordingCanvas>(100, 200, [](RecordingCanvas& canvas) {
+        canvas.drawRect(10, 20, 90, 180, SkPaint());
+    });
+
+    int count = 0;
+    playbackOps(dld->getChunks(), dld->getOps(), [&count](const RecordedOp& op) {
+        count++;
+        ASSERT_EQ(RecordedOpId::RectOp, op.opId);
+        ASSERT_EQ(Rect(0, 0, 100, 200), op.localClipRect);
+        ASSERT_EQ(Rect(10, 20, 90, 180), op.unmappedBounds);
+    });
+    ASSERT_EQ(1, count); // only one observed
+}
+
+TEST(RecordingCanvas, backgroundAndImage) {
+    auto dld = TestUtils::createDLD<RecordingCanvas>(100, 200, [](RecordingCanvas& canvas) {
+        SkBitmap bitmap;
+        bitmap.setInfo(SkImageInfo::MakeUnknown(25, 25));
+        SkPaint paint;
+        paint.setColor(SK_ColorBLUE);
+
+        canvas.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
+        {
+            // a background!
+            canvas.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
+            canvas.drawRect(0, 0, 100, 200, paint);
+            canvas.restore();
+        }
+        {
+            // an image!
+            canvas.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
+            canvas.translate(25, 25);
+            canvas.scale(2, 2);
+            canvas.drawBitmap(bitmap, 0, 0, nullptr);
+            canvas.restore();
+        }
+        canvas.restore();
+    });
+
+    int count = 0;
+    playbackOps(dld->getChunks(), dld->getOps(), [&count](const RecordedOp& op) {
+        if (count == 0) {
+            ASSERT_EQ(RecordedOpId::RectOp, op.opId);
+            ASSERT_NE(nullptr, op.paint);
+            EXPECT_EQ(SK_ColorBLUE, op.paint->getColor());
+            EXPECT_EQ(Rect(0, 0, 100, 200), op.unmappedBounds);
+            EXPECT_EQ(Rect(0, 0, 100, 200), op.localClipRect);
+
+            Matrix4 expectedMatrix;
+            expectedMatrix.loadIdentity();
+            EXPECT_MATRIX_APPROX_EQ(expectedMatrix, op.localMatrix);
+        } else {
+            ASSERT_EQ(RecordedOpId::BitmapOp, op.opId);
+            EXPECT_EQ(nullptr, op.paint);
+            EXPECT_EQ(Rect(0, 0, 25, 25), op.unmappedBounds);
+            EXPECT_EQ(Rect(0, 0, 100, 200), op.localClipRect);
+
+            Matrix4 expectedMatrix;
+            expectedMatrix.loadTranslate(25, 25, 0);
+            expectedMatrix.scale(2, 2, 1);
+            EXPECT_MATRIX_APPROX_EQ(expectedMatrix, op.localMatrix);
+        }
+        count++;
+    });
+    ASSERT_EQ(2, count); // two draws observed
+}
+
+}
+}
diff --git a/libs/hwui/unit_tests/TestUtils.h b/libs/hwui/unit_tests/TestUtils.h
new file mode 100644
index 0000000..9b7d1b9
--- /dev/null
+++ b/libs/hwui/unit_tests/TestUtils.h
@@ -0,0 +1,86 @@
+/*
+ * 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.
+ */
+#ifndef TEST_UTILS_H
+#define TEST_UTILS_H
+
+#include <Matrix.h>
+#include <Snapshot.h>
+#include <RenderNode.h>
+
+#include <memory>
+
+namespace android {
+namespace uirenderer {
+
+#define EXPECT_MATRIX_APPROX_EQ(a, b) \
+    EXPECT_TRUE(TestUtils::matricesAreApproxEqual(a, b))
+
+class TestUtils {
+public:
+    static bool matricesAreApproxEqual(const Matrix4& a, const Matrix4& b) {
+        for (int i = 0; i < 16; i++) {
+            if (!MathUtils::areEqual(a[i], b[i])) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    static std::unique_ptr<Snapshot> makeSnapshot(const Matrix4& transform, const Rect& clip) {
+        std::unique_ptr<Snapshot> snapshot(new Snapshot());
+        snapshot->clip(clip.left, clip.top, clip.right, clip.bottom, SkRegion::kReplace_Op);
+        *(snapshot->transform) = transform;
+        return snapshot;
+    }
+
+    static SkBitmap createSkBitmap(int width, int height) {
+        SkBitmap bitmap;
+        bitmap.setInfo(SkImageInfo::MakeUnknown(width, height));
+        return bitmap;
+    }
+
+    template<class CanvasType>
+    static std::unique_ptr<DisplayListData> createDLD(int width, int height,
+            std::function<void(CanvasType& canvas)> canvasCallback) {
+        CanvasType canvas(width, height);
+        canvasCallback(canvas);
+        return std::unique_ptr<DisplayListData>(canvas.finishRecording());
+    }
+
+    template<class CanvasType>
+    static sp<RenderNode> createNode(int left, int top, int right, int bottom,
+            std::function<void(CanvasType& canvas)> canvasCallback) {
+        sp<RenderNode> node = new RenderNode();
+        node->mutateStagingProperties().setLeftTopRightBottom(left, top, right, bottom);
+        node->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
+
+        CanvasType canvas(
+                node->stagingProperties().getWidth(), node->stagingProperties().getHeight());
+        canvasCallback(canvas);
+        node->setStagingDisplayList(canvas.finishRecording());
+        return node;
+    }
+
+    static void syncNodePropertiesAndDisplayList(sp<RenderNode>& node) {
+        node->syncProperties();
+        node->syncDisplayList();
+    }
+}; // class TestUtils
+
+} /* namespace uirenderer */
+} /* namespace android */
+
+#endif /* TEST_UTILS_H */
diff --git a/libs/hwui/utils/PaintUtils.h b/libs/hwui/utils/PaintUtils.h
index d00236e..db53713 100644
--- a/libs/hwui/utils/PaintUtils.h
+++ b/libs/hwui/utils/PaintUtils.h
@@ -20,6 +20,7 @@
 
 #include <SkColorFilter.h>
 #include <SkDrawLooper.h>
+#include <SkShader.h>
 #include <SkXfermode.h>
 
 namespace android {
diff --git a/libs/input/PointerController.cpp b/libs/input/PointerController.cpp
index 1152737..0f86bc6 100644
--- a/libs/input/PointerController.cpp
+++ b/libs/input/PointerController.cpp
@@ -78,6 +78,7 @@
     mLocked.pointerAlpha = 0.0f; // pointer is initially faded
     mLocked.pointerSprite = mSpriteController->createSprite();
     mLocked.pointerIconChanged = false;
+    mLocked.requestedPointerShape = 0;
 
     mLocked.buttonState = 0;
 
@@ -231,6 +232,10 @@
 void PointerController::setPresentation(Presentation presentation) {
     AutoMutex _l(mLock);
 
+    if (presentation == PRESENTATION_POINTER && mLocked.additionalMouseResources.empty()) {
+        mPolicy->loadAdditionalMouseResources(&mLocked.additionalMouseResources);
+    }
+
     if (mLocked.presentation != presentation) {
         mLocked.presentation = presentation;
         mLocked.presentationChanged = true;
@@ -391,6 +396,15 @@
     updatePointerLocked();
 }
 
+void PointerController::updatePointerShape(int iconId) {
+    AutoMutex _l(mLock);
+    if (mLocked.requestedPointerShape != iconId) {
+        mLocked.requestedPointerShape = iconId;
+        mLocked.presentationChanged = true;
+        updatePointerLocked();
+    }
+}
+
 void PointerController::setPointerIcon(const SpriteIcon& icon) {
     AutoMutex _l(mLock);
 
@@ -497,8 +511,22 @@
     }
 
     if (mLocked.pointerIconChanged || mLocked.presentationChanged) {
-        mLocked.pointerSprite->setIcon(mLocked.presentation == PRESENTATION_POINTER
-                ? mLocked.pointerIcon : mResources.spotAnchor);
+        if (mLocked.presentation == PRESENTATION_POINTER) {
+            if (mLocked.requestedPointerShape == 0) {
+                mLocked.pointerSprite->setIcon(mLocked.pointerIcon);
+            } else {
+                std::map<int, SpriteIcon>::const_iterator iter =
+                    mLocked.additionalMouseResources.find(mLocked.requestedPointerShape);
+                if (iter != mLocked.additionalMouseResources.end()) {
+                    mLocked.pointerSprite->setIcon(iter->second);
+                } else {
+                    ALOGW("Can't find the resource for icon id %d", mLocked.requestedPointerShape);
+                    mLocked.pointerSprite->setIcon(mLocked.pointerIcon);
+                }
+            }
+        } else {
+            mLocked.pointerSprite->setIcon(mResources.spotAnchor);
+        }
         mLocked.pointerIconChanged = false;
         mLocked.presentationChanged = false;
     }
diff --git a/libs/input/PointerController.h b/libs/input/PointerController.h
index b9e4ce7..308ff12 100644
--- a/libs/input/PointerController.h
+++ b/libs/input/PointerController.h
@@ -19,6 +19,8 @@
 
 #include "SpriteController.h"
 
+#include <map>
+
 #include <ui/DisplayInfo.h>
 #include <input/Input.h>
 #include <inputflinger/PointerControllerInterface.h>
@@ -40,7 +42,6 @@
     SpriteIcon spotAnchor;
 };
 
-
 /*
  * Pointer controller policy interface.
  *
@@ -57,6 +58,7 @@
 
 public:
     virtual void loadPointerResources(PointerResources* outResources) = 0;
+    virtual void loadAdditionalMouseResources(std::map<int, SpriteIcon>* outResources) = 0;
 };
 
 
@@ -93,6 +95,7 @@
             const uint32_t* spotIdToIndex, BitSet32 spotIdBits);
     virtual void clearSpots();
 
+    void updatePointerShape(int iconId);
     void setDisplayViewport(int32_t width, int32_t height, int32_t orientation);
     void setPointerIcon(const SpriteIcon& icon);
     void setInactivityTimeout(InactivityTimeout inactivityTimeout);
@@ -155,6 +158,10 @@
         SpriteIcon pointerIcon;
         bool pointerIconChanged;
 
+        std::map<int, SpriteIcon> additionalMouseResources;
+
+        int32_t requestedPointerShape;
+
         int32_t buttonState;
 
         Vector<Spot*> spots;
diff --git a/media/java/android/mtp/MtpEvent.java b/media/java/android/mtp/MtpEvent.java
index 0fa7d93..4c8a742 100644
--- a/media/java/android/mtp/MtpEvent.java
+++ b/media/java/android/mtp/MtpEvent.java
@@ -18,13 +18,33 @@
 
 /**
  * This class encapsulates information about a MTP event.
+ * Event constants are defined by the USB-IF MTP specification.
  */
 public class MtpEvent {
-    private int mEventCode;
+    public static final int EVENT_UNDEFINED = 0x4000;
+    public static final int EVENT_CANCEL_TRANSACTION = 0x4001;
+    public static final int EVENT_OBJECT_ADDED = 0x4002;
+    public static final int EVENT_OBJECT_REMOVED = 0x4003;
+    public static final int EVENT_STORE_ADDED = 0x4004;
+    public static final int EVENT_STORE_REMOVED = 0x4005;
+    public static final int EVENT_DEVICE_PROP_CHANGED = 0x4006;
+    public static final int EVENT_OBJECT_INFO_CHANGED = 0x4007;
+    public static final int EVENT_DEVICE_INFO_CHANGED = 0x4008;
+    public static final int EVENT_REQUEST_OBJECT_TRANSFER = 0x4009;
+    public static final int EVENT_STORE_FULL = 0x400A;
+    public static final int EVENT_DEVICE_RESET = 0x400B;
+    public static final int EVENT_STORAGE_INFO_CHANGED = 0x400C;
+    public static final int EVENT_CAPTURE_COMPLETE = 0x400D;
+    public static final int EVENT_UNREPORTED_STATUS = 0x400E;
+    public static final int EVENT_OBJECT_PROP_CHANGED = 0xC801;
+    public static final int EVENT_OBJECT_PROP_DESC_CHANGED = 0xC802;
+    public static final int EVENT_OBJECT_REFERENCES_CHANGED = 0xC803;
+
+    private int mEventCode = EVENT_UNDEFINED;
 
     /**
      * Returns event code of MTP event.
-     *
+     * See the USB-IF MTP specification for the details of event constants.
      * @return event code
      */
     public int getEventCode() { return mEventCode; }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
index de35cef..4fc3788 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
@@ -102,6 +102,7 @@
         mRecentsRoot.authority = null;
         mRecentsRoot.rootId = null;
         mRecentsRoot.derivedIcon = R.drawable.ic_root_recent;
+        mRecentsRoot.derivedType = RootInfo.TYPE_RECENTS;
         mRecentsRoot.flags = Root.FLAG_LOCAL_ONLY | Root.FLAG_SUPPORTS_CREATE
                 | Root.FLAG_SUPPORTS_IS_CHILD;
         mRecentsRoot.title = mContext.getString(R.string.root_recent);
diff --git a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
index d778c98..0b8da83 100644
--- a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
@@ -23,6 +23,8 @@
     android:layout_width="@dimen/notification_panel_width"
     android:layout_height="@dimen/status_bar_header_height"
     android:layout_gravity="@integer/notification_panel_layout_gravity"
+    android:paddingStart="@dimen/notification_side_padding"
+    android:paddingEnd="@dimen/notification_side_padding"
     android:baselineAligned="false"
     android:elevation="4dp"
     android:background="@drawable/notification_header_bg"
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index a64dbbd..bfa13e2 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -102,8 +102,7 @@
         android:id="@+id/status_bar_header"
         android:layout_width="@dimen/notification_panel_width"
         android:layout_height="@dimen/status_bar_header_height"
-        android:layout_marginStart="@dimen/notification_side_padding"
-        android:layout_marginEnd="@dimen/notification_side_padding" />
+        android:layout_gravity="@integer/notification_panel_layout_gravity" />
 
     <com.android.systemui.statusbar.AlphaOptimizedView
         android:id="@+id/qs_navbar_scrim"
diff --git a/packages/SystemUI/res/layout/status_bar_expanded_header.xml b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
index dd75dbf..5eca471 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
@@ -23,6 +23,8 @@
     android:layout_width="@dimen/notification_panel_width"
     android:layout_height="@dimen/status_bar_header_height"
     android:layout_gravity="@integer/notification_panel_layout_gravity"
+    android:paddingStart="@dimen/notification_side_padding"
+    android:paddingEnd="@dimen/notification_side_padding"
     android:baselineAligned="false"
     android:elevation="4dp"
     android:background="@drawable/notification_header_bg"
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index c7c7f1a..4d07cdb 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -439,6 +439,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Wys horlosiesekondes op die statusbalk. Sal batterylewe dalk beïnvloed."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Herrangskik Kitsinstellings"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Wys helderheid in Kitsinstellings"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"Gebruik verdeling in Kitsinstellings"</string>
     <string name="experimental" msgid="6198182315536726162">"Eksperimenteel"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index f49f5bc..c1180b6 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -439,6 +439,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"የሰዓት ሰከንዶችን በሁኔታ አሞሌ ውስጥ አሳይ። በባትሪ ዕድሜ ላይ ተጽዕኖ ሊኖርው ይችል ይሆናል።"</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"ፈጣን ቅንብሮችን ዳግም ያደራጁ"</string>
     <string name="show_brightness" msgid="6613930842805942519">"በፈጣን ቅንብሮች ውስጥ ብሩህነትን አሳይ"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"በፈጣን ቅንብሮች ውስጥ ምልክት መጥሪያን ይጠቀሙ"</string>
     <string name="experimental" msgid="6198182315536726162">"የሙከራ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index aaf20cc..fc2941f 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -443,6 +443,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"عرض ثواني الساعة في شريط الحالة. قد يؤثر ذلك في عمر البطارية."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"إعادة ترتيب الإعدادات السريعة"</string>
     <string name="show_brightness" msgid="6613930842805942519">"عرض السطوع في الإعدادات السريعة"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"استخدام ترقيم الصفحات في الإعدادات السريعة"</string>
     <string name="experimental" msgid="6198182315536726162">"إعدادات تجريبية"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-az-rAZ/strings.xml b/packages/SystemUI/res/values-az-rAZ/strings.xml
index 0efc82b..04d680b 100644
--- a/packages/SystemUI/res/values-az-rAZ/strings.xml
+++ b/packages/SystemUI/res/values-az-rAZ/strings.xml
@@ -439,6 +439,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Saatın saniyəsini status panelində göstərin. Batareyaya təsir edə bilər."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Sürətli Ayarları yenidən tənzimləyin"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Sürətli ayarlarda parlaqlılığı göstərin"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"Sürətli Ayarlarda səhifə nömrələməsindən istifadə edin"</string>
     <string name="experimental" msgid="6198182315536726162">"Eksperimental"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 6805779..ca45d24 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -439,6 +439,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Показване на секундите на часовника в лентата на състоянието. Може да се отрази на живота на батерията."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Пренареждане на бързите настройки"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Показване на яркостта от бързите настройки"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"Използване на разделянето на страници от бързите настройки"</string>
     <string name="experimental" msgid="6198182315536726162">"Експериментални"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-bn-rBD/strings.xml b/packages/SystemUI/res/values-bn-rBD/strings.xml
index c0ffe2c..7df68ac 100644
--- a/packages/SystemUI/res/values-bn-rBD/strings.xml
+++ b/packages/SystemUI/res/values-bn-rBD/strings.xml
@@ -439,6 +439,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"স্থিতি দন্ডে ঘড়ির সেকেন্ড দেখায়৷ ব্যাটারি লাইফকে প্রভাবিত করতে পারে৷"</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"দ্রুত সেটিংসে পুনরায় সাজান"</string>
     <string name="show_brightness" msgid="6613930842805942519">"দ্রুত সেটিংসে উজ্জ্বলতা দেখান"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"দ্রুত সেটিংসে পেজিং ব্যবহার করুন"</string>
     <string name="experimental" msgid="6198182315536726162">"পরীক্ষামূলক"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 2a7c326..c85fac6 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -441,6 +441,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Mostra els segons del rellotge a la barra d\'estat. Això pot afectar la durada de la bateria."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Torna a ordenar la Configuració ràpida"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Mostra la brillantor a la Configuració ràpida"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"Utilitza la paginació a la Configuració ràpida"</string>
     <string name="experimental" msgid="6198182315536726162">"Experimental"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 18fd994..d58b11b 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -443,6 +443,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Na stavovém řádku se bude zobrazovat sekundová ručička. Může být ovlivněna výdrž baterie."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Změnit uspořádání Rychlého nastavení"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Zobrazit jas v Rychlém nastavení"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"Použít v Rychlém nastavení stránkování"</string>
     <string name="experimental" msgid="6198182315536726162">"Experimentální"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 5a2dd33..f300b3e 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -439,6 +439,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Vis sekunder i statuslinjen. Dette kan påvirke batteriets levetid."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Omarranger Hurtige indstillinger"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Vis lysstyrke i Hurtige indstillinger"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"Brug sidelayout i Hurtige indstillinger"</string>
     <string name="experimental" msgid="6198182315536726162">"Eksperimentel"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index a8143a4..ac513e4 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -441,6 +441,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Uhrsekunden in der Statusleiste anzeigen. Kann sich auf die Akkulaufzeit auswirken."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Schnelleinstellungen neu anordnen"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Helligkeit in den Schnelleinstellungen anzeigen"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"Seitenlayout in den Schnelleinstellungen verwenden"</string>
     <string name="experimental" msgid="6198182315536726162">"Experimentell"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 6031d3b..c8ff7c6 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -441,6 +441,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Εμφάνιση δευτερολέπτων ρολογιού στη γραμμή κατάστασης. Ενδέχεται να επηρεάσει τη διάρκεια ζωής της μπαταρίας."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Αναδιάταξη Γρήγορων ρυθμίσεων"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Εμφάνιση φωτεινότητας στις Γρήγορες ρυθμίσεις"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"Χρήση τηλεειδοποίησης στις Γρήγορες ρυθμίσεις"</string>
     <string name="experimental" msgid="6198182315536726162">"Σε πειραματικό στάδιο"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index bef7661..6e66842 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -439,6 +439,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Show clock seconds in the status bar. May impact battery life."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Rearrange Quick Settings"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Show brightness in Quick Settings"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"Use paging in Quick Settings"</string>
     <string name="experimental" msgid="6198182315536726162">"Experimental"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index bef7661..6e66842 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -439,6 +439,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Show clock seconds in the status bar. May impact battery life."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Rearrange Quick Settings"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Show brightness in Quick Settings"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"Use paging in Quick Settings"</string>
     <string name="experimental" msgid="6198182315536726162">"Experimental"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index bef7661..6e66842 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -439,6 +439,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Show clock seconds in the status bar. May impact battery life."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Rearrange Quick Settings"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Show brightness in Quick Settings"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"Use paging in Quick Settings"</string>
     <string name="experimental" msgid="6198182315536726162">"Experimental"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en/donottranslate.xml b/packages/SystemUI/res/values-en/donottranslate.xml
deleted file mode 100644
index 9f04e1f..0000000
--- a/packages/SystemUI/res/values-en/donottranslate.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2015 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License
-  -->
-
-<resources>
-    <!-- DO NOT TRANSLATE - temporary hack to show the speed-less label if no translation is available -->
-    <item type="string" name="keyguard_indication_charging_time_fast_if_translated">@string/keyguard_indication_charging_time_fast</item>
-    <!-- DO NOT TRANSLATE - temporary hack to show the speed-less label if no translation is available -->
-    <item type="string" name="keyguard_indication_charging_time_slowly_if_translated">@string/keyguard_indication_charging_time_slowly</item>
-</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 1590265..72258fa 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -441,6 +441,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Muestra los segundos del reloj en la barra de estado. Puede afectar la duración de la batería."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Reorganizar la Configuración rápida"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Mostrar el brillo en la Configuración rápida"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"Usar la paginación en la Configuración rápida"</string>
     <string name="experimental" msgid="6198182315536726162">"Experimental"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 082e762..298a0c6 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -439,6 +439,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Muestra los segundos del reloj en la barra de estado. Puede afectar a la duración de la batería."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Reorganizar Ajustes rápidos"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Mostrar brillo en Ajustes rápidos"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"Utilizar paginación en Ajustes rápidos"</string>
     <string name="experimental" msgid="6198182315536726162">"Experimental"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-et-rEE/strings.xml b/packages/SystemUI/res/values-et-rEE/strings.xml
index 4add147..26b3081 100644
--- a/packages/SystemUI/res/values-et-rEE/strings.xml
+++ b/packages/SystemUI/res/values-et-rEE/strings.xml
@@ -439,6 +439,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Olekuribal kella sekundite kuvamine. See võib mõjutada aku kasutusaega."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Korralda kiirseaded ümber"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Kuva kiirseadetes heledus"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"Kasuta kiirseadetes lehe paigutust"</string>
     <string name="experimental" msgid="6198182315536726162">"Eksperimentaalne"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-eu-rES/strings.xml b/packages/SystemUI/res/values-eu-rES/strings.xml
index 4f5c9f2..83aac20 100644
--- a/packages/SystemUI/res/values-eu-rES/strings.xml
+++ b/packages/SystemUI/res/values-eu-rES/strings.xml
@@ -439,6 +439,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Erakutsi erlojuko segundoak egoera-barran. Baliteke bateria gehiago erabiltzea."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Berrantolatu ezarpen bizkorrak"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Erakutsi distira Ezarpen bizkorretan"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"Erabili orriak pasatzeko diseinu berria Ezarpen bizkorretan"</string>
     <string name="experimental" msgid="6198182315536726162">"Esperimentala"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 6fa7e1c..c8871c4 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -67,12 +67,12 @@
     <string name="usb_debugging_secondary_user_message" msgid="8572228137833020196">"‏کاربری که درحال‌حاضر در این دستگاه وارد سیستم شده نمی‌تواند اشکال‌زدای USB را روشن کند. برای استفاده از این ویژگی، لطفاً به کاربر «سرپرست» تغییر حالت دهید."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"بزرگ‌نمایی برای پر کردن صفحه"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"گسترده کردن برای پر کردن صفحه"</string>
-    <string name="screenshot_saving_ticker" msgid="7403652894056693515">"در حال ذخیره تصویر صفحه..."</string>
-    <string name="screenshot_saving_title" msgid="8242282144535555697">"در حال ذخیره تصویر صفحه..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"تصویر صفحه ذخیره شد."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"تصویر صفحه گرفته شد."</string>
+    <string name="screenshot_saving_ticker" msgid="7403652894056693515">"در حال ذخیره عکس صفحه‌نمایش..."</string>
+    <string name="screenshot_saving_title" msgid="8242282144535555697">"در حال ذخیره عکس صفحه‌نمایش..."</string>
+    <string name="screenshot_saving_text" msgid="2419718443411738818">"عکس صفحه‌نمایش ذخیره شد."</string>
+    <string name="screenshot_saved_title" msgid="6461865960961414961">"عکس صفحه‌نمایش گرفته شد."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"برای مشاهده عکس صفحه‌نمایشتان، لمس کنید."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"تصویر صفحه گرفته نشد."</string>
+    <string name="screenshot_failed_title" msgid="705781116746922771">"عکس صفحه‌نمایش گرفته نشد."</string>
     <string name="screenshot_failed_text" msgid="1260203058661337274">"به دلیل فضای ذخیره‌سازی کم یا عدم اجازه برنامه یا سازمانتان، نمی‌توان از صفحه عکس گرفت."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"‏گزینه‌های انتقال فایل USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"‏نصب به‌عنوان دستگاه پخش رسانه (MTP)"</string>
@@ -439,6 +439,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"ثانیه‌های ساعت را در نوار وضعیت نشان می‌دهد. ممکن است بر ماندگاری باتری تأثیر بگذارد."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"ترتیب مجدد در تنظیمات سریع"</string>
     <string name="show_brightness" msgid="6613930842805942519">"نمایش روشنایی در تنظیمات سریع"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"استفاده از صفحه‌بندی در تنظیمات سریع"</string>
     <string name="experimental" msgid="6198182315536726162">"آزمایشی"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 655cf31..3154d5c 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -439,6 +439,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Näytä sekunnit tilapalkin kellossa. Tämä voi vaikuttaa akun kestoon."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Järjestä pika-asetukset uudelleen"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Näytä kirkkaus pika-asetuksissa"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"Käytä sivutusta pika-asetuksissa"</string>
     <string name="experimental" msgid="6198182315536726162">"Kokeellinen"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 2f2c331..669ca9b 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -441,6 +441,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Afficher les secondes sur l\'horloge dans la barre d\'état. Cela peut réduire l\'autonomie de la pile."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Réorganiser les paramètres rapides"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Afficher la luminosité dans les paramètres rapides"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"Utiliser la pagination dans les paramètres rapides"</string>
     <string name="experimental" msgid="6198182315536726162">"Fonctions expérimentales"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 9f34431..d42190f 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -441,6 +441,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Afficher les secondes dans la barre d\'état. Cela risque de réduire l\'autonomie de la batterie."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Réorganiser la fenêtre de configuration rapide"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Afficher la luminosité dans fenêtre de configuration rapide"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"Utiliser mise en page dans fenêtre de configuration rapide"</string>
     <string name="experimental" msgid="6198182315536726162">"Paramètres expérimentaux"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-gl-rES/strings.xml b/packages/SystemUI/res/values-gl-rES/strings.xml
index df90ef4..3c53983 100644
--- a/packages/SystemUI/res/values-gl-rES/strings.xml
+++ b/packages/SystemUI/res/values-gl-rES/strings.xml
@@ -441,6 +441,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Mostra os segundos do reloxo na barra de estado. Pode influír na duración da batería."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Reorganizar Configuración rápida"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Mostrar brillo en Configuración rápida"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"Utilizar paxinación en Configuración rápida"</string>
     <string name="experimental" msgid="6198182315536726162">"Experimental"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-gu-rIN/strings.xml b/packages/SystemUI/res/values-gu-rIN/strings.xml
index 42ee460..0887e75 100644
--- a/packages/SystemUI/res/values-gu-rIN/strings.xml
+++ b/packages/SystemUI/res/values-gu-rIN/strings.xml
@@ -439,6 +439,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"ઘડિયાળ સેકન્ડ સ્થિતિ બારમાં બતાવો. બૅટરીની આવરદા પર અસર કરી શકે છે."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"ઝડપી સેટિંગ્સને ફરીથી ગોઠવો"</string>
     <string name="show_brightness" msgid="6613930842805942519">"ઝડપી સેટિંગ્સમાં તેજ બતાવો"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"ઝડપી સેટિંગ્સમાં પૃષ્ઠાંકનનો ઉપયોગ કરો"</string>
     <string name="experimental" msgid="6198182315536726162">"પ્રાયોગિક"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 86f536d..11a0d3a 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -439,6 +439,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"स्थिति बार में घड़ी के सेकंड दिखाएं. इससे बैटरी के जीवनकाल पर प्रभाव पड़ सकता है."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"त्वरित सेटिंग को पुन: व्यवस्थित करें"</string>
     <string name="show_brightness" msgid="6613930842805942519">"त्वरित सेटिंग में स्क्रीन की रोशनी दिखाएं"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"त्वरित सेटिंग में पेजिंग का उपयोग करें"</string>
     <string name="experimental" msgid="6198182315536726162">"प्रयोगात्मक"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 043e7ad..eec3a6f 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -440,6 +440,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Prikazuju se sekunde na satu na traci statusa. Može utjecati na trajanje baterije."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Promijeni raspored Brzih postavki"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Prikaži svjetlinu u Brzim postavkama"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"Upotrijebi redni broj stranice u Brzim postavkama"</string>
     <string name="experimental" msgid="6198182315536726162">"Eksperimentalno"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index e2b0812..2dc9ba0 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -439,6 +439,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Másodpercek megjelenítése az állapotsor óráján. Ez hatással lehet az akkumulátor üzemidejére."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Gyorsbeállítások átrendezése"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Fényerő megjelenítése a gyorsbeállításokban"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"Oldalelrendezés használata a gyorsbeállításokban"</string>
     <string name="experimental" msgid="6198182315536726162">"Kísérleti"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml
index b69fc0f..a7fdb43 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings.xml
+++ b/packages/SystemUI/res/values-hy-rAM/strings.xml
@@ -439,6 +439,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Ցույց տալ ժամացույցի վայրկյանները կարգավիճակի տողում: Կարող է ազդել մարտկոցի աշխատանքի ժամանակի վրա:"</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Վերադասավորել Արագ կարգավորումները"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Ցույց տալ պայծառությունն Արագ կարգավորումներում"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"Օգտագործել էջերի դասավորությունը Արագ կարգավորումներում"</string>
     <string name="experimental" msgid="6198182315536726162">"Փորձնական"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 7dbcda9..a6a68d4 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -439,6 +439,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Tampilkan detik jam di bilah status. Dapat memengaruhi masa pakai baterai."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Atur Ulang Setelan Cepat"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Tampilkan kecerahan di Setelan Cepat"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"Gunakan pembagian laman di Setelan Cepat"</string>
     <string name="experimental" msgid="6198182315536726162">"Eksperimental"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-is-rIS/strings.xml b/packages/SystemUI/res/values-is-rIS/strings.xml
index b28b6fd..83468e5 100644
--- a/packages/SystemUI/res/values-is-rIS/strings.xml
+++ b/packages/SystemUI/res/values-is-rIS/strings.xml
@@ -439,6 +439,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Sýna sekúndur á klukku í stöðustikunni. Getur haft áhrif á endingu rafhlöðu."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Endurraða flýtistillingum"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Sýna birtustig í flýtistillingum"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"Nota síðuskoðun í flýtistillingum"</string>
     <string name="experimental" msgid="6198182315536726162">"Tilraunastillingar"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 54e6f56..4449a0a 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -441,6 +441,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Mostra i secondi nell\'orologio nella barra di stato. Ciò potrebbe ridurre la durata della carica della batteria."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Riorganizza Impostazioni rapide"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Mostra luminosità in Impostazioni rapide"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"Utilizza nuovo layout in Impostazioni rapide"</string>
     <string name="experimental" msgid="6198182315536726162">"Sperimentali"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index c959feb..31c5126 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -441,6 +441,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"הצג שניות בשעון בשורת הסטטוס. פעולה זו עשויה להשפיע על אורך חיי הסוללה."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"סידור מחדש של הגדרות מהירות"</string>
     <string name="show_brightness" msgid="6613930842805942519">"הצג בהירות בהגדרות מהירות"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"השתמש באפשרות הדפדוף בהגדרות המהירות"</string>
     <string name="experimental" msgid="6198182315536726162">"ניסיוניות"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 29476d8..d1603ff 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -441,6 +441,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"ステータスバーに時計の秒を表示します。電池使用量に影響する可能性があります。"</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"クイック設定を並べ替え"</string>
     <string name="show_brightness" msgid="6613930842805942519">"クイック設定に明るさ調整バーを表示する"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"クイック設定でページ設定を使用する"</string>
     <string name="experimental" msgid="6198182315536726162">"試験運用版"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ka-rGE/strings.xml b/packages/SystemUI/res/values-ka-rGE/strings.xml
index d83c9e9..e5e9003 100644
--- a/packages/SystemUI/res/values-ka-rGE/strings.xml
+++ b/packages/SystemUI/res/values-ka-rGE/strings.xml
@@ -439,6 +439,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"საათის წამების ჩვენება სტატუსის ზოლში. შეიძლება გავლენა იქონიოს ბატარეაზე."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"სწრაფი პარამეტრების გადაწყობა"</string>
     <string name="show_brightness" msgid="6613930842805942519">"სიკაშკაშის ჩვენება სწრაფ პარამეტრებში"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"გამოიყენეთ გვერდების დანომვრა სწრაფ პარამეტრებში"</string>
     <string name="experimental" msgid="6198182315536726162">"ექსპერიმენტული"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-kk-rKZ/strings.xml b/packages/SystemUI/res/values-kk-rKZ/strings.xml
index 5c066b3..946d86b 100644
--- a/packages/SystemUI/res/values-kk-rKZ/strings.xml
+++ b/packages/SystemUI/res/values-kk-rKZ/strings.xml
@@ -439,6 +439,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Күйін көрсету жолағында сағат секундтарын көрсету. Батареяның қызмет көрсету мерзіміне әсер етуі мүмкін."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Жылдам параметрлерді қайта реттеу"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Жылдам параметрлерде жарықтықты көрсету"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"Жылдам параметрлерде беттерді нөмірлеуді пайдалану"</string>
     <string name="experimental" msgid="6198182315536726162">"Эксперименттік"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml
index 4c469b0..264438b 100644
--- a/packages/SystemUI/res/values-km-rKH/strings.xml
+++ b/packages/SystemUI/res/values-km-rKH/strings.xml
@@ -439,6 +439,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"បង្ហាញវិនាទីនៅលើរបារស្ថានភាពអាចនឹងប៉ះពាល់ដល់ថាមពលថ្ម។"</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"រៀបចំការកំណត់រហ័សឡើងវិញ"</string>
     <string name="show_brightness" msgid="6613930842805942519">"បង្ហាញកម្រិតពន្លឺនៅក្នុងការកំណត់រហ័ស"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"ប្រើការចុះទំព័រនៅក្នុងការកំណត់រហ័ស"</string>
     <string name="experimental" msgid="6198182315536726162">"ពិសោធន៍"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-kn-rIN/strings.xml b/packages/SystemUI/res/values-kn-rIN/strings.xml
index 4215a91..1696076 100644
--- a/packages/SystemUI/res/values-kn-rIN/strings.xml
+++ b/packages/SystemUI/res/values-kn-rIN/strings.xml
@@ -439,6 +439,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"ಸ್ಥಿತಿ ಪಟ್ಟಿಯಲ್ಲಿ ಗಡಿಯಾರ ಸೆಕೆಂಡುಗಳನ್ನು ತೋರಿಸು. ಇದಕ್ಕೆ ಬ್ಯಾಟರಿ ಬಾಳಿಕೆಯು ಪರಿಣಾಮಬೀರಬಹುದು."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"ತ್ವರಿತ ಸೆಟ್ಟಿಂಗ್‌‌ಗಳನ್ನು ಮರುಹೊಂದಿಸಿ"</string>
     <string name="show_brightness" msgid="6613930842805942519">"ತ್ವರಿತ ಸೆಟ್ಟಿಂಗ್‌‌ಗಳಲ್ಲಿ ಪ್ರಖರತೆಯನ್ನು ತೋರಿಸಿ"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"ತ್ವರಿತ ಸೆಟ್ಟಿಂಗ್‌‌ಗಳಲ್ಲಿ ಪುಟಗಳನ್ನು ಬಳಸಿ"</string>
     <string name="experimental" msgid="6198182315536726162">"ಪ್ರಾಯೋಗಿಕ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 8ee5946..d053b53 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -439,6 +439,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"상태 표시줄에 시계 초 단위를 표시합니다. 배터리 수명에 영향을 줄 수도 있습니다."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"빠른 설정 재정렬"</string>
     <string name="show_brightness" msgid="6613930842805942519">"빠른 설정에서 밝기 표시"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"빠른 설정에서 페이지 레이아웃 사용"</string>
     <string name="experimental" msgid="6198182315536726162">"베타"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ky-rKG/strings.xml b/packages/SystemUI/res/values-ky-rKG/strings.xml
index ce0afd4..ec4bec7 100644
--- a/packages/SystemUI/res/values-ky-rKG/strings.xml
+++ b/packages/SystemUI/res/values-ky-rKG/strings.xml
@@ -439,6 +439,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Абал тилкесинен сааттын секунддары көрсөтүлсүн. Батареянын кубаты көбүрөөк сарпталышы мүмкүн."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Ыкчам жөндөөлөрдү кайра коюу"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Ыкчам жөндөөлөрдөн жарык деңгээлин көрсөтүү"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"Ыкчам жөндөөлөрдөн баракты номерлөөнү колдонуу"</string>
     <string name="experimental" msgid="6198182315536726162">"Сынамык"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-lo-rLA/strings.xml b/packages/SystemUI/res/values-lo-rLA/strings.xml
index b45395e..e5d784f 100644
--- a/packages/SystemUI/res/values-lo-rLA/strings.xml
+++ b/packages/SystemUI/res/values-lo-rLA/strings.xml
@@ -439,6 +439,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"ສະ​ແດງວິ​ນາ​ທີ​ໂມງ​ຢູ່​ໃນ​ແຖບ​ສະ​ຖາ​ນະ. ອາດ​ຈະ​ມີ​ຜົນ​ກະ​ທົບ​ຕໍ່​ອາ​ຍຸ​ແບັດ​ເຕີ​ຣີ."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"ຈັດ​ວາງ​ການ​ຕັ້ງ​ຄ່າ​ດ່ວນ​ຄືນ​ໃໝ່"</string>
     <string name="show_brightness" msgid="6613930842805942519">"ສະ​ແດງ​ຄວາມ​ແຈ້ງ​ຢູ່​ໃນ​ການ​ຕັ້ງ​ຄ່າ​ດ່ວນ"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"ໃຊ້​ການ​ໃສ່​ໜ້າ​ຢູ່​ໃນ​ການ​ຕັ້ງ​ຄ່າ​ດ່ວນ"</string>
     <string name="experimental" msgid="6198182315536726162">"ຍັງຢູ່ໃນການທົດລອງ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 194668b..ca50956 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -441,6 +441,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Rodyti laikrodžio sekundes būsenos juostoje. Tai gali paveikti akumuliatoriaus naudojimo laiką."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Pertvarkyti sparčiuosius nustatymus"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Rodyti skaistį sparčiuosiuose nustatymuose"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"Naudoti puslapių kaitą sparčiuosiuose nustatymuose"</string>
     <string name="experimental" msgid="6198182315536726162">"Eksperimentinė versija"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 2b3be58..a87d918 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -440,6 +440,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Statusa joslā rādīt pulksteņa sekundes. Var ietekmēt akumulatora darbības laiku."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Pārkārtot ātros iestatījumus"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Rādīt spilgtumu ātrajos iestatījumos"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"Izmantot lapošanu ātrajos iestatījumos"</string>
     <string name="experimental" msgid="6198182315536726162">"Eksperimentāli"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-mk-rMK/strings.xml b/packages/SystemUI/res/values-mk-rMK/strings.xml
index 912c30f..1015018 100644
--- a/packages/SystemUI/res/values-mk-rMK/strings.xml
+++ b/packages/SystemUI/res/values-mk-rMK/strings.xml
@@ -441,6 +441,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Прикажи ги секундите на часовникот на статусната лента. Може да влијае на траењето на батеријата."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Преуредете ги Брзи поставки"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Прикажете ја осветленоста во Брзи поставки"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"Користете прелистување страници во Брзи поставки"</string>
     <string name="experimental" msgid="6198182315536726162">"Експериментално"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ml-rIN/strings.xml b/packages/SystemUI/res/values-ml-rIN/strings.xml
index c85ecc7..45ec29a 100644
--- a/packages/SystemUI/res/values-ml-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ml-rIN/strings.xml
@@ -439,6 +439,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"സ്റ്റാറ്റസ് ബാറിൽ ക്ലോക്ക് സെക്കൻഡ് കാണിക്കുന്നത് ബാറ്ററിയുടെ ലൈഫിനെ ബാധിക്കാം."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"ദ്രുത ക്രമീകരണം പുനഃസജ്ജീകരിക്കുക"</string>
     <string name="show_brightness" msgid="6613930842805942519">"ദ്രുത ക്രമീകരണത്തിൽ തെളിച്ചം കാണിക്കുക"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"ദ്രുത്ര ക്രമീകരണത്തിൽ പേജിംഗ് ഉപയോഗിക്കുക"</string>
     <string name="experimental" msgid="6198182315536726162">"പരീക്ഷണാത്മകം!"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-mn-rMN/strings.xml b/packages/SystemUI/res/values-mn-rMN/strings.xml
index 6b29aff..1051e49 100644
--- a/packages/SystemUI/res/values-mn-rMN/strings.xml
+++ b/packages/SystemUI/res/values-mn-rMN/strings.xml
@@ -437,6 +437,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Статус талбарт цагийн секундыг харуулах. Энэ нь тэжээлийн цэнэгт нөлөөлж болно."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Түргэн тохиргоог дахин засварлах"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Түргэн тохиргоонд гэрэлтүүлэг харах"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"Хуудаслалтыг түргэн тохиргоонд ашиглаарай"</string>
     <string name="experimental" msgid="6198182315536726162">"Туршилтын"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-mr-rIN/strings.xml b/packages/SystemUI/res/values-mr-rIN/strings.xml
index 9d518a0..66843fc 100644
--- a/packages/SystemUI/res/values-mr-rIN/strings.xml
+++ b/packages/SystemUI/res/values-mr-rIN/strings.xml
@@ -439,6 +439,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"स्टेटस बारमध्‍ये घड्‍याळ सेकंद दर्शवा. कदाचित बॅटरी आयुष्‍य प्रभावित होऊ शकते."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"द्रुत सेटिंग्जची पुनर्रचना करा"</string>
     <string name="show_brightness" msgid="6613930842805942519">"द्रुत सेटिंग्जमध्‍ये चमक दर्शवा"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"द्रुत सेटिंग्जमध्ये लिखाण वापरा"</string>
     <string name="experimental" msgid="6198182315536726162">"प्रायोगिक"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml
index 10dca3e..c50e214 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings.xml
@@ -439,6 +439,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Tunjukkan saat jam dalam bar status. Mungkin menjejaskan hayat bateri."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Susun Semula Tetapan Pantas"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Tunjukkan kecerahan dalam Tetapan Pantas"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"Gunakan penghalaman dalam Tetapan Pantas"</string>
     <string name="experimental" msgid="6198182315536726162">"Percubaan"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-my-rMM/strings.xml b/packages/SystemUI/res/values-my-rMM/strings.xml
index adfd9f8..f4fd3d1 100644
--- a/packages/SystemUI/res/values-my-rMM/strings.xml
+++ b/packages/SystemUI/res/values-my-rMM/strings.xml
@@ -439,6 +439,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"အခြေအနေပြနေရာမှာ နာရီ စက္ကန့်များကို ပြပါ။ ဘက်ထရီ သက်တမ်းကို အကျိုးသက်ရောက်နိုင်တယ်။"</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"အမြန် ဆက်တင်များကို ပြန်စီစဉ်ရန်"</string>
     <string name="show_brightness" msgid="6613930842805942519">"အမြန် ဆက်တင်များထဲက တောက်ပမှုကို ပြရန်"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"အမြန် ဆက်တင်များထဲတွင် စာမျက်နှာ ပုံစံချမှုကို အသုံးပြုပါ"</string>
     <string name="experimental" msgid="6198182315536726162">"စမ်းသပ်ရေး"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index ecfb7f2..cae404d 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -439,6 +439,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Vis sekunder i statusfeltet på klokken. Det kan påvirke batteritiden."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Omorganiser hurtiginnstillingene"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Vis lysstyrke i hurtiginnstillingene"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"Bruk sidetall i hurtiginnstillingene"</string>
     <string name="experimental" msgid="6198182315536726162">"På forsøksstadiet"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ne-rNP/strings.xml b/packages/SystemUI/res/values-ne-rNP/strings.xml
index d997aff..563bc87 100644
--- a/packages/SystemUI/res/values-ne-rNP/strings.xml
+++ b/packages/SystemUI/res/values-ne-rNP/strings.xml
@@ -439,6 +439,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"वस्तुस्थिति पट्टीको घडीमा सेकेन्ड देखाउनुहोस्। ब्याट्री आयु प्रभावित हुन सक्छ।"</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"द्रुत सेटिङहरू पुनः व्यवस्थित गर्नुहोस्"</string>
     <string name="show_brightness" msgid="6613930842805942519">"द्रुत सेटिङहरूमा उज्यालो देखाउनुहोस्"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"द्रुत सेटिङहरूमा पेजिंग प्रयोग गर्नुहोस्"</string>
     <string name="experimental" msgid="6198182315536726162">"प्रयोगात्मक"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index c6bab06..bf9f0f2 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -439,6 +439,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Klokseconden op de statusbalk weergeven. Kan van invloed zijn op de accuduur."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Snelle instellingen opnieuw indelen"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Helderheid weergeven in Snelle instellingen"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"Paginering gebruiken in Snelle instellingen"</string>
     <string name="experimental" msgid="6198182315536726162">"Experimenteel"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pa-rIN/strings.xml b/packages/SystemUI/res/values-pa-rIN/strings.xml
index 74e5fcb..45d56cc 100644
--- a/packages/SystemUI/res/values-pa-rIN/strings.xml
+++ b/packages/SystemUI/res/values-pa-rIN/strings.xml
@@ -439,6 +439,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"ਸਥਿਤੀ ਬਾਰ ਵਿੱਚ ਘੜੀ ਸਕਿੰਟ ਦਿਖਾਓ। ਬੈਟਰੀ ਸਮਰੱਥਾ ਤੇ ਅਸਰ ਪੈ ਸਕਦਾ ਹੈ।"</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"ਤਤਕਾਲ ਸੈਟਿੰਗਾਂ ਨੂੰ ਦੁਬਾਰਾ ਕ੍ਰਮ ਦਿਓ"</string>
     <string name="show_brightness" msgid="6613930842805942519">"ਤਤਕਾਲ ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਚਮਕ ਦਿਖਾਓ"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"ਤਤਕਾਲ ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਪੇਜਿੰਗ ਵਰਤੋ"</string>
     <string name="experimental" msgid="6198182315536726162">"ਪ੍ਰਯੋਗਾਤਮਿਕ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index e04fd71..2807c5a 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -441,6 +441,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Pokaż sekundy na zegarku na pasku stanu. Może mieć wpływ na czas pracy baterii."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Uporządkuj Szybkie ustawienia"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Pokaż jasność w Szybkich ustawieniach"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"Użyj stronicowania w Szybkich ustawieniach"</string>
     <string name="experimental" msgid="6198182315536726162">"Eksperymentalne"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 2a8e3ab..c8400c9 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -441,6 +441,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Mostrar segundos do relógio na barra de status. Pode afetar a duração da bateria."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Reorganizar \"Configurações rápidas\""</string>
     <string name="show_brightness" msgid="6613930842805942519">"Mostrar brilho nas \"Configurações rápidas\""</string>
-    <string name="qs_paging" msgid="7020133150248666132">"Usar paginação nas \"Configurações rápidas\""</string>
     <string name="experimental" msgid="6198182315536726162">"Experimentais"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 8453e5b..43088fe9 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -439,6 +439,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Mostrar segundos do relógio na barra de estado. Pode afetar a autonomia da bateria."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Reorganizar as Definições rápidas"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Mostrar luminosidade nas Definições rápidas"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"Utilizar paginação nas Definições rápidas"</string>
     <string name="experimental" msgid="6198182315536726162">"Experimental"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 2a8e3ab..c8400c9 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -441,6 +441,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Mostrar segundos do relógio na barra de status. Pode afetar a duração da bateria."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Reorganizar \"Configurações rápidas\""</string>
     <string name="show_brightness" msgid="6613930842805942519">"Mostrar brilho nas \"Configurações rápidas\""</string>
-    <string name="qs_paging" msgid="7020133150248666132">"Usar paginação nas \"Configurações rápidas\""</string>
     <string name="experimental" msgid="6198182315536726162">"Experimentais"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index de693f5..d64ca7c 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -440,6 +440,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Afișează secundele pe ceas în bara de stare. Poate afecta autonomia bateriei."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Rearanjați Setările rapide"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Afișați luminozitatea în Setările rapide"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"Folosiți paginarea în Setările rapide"</string>
     <string name="experimental" msgid="6198182315536726162">"Experimentale"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 39d8617..480de30 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -443,6 +443,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Показывать в строке состояния время с точностью до секунды (заряд батареи может расходоваться быстрее)."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Изменить порядок Быстрых настроек"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Добавить яркость в Быстрые настройки"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"Разбить Быстрые настройки на страницы"</string>
     <string name="experimental" msgid="6198182315536726162">"Экспериментальная функция"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-si-rLK/strings.xml b/packages/SystemUI/res/values-si-rLK/strings.xml
index 51bb047..e784601 100644
--- a/packages/SystemUI/res/values-si-rLK/strings.xml
+++ b/packages/SystemUI/res/values-si-rLK/strings.xml
@@ -439,6 +439,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"තත්ත්ව තීරුවෙහි ඔරලෝසු තත්පර පෙන්වන්න. බැටරි ආයු කාලයට බලපෑමට හැකිය."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"ඉක්මන් සැකසීම් යළි පිළිවෙළට සකසන්න"</string>
     <string name="show_brightness" msgid="6613930842805942519">"ඉක්මන් සැකසීම්වල දීප්තිය පෙන්වන්න"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"ඉක්මන් සැකසීම්වල පිටු පිරිසැලසුම් භාවිත කරන්න"</string>
     <string name="experimental" msgid="6198182315536726162">"පරීක්ෂණාත්මක"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 2886e36..15612ee 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -443,6 +443,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Zobrazí sekundy v stavovom riadku. Môže to ovplyvňovať výdrž batérie."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Zmeniť usporiadanie Rýchlych nastavení"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Zobraziť jas v Rýchlych nastaveniach"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"Použite stránkovanie v Rýchlych nastaveniach"</string>
     <string name="experimental" msgid="6198182315536726162">"Experimentálne"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index e325ef1..23e4233 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -441,6 +441,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Prikaže sekunde pri uri v vrstici stanja. To lahko vpliva na čas delovanja pri akumulatorskem napajanju."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Preuredi hitre nastavitve"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Prikaz svetlosti v hitrih nastavitvah"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"Uporaba postavitve strani v hitrih nastavitvah"</string>
     <string name="experimental" msgid="6198182315536726162">"Poskusno"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sq-rAL/strings.xml b/packages/SystemUI/res/values-sq-rAL/strings.xml
index 5bcf941..771ad53 100644
--- a/packages/SystemUI/res/values-sq-rAL/strings.xml
+++ b/packages/SystemUI/res/values-sq-rAL/strings.xml
@@ -439,6 +439,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Trego sekondat e orës në shiritin e statusit. Mund të ndikojë te jeta e baterisë."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Risistemo Cilësimet e shpejta"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Shfaq ndriçimin te Cilësimet e shpejta"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"Përdor faqosjen te Cilësimet e shpejta"</string>
     <string name="experimental" msgid="6198182315536726162">"Eksperimentale"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 522b2af..f3abc81 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -440,6 +440,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Секунде на сату се приказују на статусној траци. То може да утиче на трајање батерије."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Преуреди Брза подешавања"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Прикажи осветљеност у Брзим подешавањима"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"Користи листање страница у Брзим подешавањима"</string>
     <string name="experimental" msgid="6198182315536726162">"Експериментално"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 7323126..3593b34 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -439,6 +439,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Visa klocksekunder i statusfältet. Detta kan påverka batteritiden."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Ordna snabbinställningarna"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Visa ljusstyrka i snabbinställningarna"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"Använd sidindelning i snabbinställningarna"</string>
     <string name="experimental" msgid="6198182315536726162">"Experimentella"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 1cf4293..de39e9b 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -439,6 +439,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Onyesha sekunde za saa katika sehemu ya arifa. Inaweza kuathiri muda wa matumizi ya betri."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Panga Upya Mipangilio ya Haraka"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Onyesha unga\'avu katika Mipangilio ya Haraka"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"Tumia nambari za ukurasa katika Mipangilio ya Haraka"</string>
     <string name="experimental" msgid="6198182315536726162">"Ya majaribio"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ta-rIN/strings.xml b/packages/SystemUI/res/values-ta-rIN/strings.xml
index 670bccc..a895df7 100644
--- a/packages/SystemUI/res/values-ta-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ta-rIN/strings.xml
@@ -439,6 +439,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"நிலைப் பட்டியில் கடிகார வினாடிகளைக் காட்டும். பேட்டரியின் ஆயுளைக் குறைக்கலாம்."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"விரைவு அமைப்புகளை மறுவரிசைப்படுத்து"</string>
     <string name="show_brightness" msgid="6613930842805942519">"விரைவு அமைப்புகளில் ஒளிர்வுப் பட்டியைக் காட்டு"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"விரைவு அமைப்புகளில் புதிய பக்கத் தளவமைப்பைப் பயன்படுத்து"</string>
     <string name="experimental" msgid="6198182315536726162">"சோதனை முயற்சி"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-te-rIN/strings.xml b/packages/SystemUI/res/values-te-rIN/strings.xml
index bbd9979..c34a33d 100644
--- a/packages/SystemUI/res/values-te-rIN/strings.xml
+++ b/packages/SystemUI/res/values-te-rIN/strings.xml
@@ -439,6 +439,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"స్థితి పట్టీలో గడియారం సెకన్లు చూపుతుంది. బ్యాటరీ శక్తి ప్రభావితం చేయవచ్చు."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"శీఘ్ర సెట్టింగ్‌ల ఏర్పాటు క్రమం మార్చు"</string>
     <string name="show_brightness" msgid="6613930842805942519">"శీఘ్ర సెట్టింగ్‌ల్లో ప్రకాశం చూపు"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"శీఘ్ర సెట్టింగ్‌ల్లో పేజింగ్‌ను ఉపయోగించు"</string>
     <string name="experimental" msgid="6198182315536726162">"ప్రయోగాత్మకం"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 2486519..d777a0a 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -439,6 +439,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"แสดงวินาทีของนาฬิกาในแถบสถานะ อาจส่งผลต่ออายุแบตเตอรี"</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"จัดเรียงการตั้งค่าด่วนใหม่"</string>
     <string name="show_brightness" msgid="6613930842805942519">"แสดงความสว่างในการตั้งค่าด่วน"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"ใช้การแบ่งหน้าในการตั้งค่าด่วน"</string>
     <string name="experimental" msgid="6198182315536726162">"ทดสอบ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 3d1243e..292d3a2 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -439,6 +439,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Ipakita ang mga segundo ng orasan sa status bar. Maaaring makaapekto sa tagal ng baterya."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Ayusing Muli ang Mga Mabilisang Setting"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Ipakita ang liwanag sa Mga Mabilisang Setting"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"Gamitin ang paging sa Mga Mabilisang Setting"</string>
     <string name="experimental" msgid="6198182315536726162">"Pang-eksperimento"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 4dadfbc..9c42e93 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -439,6 +439,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Durum çubuğunda saatin saniyelerini gösterir. Pil ömrünü etkileyebilir."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Hızlı Ayarlar\'ı Yeniden Düzenle"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Hızlı Ayarlar\'da parlaklığı göster"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"Hızlı Ayarlar\'da sayfa ayırmayı kullan"</string>
     <string name="experimental" msgid="6198182315536726162">"Deneysel"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index d158dbe..9638e80 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -441,6 +441,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Показувати секунди на годиннику в рядку стану. Акумулятор може розряджатися швидше."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Упорядкувати швидкі налаштування"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Показувати панель яскравості у швидких налаштуваннях"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"Показувати швидкі налаштування у вигляді сторінок"</string>
     <string name="experimental" msgid="6198182315536726162">"Експериментальні налаштування"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ur-rPK/strings.xml b/packages/SystemUI/res/values-ur-rPK/strings.xml
index f8d8c71..8c2fb64 100644
--- a/packages/SystemUI/res/values-ur-rPK/strings.xml
+++ b/packages/SystemUI/res/values-ur-rPK/strings.xml
@@ -439,6 +439,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"گھڑی کے سیکنڈز اسٹیٹس بار میں دکھائیں۔ اس کا بیٹری کی زندگی پر اثر پڑ سکتا ہے۔"</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"فوری ترتیبات کو دوبارہ ترتیب دیں"</string>
     <string name="show_brightness" msgid="6613930842805942519">"فوری ترتیبات میں چمکیلا پن دکھائیں"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"فوری ترتیبات میں پیجنگ استعمال کریں"</string>
     <string name="experimental" msgid="6198182315536726162">"تجرباتی"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-uz-rUZ/strings.xml b/packages/SystemUI/res/values-uz-rUZ/strings.xml
index 0186809..0ad5a69 100644
--- a/packages/SystemUI/res/values-uz-rUZ/strings.xml
+++ b/packages/SystemUI/res/values-uz-rUZ/strings.xml
@@ -439,6 +439,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Holat panelida soat soniyalari ko‘rsatilsin. Bu batareya resursiga ta’sir qilishi mumkin."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Tezkor sozlamalarni qayta tartiblash"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Tezkor sozlamalarda yorqinlikni ko‘rsatish"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"Tezkor sozlamalarni sahifalarga ajratish"</string>
     <string name="experimental" msgid="6198182315536726162">"Tajribaviy"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 49b5d1d..c1aeeb4 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -439,6 +439,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Hiển thị giây đồng hồ trong thanh trạng thái. Có thể ảnh hưởng đến thời lượng pin."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Sắp xếp lại Cài đặt nhanh"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Hiển thị độ sáng trong Cài đặt nhanh"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"Sử dụng đánh số trang trong Cài đặt nhanh"</string>
     <string name="experimental" msgid="6198182315536726162">"Thử nghiệm"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 93ed5ca..fe1c311 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -441,6 +441,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"在状态栏中显示时钟的秒数。这可能会影响电池的续航时间。"</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"重新排列快速设置"</string>
     <string name="show_brightness" msgid="6613930842805942519">"在快速设置中显示亮度栏"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"在快速设置中使用分页功能"</string>
     <string name="experimental" msgid="6198182315536726162">"实验性"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 2196111..d39adc0 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -441,6 +441,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"在狀態列中顯示時鐘秒數,但可能會影響電池壽命。"</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"重新排列快速設定"</string>
     <string name="show_brightness" msgid="6613930842805942519">"在快速設定顯示亮度"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"在快速設定使用分頁"</string>
     <string name="experimental" msgid="6198182315536726162">"實驗版"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index fe4fe06..6606167 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -441,6 +441,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"在狀態列中顯示時鐘秒數。這可能會影響電池續航力。"</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"重新排列快速設定"</string>
     <string name="show_brightness" msgid="6613930842805942519">"在快速設定中顯示亮度"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"在快速設定中使用分頁功能"</string>
     <string name="experimental" msgid="6198182315536726162">"實驗性"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 2f068af..229c16b 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -439,6 +439,5 @@
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Bonisa amasekhondi wewashi kubha yesimo. Ingathinta impilo yebhethri."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Hlela kabusha izilungiselelo ezisheshayo"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Bonisa ukukhanya kuzilungiselelo ezisheshayo"</string>
-    <string name="qs_paging" msgid="7020133150248666132">"Sebenzisa i-paging kuzilungiselelo ezisheshayo"</string>
     <string name="experimental" msgid="6198182315536726162">"Okokulinga"</string>
 </resources>
diff --git a/packages/SystemUI/res/values/donottranslate.xml b/packages/SystemUI/res/values/donottranslate.xml
index 30ff704..351a1fd 100644
--- a/packages/SystemUI/res/values/donottranslate.xml
+++ b/packages/SystemUI/res/values/donottranslate.xml
@@ -20,10 +20,4 @@
     <!-- Date format for display: should match the lockscreen in /policy.  -->
     <string name="system_ui_date_pattern">@*android:string/system_ui_date_pattern</string>
 
-    <!-- DO NOT TRANSLATE - temporary hack to show the speed-less label if no translation is available -->
-    <item type="string" name="keyguard_indication_charging_time_fast_if_translated">@string/keyguard_indication_charging_time</item>
-
-    <!-- DO NOT TRANSLATE - temporary hack to show the speed-less label if no translation is available -->
-    <item type="string" name="keyguard_indication_charging_time_slowly_if_translated">@string/keyguard_indication_charging_time</item>
-
 </resources>
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
index e562682..8e98f10 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.qs;
 
+import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
 import android.graphics.drawable.Animatable;
@@ -325,6 +326,7 @@
 
     public interface Host {
         void startActivityDismissingKeyguard(Intent intent);
+        void startActivityDismissingKeyguard(PendingIntent intent);
         void warn(String message, Throwable t);
         void collapsePanels();
         Looper getLooper();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
index 3d0dc7b..c7f2284 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
@@ -99,7 +99,7 @@
         try {
             if (pi != null) {
                 if (pi.isActivity()) {
-                    getHost().startActivityDismissingKeyguard(pi.getIntent());
+                    getHost().startActivityDismissingKeyguard(pi);
                 } else {
                     pi.send();
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsResizeTaskDialog.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsResizeTaskDialog.java
index 8827065..d3c65d2 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsResizeTaskDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsResizeTaskDialog.java
@@ -16,6 +16,9 @@
 
 package com.android.systemui.recents;
 
+import static android.app.ActivityManager.DOCKED_STACK_ID;
+import static android.app.ActivityManager.FREEFORM_WORKSPACE_STACK_ID;
+
 import android.app.ActivityManager;
 import android.app.AlertDialog;
 import android.app.Dialog;
@@ -245,7 +248,7 @@
         // the focus ends on the selected one.
         for (int i = additionalTasks; i >= 0; --i) {
             if (mTasks[i] != null) {
-                mRecentsView.launchTask(mTasks[i], mBounds[i]);
+                mRecentsView.launchTask(mTasks[i], mBounds[i], FREEFORM_WORKSPACE_STACK_ID);
             }
         }
     }
@@ -273,11 +276,11 @@
         // Dismiss the dialog before trying to launch the task
         dismissAllowingStateLoss();
 
-        if (mTasks[0].key.stackId != ActivityManager.DOCKED_STACK_ID) {
+        if (mTasks[0].key.stackId != DOCKED_STACK_ID) {
             int taskId = mTasks[0].key.id;
             mSsp.setTaskResizeable(taskId);
             mSsp.dockTask(taskId, createMode);
-            mRecentsView.launchTask(mTasks[0], null);
+            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/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index 1266120..a5fd3eb 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.recents.views;
 
+import static android.app.ActivityManager.INVALID_STACK_ID;
+
 import android.app.ActivityManager;
 import android.app.ActivityOptions;
 import android.content.Context;
@@ -185,7 +187,8 @@
                 TaskView tv = taskViews.get(j);
                 Task task = tv.getTask();
                 if (tv.isFocusedTask()) {
-                    onTaskViewClicked(mTaskStackView, tv, stack, task, false, false, null);
+                    onTaskViewClicked(mTaskStackView, tv, stack, task, false, false, null,
+                            INVALID_STACK_ID);
                     return true;
                 }
             }
@@ -194,7 +197,7 @@
     }
 
     /** Launches a given task. */
-    public boolean launchTask(Task task, Rect taskBounds) {
+    public boolean launchTask(Task task, Rect taskBounds, int destinationStack) {
         if (mTaskStackView != null) {
             TaskStack stack = mTaskStackView.getStack();
             // Iterate the stack views and try and find the given task.
@@ -204,7 +207,7 @@
                 TaskView tv = taskViews.get(j);
                 if (tv.getTask() == task) {
                     onTaskViewClicked(mTaskStackView, tv, stack, task, false, taskBounds != null,
-                            taskBounds);
+                            taskBounds, destinationStack);
                     return true;
                 }
             }
@@ -226,7 +229,8 @@
                     if (tasks.get(j).isLaunchTarget) {
                         Task task = tasks.get(j);
                         TaskView tv = mTaskStackView.getChildViewForTask(task);
-                        onTaskViewClicked(mTaskStackView, tv, stack, task, false, false, null);
+                        onTaskViewClicked(mTaskStackView, tv, stack, task, false, false, null,
+                                INVALID_STACK_ID);
                         return true;
                     }
                 }
@@ -451,12 +455,13 @@
     private void postDrawHeaderThumbnailTransitionRunnable(final TaskStackView view,
             final TaskView clickedView, final int offsetX, final int offsetY,
             final float stackScroll,
-            final ActivityOptions.OnAnimationStartedListener animStartedListener) {
+            final ActivityOptions.OnAnimationStartedListener animStartedListener,
+            final int destinationStack) {
         Runnable r = new Runnable() {
             @Override
             public void run() {
                 overrideDrawHeaderThumbnailTransition(view, clickedView, offsetX, offsetY,
-                        stackScroll, animStartedListener);
+                        stackScroll, animStartedListener, destinationStack);
 
             }
         };
@@ -466,9 +471,10 @@
 
     private void overrideDrawHeaderThumbnailTransition(TaskStackView stackView,
             TaskView clickedTask, int offsetX, int offsetY, float stackScroll,
-            final ActivityOptions.OnAnimationStartedListener animStartedListener) {
+            final ActivityOptions.OnAnimationStartedListener animStartedListener,
+            int destinationStack) {
         List<AppTransitionAnimationSpec> specs = getAppTransitionAnimationSpecs(stackView,
-                clickedTask, offsetX, offsetY, stackScroll);
+                clickedTask, offsetX, offsetY, stackScroll, destinationStack);
         if (specs == null) {
             return;
         }
@@ -499,8 +505,10 @@
     }
 
     private List<AppTransitionAnimationSpec> getAppTransitionAnimationSpecs(TaskStackView stackView,
-            TaskView clickedTask, int offsetX, int offsetY, float stackScroll) {
-        final int targetStackId = clickedTask.getTask().key.stackId;
+            TaskView clickedTask, int offsetX, int offsetY, float stackScroll,
+            int destinationStack) {
+        final int targetStackId = destinationStack != INVALID_STACK_ID ?
+                destinationStack : clickedTask.getTask().key.stackId;
         if (targetStackId != ActivityManager.FREEFORM_WORKSPACE_STACK_ID
                 && targetStackId != ActivityManager.FULLSCREEN_WORKSPACE_STACK_ID) {
             return null;
@@ -604,9 +612,8 @@
 
     @Override
     public void onTaskViewClicked(final TaskStackView stackView, final TaskView tv,
-                                  final TaskStack stack, final Task task, final boolean lockToTask,
-                                  final boolean boundsValid, final Rect bounds) {
-
+            final TaskStack stack, final Task task, final boolean lockToTask,
+            final boolean boundsValid, final Rect bounds, int destinationStack) {
         // Notify any callbacks of the launching of a new task
         if (mCb != null) {
             mCb.onTaskViewClicked();
@@ -654,7 +661,7 @@
                 };
             }
             postDrawHeaderThumbnailTransitionRunnable(stackView, tv, offsetX, offsetY, stackScroll,
-                    animStartedListener);
+                    animStartedListener, destinationStack);
             opts = ActivityOptions.makeThumbnailAspectScaleUpAnimation(sourceView,
                     Bitmap.createBitmap(1, 1, Bitmap.Config.ALPHA_8).createAshmemBitmap(),
                     offsetX, offsetY, transform.rect.width(), transform.rect.height(),
@@ -810,7 +817,7 @@
                     SystemServicesProxy ssp = RecentsTaskLoader.getInstance().getSystemServicesProxy();
                     ssp.setTaskResizeable(event.task.key.id);
                     ssp.dockTask(event.task.key.id, event.dockState.createMode);
-                    launchTask(event.task, null);
+                    launchTask(event.task, null, INVALID_STACK_ID);
                 }
             }
         });
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 08e4e20..f637407 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -16,7 +16,10 @@
 
 package com.android.systemui.recents.views;
 
+import static android.app.ActivityManager.INVALID_STACK_ID;
+
 import android.animation.ValueAnimator;
+import android.app.ActivityManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.graphics.Canvas;
@@ -59,7 +62,7 @@
     /** The TaskView callbacks */
     interface TaskStackViewCallbacks {
         public void onTaskViewClicked(TaskStackView stackView, TaskView tv, TaskStack stack, Task t,
-                                      boolean lockToTask, boolean boundsValid, Rect bounds);
+                boolean lockToTask, boolean boundsValid, Rect bounds, int destinationStack);
         public void onAllTaskViewsDismissed(ArrayList<Task> removedTasks);
         public void onTaskStackFilterTriggered();
         public void onTaskStackUnfilterTriggered();
@@ -1227,7 +1230,8 @@
         mUIDozeTrigger.stopDozing();
 
         if (mCb != null) {
-            mCb.onTaskViewClicked(this, tv, mStack, task, lockToTask, false, null);
+            mCb.onTaskViewClicked(this, tv, mStack, task, lockToTask, false, null,
+                    INVALID_STACK_ID);
         }
     }
 
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 18e07a3..4322f1a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
@@ -157,6 +157,14 @@
                 mVelocityTracker.addMovement(createMotionEventForStackScroll(ev));
                 break;
             }
+            case MotionEvent.ACTION_POINTER_DOWN: {
+                final int index = ev.getActionIndex();
+                mActivePointerId = ev.getPointerId(index);
+                mLastMotionX = (int) ev.getX(index);
+                mLastMotionY = (int) ev.getY(index);
+                mLastP = layoutAlgorithm.sCurve.xToP(mLastMotionY, layoutAlgorithm.mStackRect);
+                break;
+            }
             case MotionEvent.ACTION_MOVE: {
                 if (mActivePointerId == INACTIVE_POINTER_ID) break;
 
@@ -182,6 +190,20 @@
                 mLastP = layoutAlgorithm.sCurve.xToP(mLastMotionY, layoutAlgorithm.mStackRect);
                 break;
             }
+            case MotionEvent.ACTION_POINTER_UP: {
+                int pointerIndex = ev.getActionIndex();
+                int pointerId = ev.getPointerId(pointerIndex);
+                if (pointerId == mActivePointerId) {
+                    // Select a new active pointer id and reset the motion state
+                    final int newPointerIndex = (pointerIndex == 0) ? 1 : 0;
+                    mActivePointerId = ev.getPointerId(newPointerIndex);
+                    mLastMotionX = (int) ev.getX(newPointerIndex);
+                    mLastMotionY = (int) ev.getY(newPointerIndex);
+                    mLastP = layoutAlgorithm.sCurve.xToP(mLastMotionY, layoutAlgorithm.mStackRect);
+                    mVelocityTracker.clear();
+                }
+                break;
+            }
             case MotionEvent.ACTION_CANCEL:
             case MotionEvent.ACTION_UP: {
                 // Animate the scroll back if we've cancelled
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 d2003bf..d227d55 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -167,7 +167,6 @@
         mContent = findViewById(R.id.task_view_content);
         mHeaderView = (TaskViewHeader) findViewById(R.id.task_view_bar);
         mThumbnailView = (TaskViewThumbnail) findViewById(R.id.task_view_thumbnail);
-        mThumbnailView.updateClipToTaskBar(mHeaderView);
         mActionButtonView = findViewById(R.id.lock_to_app_fab);
         mActionButtonView.setOutlineProvider(new ViewOutlineProvider() {
             @Override
@@ -210,6 +209,7 @@
         mThumbnailView.measure(
                 MeasureSpec.makeMeasureSpec(widthWithoutPadding, MeasureSpec.EXACTLY),
                 MeasureSpec.makeMeasureSpec(widthWithoutPadding, MeasureSpec.EXACTLY));
+        mThumbnailView.updateClipToTaskBar(mHeaderView);
         setMeasuredDimension(width, height);
         invalidateOutline();
     }
@@ -786,8 +786,8 @@
             // Start listening for drag events
             setClipViewInStack(false);
 
-            int width = (int) (getScaleX() * getWidth());
-            int height = (int) (getScaleY() * getHeight());
+            final int width = (int) (getScaleX() * getWidth());
+            final int height = (int) (getScaleY() * getHeight());
             Bitmap dragBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
             Canvas c = new Canvas(dragBitmap);
             c.scale(getScaleX(), getScaleY());
@@ -797,7 +797,12 @@
 
             // Initiate the drag
             final DragView dragView = new DragView(getContext(), dragBitmap, mDownTouchPos);
-            dragView.setOutlineProvider(mViewBounds);
+            dragView.setOutlineProvider(new ViewOutlineProvider() {
+                @Override
+                public void getOutline(View view, Outline outline) {
+                    outline.setRect(0, 0, width, height);
+                }
+            });
             dragView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
                 @Override
                 public void onViewAttachedToWindow(View v) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index aaed735..8938669 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -1617,6 +1617,59 @@
         return null;
     }
 
+    public void startPendingIntentDismissingKeyguard(final PendingIntent intent) {
+        if (!isDeviceProvisioned()) return;
+
+        final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing();
+        final boolean afterKeyguardGone = intent.isActivity()
+                && PreviewInflater.wouldLaunchResolverActivity(mContext, intent.getIntent(),
+                mCurrentUserId);
+        dismissKeyguardThenExecute(new OnDismissAction() {
+            public boolean onDismiss() {
+                new Thread() {
+                    @Override
+                    public void run() {
+                        try {
+                            if (keyguardShowing && !afterKeyguardGone) {
+                                ActivityManagerNative.getDefault()
+                                        .keyguardWaitingForActivityDrawn();
+                            }
+
+                            // The intent we are sending is for the application, which
+                            // won't have permission to immediately start an activity after
+                            // the user switches to home.  We know it is safe to do at this
+                            // point, so make sure new activity switches are now allowed.
+                            ActivityManagerNative.getDefault().resumeAppSwitches();
+                        } catch (RemoteException e) {
+                        }
+
+                        try {
+                            intent.send();
+                        } catch (PendingIntent.CanceledException e) {
+                            // the stack trace isn't very helpful here.
+                            // Just log the exception message.
+                            Log.w(TAG, "Sending intent failed: " + e);
+
+                            // TODO: Dismiss Keyguard.
+                        }
+                        if (intent.isActivity()) {
+                            mAssistManager.hideAssist();
+                            overrideActivityPendingAppTransition(keyguardShowing
+                                    && !afterKeyguardGone);
+                        }
+                    }
+                }.start();
+
+                // close the shade if it was open
+                animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL,
+                        true /* force */, true /* delayed */);
+                visibilityChanged(false);
+
+                return true;
+            }
+        }, afterKeyguardGone);
+    }
+
     private final class NotificationClicker implements View.OnClickListener {
         public void onClick(final View v) {
             if (!(v instanceof ExpandableNotificationRow)) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 5e6fdd0..6d13947 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -200,12 +200,12 @@
         switch (mChargingSpeed) {
             case KeyguardUpdateMonitor.BatteryStatus.CHARGING_FAST:
                 chargingId = hasChargingTime
-                        ? R.string.keyguard_indication_charging_time_fast_if_translated
+                        ? R.string.keyguard_indication_charging_time_fast
                         : R.string.keyguard_plugged_in_charging_fast;
                 break;
             case KeyguardUpdateMonitor.BatteryStatus.CHARGING_SLOWLY:
                 chargingId = hasChargingTime
-                        ? R.string.keyguard_indication_charging_time_slowly_if_translated
+                        ? R.string.keyguard_indication_charging_time_slowly
                         : R.string.keyguard_plugged_in_charging_slowly;
                 break;
             default:
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarter.java
index 9ef320bc..8f689c6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarter.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.statusbar.phone;
 
+import android.app.PendingIntent;
 import android.content.Intent;
 
 /**
@@ -24,6 +25,7 @@
  * Keyguard.
  */
 public interface ActivityStarter {
+    void startPendingIntentDismissingKeyguard(PendingIntent intent);
     void startActivity(Intent intent, boolean dismissShade);
     void startActivity(Intent intent, boolean dismissShade, Callback callback);
     void preventNextAnimation();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index bd16257..76edafa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -25,6 +25,7 @@
 import android.content.res.Resources;
 import android.util.AttributeSet;
 import android.util.Log;
+import android.view.InputDevice;
 import android.view.MotionEvent;
 import android.view.ViewConfiguration;
 import android.view.ViewTreeObserver;
@@ -228,8 +229,7 @@
         }
 
         // On expanding, single mouse click expands the panel instead of dragging.
-        if (isFullyCollapsed() && event.getPointerCount() == 1
-                && event.getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE) {
+        if (isFullyCollapsed() && event.getDevice().getSources() == InputDevice.SOURCE_MOUSE) {
             if (event.getAction() == MotionEvent.ACTION_UP) {
                 expand(true);
             }
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 1c1a1d7..cfde791 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -3261,6 +3261,15 @@
         return !isDeviceProvisioned() || (mDisabled1 & StatusBarManager.DISABLE_SEARCH) != 0;
     }
 
+    public void postStartActivityDismissingKeyguard(final PendingIntent intent) {
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                startPendingIntentDismissingKeyguard(intent);
+            }
+        });
+    }
+
     public void postStartActivityDismissingKeyguard(final Intent intent, int delay) {
         mHandler.postDelayed(new Runnable() {
             @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
index 6906a52..f8ddc73 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.statusbar.phone;
 
+import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.Resources;
@@ -121,6 +122,11 @@
     }
 
     @Override
+    public void startActivityDismissingKeyguard(PendingIntent intent) {
+        mStatusBar.postStartActivityDismissingKeyguard(intent);
+    }
+
+    @Override
     public void warn(String message, Throwable t) {
         // already logged
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
index 65d84e2..6cda561 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
@@ -554,8 +554,8 @@
             startBatteryActivity();
         } else if (v == mAlarmStatus && mNextAlarm != null) {
             PendingIntent showIntent = mNextAlarm.getShowIntent();
-            if (showIntent != null && showIntent.isActivity()) {
-                mActivityStarter.startActivity(showIntent.getIntent(), true /* dismissShade */);
+            if (showIntent != null) {
+                mActivityStarter.startPendingIntentDismissingKeyguard(showIntent);
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeController.java
index b2df40a..0e91b0b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeController.java
@@ -27,7 +27,6 @@
     void removeCallback(Callback callback);
     void setZen(int zen, Uri conditionId, String reason);
     int getZen();
-    void requestConditions(boolean request);
     ZenRule getManualRule();
     ZenModeConfig getConfig();
     long getNextAlarm();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
index c07f1a8..96efea1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
@@ -121,15 +121,6 @@
     }
 
     @Override
-    public void requestConditions(boolean request) {
-        mRequesting = request;
-        mNoMan.requestZenModeConditions(mListener, request ? Condition.FLAG_RELEVANT_NOW : 0);
-        if (!mRequesting) {
-            mConditions.clear();
-        }
-    }
-
-    @Override
     public ZenRule getManualRule() {
         return mConfig == null ? null : mConfig.manualRule;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
index 3c9a7fc..02ee5d4 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
@@ -1,4 +1,4 @@
-/*
+/**
  * Copyright (C) 2014 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -58,6 +58,8 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.Arrays;
+import java.util.Calendar;
+import java.util.GregorianCalendar;
 import java.util.Locale;
 import java.util.Objects;
 
@@ -76,6 +78,7 @@
     private static final int DEFAULT_BUCKET_INDEX = Arrays.binarySearch(MINUTE_BUCKETS, 60);
     private static final int FOREVER_CONDITION_INDEX = 0;
     private static final int COUNTDOWN_CONDITION_INDEX = 1;
+    private static final int COUNTDOWN_ALARM_CONDITION_INDEX = 2;
 
     public static final Intent ZEN_SETTINGS
             = new Intent(Settings.ACTION_ZEN_MODE_SETTINGS);
@@ -104,9 +107,6 @@
     private Callback mCallback;
     private ZenModeController mController;
     private boolean mCountdownConditionSupported;
-    private int mMaxConditions;
-    private int mMaxOptionalConditions;
-    private int mFirstConditionIndex;
     private boolean mRequestingConditions;
     private Condition mExitCondition;
     private int mBucketIndex = -1;
@@ -118,6 +118,7 @@
     private Condition mSessionExitCondition;
     private Condition[] mConditions;
     private Condition mTimeCondition;
+    private Condition mTimeUntilAlarmCondition;
     private boolean mVoiceCapable;
 
     public ZenModePanel(Context context, AttributeSet attrs) {
@@ -135,7 +136,6 @@
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         pw.println("ZenModePanel state:");
         pw.print("  mCountdownConditionSupported="); pw.println(mCountdownConditionSupported);
-        pw.print("  mMaxConditions="); pw.println(mMaxConditions);
         pw.print("  mRequestingConditions="); pw.println(mRequestingConditions);
         pw.print("  mAttached="); pw.println(mAttached);
         pw.print("  mHidden="); pw.println(mHidden);
@@ -286,14 +286,6 @@
         if (mRequestingConditions == requesting) return;
         if (DEBUG) Log.d(mTag, "setRequestingConditions " + requesting);
         mRequestingConditions = requesting;
-        if (mController != null) {
-            AsyncTask.execute(new Runnable() {
-                @Override
-                public void run() {
-                    mController.requestConditions(requesting);
-                }
-            });
-        }
         if (mRequestingConditions) {
             mTimeCondition = parseExistingTimeCondition(mContext, mExitCondition);
             if (mTimeCondition != null) {
@@ -304,6 +296,11 @@
                         MINUTE_BUCKETS[mBucketIndex], ActivityManager.getCurrentUser());
             }
             if (DEBUG) Log.d(mTag, "Initial bucket index: " + mBucketIndex);
+
+            mTimeUntilAlarmCondition = parseExistingTimeCondition(mContext, mExitCondition);
+            if (mTimeUntilAlarmCondition == null) {
+                mTimeUntilAlarmCondition = getTimeUntilNextAlarmCondition();
+            }
             mConditions = null; // reset conditions
             handleUpdateConditions();
         } else {
@@ -314,13 +311,9 @@
     public void init(ZenModeController controller) {
         mController = controller;
         mCountdownConditionSupported = mController.isCountdownConditionSupported();
-        final int countdownDelta = mCountdownConditionSupported ? 1 : 0;
-        mFirstConditionIndex = COUNTDOWN_CONDITION_INDEX + countdownDelta;
+        final int countdownDelta = mCountdownConditionSupported ? 2 : 0;
         final int minConditions = 1 /*forever*/ + countdownDelta;
-        mMaxConditions = MathUtils.constrain(mContext.getResources()
-                .getInteger(R.integer.zen_mode_max_conditions), minConditions, 100);
-        mMaxOptionalConditions = mMaxConditions - minConditions;
-        for (int i = 0; i < mMaxConditions; i++) {
+        for (int i = 0; i < minConditions; i++) {
             mZenConditions.addView(mInflater.inflate(R.layout.zen_mode_condition, this, false));
         }
         mSessionZen = getSelectedZen(-1);
@@ -357,28 +350,10 @@
         return condition == null ? null : condition.copy();
     }
 
-    public static String getExitConditionText(Context context, Condition exitCondition) {
-        if (exitCondition == null) {
-            return foreverSummary(context);
-        } else if (isCountdown(exitCondition)) {
-            final Condition condition = parseExistingTimeCondition(context, exitCondition);
-            return condition != null ? condition.summary : foreverSummary(context);
-        } else {
-            return exitCondition.summary;
-        }
-    }
-
     public void setCallback(Callback callback) {
         mCallback = callback;
     }
 
-    public void showSilentHint() {
-        if (DEBUG) Log.d(mTag, "showSilentHint");
-        if (mZenButtons == null || mZenButtons.getChildCount() == 0) return;
-        final View noneButton = mZenButtons.getChildAt(0);
-        mIconPulser.start(noneButton);
-    }
-
     private void handleUpdateManualRule(ZenRule rule) {
         final int zen = rule != null ? rule.zenMode : Global.ZEN_MODE_OFF;
         handleUpdateZen(zen);
@@ -410,7 +385,7 @@
             final ConditionTag tag = getConditionTagAt(i);
             if (tag != null) {
                 if (sameConditionId(tag.condition, mExitCondition)) {
-                    bind(exitCondition, mZenConditions.getChildAt(i));
+                    bind(exitCondition, mZenConditions.getChildAt(i), i);
                 }
             }
         }
@@ -495,64 +470,29 @@
         final long span = time - now;
         if (span <= 0 || span > MAX_BUCKET_MINUTES * MINUTES_MS) return null;
         return ZenModeConfig.toTimeCondition(context,
-                time, Math.round(span / (float) MINUTES_MS), now, ActivityManager.getCurrentUser(),
+                time, Math.round(span / (float) MINUTES_MS), ActivityManager.getCurrentUser(),
                 false /*shortVersion*/);
     }
 
-    private void handleUpdateConditions(Condition[] conditions) {
-        conditions = trimConditions(conditions);
-        if (Arrays.equals(conditions, mConditions)) {
-            final int count = mConditions == null ? 0 : mConditions.length;
-            if (DEBUG) Log.d(mTag, "handleUpdateConditions unchanged conditionCount=" + count);
-            return;
-        }
-        mConditions = conditions;
-        handleUpdateConditions();
-    }
-
-    private Condition[] trimConditions(Condition[] conditions) {
-        if (conditions == null || conditions.length <= mMaxOptionalConditions) {
-            // no need to trim
-            return conditions;
-        }
-        // look for current exit condition, ensure it is included if found
-        int found = -1;
-        for (int i = 0; i < conditions.length; i++) {
-            final Condition c = conditions[i];
-            if (mSessionExitCondition != null && sameConditionId(mSessionExitCondition, c)) {
-                found = i;
-                break;
-            }
-        }
-        final Condition[] rt = Arrays.copyOf(conditions, mMaxOptionalConditions);
-        if (found >= mMaxOptionalConditions) {
-            // found after the first N, promote to the end of the first N
-            rt[mMaxOptionalConditions - 1] = conditions[found];
-        }
-        return rt;
-    }
-
     private void handleUpdateConditions() {
         if (mTransitionHelper.isTransitioning()) {
-            mTransitionHelper.pendingUpdateConditions();
             return;
         }
         final int conditionCount = mConditions == null ? 0 : mConditions.length;
         if (DEBUG) Log.d(mTag, "handleUpdateConditions conditionCount=" + conditionCount);
         // forever
-        bind(forever(), mZenConditions.getChildAt(FOREVER_CONDITION_INDEX));
+        bind(forever(), mZenConditions.getChildAt(FOREVER_CONDITION_INDEX),
+                FOREVER_CONDITION_INDEX);
         // countdown
         if (mCountdownConditionSupported && mTimeCondition != null) {
-            bind(mTimeCondition, mZenConditions.getChildAt(COUNTDOWN_CONDITION_INDEX));
+            bind(mTimeCondition, mZenConditions.getChildAt(COUNTDOWN_CONDITION_INDEX),
+                    COUNTDOWN_CONDITION_INDEX);
         }
-        // provider conditions
-        for (int i = 0; i < conditionCount; i++) {
-            bind(mConditions[i], mZenConditions.getChildAt(mFirstConditionIndex + i));
-        }
-        // hide the rest
-        for (int i = mZenConditions.getChildCount() - 1; i > mFirstConditionIndex + conditionCount;
-                i--) {
-            mZenConditions.getChildAt(i).setVisibility(GONE);
+        // countdown until alarm
+        if (mCountdownConditionSupported && mTimeUntilAlarmCondition != null) {
+            bind(mTimeUntilAlarmCondition,
+                    mZenConditions.getChildAt(COUNTDOWN_ALARM_CONDITION_INDEX),
+                    COUNTDOWN_ALARM_CONDITION_INDEX);
         }
         // ensure something is selected
         if (mExpanded && isShown()) {
@@ -569,6 +509,33 @@
         return context.getString(com.android.internal.R.string.zen_mode_forever);
     }
 
+    // Returns a time condition if the next alarm is within the next week.
+    private Condition getTimeUntilNextAlarmCondition() {
+        GregorianCalendar weekRange = new GregorianCalendar();
+        final long now = weekRange.getTimeInMillis();
+        setToMidnight(weekRange);
+        weekRange.roll(Calendar.DATE, 6);
+        final long nextAlarmMs = mController.getNextAlarm();
+        if (nextAlarmMs > 0) {
+            GregorianCalendar nextAlarm = new GregorianCalendar();
+            nextAlarm.setTimeInMillis(nextAlarmMs);
+            setToMidnight(nextAlarm);
+
+            if (weekRange.compareTo(nextAlarm) >= 0) {
+                return ZenModeConfig.toNextAlarmCondition(mContext, now, nextAlarmMs,
+                        ActivityManager.getCurrentUser());
+            }
+        }
+        return null;
+    }
+
+    private void setToMidnight(Calendar calendar) {
+        calendar.set(Calendar.HOUR_OF_DAY, 0);
+        calendar.set(Calendar.MINUTE, 0);
+        calendar.set(Calendar.SECOND, 0);
+        calendar.set(Calendar.MILLISECOND, 0);
+    }
+
     private ConditionTag getConditionTagAt(int index) {
         return (ConditionTag) mZenConditions.getChildAt(index).getTag();
     }
@@ -610,7 +577,8 @@
             mTimeCondition = ZenModeConfig.toTimeCondition(mContext,
                     MINUTE_BUCKETS[favoriteIndex], ActivityManager.getCurrentUser());
             mBucketIndex = favoriteIndex;
-            bind(mTimeCondition, mZenConditions.getChildAt(COUNTDOWN_CONDITION_INDEX));
+            bind(mTimeCondition, mZenConditions.getChildAt(COUNTDOWN_CONDITION_INDEX),
+                    COUNTDOWN_CONDITION_INDEX);
             getConditionTagAt(COUNTDOWN_CONDITION_INDEX).rb.setChecked(true);
         }
     }
@@ -623,7 +591,7 @@
         return c != null && mForeverId.equals(c.id);
     }
 
-    private void bind(final Condition condition, final View row) {
+    private void bind(final Condition condition, final View row, final int rowId) {
         if (condition == null) throw new IllegalArgumentException("condition must not be null");
         final boolean enabled = condition.state == Condition.STATE_TRUE;
         final ConditionTag tag =
@@ -640,8 +608,7 @@
         tag.rb.setEnabled(enabled);
         final boolean checked = (mSessionExitCondition != null
                     || mAttachedZen != Global.ZEN_MODE_OFF)
-                && (sameConditionId(mSessionExitCondition, tag.condition)
-                    || isCountdown(mSessionExitCondition) && isCountdown(tag.condition));
+                && (sameConditionId(mSessionExitCondition, tag.condition));
         if (checked != tag.rb.isChecked()) {
             if (DEBUG) Log.d(mTag, "bind checked=" + checked + " condition=" + conditionId);
             tag.rb.setChecked(checked);
@@ -692,7 +659,7 @@
         button1.setOnClickListener(new OnClickListener() {
             @Override
             public void onClick(View v) {
-                onClickTimeButton(row, tag, false /*down*/);
+                onClickTimeButton(row, tag, false /*down*/, rowId);
             }
         });
 
@@ -700,7 +667,7 @@
         button2.setOnClickListener(new OnClickListener() {
             @Override
             public void onClick(View v) {
-                onClickTimeButton(row, tag, true /*up*/);
+                onClickTimeButton(row, tag, true /*up*/, rowId);
             }
         });
         tag.lines.setOnClickListener(new OnClickListener() {
@@ -711,7 +678,7 @@
         });
 
         final long time = ZenModeConfig.tryParseCountdownConditionId(conditionId);
-        if (time > 0) {
+        if (rowId != COUNTDOWN_ALARM_CONDITION_INDEX && time > 0) {
             button1.setVisibility(VISIBLE);
             button2.setVisibility(VISIBLE);
             if (mBucketIndex > -1) {
@@ -761,7 +728,7 @@
                 tag.line1.getText()));
     }
 
-    private void onClickTimeButton(View row, ConditionTag tag, boolean up) {
+    private void onClickTimeButton(View row, ConditionTag tag, boolean up, int rowId) {
         MetricsLogger.action(mContext, MetricsLogger.QS_DND_TIME, up);
         Condition newCondition = null;
         final int N = MINUTE_BUCKETS.length;
@@ -777,7 +744,7 @@
                 if (up && bucketTime > time || !up && bucketTime < time) {
                     mBucketIndex = j;
                     newCondition = ZenModeConfig.toTimeCondition(mContext,
-                            bucketTime, bucketMinutes, now, ActivityManager.getCurrentUser(),
+                            bucketTime, bucketMinutes, ActivityManager.getCurrentUser(),
                             false /*shortVersion*/);
                     break;
                 }
@@ -794,7 +761,7 @@
                     MINUTE_BUCKETS[mBucketIndex], ActivityManager.getCurrentUser());
         }
         mTimeCondition = newCondition;
-        bind(mTimeCondition, row);
+        bind(mTimeCondition, row, rowId);
         tag.rb.setChecked(true);
         select(mTimeCondition);
         announceConditionSelection(tag);
@@ -838,18 +805,12 @@
 
     private final ZenModeController.Callback mZenCallback = new ZenModeController.Callback() {
         @Override
-        public void onConditionsChanged(Condition[] conditions) {
-            mHandler.obtainMessage(H.UPDATE_CONDITIONS, conditions).sendToTarget();
-        }
-
-        @Override
         public void onManualRuleChanged(ZenRule rule) {
             mHandler.obtainMessage(H.MANUAL_RULE_CHANGED, rule).sendToTarget();
         }
     };
 
     private final class H extends Handler {
-        private static final int UPDATE_CONDITIONS = 1;
         private static final int MANUAL_RULE_CHANGED = 2;
         private static final int UPDATE_WIDGETS = 3;
 
@@ -860,7 +821,6 @@
         @Override
         public void handleMessage(Message msg) {
             switch (msg.what) {
-                case UPDATE_CONDITIONS: handleUpdateConditions((Condition[]) msg.obj); break;
                 case MANUAL_RULE_CHANGED: handleUpdateManualRule((ZenRule) msg.obj); break;
                 case UPDATE_WIDGETS: updateWidgets(); break;
             }
@@ -1005,26 +965,20 @@
         private final ArraySet<View> mTransitioningViews = new ArraySet<View>();
 
         private boolean mTransitioning;
-        private boolean mPendingUpdateConditions;
         private boolean mPendingUpdateWidgets;
 
         public void clear() {
             mTransitioningViews.clear();
-            mPendingUpdateConditions = mPendingUpdateWidgets = false;
+            mPendingUpdateWidgets = false;
         }
 
         public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
             pw.println("  TransitionHelper state:");
-            pw.print("    mPendingUpdateConditions="); pw.println(mPendingUpdateConditions);
             pw.print("    mPendingUpdateWidgets="); pw.println(mPendingUpdateWidgets);
             pw.print("    mTransitioning="); pw.println(mTransitioning);
             pw.print("    mTransitioningViews="); pw.println(mTransitioningViews);
         }
 
-        public void pendingUpdateConditions() {
-            mPendingUpdateConditions = true;
-        }
-
         public void pendingUpdateWidgets() {
             mPendingUpdateWidgets = true;
         }
@@ -1050,15 +1004,11 @@
         @Override
         public void run() {
             if (DEBUG) Log.d(mTag, "TransitionHelper run"
-                    + " mPendingUpdateWidgets=" + mPendingUpdateWidgets
-                    + " mPendingUpdateConditions=" + mPendingUpdateConditions);
+                    + " mPendingUpdateWidgets=" + mPendingUpdateWidgets);
             if (mPendingUpdateWidgets) {
                 updateWidgets();
             }
-            if (mPendingUpdateConditions) {
-                handleUpdateConditions();
-            }
-            mPendingUpdateWidgets = mPendingUpdateConditions = false;
+            mPendingUpdateWidgets = false;
         }
 
         private void updateTransitioning() {
@@ -1067,10 +1017,10 @@
             mTransitioning = transitioning;
             if (DEBUG) Log.d(mTag, "TransitionHelper mTransitioning=" + mTransitioning);
             if (!mTransitioning) {
-                if (mPendingUpdateConditions || mPendingUpdateWidgets) {
+                if (mPendingUpdateWidgets) {
                     mHandler.post(this);
                 } else {
-                    mPendingUpdateConditions = mPendingUpdateWidgets = false;
+                    mPendingUpdateWidgets = false;
                 }
             }
         }
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index f914b20..d031165 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -3215,6 +3215,11 @@
             final String profileName = new String(mKeyStore.get(Credentials.LOCKDOWN_VPN));
             final VpnProfile profile = VpnProfile.decode(
                     profileName, mKeyStore.get(Credentials.VPN + profileName));
+            if (profile == null) {
+                Slog.e(TAG, "Lockdown VPN configured invalid profile " + profileName);
+                setLockdownTracker(null);
+                return true;
+            }
             int user = UserHandle.getUserId(Binder.getCallingUid());
             synchronized(mVpns) {
                 setLockdownTracker(new LockdownVpnTracker(mContext, mNetd, this, mVpns.get(user),
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 087ddd6..9405d8e0 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -341,8 +341,10 @@
             gpsProvider.disable();
         }
 
-        FlpHardwareProvider flpHardwareProvider = FlpHardwareProvider.getInstance(mContext);
-        if (FlpHardwareProvider.isSupported() && flpHardwareProvider != null) {
+        // it is needed to check if FLP HW provider is supported before accessing the instance, this
+        // avoids an exception to be thrown by the singleton factory method
+        if (FlpHardwareProvider.isSupported()) {
+            FlpHardwareProvider flpHardwareProvider = FlpHardwareProvider.getInstance(mContext);
             flpHardwareProvider.cleanup();
         }
     }
diff --git a/services/core/java/com/android/server/display/ColorFade.java b/services/core/java/com/android/server/display/ColorFade.java
index bb4dbc3..835ba17 100644
--- a/services/core/java/com/android/server/display/ColorFade.java
+++ b/services/core/java/com/android/server/display/ColorFade.java
@@ -74,6 +74,7 @@
 
     // Set to true when the animation context has been fully prepared.
     private boolean mPrepared;
+    private boolean mCreatedResources;
     private int mMode;
 
     private final DisplayManagerInternal mDisplayManagerInternal;
@@ -169,6 +170,7 @@
         }
 
         // Done.
+        mCreatedResources = true;
         mPrepared = true;
 
         // Dejanking optimization.
@@ -313,6 +315,34 @@
     }
 
     /**
+     * Dismisses the color fade animation resources.
+     *
+     * This function destroys the resources that are created for the color fade
+     * animation but does not clean up the surface.
+     */
+    public void dismissResources() {
+        if (DEBUG) {
+            Slog.d(TAG, "dismissResources");
+        }
+
+        if (mCreatedResources) {
+            attachEglContext();
+            try {
+                destroyScreenshotTexture();
+                destroyGLShaders();
+                destroyGLBuffers();
+                destroyEglSurface();
+            } finally {
+                detachEglContext();
+            }
+            // This is being called with no active context so shouldn't be
+            // needed but is safer to not change for now.
+            GLES20.glFlush();
+            mCreatedResources = false;
+        }
+    }
+
+    /**
      * Dismisses the color fade animation surface and cleans up.
      *
      * To prevent stray photons from leaking out after the color fade has been
@@ -325,17 +355,8 @@
         }
 
         if (mPrepared) {
-            attachEglContext();
-            try {
-                destroyScreenshotTexture();
-                destroyGLShaders();
-                destroyGLBuffers();
-                destroyEglSurface();
-            } finally {
-                detachEglContext();
-            }
+            dismissResources();
             destroySurface();
-            GLES20.glFlush();
             mPrepared = false;
         }
     }
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 452378f..7b49530 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -837,6 +837,7 @@
         if (mPendingScreenOff && target != Display.STATE_OFF) {
             setScreenState(Display.STATE_OFF);
             mPendingScreenOff = false;
+            mPowerState.dismissColorFadeResources();
         }
 
         if (target == Display.STATE_ON) {
@@ -910,6 +911,7 @@
                 // A black surface is already hiding the contents of the screen.
                 setScreenState(Display.STATE_OFF);
                 mPendingScreenOff = false;
+                mPowerState.dismissColorFadeResources();
             } else if (performScreenOffTransition
                     && mPowerState.prepareColorFade(mContext,
                             mColorFadeFadesConfig ?
diff --git a/services/core/java/com/android/server/display/DisplayPowerState.java b/services/core/java/com/android/server/display/DisplayPowerState.java
index 2eabd32..9862516 100644
--- a/services/core/java/com/android/server/display/DisplayPowerState.java
+++ b/services/core/java/com/android/server/display/DisplayPowerState.java
@@ -187,7 +187,7 @@
     }
 
     /**
-     * Dismisses the electron beam surface.
+     * Dismisses the color fade surface.
      */
     public void dismissColorFade() {
         mColorFade.dismiss();
@@ -195,6 +195,13 @@
         mColorFadeReady = true;
     }
 
+   /**
+     * Dismisses the color fade resources.
+     */
+    public void dismissColorFadeResources() {
+        mColorFade.dismissResources();
+    }
+
     /**
      * Sets the level of the electron beam steering current.
      *
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 5a13672..5b40375 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -206,6 +206,7 @@
     private static native void nativeReloadDeviceAliases(long ptr);
     private static native String nativeDump(long ptr);
     private static native void nativeMonitor(long ptr);
+    private static native void nativeSetPointerIconShape(long ptr, int iconId);
 
     // Input event injection constants defined in InputDispatcher.h.
     private static final int INPUT_EVENT_INJECTION_SUCCEEDED = 0;
@@ -1407,6 +1408,12 @@
         }
     }
 
+  // Binder call
+  @Override
+  public void setPointerIconShape(int iconId) {
+      nativeSetPointerIconShape(mPtr, iconId);
+  }
+
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
diff --git a/services/core/java/com/android/server/pm/SELinuxMMAC.java b/services/core/java/com/android/server/pm/SELinuxMMAC.java
index 66170d4..5d8b1d2 100644
--- a/services/core/java/com/android/server/pm/SELinuxMMAC.java
+++ b/services/core/java/com/android/server/pm/SELinuxMMAC.java
@@ -100,6 +100,9 @@
     private static final String SEAPP_HASH_FILE =
             Environment.getDataDirectory().toString() + "/system/seapp_hash";
 
+    // Append privapp to existing seinfo label
+    private static final String PRIVILEGED_APP_STR = ":privapp";
+
     /**
      * Load the mac_permissions.xml file containing all seinfo assignments used to
      * label apps. The loaded mac_permissions.xml file is determined by the
@@ -313,6 +316,9 @@
             }
         }
 
+        if (pkg.applicationInfo.isPrivilegedApp())
+            pkg.applicationInfo.seinfo += PRIVILEGED_APP_STR;
+
         if (DEBUG_POLICY_INSTALL) {
             Slog.i(TAG, "package (" + pkg.packageName + ") labeled with " +
                     "seinfo=" + pkg.applicationInfo.seinfo);
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 16add37..e354029 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -4614,7 +4614,8 @@
                 final int fl = PolicyControl.getWindowFlags(null, lp);
                 if (localLOGV) {
                     Slog.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw()
-                            + " shown frame: " + mTopFullscreenOpaqueWindowState.getShownFrameLw());
+                            + " shown position: "
+                            + mTopFullscreenOpaqueWindowState.getShownPositionLw());
                     Slog.d(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs()
                             + " lp.flags=0x" + Integer.toHexString(fl));
                 }
diff --git a/services/core/java/com/android/server/policy/SystemGesturesPointerEventListener.java b/services/core/java/com/android/server/policy/SystemGesturesPointerEventListener.java
index 4ae3154..db2b941 100644
--- a/services/core/java/com/android/server/policy/SystemGesturesPointerEventListener.java
+++ b/services/core/java/com/android/server/policy/SystemGesturesPointerEventListener.java
@@ -22,6 +22,7 @@
 import android.os.SystemClock;
 import android.util.Slog;
 import android.view.GestureDetector;
+import android.view.InputDevice;
 import android.view.MotionEvent;
 import android.view.WindowManagerPolicy.PointerEventListener;
 import android.widget.OverScroller;
@@ -130,8 +131,7 @@
                 }
                 break;
             case MotionEvent.ACTION_HOVER_MOVE:
-                if (event.getPointerCount() == 1
-                        && event.getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE) {
+                if (event.getDevice().getSources() == InputDevice.SOURCE_MOUSE) {
                     if (!mMouseHoveringAtEdge && event.getY() == 0) {
                         mCallbacks.onMouseHoverAtTop();
                         mMouseHoveringAtEdge = true;
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index 66ae9ef..d713751 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -206,8 +206,8 @@
         sTempFloats[Matrix.MSKEW_Y] = windowState.mWinAnimator.mDtDx;
         sTempFloats[Matrix.MSKEW_X] = windowState.mWinAnimator.mDsDy;
         sTempFloats[Matrix.MSCALE_Y] = windowState.mWinAnimator.mDtDy;
-        sTempFloats[Matrix.MTRANS_X] = windowState.mShownFrame.left;
-        sTempFloats[Matrix.MTRANS_Y] = windowState.mShownFrame.top;
+        sTempFloats[Matrix.MTRANS_X] = windowState.mShownPosition.x;
+        sTempFloats[Matrix.MTRANS_Y] = windowState.mShownPosition.y;
         sTempFloats[Matrix.MPERSP_0] = 0;
         sTempFloats[Matrix.MPERSP_1] = 0;
         sTempFloats[Matrix.MPERSP_2] = 1;
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index cc51d20..9f44fea 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -760,26 +760,24 @@
                     a = createAspectScaledThumbnailEnterNonFullscreenAnimationLocked(
                             containingFrame, surfaceInsets, taskId);
                 } else {
+                    mTmpFromClipRect.set(containingFrame);
+                    // exclude top screen decor (status bar) region from the source clip.
+                    mTmpFromClipRect.top = contentInsets.top;
                     // App window scaling up to become full screen
+                    mTmpToClipRect.set(containingFrame);
                     if (orientation == Configuration.ORIENTATION_PORTRAIT) {
                         // In portrait, we scale the width and clip to the top/left square
                         scale = thumbWidth / appWidth;
                         scaledTopDecor = (int) (scale * contentInsets.top);
                         int unscaledThumbHeight = (int) (thumbHeight / scale);
-                        mTmpFromClipRect.set(containingFrame);
-                        mTmpFromClipRect.bottom = (mTmpFromClipRect.top + unscaledThumbHeight);
-                        mTmpToClipRect.set(containingFrame);
+                        mTmpFromClipRect.bottom = mTmpFromClipRect.top + unscaledThumbHeight;
                     } else {
                         // In landscape, we scale the height and clip to the top/left square
                         scale = thumbHeight / (appHeight - contentInsets.top);
                         scaledTopDecor = (int) (scale * contentInsets.top);
                         int unscaledThumbWidth = (int) (thumbWidth / scale);
-                        mTmpFromClipRect.set(containingFrame);
-                        mTmpFromClipRect.right = (mTmpFromClipRect.left + unscaledThumbWidth);
-                        mTmpToClipRect.set(containingFrame);
+                        mTmpFromClipRect.right = mTmpFromClipRect.left + unscaledThumbWidth;
                     }
-                    // exclude top screen decor (status bar) region from the source clip.
-                    mTmpFromClipRect.top = contentInsets.top;
 
                     mNextAppTransitionInsets.set(contentInsets);
 
@@ -821,25 +819,23 @@
             }
             case THUMBNAIL_TRANSITION_EXIT_SCALE_DOWN: {
                 // App window scaling down from full screen
+                mTmpFromClipRect.set(containingFrame);
+                mTmpToClipRect.set(containingFrame);
+                // exclude top screen decor (status bar) region from the destination clip.
+                mTmpToClipRect.top = contentInsets.top;
                 if (orientation == Configuration.ORIENTATION_PORTRAIT) {
                     // In portrait, we scale the width and clip to the top/left square
                     scale = thumbWidth / appWidth;
                     scaledTopDecor = (int) (scale * contentInsets.top);
                     int unscaledThumbHeight = (int) (thumbHeight / scale);
-                    mTmpFromClipRect.set(containingFrame);
-                    mTmpToClipRect.set(containingFrame);
-                    mTmpToClipRect.bottom = (mTmpToClipRect.top + unscaledThumbHeight);
+                    mTmpToClipRect.bottom = mTmpToClipRect.top + unscaledThumbHeight;
                 } else {
                     // In landscape, we scale the height and clip to the top/left square
                     scale = thumbHeight / (appHeight - contentInsets.top);
                     scaledTopDecor = (int) (scale * contentInsets.top);
                     int unscaledThumbWidth = (int) (thumbWidth / scale);
-                    mTmpFromClipRect.set(containingFrame);
-                    mTmpToClipRect.set(containingFrame);
-                    mTmpToClipRect.right = (mTmpToClipRect.left + unscaledThumbWidth);
+                    mTmpToClipRect.right = mTmpToClipRect.left + unscaledThumbWidth;
                 }
-                // exclude top screen decor (status bar) region from the destination clip.
-                mTmpToClipRect.top = contentInsets.top;
 
                 mNextAppTransitionInsets.set(contentInsets);
 
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index 1a946b2..7f2f2cd 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -419,7 +419,7 @@
                     winAnimator.computeShownFrameLocked();
                     // No need to lay out the windows - we can just set the wallpaper position
                     // directly.
-                    winAnimator.setWallpaperOffset(wallpaper.mShownFrame);
+                    winAnimator.setWallpaperOffset(wallpaper.mShownPosition);
                     // We only want to be synchronous with one wallpaper.
                     sync = false;
                 }
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 383ad8c..e72d35c 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -29,15 +29,14 @@
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
 import static com.android.server.wm.WindowManagerService.DEBUG_CONFIGURATION;
-import static com.android.server.wm.WindowManagerService.DEBUG_DIM_LAYER;
 import static com.android.server.wm.WindowManagerService.DEBUG_LAYOUT;
 import static com.android.server.wm.WindowManagerService.DEBUG_ORIENTATION;
 import static com.android.server.wm.WindowManagerService.DEBUG_POWER;
 import static com.android.server.wm.WindowManagerService.DEBUG_RESIZE;
 import static com.android.server.wm.WindowManagerService.DEBUG_VISIBILITY;
 
-import android.app.ActivityManager;
 import android.app.AppOpsManager;
+import android.graphics.Point;
 import android.os.PowerManager;
 import android.os.RemoteCallbackList;
 import android.os.SystemClock;
@@ -159,11 +158,10 @@
     private boolean mConfigHasChanged;
 
     /**
-     * Actual frame shown on-screen (may be modified by animation).  These
-     * are in the screen's coordinate space (WITH the compatibility scale
-     * applied).
+     * Actual position of the surface shown on-screen (may be modified by animation). These are
+     * in the screen's coordinate space (WITH the compatibility scale applied).
      */
-    final RectF mShownFrame = new RectF();
+    final Point mShownPosition = new Point();
 
     /**
      * Insets that determine the actually visible area.  These are in the application's
@@ -787,8 +785,8 @@
     }
 
     @Override
-    public RectF getShownFrameLw() {
-        return mShownFrame;
+    public Point getShownPositionLw() {
+        return mShownPosition;
     }
 
     @Override
@@ -1822,7 +1820,7 @@
             }
         }
         pw.print(prefix); pw.print("mHasSurface="); pw.print(mHasSurface);
-                pw.print(" mShownFrame="); mShownFrame.printShortString(pw);
+                pw.print(" mShownPosition="); mShownPosition.printShortString(pw);
                 pw.print(" isReadyForDisplay()="); pw.println(isReadyForDisplay());
         if (dumpAll) {
             pw.print(prefix); pw.print("mFrame="); mFrame.printShortString(pw);
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 2733933..1913604 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -1190,9 +1190,7 @@
             mDtDy = tmpFloats[Matrix.MSCALE_Y];
             float x = tmpFloats[Matrix.MTRANS_X];
             float y = tmpFloats[Matrix.MTRANS_Y];
-            int w = frame.width();
-            int h = frame.height();
-            mWin.mShownFrame.set(x, y, x+w, y+h);
+            mWin.mShownPosition.set((int) x, (int) y);
 
             // Now set the alpha...  but because our current hardware
             // can't do alpha transformation on a non-opaque surface,
@@ -1287,13 +1285,13 @@
             float y = tmpFloats[Matrix.MTRANS_Y];
             int w = frame.width();
             int h = frame.height();
-            mWin.mShownFrame.set(x, y, x + w, y + h);
+            mWin.mShownPosition.set((int) x, (int) y);
 
             mShownAlpha = mAlpha;
         } else {
-            mWin.mShownFrame.set(mWin.mFrame);
+            mWin.mShownPosition.set(mWin.mFrame.left, mWin.mFrame.top);
             if (mWin.mXOffset != 0 || mWin.mYOffset != 0) {
-                mWin.mShownFrame.offset(mWin.mXOffset, mWin.mYOffset);
+                mWin.mShownPosition.offset(mWin.mXOffset, mWin.mYOffset);
             }
             mShownAlpha = mAlpha;
             mHaveMatrix = false;
@@ -1458,8 +1456,8 @@
     void setSurfaceBoundariesLocked(final boolean recoveringMemory) {
         final WindowState w = mWin;
 
-        float left = w.mShownFrame.left;
-        float top = w.mShownFrame.top;
+        float left = w.mShownPosition.x;
+        float top = w.mShownPosition.y;
 
         int width;
         int height;
@@ -1701,10 +1699,10 @@
         }
     }
 
-    void setWallpaperOffset(RectF shownFrame) {
+    void setWallpaperOffset(Point shownPosition) {
         final LayoutParams attrs = mWin.getAttrs();
-        final int left = ((int) shownFrame.left) - attrs.surfaceInsets.left;
-        final int top = ((int) shownFrame.top) - attrs.surfaceInsets.top;
+        final int left = shownPosition.x - attrs.surfaceInsets.left;
+        final int top = shownPosition.y - attrs.surfaceInsets.top;
         if (mSurfaceX != left || mSurfaceY != top) {
             if (mAnimating) {
                 // If this window (or its app token) is animating, then the position
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index 112646a..247562f 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -717,7 +717,8 @@
                     /*
                      * Updates the shown frame before we set up the surface. This is needed because
                      * the resizing could change the top-left position (in addition to size) of the
-                     * window. setSurfaceBoundariesLocked uses mShownFrame to position the surface.
+                     * window. setSurfaceBoundariesLocked uses mShownPosition to position the
+                      * surface.
                      */
                     winAnimator.computeShownFrameLocked();
                     winAnimator.setSurfaceBoundariesLocked(recoveringMemory);
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 1d4f047..8cb0a13 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -199,6 +199,7 @@
     void setShowTouches(bool enabled);
     void setInteractive(bool interactive);
     void reloadCalibration();
+    void setPointerIconShape(int32_t iconId);
 
     /* --- InputReaderPolicyInterface implementation --- */
 
@@ -237,6 +238,7 @@
     /* --- PointerControllerPolicyInterface implementation --- */
 
     virtual void loadPointerResources(PointerResources* outResources);
+    virtual void loadAdditionalMouseResources(std::map<int, SpriteIcon>* outResources);
 
 private:
     sp<InputManager> mInputManager;
@@ -779,6 +781,15 @@
             InputReaderConfiguration::CHANGE_TOUCH_AFFINE_TRANSFORMATION);
 }
 
+void NativeInputManager::setPointerIconShape(int32_t iconId) {
+  AutoMutex _l(mLock);
+  sp<PointerController> controller = mLocked.pointerController.promote();
+  if (controller != NULL) {
+        // Use 0 (the default icon) for ARROW.
+        controller->updatePointerShape((iconId == POINTER_ICON_STYLE_ARROW) ? 0 : iconId);
+  }
+}
+
 TouchAffineTransformation NativeInputManager::getTouchAffineTransformation(
         JNIEnv *env, jfloatArray matrixArr) {
     ScopedFloatArrayRO matrix(env, matrixArr);
@@ -1029,6 +1040,15 @@
             &outResources->spotAnchor);
 }
 
+void NativeInputManager::loadAdditionalMouseResources(std::map<int, SpriteIcon>* outResources) {
+    JNIEnv* env = jniEnv();
+
+    for (int iconId = POINTER_ICON_STYLE_CONTEXT_MENU; iconId <= POINTER_ICON_STYLE_GRABBING;
+             ++iconId) {
+        loadSystemIconAsSprite(env, mContextObj, iconId, &((*outResources)[iconId]));
+    }
+}
+
 
 // ----------------------------------------------------------------------------
 
@@ -1367,6 +1387,11 @@
     im->getInputManager()->getDispatcher()->monitor();
 }
 
+static void nativeSetPointerIconShape(JNIEnv* /* env */, jclass /* clazz */, jlong ptr, jint iconId) {
+    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
+    im->setPointerIconShape(iconId);
+}
+
 // ----------------------------------------------------------------------------
 
 static const JNINativeMethod gInputManagerMethods[] = {
@@ -1425,6 +1450,8 @@
             (void*) nativeDump },
     { "nativeMonitor", "(J)V",
             (void*) nativeMonitor },
+    { "nativeSetPointerIconShape", "(JI)V",
+            (void*) nativeSetPointerIconShape },
 };
 
 #define FIND_CLASS(var, className) \
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerHelper.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerHelper.java
index 3ca0c84..31d859f 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerHelper.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerHelper.java
@@ -87,6 +87,7 @@
     // This is an indirect indication of the microphone being open in some other application.
     private boolean mServiceDisabled = false;
     private boolean mStarted = false;
+    private boolean mRecognitionAborted = false;
     private PowerSaveModeListener mPowerSaveModeListener;
 
     SoundTriggerHelper(Context context) {
@@ -386,8 +387,9 @@
 
     private void onRecognitionAbortLocked() {
         Slog.w(TAG, "Recognition aborted");
-        // No-op
-        // This is handled via service state changes instead.
+        // If abort has been called, the hardware has already stopped recognition, so we shouldn't
+        // call it again when we process the state change.
+        mRecognitionAborted = true;
     }
 
     private void onRecognitionFailureLocked() {
@@ -490,8 +492,13 @@
             }
             return status;
         } else {
-            // Stop recognition.
-            int status = mModule.stopRecognition(mCurrentSoundModelHandle);
+            // Stop recognition (only if we haven't been aborted).
+            int status = STATUS_OK;
+            if (!mRecognitionAborted) {
+                status = mModule.stopRecognition(mCurrentSoundModelHandle);
+            } else {
+                mRecognitionAborted = false;
+            }
             if (status != SoundTrigger.STATUS_OK) {
                 Slog.w(TAG, "stopRecognition call failed with " + status);
                 if (notify) {
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index ba91254..7cf5f73 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -191,7 +191,7 @@
     public static final String
             KEY_DISABLE_CDMA_ACTIVATION_CODE_BOOL = "disable_cdma_activation_code_bool";
 
-   /**
+    /**
      * Override the platform's notion of a network operator being considered roaming.
      * Value is string array of MCCMNCs to be considered roaming for 3GPP RATs.
      */
@@ -468,6 +468,12 @@
      */
     public static final String KEY_CSP_ENABLED_BOOL = "csp_enabled_bool";
 
+    /**
+     * Allow user to add APNs
+     * @hide
+     */
+    public static final String KEY_ALLOW_ADDING_APNS_BOOL = "allow_adding_apns_bool";
+
     // These variables are used by the MMS service and exposed through another API, {@link
     // SmsManager}. The variable names and string values are copied from there.
     public static final String KEY_MMS_ALIAS_ENABLED_BOOL = "aliasEnabled";
@@ -567,6 +573,7 @@
         sDefaults.putString(KEY_CI_ACTION_ON_SYS_UPDATE_EXTRA_STRING, "");
         sDefaults.putString(KEY_CI_ACTION_ON_SYS_UPDATE_EXTRA_VAL_STRING, "");
         sDefaults.putBoolean(KEY_CSP_ENABLED_BOOL, false);
+        sDefaults.putBoolean(KEY_ALLOW_ADDING_APNS_BOOL, true);
         sDefaults.putBoolean(KEY_ALWAYS_SHOW_EMERGENCY_ALERT_ONOFF_BOOL, false);
 
         sDefaults.putStringArray(KEY_GSM_ROAMING_NETWORKS_STRING_ARRAY, null);
diff --git a/telephony/java/android/telephony/SignalStrength.java b/telephony/java/android/telephony/SignalStrength.java
index f535e5d..fced667 100644
--- a/telephony/java/android/telephony/SignalStrength.java
+++ b/telephony/java/android/telephony/SignalStrength.java
@@ -911,7 +911,7 @@
         else if (tdScdmaDbm >= -49) level = SIGNAL_STRENGTH_GREAT;
         else if (tdScdmaDbm >= -73) level = SIGNAL_STRENGTH_GOOD;
         else if (tdScdmaDbm >= -97) level = SIGNAL_STRENGTH_MODERATE;
-        else if (tdScdmaDbm >= -120) level = SIGNAL_STRENGTH_POOR;
+        else if (tdScdmaDbm >= -110) level = SIGNAL_STRENGTH_POOR;
         else level = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
 
         if (DBG) log("getTdScdmaLevel = " + level);