Merge "Add transition support to PopupWindow"
diff --git a/api/current.txt b/api/current.txt
index 6d94dcb..47fa5d1 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -4767,6 +4767,37 @@
     method public android.app.Notification.Builder setWhen(long);
   }
 
+  public static final class Notification.CarExtender implements android.app.Notification.Extender {
+    ctor public Notification.CarExtender();
+    ctor public Notification.CarExtender(android.app.Notification);
+    method public android.app.Notification.Builder extend(android.app.Notification.Builder);
+    method public int getColor();
+    method public android.graphics.Bitmap getLargeIcon();
+    method public android.app.Notification.CarExtender.UnreadConversation getUnreadConversation();
+    method public android.app.Notification.CarExtender setColor(int);
+    method public android.app.Notification.CarExtender setLargeIcon(android.graphics.Bitmap);
+    method public android.app.Notification.CarExtender setUnreadConversation(android.app.Notification.CarExtender.UnreadConversation);
+  }
+
+  public static class Notification.CarExtender.Builder {
+    ctor public Notification.CarExtender.Builder(java.lang.String);
+    method public android.app.Notification.CarExtender.Builder addMessage(java.lang.String);
+    method public android.app.Notification.CarExtender.UnreadConversation build();
+    method public android.app.Notification.CarExtender.Builder setLatestTimestamp(long);
+    method public android.app.Notification.CarExtender.Builder setReadPendingIntent(android.app.PendingIntent);
+    method public android.app.Notification.CarExtender.Builder setReplyAction(android.app.PendingIntent, android.app.RemoteInput);
+  }
+
+  public static class Notification.CarExtender.UnreadConversation {
+    method public long getLatestTimestamp();
+    method public java.lang.String[] getMessages();
+    method public java.lang.String getParticipant();
+    method public java.lang.String[] getParticipants();
+    method public android.app.PendingIntent getReadPendingIntent();
+    method public android.app.RemoteInput getRemoteInput();
+    method public android.app.PendingIntent getReplyPendingIntent();
+  }
+
   public static abstract interface Notification.Extender {
     method public abstract android.app.Notification.Builder extend(android.app.Notification.Builder);
   }
@@ -12616,6 +12647,8 @@
     field public static final int CAMERA_DISABLED = 1; // 0x1
     field public static final int CAMERA_DISCONNECTED = 2; // 0x2
     field public static final int CAMERA_ERROR = 3; // 0x3
+    field public static final int CAMERA_IN_USE = 4; // 0x4
+    field public static final int MAX_CAMERAS_IN_USE = 5; // 0x5
   }
 
   public abstract class CameraCaptureSession implements java.lang.AutoCloseable {
@@ -12682,6 +12715,7 @@
     field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Float> LENS_INFO_MINIMUM_FOCUS_DISTANCE;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> REQUEST_AVAILABLE_CAPABILITIES;
+    field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> REQUEST_MAX_NUM_INPUT_STREAMS;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> REQUEST_MAX_NUM_OUTPUT_PROC;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> REQUEST_MAX_NUM_OUTPUT_PROC_STALLING;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> REQUEST_MAX_NUM_OUTPUT_RAW;
@@ -12756,7 +12790,10 @@
     method public java.lang.String[] getCameraIdList() throws android.hardware.camera2.CameraAccessException;
     method public void openCamera(java.lang.String, android.hardware.camera2.CameraDevice.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
     method public void registerAvailabilityCallback(android.hardware.camera2.CameraManager.AvailabilityCallback, android.os.Handler);
+    method public void registerTorchCallback(android.hardware.camera2.CameraManager.TorchCallback, android.os.Handler);
+    method public void setTorchMode(java.lang.String, boolean) throws android.hardware.camera2.CameraAccessException;
     method public void unregisterAvailabilityCallback(android.hardware.camera2.CameraManager.AvailabilityCallback);
+    method public void unregisterTorchCallback(android.hardware.camera2.CameraManager.TorchCallback);
   }
 
   public static abstract class CameraManager.AvailabilityCallback {
@@ -12765,6 +12802,13 @@
     method public void onCameraUnavailable(java.lang.String);
   }
 
+  public static abstract class CameraManager.TorchCallback {
+    ctor public CameraManager.TorchCallback();
+    method public void onTorchModeAvailable(java.lang.String);
+    method public void onTorchModeChanged(java.lang.String, boolean);
+    method public void onTorchModeUnavailable(java.lang.String);
+  }
+
   public abstract class CameraMetadata {
     method public java.util.List<TKey> getKeys();
     field public static final int COLOR_CORRECTION_ABERRATION_MODE_FAST = 1; // 0x1
@@ -12889,13 +12933,16 @@
     field public static final int LENS_STATE_STATIONARY = 0; // 0x0
     field public static final int NOISE_REDUCTION_MODE_FAST = 1; // 0x1
     field public static final int NOISE_REDUCTION_MODE_HIGH_QUALITY = 2; // 0x2
+    field public static final int NOISE_REDUCTION_MODE_MINIMAL = 3; // 0x3
     field public static final int NOISE_REDUCTION_MODE_OFF = 0; // 0x0
     field public static final int REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE = 0; // 0x0
     field public static final int REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE = 6; // 0x6
     field public static final int REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING = 2; // 0x2
     field public static final int REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR = 1; // 0x1
+    field public static final int REQUEST_AVAILABLE_CAPABILITIES_OPAQUE_REPROCESSING = 4; // 0x4
     field public static final int REQUEST_AVAILABLE_CAPABILITIES_RAW = 3; // 0x3
     field public static final int REQUEST_AVAILABLE_CAPABILITIES_READ_SENSOR_SETTINGS = 5; // 0x5
+    field public static final int REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING = 7; // 0x7
     field public static final int SCALER_CROPPING_TYPE_CENTER_ONLY = 0; // 0x0
     field public static final int SCALER_CROPPING_TYPE_FREEFORM = 1; // 0x1
     field public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_BGGR = 3; // 0x3
@@ -13001,6 +13048,7 @@
     field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Float> LENS_FOCUS_DISTANCE;
     field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> LENS_OPTICAL_STABILIZATION_MODE;
     field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> NOISE_REDUCTION_MODE;
+    field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Float> REPROCESS_EFFECTIVE_EXPOSURE_FACTOR;
     field public static final android.hardware.camera2.CaptureRequest.Key<android.graphics.Rect> SCALER_CROP_REGION;
     field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Long> SENSOR_EXPOSURE_TIME;
     field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Long> SENSOR_FRAME_DURATION;
@@ -13078,6 +13126,7 @@
     field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> LENS_OPTICAL_STABILIZATION_MODE;
     field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> LENS_STATE;
     field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> NOISE_REDUCTION_MODE;
+    field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Float> REPROCESS_EFFECTIVE_EXPOSURE_FACTOR;
     field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Byte> REQUEST_PIPELINE_DEPTH;
     field public static final android.hardware.camera2.CaptureResult.Key<android.graphics.Rect> SCALER_CROP_REGION;
     field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Long> SENSOR_EXPOSURE_TIME;
@@ -16205,6 +16254,7 @@
     method public void connect();
     method public void disconnect();
     method public android.os.Bundle getExtras();
+    method public void getMediaItem(java.lang.String, android.media.browse.MediaBrowser.MediaItemCallback);
     method public java.lang.String getRoot();
     method public android.content.ComponentName getServiceComponent();
     method public android.media.session.MediaSession.Token getSessionToken();
@@ -16234,6 +16284,12 @@
     field public static final int FLAG_PLAYABLE = 2; // 0x2
   }
 
+  public static abstract class MediaBrowser.MediaItemCallback {
+    ctor public MediaBrowser.MediaItemCallback();
+    method public void onError();
+    method public void onMediaItemLoaded(android.media.browse.MediaBrowser.MediaItem);
+  }
+
   public static abstract class MediaBrowser.SubscriptionCallback {
     ctor public MediaBrowser.SubscriptionCallback();
     method public void onChildrenLoaded(java.lang.String, java.util.List<android.media.browse.MediaBrowser.MediaItem>);
@@ -21770,6 +21826,7 @@
     field public static final int KITKAT_WATCH = 20; // 0x14
     field public static final int LOLLIPOP = 21; // 0x15
     field public static final int LOLLIPOP_MR1 = 22; // 0x16
+    field public static final int MNC = 10000; // 0x2710
   }
 
   public final class Bundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable {
@@ -27348,6 +27405,7 @@
   public abstract class MediaBrowserService extends android.app.Service {
     ctor public MediaBrowserService();
     method public void dump(java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
+    method public void getMediaItem(java.lang.String, android.service.media.MediaBrowserService.Result<android.media.browse.MediaBrowser.MediaItem>) throws java.lang.UnsupportedOperationException;
     method public android.media.session.MediaSession.Token getSessionToken();
     method public void notifyChildrenChanged(java.lang.String);
     method public android.os.IBinder onBind(android.content.Intent);
@@ -34084,6 +34142,7 @@
     method public void setOnHoverListener(android.view.View.OnHoverListener);
     method public void setOnKeyListener(android.view.View.OnKeyListener);
     method public void setOnLongClickListener(android.view.View.OnLongClickListener);
+    method public void setOnScrollChangeListener(android.view.View.OnScrollChangeListener);
     method public void setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener);
     method public void setOnTouchListener(android.view.View.OnTouchListener);
     method public void setOutlineProvider(android.view.ViewOutlineProvider);
@@ -34351,6 +34410,10 @@
     method public abstract boolean onLongClick(android.view.View);
   }
 
+  public static abstract interface View.OnScrollChangeListener {
+    method public abstract void onScrollChange(android.view.View, int, int, int, int);
+  }
+
   public static abstract interface View.OnSystemUiVisibilityChangeListener {
     method public abstract void onSystemUiVisibilityChange(int);
   }
diff --git a/api/system-current.txt b/api/system-current.txt
index d73556a..4eb00f4 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -4857,6 +4857,37 @@
     method public android.app.Notification.Builder setWhen(long);
   }
 
+  public static final class Notification.CarExtender implements android.app.Notification.Extender {
+    ctor public Notification.CarExtender();
+    ctor public Notification.CarExtender(android.app.Notification);
+    method public android.app.Notification.Builder extend(android.app.Notification.Builder);
+    method public int getColor();
+    method public android.graphics.Bitmap getLargeIcon();
+    method public android.app.Notification.CarExtender.UnreadConversation getUnreadConversation();
+    method public android.app.Notification.CarExtender setColor(int);
+    method public android.app.Notification.CarExtender setLargeIcon(android.graphics.Bitmap);
+    method public android.app.Notification.CarExtender setUnreadConversation(android.app.Notification.CarExtender.UnreadConversation);
+  }
+
+  public static class Notification.CarExtender.Builder {
+    ctor public Notification.CarExtender.Builder(java.lang.String);
+    method public android.app.Notification.CarExtender.Builder addMessage(java.lang.String);
+    method public android.app.Notification.CarExtender.UnreadConversation build();
+    method public android.app.Notification.CarExtender.Builder setLatestTimestamp(long);
+    method public android.app.Notification.CarExtender.Builder setReadPendingIntent(android.app.PendingIntent);
+    method public android.app.Notification.CarExtender.Builder setReplyAction(android.app.PendingIntent, android.app.RemoteInput);
+  }
+
+  public static class Notification.CarExtender.UnreadConversation {
+    method public long getLatestTimestamp();
+    method public java.lang.String[] getMessages();
+    method public java.lang.String getParticipant();
+    method public java.lang.String[] getParticipants();
+    method public android.app.PendingIntent getReadPendingIntent();
+    method public android.app.RemoteInput getRemoteInput();
+    method public android.app.PendingIntent getReplyPendingIntent();
+  }
+
   public static abstract interface Notification.Extender {
     method public abstract android.app.Notification.Builder extend(android.app.Notification.Builder);
   }
@@ -12884,6 +12915,8 @@
     field public static final int CAMERA_DISABLED = 1; // 0x1
     field public static final int CAMERA_DISCONNECTED = 2; // 0x2
     field public static final int CAMERA_ERROR = 3; // 0x3
+    field public static final int CAMERA_IN_USE = 4; // 0x4
+    field public static final int MAX_CAMERAS_IN_USE = 5; // 0x5
   }
 
   public abstract class CameraCaptureSession implements java.lang.AutoCloseable {
@@ -12950,6 +12983,7 @@
     field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Float> LENS_INFO_MINIMUM_FOCUS_DISTANCE;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> REQUEST_AVAILABLE_CAPABILITIES;
+    field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> REQUEST_MAX_NUM_INPUT_STREAMS;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> REQUEST_MAX_NUM_OUTPUT_PROC;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> REQUEST_MAX_NUM_OUTPUT_PROC_STALLING;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> REQUEST_MAX_NUM_OUTPUT_RAW;
@@ -13024,7 +13058,10 @@
     method public java.lang.String[] getCameraIdList() throws android.hardware.camera2.CameraAccessException;
     method public void openCamera(java.lang.String, android.hardware.camera2.CameraDevice.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
     method public void registerAvailabilityCallback(android.hardware.camera2.CameraManager.AvailabilityCallback, android.os.Handler);
+    method public void registerTorchCallback(android.hardware.camera2.CameraManager.TorchCallback, android.os.Handler);
+    method public void setTorchMode(java.lang.String, boolean) throws android.hardware.camera2.CameraAccessException;
     method public void unregisterAvailabilityCallback(android.hardware.camera2.CameraManager.AvailabilityCallback);
+    method public void unregisterTorchCallback(android.hardware.camera2.CameraManager.TorchCallback);
   }
 
   public static abstract class CameraManager.AvailabilityCallback {
@@ -13033,6 +13070,13 @@
     method public void onCameraUnavailable(java.lang.String);
   }
 
+  public static abstract class CameraManager.TorchCallback {
+    ctor public CameraManager.TorchCallback();
+    method public void onTorchModeAvailable(java.lang.String);
+    method public void onTorchModeChanged(java.lang.String, boolean);
+    method public void onTorchModeUnavailable(java.lang.String);
+  }
+
   public abstract class CameraMetadata {
     method public java.util.List<TKey> getKeys();
     field public static final int COLOR_CORRECTION_ABERRATION_MODE_FAST = 1; // 0x1
@@ -13157,13 +13201,16 @@
     field public static final int LENS_STATE_STATIONARY = 0; // 0x0
     field public static final int NOISE_REDUCTION_MODE_FAST = 1; // 0x1
     field public static final int NOISE_REDUCTION_MODE_HIGH_QUALITY = 2; // 0x2
+    field public static final int NOISE_REDUCTION_MODE_MINIMAL = 3; // 0x3
     field public static final int NOISE_REDUCTION_MODE_OFF = 0; // 0x0
     field public static final int REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE = 0; // 0x0
     field public static final int REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE = 6; // 0x6
     field public static final int REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING = 2; // 0x2
     field public static final int REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR = 1; // 0x1
+    field public static final int REQUEST_AVAILABLE_CAPABILITIES_OPAQUE_REPROCESSING = 4; // 0x4
     field public static final int REQUEST_AVAILABLE_CAPABILITIES_RAW = 3; // 0x3
     field public static final int REQUEST_AVAILABLE_CAPABILITIES_READ_SENSOR_SETTINGS = 5; // 0x5
+    field public static final int REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING = 7; // 0x7
     field public static final int SCALER_CROPPING_TYPE_CENTER_ONLY = 0; // 0x0
     field public static final int SCALER_CROPPING_TYPE_FREEFORM = 1; // 0x1
     field public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_BGGR = 3; // 0x3
@@ -13269,6 +13316,7 @@
     field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Float> LENS_FOCUS_DISTANCE;
     field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> LENS_OPTICAL_STABILIZATION_MODE;
     field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> NOISE_REDUCTION_MODE;
+    field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Float> REPROCESS_EFFECTIVE_EXPOSURE_FACTOR;
     field public static final android.hardware.camera2.CaptureRequest.Key<android.graphics.Rect> SCALER_CROP_REGION;
     field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Long> SENSOR_EXPOSURE_TIME;
     field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Long> SENSOR_FRAME_DURATION;
@@ -13346,6 +13394,7 @@
     field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> LENS_OPTICAL_STABILIZATION_MODE;
     field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> LENS_STATE;
     field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> NOISE_REDUCTION_MODE;
+    field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Float> REPROCESS_EFFECTIVE_EXPOSURE_FACTOR;
     field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Byte> REQUEST_PIPELINE_DEPTH;
     field public static final android.hardware.camera2.CaptureResult.Key<android.graphics.Rect> SCALER_CROP_REGION;
     field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Long> SENSOR_EXPOSURE_TIME;
@@ -17255,6 +17304,7 @@
     method public void connect();
     method public void disconnect();
     method public android.os.Bundle getExtras();
+    method public void getMediaItem(java.lang.String, android.media.browse.MediaBrowser.MediaItemCallback);
     method public java.lang.String getRoot();
     method public android.content.ComponentName getServiceComponent();
     method public android.media.session.MediaSession.Token getSessionToken();
@@ -17284,6 +17334,12 @@
     field public static final int FLAG_PLAYABLE = 2; // 0x2
   }
 
+  public static abstract class MediaBrowser.MediaItemCallback {
+    ctor public MediaBrowser.MediaItemCallback();
+    method public void onError();
+    method public void onMediaItemLoaded(android.media.browse.MediaBrowser.MediaItem);
+  }
+
   public static abstract class MediaBrowser.SubscriptionCallback {
     ctor public MediaBrowser.SubscriptionCallback();
     method public void onChildrenLoaded(java.lang.String, java.util.List<android.media.browse.MediaBrowser.MediaItem>);
@@ -23349,6 +23405,7 @@
     field public static final int KITKAT_WATCH = 20; // 0x14
     field public static final int LOLLIPOP = 21; // 0x15
     field public static final int LOLLIPOP_MR1 = 22; // 0x16
+    field public static final int MNC = 10000; // 0x2710
   }
 
   public final class Bundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable {
@@ -28937,6 +28994,7 @@
   public abstract class MediaBrowserService extends android.app.Service {
     ctor public MediaBrowserService();
     method public void dump(java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
+    method public void getMediaItem(java.lang.String, android.service.media.MediaBrowserService.Result<android.media.browse.MediaBrowser.MediaItem>) throws java.lang.UnsupportedOperationException;
     method public android.media.session.MediaSession.Token getSessionToken();
     method public void notifyChildrenChanged(java.lang.String);
     method public android.os.IBinder onBind(android.content.Intent);
@@ -36283,6 +36341,7 @@
     method public void setOnHoverListener(android.view.View.OnHoverListener);
     method public void setOnKeyListener(android.view.View.OnKeyListener);
     method public void setOnLongClickListener(android.view.View.OnLongClickListener);
+    method public void setOnScrollChangeListener(android.view.View.OnScrollChangeListener);
     method public void setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener);
     method public void setOnTouchListener(android.view.View.OnTouchListener);
     method public void setOutlineProvider(android.view.ViewOutlineProvider);
@@ -36550,6 +36609,10 @@
     method public abstract boolean onLongClick(android.view.View);
   }
 
+  public static abstract interface View.OnScrollChangeListener {
+    method public abstract void onScrollChange(android.view.View, int, int, int, int);
+  }
+
   public static abstract interface View.OnSystemUiVisibilityChangeListener {
     method public abstract void onSystemUiVisibilityChange(int);
   }
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 2a0ed90..fb3d423 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -1735,6 +1735,22 @@
         int right = Integer.valueOf(rightStr);
         String bottomStr = nextArgRequired();
         int bottom = Integer.valueOf(bottomStr);
+        if (left < 0) {
+            System.err.println("Error: bad left arg: " + leftStr);
+            return;
+        }
+        if (top < 0) {
+            System.err.println("Error: bad top arg: " + topStr);
+            return;
+        }
+        if (right <= 0) {
+            System.err.println("Error: bad right arg: " + rightStr);
+            return;
+        }
+        if (bottom <= 0) {
+            System.err.println("Error: bad bottom arg: " + bottomStr);
+            return;
+        }
 
         try {
             mAm.resizeStack(stackId, new Rect(left, top, right, bottom));
diff --git a/cmds/bootanimation/bootanimation_main.cpp b/cmds/bootanimation/bootanimation_main.cpp
index 6550d22..48a34e7 100644
--- a/cmds/bootanimation/bootanimation_main.cpp
+++ b/cmds/bootanimation/bootanimation_main.cpp
@@ -16,20 +16,14 @@
 
 #define LOG_TAG "BootAnimation"
 
-#include <cutils/properties.h>
-
 #include <binder/IPCThreadState.h>
 #include <binder/ProcessState.h>
 #include <binder/IServiceManager.h>
-
+#include <cutils/properties.h>
+#include <sys/resource.h>
 #include <utils/Log.h>
 #include <utils/threads.h>
 
-#if defined(HAVE_PTHREADS)
-# include <pthread.h>
-# include <sys/resource.h>
-#endif
-
 #include "BootAnimation.h"
 
 using namespace android;
@@ -38,9 +32,7 @@
 
 int main()
 {
-#if defined(HAVE_PTHREADS)
     setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_DISPLAY);
-#endif
 
     char value[PROPERTY_VALUE_MAX];
     property_get("debug.sf.nobootanimation", value, "0");
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 74c468d..a09bca1 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -3226,7 +3226,9 @@
      * Programmatically closes the most recently opened context menu, if showing.
      */
     public void closeContextMenu() {
-        mWindow.closePanel(Window.FEATURE_CONTEXT_MENU);
+        if (mWindow.hasFeature(Window.FEATURE_CONTEXT_MENU)) {
+            mWindow.closePanel(Window.FEATURE_CONTEXT_MENU);
+        }
     }
 
     /**
diff --git a/core/java/android/app/ActivityTransitionCoordinator.java b/core/java/android/app/ActivityTransitionCoordinator.java
index d0d9d71..e3b27b5 100644
--- a/core/java/android/app/ActivityTransitionCoordinator.java
+++ b/core/java/android/app/ActivityTransitionCoordinator.java
@@ -799,6 +799,15 @@
         mIsStartingTransition = false;
     }
 
+    /**
+     * Cancels any pending transitions and returns true if there is a transition is in
+     * the middle of starting.
+     */
+    protected boolean cancelPendingTransitions() {
+        mPendingTransition = null;
+        return mIsStartingTransition;
+    }
+
     protected void moveSharedElementsToOverlay() {
         if (mWindow == null || !mWindow.getSharedElementsUseOverlay()) {
             return;
diff --git a/core/java/android/app/ActivityTransitionState.java b/core/java/android/app/ActivityTransitionState.java
index 555d20b..a2bfa4e 100644
--- a/core/java/android/app/ActivityTransitionState.java
+++ b/core/java/android/app/ActivityTransitionState.java
@@ -22,6 +22,7 @@
 import android.util.SparseArray;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
 import android.view.Window;
 
 import java.lang.ref.WeakReference;
@@ -252,7 +253,7 @@
         }
     }
 
-    public boolean startExitBackTransition(Activity activity) {
+    public boolean startExitBackTransition(final Activity activity) {
         if (mEnteringNames == null) {
             return false;
         } else {
@@ -260,10 +261,11 @@
                 mHasExited = true;
                 Transition enterViewsTransition = null;
                 ViewGroup decor = null;
+                boolean delayExitBack = false;
                 if (mEnterTransitionCoordinator != null) {
                     enterViewsTransition = mEnterTransitionCoordinator.getEnterViewsTransition();
                     decor = mEnterTransitionCoordinator.getDecor();
-                    mEnterTransitionCoordinator.cancelEnter();
+                    delayExitBack = mEnterTransitionCoordinator.cancelEnter();
                     mEnterTransitionCoordinator = null;
                     if (enterViewsTransition != null && decor != null) {
                         enterViewsTransition.pause(decor);
@@ -275,7 +277,23 @@
                 if (enterViewsTransition != null && decor != null) {
                     enterViewsTransition.resume(decor);
                 }
-                mReturnExitCoordinator.startExit(activity.mResultCode, activity.mResultData);
+                if (delayExitBack && decor != null) {
+                    final ViewGroup finalDecor = decor;
+                    decor.getViewTreeObserver().addOnPreDrawListener(
+                            new ViewTreeObserver.OnPreDrawListener() {
+                                @Override
+                                public boolean onPreDraw() {
+                                    finalDecor.getViewTreeObserver().removeOnPreDrawListener(this);
+                                    if (mReturnExitCoordinator != null) {
+                                        mReturnExitCoordinator.startExit(activity.mResultCode,
+                                                activity.mResultData);
+                                    }
+                                    return true;
+                                }
+                            });
+                } else {
+                    mReturnExitCoordinator.startExit(activity.mResultCode, activity.mResultData);
+                }
             }
             return true;
         }
diff --git a/core/java/android/app/EnterTransitionCoordinator.java b/core/java/android/app/EnterTransitionCoordinator.java
index ecf19c7..c053c83 100644
--- a/core/java/android/app/EnterTransitionCoordinator.java
+++ b/core/java/android/app/EnterTransitionCoordinator.java
@@ -18,7 +18,6 @@
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ObjectAnimator;
-import android.graphics.Matrix;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.os.ResultReceiver;
@@ -565,7 +564,12 @@
         clearState();
     }
 
-    public void cancelEnter() {
+    /**
+     * Cancels the enter transition.
+     * @return True if the enter transition is still pending capturing the target state. If so,
+     * any transition started on the decor will do nothing.
+     */
+    public boolean cancelEnter() {
         setGhostVisibility(View.INVISIBLE);
         mHasStopped = true;
         mIsCanceled = true;
@@ -576,6 +580,7 @@
         }
         mActivity = null;
         clearState();
+        return super.cancelPendingTransitions();
     }
 
     private void makeOpaque() {
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 860b9cc..87e744c 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -5065,6 +5065,403 @@
     }
 
     /**
+     * <p>Helper class to add Android Auto extensions to notifications. To create a notification
+     * with car extensions:
+     *
+     * <ol>
+     *  <li>Create an {@link Notification.Builder}, setting any desired
+     *  properties.
+     *  <li>Create a {@link CarExtender}.
+     *  <li>Set car-specific properties using the {@code add} and {@code set} methods of
+     *  {@link CarExtender}.
+     *  <li>Call {@link Notification.Builder#extend(Notification.Extender)}
+     *  to apply the extensions to a notification.
+     * </ol>
+     *
+     * <pre class="prettyprint">
+     * Notification notification = new Notification.Builder(context)
+     *         ...
+     *         .extend(new CarExtender()
+     *                 .set*(...))
+     *         .build();
+     * </pre>
+     *
+     * <p>Car extensions can be accessed on an existing notification by using the
+     * {@code CarExtender(Notification)} constructor, and then using the {@code get} methods
+     * to access values.
+     */
+    public static final class CarExtender implements Extender {
+        private static final String TAG = "CarExtender";
+
+        private static final String EXTRA_CAR_EXTENDER = "android.car.EXTENSIONS";
+        private static final String EXTRA_LARGE_ICON = "large_icon";
+        private static final String EXTRA_CONVERSATION = "car_conversation";
+        private static final String EXTRA_COLOR = "app_color";
+
+        private Bitmap mLargeIcon;
+        private UnreadConversation mUnreadConversation;
+        private int mColor = Notification.COLOR_DEFAULT;
+
+        /**
+         * Create a {@link CarExtender} with default options.
+         */
+        public CarExtender() {
+        }
+
+        /**
+         * Create a {@link CarExtender} from the CarExtender options of an existing Notification.
+         *
+         * @param notif The notification from which to copy options.
+         */
+        public CarExtender(Notification notif) {
+            Bundle carBundle = notif.extras == null ?
+                    null : notif.extras.getBundle(EXTRA_CAR_EXTENDER);
+            if (carBundle != null) {
+                mLargeIcon = carBundle.getParcelable(EXTRA_LARGE_ICON);
+                mColor = carBundle.getInt(EXTRA_COLOR, Notification.COLOR_DEFAULT);
+
+                Bundle b = carBundle.getBundle(EXTRA_CONVERSATION);
+                mUnreadConversation = UnreadConversation.getUnreadConversationFromBundle(b);
+            }
+        }
+
+        /**
+         * Apply car extensions to a notification that is being built. This is typically called by
+         * the {@link Notification.Builder#extend(Notification.Extender)}
+         * method of {@link Notification.Builder}.
+         */
+        @Override
+        public Notification.Builder extend(Notification.Builder builder) {
+            Bundle carExtensions = new Bundle();
+
+            if (mLargeIcon != null) {
+                carExtensions.putParcelable(EXTRA_LARGE_ICON, mLargeIcon);
+            }
+            if (mColor != Notification.COLOR_DEFAULT) {
+                carExtensions.putInt(EXTRA_COLOR, mColor);
+            }
+
+            if (mUnreadConversation != null) {
+                Bundle b = mUnreadConversation.getBundleForUnreadConversation();
+                carExtensions.putBundle(EXTRA_CONVERSATION, b);
+            }
+
+            builder.getExtras().putBundle(EXTRA_CAR_EXTENDER, carExtensions);
+            return builder;
+        }
+
+        /**
+         * Sets the accent color to use when Android Auto presents the notification.
+         *
+         * Android Auto uses the color set with {@link Notification.Builder#setColor(int)}
+         * to accent the displayed notification. However, not all colors are acceptable in an
+         * automotive setting. This method can be used to override the color provided in the
+         * notification in such a situation.
+         */
+        public CarExtender setColor(int color) {
+            mColor = color;
+            return this;
+        }
+
+        /**
+         * Gets the accent color.
+         *
+         * @see setColor
+         */
+        public int getColor() {
+            return mColor;
+        }
+
+        /**
+         * Sets the large icon of the car notification.
+         *
+         * If no large icon is set in the extender, Android Auto will display the icon
+         * specified by {@link Notification.Builder#setLargeIcon(android.graphics.Bitmap)}
+         *
+         * @param largeIcon The large icon to use in the car notification.
+         * @return This object for method chaining.
+         */
+        public CarExtender setLargeIcon(Bitmap largeIcon) {
+            mLargeIcon = largeIcon;
+            return this;
+        }
+
+        /**
+         * Gets the large icon used in this car notification, or null if no icon has been set.
+         *
+         * @return The large icon for the car notification.
+         * @see CarExtender#setLargeIcon
+         */
+        public Bitmap getLargeIcon() {
+            return mLargeIcon;
+        }
+
+        /**
+         * Sets the unread conversation in a message notification.
+         *
+         * @param unreadConversation The unread part of the conversation this notification conveys.
+         * @return This object for method chaining.
+         */
+        public CarExtender setUnreadConversation(UnreadConversation unreadConversation) {
+            mUnreadConversation = unreadConversation;
+            return this;
+        }
+
+        /**
+         * Returns the unread conversation conveyed by this notification.
+         * @see #setUnreadConversation(UnreadConversation)
+         */
+        public UnreadConversation getUnreadConversation() {
+            return mUnreadConversation;
+        }
+
+        /**
+         * A class which holds the unread messages from a conversation.
+         */
+        public static class UnreadConversation {
+            private static final String KEY_AUTHOR = "author";
+            private static final String KEY_TEXT = "text";
+            private static final String KEY_MESSAGES = "messages";
+            private static final String KEY_REMOTE_INPUT = "remote_input";
+            private static final String KEY_ON_REPLY = "on_reply";
+            private static final String KEY_ON_READ = "on_read";
+            private static final String KEY_PARTICIPANTS = "participants";
+            private static final String KEY_TIMESTAMP = "timestamp";
+
+            private final String[] mMessages;
+            private final RemoteInput mRemoteInput;
+            private final PendingIntent mReplyPendingIntent;
+            private final PendingIntent mReadPendingIntent;
+            private final String[] mParticipants;
+            private final long mLatestTimestamp;
+
+            UnreadConversation(String[] messages, RemoteInput remoteInput,
+                    PendingIntent replyPendingIntent, PendingIntent readPendingIntent,
+                    String[] participants, long latestTimestamp) {
+                mMessages = messages;
+                mRemoteInput = remoteInput;
+                mReadPendingIntent = readPendingIntent;
+                mReplyPendingIntent = replyPendingIntent;
+                mParticipants = participants;
+                mLatestTimestamp = latestTimestamp;
+            }
+
+            /**
+             * Gets the list of messages conveyed by this notification.
+             */
+            public String[] getMessages() {
+                return mMessages;
+            }
+
+            /**
+             * Gets the remote input that will be used to convey the response to a message list, or
+             * null if no such remote input exists.
+             */
+            public RemoteInput getRemoteInput() {
+                return mRemoteInput;
+            }
+
+            /**
+             * Gets the pending intent that will be triggered when the user replies to this
+             * notification.
+             */
+            public PendingIntent getReplyPendingIntent() {
+                return mReplyPendingIntent;
+            }
+
+            /**
+             * Gets the pending intent that Android Auto will send after it reads aloud all messages
+             * in this object's message list.
+             */
+            public PendingIntent getReadPendingIntent() {
+                return mReadPendingIntent;
+            }
+
+            /**
+             * Gets the participants in the conversation.
+             */
+            public String[] getParticipants() {
+                return mParticipants;
+            }
+
+            /**
+             * Gets the firs participant in the conversation.
+             */
+            public String getParticipant() {
+                return mParticipants.length > 0 ? mParticipants[0] : null;
+            }
+
+            /**
+             * Gets the timestamp of the conversation.
+             */
+            public long getLatestTimestamp() {
+                return mLatestTimestamp;
+            }
+
+            Bundle getBundleForUnreadConversation() {
+                Bundle b = new Bundle();
+                String author = null;
+                if (mParticipants != null && mParticipants.length > 1) {
+                    author = mParticipants[0];
+                }
+                Parcelable[] messages = new Parcelable[mMessages.length];
+                for (int i = 0; i < messages.length; i++) {
+                    Bundle m = new Bundle();
+                    m.putString(KEY_TEXT, mMessages[i]);
+                    m.putString(KEY_AUTHOR, author);
+                    messages[i] = m;
+                }
+                b.putParcelableArray(KEY_MESSAGES, messages);
+                if (mRemoteInput != null) {
+                    b.putParcelable(KEY_REMOTE_INPUT, mRemoteInput);
+                }
+                b.putParcelable(KEY_ON_REPLY, mReplyPendingIntent);
+                b.putParcelable(KEY_ON_READ, mReadPendingIntent);
+                b.putStringArray(KEY_PARTICIPANTS, mParticipants);
+                b.putLong(KEY_TIMESTAMP, mLatestTimestamp);
+                return b;
+            }
+
+            static UnreadConversation getUnreadConversationFromBundle(Bundle b) {
+                if (b == null) {
+                    return null;
+                }
+                Parcelable[] parcelableMessages = b.getParcelableArray(KEY_MESSAGES);
+                String[] messages = null;
+                if (parcelableMessages != null) {
+                    String[] tmp = new String[parcelableMessages.length];
+                    boolean success = true;
+                    for (int i = 0; i < tmp.length; i++) {
+                        if (!(parcelableMessages[i] instanceof Bundle)) {
+                            success = false;
+                            break;
+                        }
+                        tmp[i] = ((Bundle) parcelableMessages[i]).getString(KEY_TEXT);
+                        if (tmp[i] == null) {
+                            success = false;
+                            break;
+                        }
+                    }
+                    if (success) {
+                        messages = tmp;
+                    } else {
+                        return null;
+                    }
+                }
+
+                PendingIntent onRead = b.getParcelable(KEY_ON_READ);
+                PendingIntent onReply = b.getParcelable(KEY_ON_REPLY);
+
+                RemoteInput remoteInput = b.getParcelable(KEY_REMOTE_INPUT);
+
+                String[] participants = b.getStringArray(KEY_PARTICIPANTS);
+                if (participants == null || participants.length != 1) {
+                    return null;
+                }
+
+                return new UnreadConversation(messages,
+                        remoteInput,
+                        onReply,
+                        onRead,
+                        participants, b.getLong(KEY_TIMESTAMP));
+            }
+        };
+
+        /**
+         * Builder class for {@link CarExtender.UnreadConversation} objects.
+         */
+        public static class Builder {
+            private final List<String> mMessages = new ArrayList<String>();
+            private final String mParticipant;
+            private RemoteInput mRemoteInput;
+            private PendingIntent mReadPendingIntent;
+            private PendingIntent mReplyPendingIntent;
+            private long mLatestTimestamp;
+
+            /**
+             * Constructs a new builder for {@link CarExtender.UnreadConversation}.
+             *
+             * @param name The name of the other participant in the conversation.
+             */
+            public Builder(String name) {
+                mParticipant = name;
+            }
+
+            /**
+             * Appends a new unread message to the list of messages for this conversation.
+             *
+             * The messages should be added from oldest to newest.
+             *
+             * @param message The text of the new unread message.
+             * @return This object for method chaining.
+             */
+            public Builder addMessage(String message) {
+                mMessages.add(message);
+                return this;
+            }
+
+            /**
+             * Sets the pending intent and remote input which will convey the reply to this
+             * notification.
+             *
+             * @param pendingIntent The pending intent which will be triggered on a reply.
+             * @param remoteInput The remote input parcelable which will carry the reply.
+             * @return This object for method chaining.
+             *
+             * @see CarExtender.UnreadConversation#getRemoteInput
+             * @see CarExtender.UnreadConversation#getReplyPendingIntent
+             */
+            public Builder setReplyAction(
+                    PendingIntent pendingIntent, RemoteInput remoteInput) {
+                mRemoteInput = remoteInput;
+                mReplyPendingIntent = pendingIntent;
+
+                return this;
+            }
+
+            /**
+             * Sets the pending intent that will be sent once the messages in this notification
+             * are read.
+             *
+             * @param pendingIntent The pending intent to use.
+             * @return This object for method chaining.
+             */
+            public Builder setReadPendingIntent(PendingIntent pendingIntent) {
+                mReadPendingIntent = pendingIntent;
+                return this;
+            }
+
+            /**
+             * Sets the timestamp of the most recent message in an unread conversation.
+             *
+             * If a messaging notification has been posted by your application and has not
+             * yet been cancelled, posting a later notification with the same id and tag
+             * but without a newer timestamp may result in Android Auto not displaying a
+             * heads up notification for the later notification.
+             *
+             * @param timestamp The timestamp of the most recent message in the conversation.
+             * @return This object for method chaining.
+             */
+            public Builder setLatestTimestamp(long timestamp) {
+                mLatestTimestamp = timestamp;
+                return this;
+            }
+
+            /**
+             * Builds a new unread conversation object.
+             *
+             * @return The new unread conversation object.
+             */
+            public UnreadConversation build() {
+                String[] messages = mMessages.toArray(new String[mMessages.size()]);
+                String[] participants = { mParticipant };
+                return new UnreadConversation(messages, mRemoteInput, mReplyPendingIntent,
+                        mReadPendingIntent, participants, mLatestTimestamp);
+            }
+        }
+    }
+
+    /**
      * Get an array of Notification objects from a parcelable array bundle field.
      * Update the bundle to have a typed array so fetches in the future don't need
      * to do an array copy.
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index d7d9e8b..5c09b42 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -3082,6 +3082,12 @@
             a.info.flags |= ActivityInfo.FLAG_IMMERSIVE;
         }
 
+        if (sa.getBoolean(
+                com.android.internal.R.styleable.AndroidManifestActivity_primaryUserOnly,
+                false)) {
+            a.info.flags |= ActivityInfo.FLAG_PRIMARY_USER_ONLY;
+        }
+
         if (!receiver) {
             if (sa.getBoolean(
                     com.android.internal.R.styleable.AndroidManifestActivity_hardwareAccelerated,
@@ -3153,11 +3159,6 @@
                     setExported = true;
                 }
             }
-            if (sa.getBoolean(
-                    com.android.internal.R.styleable.AndroidManifestActivity_primaryUserOnly,
-                    false)) {
-                a.info.flags |= ActivityInfo.FLAG_PRIMARY_USER_ONLY;
-            }
         }
 
         sa.recycle();
diff --git a/core/java/android/hardware/camera2/CameraAccessException.java b/core/java/android/hardware/camera2/CameraAccessException.java
index 91ef6ca..84e9912 100644
--- a/core/java/android/hardware/camera2/CameraAccessException.java
+++ b/core/java/android/hardware/camera2/CameraAccessException.java
@@ -28,16 +28,14 @@
  */
 public class CameraAccessException extends AndroidException {
     /**
-     * The camera device is in use already
-     * @hide
+     * The camera device is in use already.
      */
     public static final int CAMERA_IN_USE = 4;
 
     /**
-     * The system-wide limit for number of open cameras has been reached,
-     * and more camera devices cannot be opened until previous instances are
-     * closed.
-     * @hide
+     * The system-wide limit for number of open cameras or camera resources has
+     * been reached, and more camera devices cannot be opened or torch mode
+     * cannot be turned on until previous instances are closed.
      */
     public static final int MAX_CAMERAS_IN_USE = 5;
 
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index eace1c4..5310071 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -1069,8 +1069,11 @@
      * android.scaler.availableInputOutputFormatsMap. When using an
      * input stream, there must be at least one output stream
      * configured to to receive the reprocessed images.</p>
+     * <p>When an input stream and some output streams are used in a reprocessing request,
+     * only the input buffer will be used to produce these output stream buffers, and a
+     * new sensor image will not be captured.</p>
      * <p>For example, for Zero Shutter Lag (ZSL) still capture use case, the input
-     * stream image format will be RAW_OPAQUE, the associated output stream image format
+     * stream image format will be OPAQUE, the associated output stream image format
      * should be JPEG.</p>
      * <p><b>Range of valid values:</b><br></p>
      * <p>0 or 1.</p>
@@ -1080,8 +1083,8 @@
      * {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel} key</p>
      *
      * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
-     * @hide
      */
+    @PublicKey
     public static final Key<Integer> REQUEST_MAX_NUM_INPUT_STREAMS =
             new Key<Integer>("android.request.maxNumInputStreams", int.class);
 
@@ -1157,8 +1160,10 @@
      *   <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR MANUAL_SENSOR}</li>
      *   <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING MANUAL_POST_PROCESSING}</li>
      *   <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_RAW RAW}</li>
+     *   <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_OPAQUE_REPROCESSING OPAQUE_REPROCESSING}</li>
      *   <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_READ_SENSOR_SETTINGS READ_SENSOR_SETTINGS}</li>
      *   <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE BURST_CAPTURE}</li>
+     *   <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING YUV_REPROCESSING}</li>
      * </ul></p>
      * <p>This key is available on all devices.</p>
      *
@@ -1167,8 +1172,10 @@
      * @see #REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR
      * @see #REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING
      * @see #REQUEST_AVAILABLE_CAPABILITIES_RAW
+     * @see #REQUEST_AVAILABLE_CAPABILITIES_OPAQUE_REPROCESSING
      * @see #REQUEST_AVAILABLE_CAPABILITIES_READ_SENSOR_SETTINGS
      * @see #REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE
+     * @see #REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING
      */
     @PublicKey
     public static final Key<int[]> REQUEST_AVAILABLE_CAPABILITIES =
@@ -1345,10 +1352,10 @@
      * <p>The mapping of image formats that are supported by this
      * camera device for input streams, to their corresponding output formats.</p>
      * <p>All camera devices with at least 1
-     * android.request.maxNumInputStreams will have at least one
+     * {@link CameraCharacteristics#REQUEST_MAX_NUM_INPUT_STREAMS android.request.maxNumInputStreams} will have at least one
      * available input format.</p>
      * <p>The camera device will support the following map of formats,
-     * if its dependent capability is supported:</p>
+     * if its dependent capability ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities}) is supported:</p>
      * <table>
      * <thead>
      * <tr>
@@ -1359,45 +1366,42 @@
      * </thead>
      * <tbody>
      * <tr>
-     * <td align="left">RAW_OPAQUE</td>
+     * <td align="left">OPAQUE</td>
      * <td align="left">JPEG</td>
-     * <td align="left">ZSL</td>
+     * <td align="left">OPAQUE_REPROCESSING</td>
      * </tr>
      * <tr>
-     * <td align="left">RAW_OPAQUE</td>
+     * <td align="left">OPAQUE</td>
      * <td align="left">YUV_420_888</td>
-     * <td align="left">ZSL</td>
+     * <td align="left">OPAQUE_REPROCESSING</td>
      * </tr>
      * <tr>
-     * <td align="left">RAW_OPAQUE</td>
-     * <td align="left">RAW16</td>
-     * <td align="left">RAW</td>
-     * </tr>
-     * <tr>
-     * <td align="left">RAW16</td>
      * <td align="left">YUV_420_888</td>
-     * <td align="left">RAW</td>
-     * </tr>
-     * <tr>
-     * <td align="left">RAW16</td>
      * <td align="left">JPEG</td>
-     * <td align="left">RAW</td>
+     * <td align="left">YUV_REPROCESSING</td>
+     * </tr>
+     * <tr>
+     * <td align="left">YUV_420_888</td>
+     * <td align="left">YUV_420_888</td>
+     * <td align="left">YUV_REPROCESSING</td>
      * </tr>
      * </tbody>
      * </table>
-     * <p>For ZSL-capable camera devices, using the RAW_OPAQUE format
+     * <p>OPAQUE refers to a device-internal format that is not directly application-visible.
+     * An OPAQUE input or output surface can be acquired by
+     * OpaqueImageRingBufferQueue#getInputSurface() or
+     * OpaqueImageRingBufferQueue#getOutputSurface().
+     * For a OPAQUE_REPROCESSING-capable camera device, using the OPAQUE format
      * as either input or output will never hurt maximum frame rate (i.e.
-     * StreamConfigurationMap#getOutputStallDuration(int,Size)
-     * for a <code>format =</code> RAW_OPAQUE is always 0).</p>
+     * StreamConfigurationMap#getOutputStallDuration(klass,Size) is always 0),
+     * where klass is android.media.OpaqueImageRingBufferQueue.class.</p>
      * <p>Attempting to configure an input stream with output streams not
      * listed as available in this map is not valid.</p>
      * <p>TODO: typedef to ReprocessFormatMap</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
-     * <p><b>Full capability</b> -
-     * Present on all camera devices that report being {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_FULL HARDWARE_LEVEL_FULL} devices in the
-     * {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel} key</p>
      *
-     * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
+     * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
+     * @see CameraCharacteristics#REQUEST_MAX_NUM_INPUT_STREAMS
      * @hide
      */
     public static final Key<int[]> SCALER_AVAILABLE_INPUT_OUTPUT_FORMATS_MAP =
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index b6bb33b..8af3c15 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -109,8 +109,11 @@
      * of the state of individual CameraManager instances.</p>
      *
      * @param callback the new callback to send camera availability notices to
-     * @param handler The handler on which the callback should be invoked, or
-     * {@code null} to use the current thread's {@link android.os.Looper looper}.
+     * @param handler The handler on which the callback should be invoked, or {@code null} to use
+     *             the current thread's {@link android.os.Looper looper}.
+     *
+     * @throws IllegalArgumentException if the handler is {@code null} but the current thread has
+     *             no looper.
      */
     public void registerAvailabilityCallback(AvailabilityCallback callback, Handler handler) {
         if (handler == null) {
@@ -138,6 +141,42 @@
     }
 
     /**
+     * Register a callback to be notified about torch mode status.
+     *
+     * <p>Registering the same callback again will replace the handler with the
+     * new one provided.</p>
+     *
+     * <p>The first time a callback is registered, it is immediately called
+     * with the torch mode status of all currently known camera devices.</p>
+     *
+     * <p>Since this callback will be registered with the camera service, remember to unregister it
+     * once it is no longer needed; otherwise the callback will continue to receive events
+     * indefinitely and it may prevent other resources from being released. Specifically, the
+     * callbacks will be invoked independently of the general activity lifecycle and independently
+     * of the state of individual CameraManager instances.</p>
+     *
+     * @param callback The new callback to send torch mode status to
+     * @param handler The handler on which the callback should be invoked, or {@code null} to use
+     *             the current thread's {@link android.os.Looper looper}.
+     *
+     * @throws IllegalArgumentException if the handler is {@code null} but the current thread has
+     *             no looper.
+     */
+    public void registerTorchCallback(TorchCallback callback, Handler handler) {
+    }
+
+    /**
+     * Remove a previously-added callback; the callback will no longer receive torch mode status
+     * callbacks.
+     *
+     * <p>Removing a callback that isn't registered has no effect.</p>
+     *
+     * @param callback The callback to remove from the notification list
+     */
+    public void unregisterTorchCallback(TorchCallback callback) {
+    }
+
+    /**
      * <p>Query the capabilities of a camera device. These capabilities are
      * immutable for a given camera.</p>
      *
@@ -384,6 +423,47 @@
     }
 
     /**
+     * Set the flash unit's torch mode of the camera of the given ID without opening the camera
+     * device.
+     *
+     * <p>Use {@link #getCameraIdList} to get the list of available camera devices and use
+     * {@link #getCameraCharacteristics} to check whether the camera device has a flash unit.
+     * Note that even if a camera device has a flash unit, turning on the torch mode may fail
+     * if the camera device or other camera resources needed to turn on the torch mode are in use.
+     * </p>
+     *
+     * <p> If {@link #setTorchMode} is called to turn on or off the torch mode successfully,
+     * {@link CameraManager.TorchCallback#onTorchModeChanged} will be invoked.
+     * However, even if turning on the torch mode is successful, the application does not have the
+     * exclusive ownership of the flash unit or the camera device. The torch mode will be turned
+     * off and becomes unavailable when the camera device that the flash unit belongs to becomes
+     * unavailable ({@link CameraManager.TorchCallback#onTorchModeAvailable} will be
+     * invoked) or when other camera resources to keep the torch on become unavailable (
+     * {@link CameraManager.TorchCallback#onTorchModeUnavailable} will be invoked). Also,
+     * other applications are free to call {@link #setTorchMode} to turn off the torch mode (
+     * {@link CameraManager.TorchCallback#onTorchModeChanged} will be invoked).
+     *
+     * @param cameraId
+     *             The unique identifier of the camera device that the flash unit belongs to.
+     * @param enabled
+     *             The desired state of the torch mode for the target camera device. Set to
+     *             {@code true} to turn on the torch mode. Set to {@code false} to turn off the
+     *             torch mode.
+     *
+     * @throws CameraAccessException if it failed to access the flash unit.
+     *             {@link CameraAccessException#CAMERA_IN_USE} will be thrown if the camera device
+     *             is in use. {@link CameraAccessException#MAX_CAMERAS_IN_USE} will be thrown if
+     *             other camera resources needed to turn on the torch mode are in use.
+     *
+     * @throws IllegalArgumentException if cameraId was null, cameraId doesn't match any currently
+     *             or previously available camera device, or the camera device doesn't have a
+     *             flash unit.
+     */
+    public void setTorchMode(String cameraId, boolean enabled) throws CameraAccessException {
+
+    }
+
+    /**
      * A callback for camera devices becoming available or
      * unavailable to open.
      *
@@ -428,6 +508,68 @@
     }
 
     /**
+     * A callback for camera flash torch modes becoming available, unavailable, enabled, or
+     * disabled.
+     *
+     * <p>The torch mode becomes available when the camera device it belongs to is no longer in use
+     * and other camera resources it needs are no longer busy. It becomes unavailable when the
+     * camera device it belongs to becomes unavailable or other camera resouces it needs become
+     * busy due to other higher priority camera activities. The torch mode changes when an
+     * application calls {@link #setTorchMode} successfully.
+     *
+     * <p>Extend this callback and pass an instance of the subclass to
+     * {@link CameraManager#registerTorchCallback} to be notified of such status changes.
+     * </p>
+     *
+     * @see registerTorchCallback
+     */
+    public static abstract class TorchCallback {
+        /**
+         * The torch mode of a camera has become available to use.
+         *
+         * <p>The default implementation of this method does nothing.</p>
+         *
+         * @param cameraId The unique identifier of the camera whose torch mode has become
+         *                 available.
+         */
+        public void onTorchModeAvailable(String cameraId) {
+            // default empty implementation
+        }
+
+        /**
+         * A previously-available torch mode of a camera has become unavailable.
+         *
+         * <p>If torch mode was previously turned on by calling {@link #setTorchMode}, it will be
+         * turned off before {@link CameraManager.TorchCallback#onTorchModeUnavailable} is
+         * invoked. {@link #setTorchMode} will fail until the flash unit becomes available again.
+         * </p>
+         *
+         * <p>The default implementation of this method does nothing.</p>
+         *
+         * @param cameraId The unique identifier of the camera whose torch mode has become
+         *                 unavailable.
+         */
+        public void onTorchModeUnavailable(String cameraId) {
+            // default empty implementation
+        }
+
+        /**
+         * Torch mode of a camera has been turned on or off through {@link #setTorchMode}.
+         *
+         * <p>The default implementation of this method does nothing.</p>
+         *
+         * @param cameraId The unique identifier of the camera whose torch mode has been changed.
+         *
+         * @param enabled The state that the torch mode of the camera has been changed to.
+         *                {@code true} when the torch mode has been turned on. {@code false} when
+         *                the torch mode has been turned off.
+         */
+        public void onTorchModeChanged(String cameraId, boolean enabled) {
+            // default empty implementation
+        }
+    }
+
+    /**
      * Return or create the list of currently connected camera devices.
      *
      * <p>In case of errors connecting to the camera service, will return an empty list.</p>
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index f6df302..af7d365 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -439,23 +439,40 @@
     public static final int REQUEST_AVAILABLE_CAPABILITIES_RAW = 3;
 
     /**
-     * <p>The camera device supports the Zero Shutter Lag use case.</p>
+     * <p>The camera device supports the Zero Shutter Lag reprocessing use case.</p>
      * <ul>
-     * <li>At least one input stream can be used.</li>
-     * <li>RAW_OPAQUE is supported as an output/input format</li>
-     * <li>Using RAW_OPAQUE does not cause a frame rate drop
+     * <li>One input stream is supported, that is, <code>{@link CameraCharacteristics#REQUEST_MAX_NUM_INPUT_STREAMS android.request.maxNumInputStreams} == 1</code>.</li>
+     * <li>OPAQUE is supported as an output/input format, that is,
+     *   StreamConfigurationMap#getOutputSizes(klass) and
+     *   StreamConfigurationMap#getInputSizes(klass) return non empty Size[] and have common
+     *   sizes, where klass is android.media.OpaqueImageRingBufferQueue.class. See
+     *   android.scaler.availableInputOutputFormatsMap for detailed information about
+     *   OPAQUE format.</li>
+     * <li>android.scaler.availableInputOutputFormatsMap has the required map entries.</li>
+     * <li>Using OPAQUE does not cause a frame rate drop
      *   relative to the sensor's maximum capture rate (at that
-     *   resolution).</li>
-     * <li>RAW_OPAQUE will be reprocessable into both YUV_420_888
+     *   resolution), see android.scaler.availableInputOutputFormatsMap for more details.</li>
+     * <li>OPAQUE will be reprocessable into both YUV_420_888
      *   and JPEG formats.</li>
-     * <li>The maximum available resolution for RAW_OPAQUE streams
+     * <li>The maximum available resolution for OPAQUE streams
      *   (both input/output) will match the maximum available
      *   resolution of JPEG streams.</li>
+     * <li>Only below controls are effective for reprocessing requests and
+     *   will be present in capture results, other controls in reprocess
+     *   requests will be ignored by the camera device.<ul>
+     * <li>android.jpeg.*</li>
+     * <li>{@link CaptureRequest#NOISE_REDUCTION_MODE android.noiseReduction.mode}</li>
+     * <li>{@link CaptureRequest#EDGE_MODE android.edge.mode}</li>
      * </ul>
+     * </li>
+     * </ul>
+     *
+     * @see CaptureRequest#EDGE_MODE
+     * @see CaptureRequest#NOISE_REDUCTION_MODE
+     * @see CameraCharacteristics#REQUEST_MAX_NUM_INPUT_STREAMS
      * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
-     * @hide
      */
-    public static final int REQUEST_AVAILABLE_CAPABILITIES_ZSL = 4;
+    public static final int REQUEST_AVAILABLE_CAPABILITIES_OPAQUE_REPROCESSING = 4;
 
     /**
      * <p>The camera device supports accurately reporting the sensor settings for many of
@@ -515,6 +532,45 @@
      */
     public static final int REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE = 6;
 
+    /**
+     * <p>The camera device supports the YUV420_888 reprocessing use case, similar as
+     * OPAQUE_REPROCESSING, This capability requires the camera device to support the
+     * following:</p>
+     * <ul>
+     * <li>One input stream is supported, that is, <code>{@link CameraCharacteristics#REQUEST_MAX_NUM_INPUT_STREAMS android.request.maxNumInputStreams} == 1</code>.</li>
+     * <li>YUV420_888 is supported as a common format for both input and output, that is,
+     *   StreamConfigurationMap#getOutputSizes(YUV420_888) and
+     *   StreamConfigurationMap#getInputSizes(YUV420_888) return non empty Size[] and have
+     *   common sizes.</li>
+     * <li>android.scaler.availableInputOutputFormatsMap has the required map entries.</li>
+     * <li>Using YUV420_888 does not cause a frame rate drop
+     *   relative to the sensor's maximum capture rate (at that
+     *   resolution), see android.scaler.availableInputOutputFormatsMap for more details.</li>
+     * <li>YUV420_888 will be reprocessable into both YUV_420_888
+     *   and JPEG formats.</li>
+     * <li>The maximum available resolution for YUV420_888 streams
+     *   (both input/output) will match the maximum available
+     *   resolution of JPEG streams.</li>
+     * <li>Only the below controls are effective for reprocessing requests and will be
+     *   present in capture results. The reprocess requests are from the original capture
+     *   results that are assocaited with the intermidate YUV420_888 output buffers.
+     *   All other controls in the reprocess requests will be ignored by the camera device.<ul>
+     * <li>android.jpeg.*</li>
+     * <li>{@link CaptureRequest#NOISE_REDUCTION_MODE android.noiseReduction.mode}</li>
+     * <li>{@link CaptureRequest#EDGE_MODE android.edge.mode}</li>
+     * <li>{@link CaptureRequest#REPROCESS_EFFECTIVE_EXPOSURE_FACTOR android.reprocess.effectiveExposureFactor}</li>
+     * </ul>
+     * </li>
+     * </ul>
+     *
+     * @see CaptureRequest#EDGE_MODE
+     * @see CaptureRequest#NOISE_REDUCTION_MODE
+     * @see CaptureRequest#REPROCESS_EFFECTIVE_EXPOSURE_FACTOR
+     * @see CameraCharacteristics#REQUEST_MAX_NUM_INPUT_STREAMS
+     * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
+     */
+    public static final int REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING = 7;
+
     //
     // Enumeration values for CameraCharacteristics#SCALER_CROPPING_TYPE
     //
@@ -1830,6 +1886,13 @@
      */
     public static final int NOISE_REDUCTION_MODE_HIGH_QUALITY = 2;
 
+    /**
+     * <p>MINIMAL noise reduction is applied without reducing frame rate relative to
+     * sensor output. </p>
+     * @see CaptureRequest#NOISE_REDUCTION_MODE
+     */
+    public static final int NOISE_REDUCTION_MODE_MINIMAL = 3;
+
     //
     // Enumeration values for CaptureRequest#SENSOR_TEST_PATTERN_MODE
     //
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index 0849df8..fb37ae5 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -1154,7 +1154,7 @@
      * <p>This control (except for MANUAL) is only effective if
      * <code>{@link CaptureRequest#CONTROL_MODE android.control.mode} != OFF</code> and any 3A routine is active.</p>
      * <p>ZERO_SHUTTER_LAG will be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities}
-     * contains ZSL. MANUAL will be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities}
+     * contains OPAQUE_REPROCESSING. MANUAL will be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities}
      * contains MANUAL_SENSOR. Other intent values are always supported.</p>
      * <p><b>Possible values:</b>
      * <ul>
@@ -1372,6 +1372,10 @@
      * camera device will use the highest-quality enhancement algorithms,
      * even if it slows down capture rate. FAST means the camera device will
      * not slow down capture rate when applying edge enhancement.</p>
+     * <p>For YUV_REPROCESSING, these FAST/HIGH_QUALITY modes both mean that the camera
+     * device will apply FAST/HIGH_QUALITY YUV-domain edge enhancement, respectively.
+     * The camera device may adjust its internal noise reduction parameters for best
+     * image quality based on the {@link CaptureRequest#REPROCESS_EFFECTIVE_EXPOSURE_FACTOR android.reprocess.effectiveExposureFactor}, if it is set.</p>
      * <p><b>Possible values:</b>
      * <ul>
      *   <li>{@link #EDGE_MODE_OFF OFF}</li>
@@ -1387,6 +1391,7 @@
      *
      * @see CameraCharacteristics#EDGE_AVAILABLE_EDGE_MODES
      * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
+     * @see CaptureRequest#REPROCESS_EFFECTIVE_EXPOSURE_FACTOR
      * @see #EDGE_MODE_OFF
      * @see #EDGE_MODE_FAST
      * @see #EDGE_MODE_HIGH_QUALITY
@@ -1751,18 +1756,28 @@
     /**
      * <p>Mode of operation for the noise reduction algorithm.</p>
      * <p>The noise reduction algorithm attempts to improve image quality by removing
-     * excessive noise added by the capture process, especially in dark conditions.
-     * OFF means no noise reduction will be applied by the camera device.</p>
+     * excessive noise added by the capture process, especially in dark conditions.</p>
+     * <p>OFF means no noise reduction will be applied by the camera device, for both raw and
+     * YUV domain.</p>
+     * <p>MINIMAL means that only sensor raw domain basic noise reduction is enabled ,to remove
+     * demosaicing or other processing artifacts. For YUV_REPROCESSING, MINIMAL is same as OFF.
+     * This mode is optional, may not be support by all devices. The application should check
+     * {@link CameraCharacteristics#NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES android.noiseReduction.availableNoiseReductionModes} before using it.</p>
      * <p>FAST/HIGH_QUALITY both mean camera device determined noise filtering
      * will be applied. HIGH_QUALITY mode indicates that the camera device
      * will use the highest-quality noise filtering algorithms,
      * even if it slows down capture rate. FAST means the camera device will not
      * slow down capture rate when applying noise filtering.</p>
+     * <p>For YUV_REPROCESSING, these FAST/HIGH_QUALITY modes both mean that the camera device
+     * will apply FAST/HIGH_QUALITY YUV domain noise reduction, respectively. The camera device
+     * may adjust the noise reduction parameters for best image quality based on the
+     * {@link CaptureRequest#REPROCESS_EFFECTIVE_EXPOSURE_FACTOR android.reprocess.effectiveExposureFactor} if it is set.</p>
      * <p><b>Possible values:</b>
      * <ul>
      *   <li>{@link #NOISE_REDUCTION_MODE_OFF OFF}</li>
      *   <li>{@link #NOISE_REDUCTION_MODE_FAST FAST}</li>
      *   <li>{@link #NOISE_REDUCTION_MODE_HIGH_QUALITY HIGH_QUALITY}</li>
+     *   <li>{@link #NOISE_REDUCTION_MODE_MINIMAL MINIMAL}</li>
      * </ul></p>
      * <p><b>Available values for this device:</b><br>
      * {@link CameraCharacteristics#NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES android.noiseReduction.availableNoiseReductionModes}</p>
@@ -1773,9 +1788,11 @@
      *
      * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
      * @see CameraCharacteristics#NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES
+     * @see CaptureRequest#REPROCESS_EFFECTIVE_EXPOSURE_FACTOR
      * @see #NOISE_REDUCTION_MODE_OFF
      * @see #NOISE_REDUCTION_MODE_FAST
      * @see #NOISE_REDUCTION_MODE_HIGH_QUALITY
+     * @see #NOISE_REDUCTION_MODE_MINIMAL
      */
     @PublicKey
     public static final Key<Integer> NOISE_REDUCTION_MODE =
@@ -2416,6 +2433,52 @@
     public static final Key<Boolean> BLACK_LEVEL_LOCK =
             new Key<Boolean>("android.blackLevel.lock", boolean.class);
 
+    /**
+     * <p>The amount of exposure time increase factor applied to the original output
+     * frame by the application processing before sending for reprocessing.</p>
+     * <p>This is optional, and will be supported if the camera device supports YUV_REPROCESSING
+     * capability ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} contains YUV_REPROCESSING).</p>
+     * <p>For some YUV reprocessing use cases, the application may choose to filter the original
+     * output frames to effectively reduce the noise to the same level as a frame that was
+     * captured with longer exposure time. To be more specific, assuming the original captured
+     * images were captured with a sensitivity of S and an exposure time of T, the model in
+     * the camera device is that the amount of noise in the image would be approximately what
+     * would be expected if the original capture parameters had been a sensitivity of
+     * S/effectiveExposureFactor and an exposure time of T*effectiveExposureFactor, rather
+     * than S and T respectively. If the captured images were processed by the application
+     * before being sent for reprocessing, then the application may have used image processing
+     * algorithms and/or multi-frame image fusion to reduce the noise in the
+     * application-processed images (input images). By using the effectiveExposureFactor
+     * control, the application can communicate to the camera device the actual noise level
+     * improvement in the application-processed image. With this information, the camera
+     * device can select appropriate noise reduction and edge enhancement parameters to avoid
+     * excessive noise reduction ({@link CaptureRequest#NOISE_REDUCTION_MODE android.noiseReduction.mode}) and insufficient edge
+     * enhancement ({@link CaptureRequest#EDGE_MODE android.edge.mode}) being applied to the reprocessed frames.</p>
+     * <p>For example, for multi-frame image fusion use case, the application may fuse
+     * multiple output frames together to a final frame for reprocessing. When N image are
+     * fused into 1 image for reprocessing, the exposure time increase factor could be up to
+     * square root of N (based on a simple photon shot noise model). The camera device will
+     * adjust the reprocessing noise reduction and edge enhancement parameters accordingly to
+     * produce the best quality images.</p>
+     * <p>This is relative factor, 1.0 indicates the application hasn't processed the input
+     * buffer in a way that affects its effective exposure time.</p>
+     * <p>This control is only effective for YUV reprocessing capture request. For noise
+     * reduction reprocessing, it is only effective when <code>{@link CaptureRequest#NOISE_REDUCTION_MODE android.noiseReduction.mode} != OFF</code>.
+     * Similarly, for edge enhancement reprocessing, it is only effective when
+     * <code>{@link CaptureRequest#EDGE_MODE android.edge.mode} != OFF</code>.</p>
+     * <p><b>Units</b>: Relative exposure time increase factor.</p>
+     * <p><b>Range of valid values:</b><br>
+     * &gt;= 1.0</p>
+     * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+     *
+     * @see CaptureRequest#EDGE_MODE
+     * @see CaptureRequest#NOISE_REDUCTION_MODE
+     * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
+     */
+    @PublicKey
+    public static final Key<Float> REPROCESS_EFFECTIVE_EXPOSURE_FACTOR =
+            new Key<Float>("android.reprocess.effectiveExposureFactor", float.class);
+
     /*~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~
      * End generated code
      *~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~O@*/
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index 1396940..5642f6f 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -1627,7 +1627,7 @@
      * <p>This control (except for MANUAL) is only effective if
      * <code>{@link CaptureRequest#CONTROL_MODE android.control.mode} != OFF</code> and any 3A routine is active.</p>
      * <p>ZERO_SHUTTER_LAG will be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities}
-     * contains ZSL. MANUAL will be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities}
+     * contains OPAQUE_REPROCESSING. MANUAL will be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities}
      * contains MANUAL_SENSOR. Other intent values are always supported.</p>
      * <p><b>Possible values:</b>
      * <ul>
@@ -1988,6 +1988,10 @@
      * camera device will use the highest-quality enhancement algorithms,
      * even if it slows down capture rate. FAST means the camera device will
      * not slow down capture rate when applying edge enhancement.</p>
+     * <p>For YUV_REPROCESSING, these FAST/HIGH_QUALITY modes both mean that the camera
+     * device will apply FAST/HIGH_QUALITY YUV-domain edge enhancement, respectively.
+     * The camera device may adjust its internal noise reduction parameters for best
+     * image quality based on the {@link CaptureRequest#REPROCESS_EFFECTIVE_EXPOSURE_FACTOR android.reprocess.effectiveExposureFactor}, if it is set.</p>
      * <p><b>Possible values:</b>
      * <ul>
      *   <li>{@link #EDGE_MODE_OFF OFF}</li>
@@ -2003,6 +2007,7 @@
      *
      * @see CameraCharacteristics#EDGE_AVAILABLE_EDGE_MODES
      * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
+     * @see CaptureRequest#REPROCESS_EFFECTIVE_EXPOSURE_FACTOR
      * @see #EDGE_MODE_OFF
      * @see #EDGE_MODE_FAST
      * @see #EDGE_MODE_HIGH_QUALITY
@@ -2465,18 +2470,28 @@
     /**
      * <p>Mode of operation for the noise reduction algorithm.</p>
      * <p>The noise reduction algorithm attempts to improve image quality by removing
-     * excessive noise added by the capture process, especially in dark conditions.
-     * OFF means no noise reduction will be applied by the camera device.</p>
+     * excessive noise added by the capture process, especially in dark conditions.</p>
+     * <p>OFF means no noise reduction will be applied by the camera device, for both raw and
+     * YUV domain.</p>
+     * <p>MINIMAL means that only sensor raw domain basic noise reduction is enabled ,to remove
+     * demosaicing or other processing artifacts. For YUV_REPROCESSING, MINIMAL is same as OFF.
+     * This mode is optional, may not be support by all devices. The application should check
+     * {@link CameraCharacteristics#NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES android.noiseReduction.availableNoiseReductionModes} before using it.</p>
      * <p>FAST/HIGH_QUALITY both mean camera device determined noise filtering
      * will be applied. HIGH_QUALITY mode indicates that the camera device
      * will use the highest-quality noise filtering algorithms,
      * even if it slows down capture rate. FAST means the camera device will not
      * slow down capture rate when applying noise filtering.</p>
+     * <p>For YUV_REPROCESSING, these FAST/HIGH_QUALITY modes both mean that the camera device
+     * will apply FAST/HIGH_QUALITY YUV domain noise reduction, respectively. The camera device
+     * may adjust the noise reduction parameters for best image quality based on the
+     * {@link CaptureRequest#REPROCESS_EFFECTIVE_EXPOSURE_FACTOR android.reprocess.effectiveExposureFactor} if it is set.</p>
      * <p><b>Possible values:</b>
      * <ul>
      *   <li>{@link #NOISE_REDUCTION_MODE_OFF OFF}</li>
      *   <li>{@link #NOISE_REDUCTION_MODE_FAST FAST}</li>
      *   <li>{@link #NOISE_REDUCTION_MODE_HIGH_QUALITY HIGH_QUALITY}</li>
+     *   <li>{@link #NOISE_REDUCTION_MODE_MINIMAL MINIMAL}</li>
      * </ul></p>
      * <p><b>Available values for this device:</b><br>
      * {@link CameraCharacteristics#NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES android.noiseReduction.availableNoiseReductionModes}</p>
@@ -2487,9 +2502,11 @@
      *
      * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
      * @see CameraCharacteristics#NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES
+     * @see CaptureRequest#REPROCESS_EFFECTIVE_EXPOSURE_FACTOR
      * @see #NOISE_REDUCTION_MODE_OFF
      * @see #NOISE_REDUCTION_MODE_FAST
      * @see #NOISE_REDUCTION_MODE_HIGH_QUALITY
+     * @see #NOISE_REDUCTION_MODE_MINIMAL
      */
     @PublicKey
     public static final Key<Integer> NOISE_REDUCTION_MODE =
@@ -3647,6 +3664,52 @@
     public static final Key<Long> SYNC_FRAME_NUMBER =
             new Key<Long>("android.sync.frameNumber", long.class);
 
+    /**
+     * <p>The amount of exposure time increase factor applied to the original output
+     * frame by the application processing before sending for reprocessing.</p>
+     * <p>This is optional, and will be supported if the camera device supports YUV_REPROCESSING
+     * capability ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} contains YUV_REPROCESSING).</p>
+     * <p>For some YUV reprocessing use cases, the application may choose to filter the original
+     * output frames to effectively reduce the noise to the same level as a frame that was
+     * captured with longer exposure time. To be more specific, assuming the original captured
+     * images were captured with a sensitivity of S and an exposure time of T, the model in
+     * the camera device is that the amount of noise in the image would be approximately what
+     * would be expected if the original capture parameters had been a sensitivity of
+     * S/effectiveExposureFactor and an exposure time of T*effectiveExposureFactor, rather
+     * than S and T respectively. If the captured images were processed by the application
+     * before being sent for reprocessing, then the application may have used image processing
+     * algorithms and/or multi-frame image fusion to reduce the noise in the
+     * application-processed images (input images). By using the effectiveExposureFactor
+     * control, the application can communicate to the camera device the actual noise level
+     * improvement in the application-processed image. With this information, the camera
+     * device can select appropriate noise reduction and edge enhancement parameters to avoid
+     * excessive noise reduction ({@link CaptureRequest#NOISE_REDUCTION_MODE android.noiseReduction.mode}) and insufficient edge
+     * enhancement ({@link CaptureRequest#EDGE_MODE android.edge.mode}) being applied to the reprocessed frames.</p>
+     * <p>For example, for multi-frame image fusion use case, the application may fuse
+     * multiple output frames together to a final frame for reprocessing. When N image are
+     * fused into 1 image for reprocessing, the exposure time increase factor could be up to
+     * square root of N (based on a simple photon shot noise model). The camera device will
+     * adjust the reprocessing noise reduction and edge enhancement parameters accordingly to
+     * produce the best quality images.</p>
+     * <p>This is relative factor, 1.0 indicates the application hasn't processed the input
+     * buffer in a way that affects its effective exposure time.</p>
+     * <p>This control is only effective for YUV reprocessing capture request. For noise
+     * reduction reprocessing, it is only effective when <code>{@link CaptureRequest#NOISE_REDUCTION_MODE android.noiseReduction.mode} != OFF</code>.
+     * Similarly, for edge enhancement reprocessing, it is only effective when
+     * <code>{@link CaptureRequest#EDGE_MODE android.edge.mode} != OFF</code>.</p>
+     * <p><b>Units</b>: Relative exposure time increase factor.</p>
+     * <p><b>Range of valid values:</b><br>
+     * &gt;= 1.0</p>
+     * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+     *
+     * @see CaptureRequest#EDGE_MODE
+     * @see CaptureRequest#NOISE_REDUCTION_MODE
+     * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
+     */
+    @PublicKey
+    public static final Key<Float> REPROCESS_EFFECTIVE_EXPOSURE_FACTOR =
+            new Key<Float>("android.reprocess.effectiveExposureFactor", float.class);
+
     /*~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~
      * End generated code
      *~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~O@*/
diff --git a/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java b/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
index 03540e1..347db05 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
@@ -328,15 +328,15 @@
         appendStreamConfig(availableStreamConfigs,
                 ImageFormat.YUV_420_888, previewSizes);
         for (int format : p.getSupportedPreviewFormats()) {
-            if (ImageFormat.isPublicFormat(format)) {
+            if (ImageFormat.isPublicFormat(format) && format != ImageFormat.NV21) {
                 appendStreamConfig(availableStreamConfigs, format, previewSizes);
-            } else {
+            } else if (VERBOSE) {
                 /*
                  *  Do not add any formats unknown to us
                  * (since it would fail runtime checks in StreamConfigurationMap)
                  */
-                Log.w(TAG,
-                        String.format("mapStreamConfigs - Skipping non-public format %x", format));
+                Log.v(TAG,
+                        String.format("mapStreamConfigs - Skipping format %x", format));
             }
         }
 
@@ -389,8 +389,8 @@
             int j = 0;
             for (String mode : antiBandingModes) {
                 int convertedMode = convertAntiBandingMode(mode);
-                if (convertedMode == -1) {
-                    Log.w(TAG, "Antibanding mode " + ((mode == null) ? "NULL" : mode) +
+                if (VERBOSE && convertedMode == -1) {
+                    Log.v(TAG, "Antibanding mode " + ((mode == null) ? "NULL" : mode) +
                             " not supported, skipping...");
                 } else {
                     modes[j++] = convertedMode;
diff --git a/core/java/android/hardware/camera2/utils/ArrayUtils.java b/core/java/android/hardware/camera2/utils/ArrayUtils.java
index 5a78bbd..79a335c 100644
--- a/core/java/android/hardware/camera2/utils/ArrayUtils.java
+++ b/core/java/android/hardware/camera2/utils/ArrayUtils.java
@@ -117,7 +117,7 @@
 
             // Guard against unexpected values
             if (strIndex < 0) {
-                Log.w(TAG, "Ignoring invalid value " + str);
+                if (VERBOSE) Log.v(TAG, "Ignoring invalid value " + str);
                 continue;
             }
 
diff --git a/core/java/android/hardware/hdmi/HdmiRecordSources.java b/core/java/android/hardware/hdmi/HdmiRecordSources.java
index 922b8e7..7e94b89 100644
--- a/core/java/android/hardware/hdmi/HdmiRecordSources.java
+++ b/core/java/android/hardware/hdmi/HdmiRecordSources.java
@@ -759,6 +759,8 @@
      */
     @SystemApi
     public static boolean checkRecordSource(byte[] recordSource) {
+        if (recordSource == null || recordSource.length == 0) return false;
+
         int recordSourceType = recordSource[0];
         int extraDataSize = recordSource.length - 1;
         switch (recordSourceType) {
diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java
index f64ef87..f283051 100644
--- a/core/java/android/hardware/usb/UsbManager.java
+++ b/core/java/android/hardware/usb/UsbManager.java
@@ -68,6 +68,8 @@
      * accessory function is enabled
      * <li> {@link #USB_FUNCTION_AUDIO_SOURCE} boolean extra indicating whether the
      * audio source function is enabled
+     * <li> {@link #USB_FUNCTION_MIDI} boolean extra indicating whether the
+     * MIDI function is enabled
      * </ul>
      *
      * {@hide}
@@ -188,6 +190,14 @@
     public static final String USB_FUNCTION_AUDIO_SOURCE = "audio_source";
 
     /**
+     * Name of the MIDI USB function.
+     * Used in extras for the {@link #ACTION_USB_STATE} broadcast
+     *
+     * {@hide}
+     */
+    public static final String USB_FUNCTION_MIDI = "midi";
+
+    /**
      * Name of the Accessory USB function.
      * Used in extras for the {@link #ACTION_USB_STATE} broadcast
      *
diff --git a/core/java/android/midi/MidiInputPort.java b/core/java/android/midi/MidiInputPort.java
index 5d806cf8..88ace5f 100644
--- a/core/java/android/midi/MidiInputPort.java
+++ b/core/java/android/midi/MidiInputPort.java
@@ -33,7 +33,7 @@
     private final FileOutputStream mOutputStream;
 
     // buffer to use for sending messages out our output stream
-    private final byte[] mBuffer = new byte[MAX_PACKED_MESSAGE_SIZE];
+    private final byte[] mBuffer = new byte[MAX_PACKET_SIZE];
 
   /* package */ MidiInputPort(ParcelFileDescriptor pfd, int portNumber) {
         super(portNumber);
@@ -50,10 +50,19 @@
      *                  {@link java.lang.System#nanoTime}
      */
     public void onPost(byte[] msg, int offset, int count, long timestamp) throws IOException {
+        assert(offset >= 0 && count >= 0 && offset + count <= msg.length);
+
         synchronized (mBuffer) {
-            int length = packMessage(msg, offset, count, timestamp, mBuffer);
             try {
-                mOutputStream.write(mBuffer, 0, length);
+                while (count > 0) {
+                    int length = packMessage(msg, offset, count, timestamp, mBuffer);
+                    mOutputStream.write(mBuffer, 0, length);
+                    int sent = getMessageSize(mBuffer, length);
+                    assert(sent >= 0 && sent <= length);
+
+                    offset += sent;
+                    count -= sent;
+                }
             } catch (IOException e) {
                 IoUtils.closeQuietly(mOutputStream);
                 // report I/O failure
diff --git a/core/java/android/midi/MidiOutputPort.java b/core/java/android/midi/MidiOutputPort.java
index b550ed4..00b7bad 100644
--- a/core/java/android/midi/MidiOutputPort.java
+++ b/core/java/android/midi/MidiOutputPort.java
@@ -45,7 +45,7 @@
     private final Thread mThread = new Thread() {
         @Override
         public void run() {
-            byte[] buffer = new byte[MAX_PACKED_MESSAGE_SIZE];
+            byte[] buffer = new byte[MAX_PACKET_SIZE];
             ArrayList<MidiReceiver> deadReceivers = new ArrayList<MidiReceiver>();
 
             try {
@@ -54,9 +54,6 @@
                     int count = mInputStream.read(buffer);
                     if (count < 0) {
                         break;
-                    } else if (count < MIN_PACKED_MESSAGE_SIZE || count > MAX_PACKED_MESSAGE_SIZE) {
-                        Log.e(TAG, "Number of bytes read out of range: " + count);
-                        continue;
                     }
 
                     int offset = getMessageOffset(buffer, count);
@@ -96,7 +93,6 @@
         }
     };
 
-
   /* package */ MidiOutputPort(ParcelFileDescriptor pfd, int portNumber) {
         super(portNumber);
         mInputStream = new ParcelFileDescriptor.AutoCloseInputStream(pfd);
diff --git a/core/java/android/midi/MidiPort.java b/core/java/android/midi/MidiPort.java
index 1fa7946..44d1a88 100644
--- a/core/java/android/midi/MidiPort.java
+++ b/core/java/android/midi/MidiPort.java
@@ -32,16 +32,19 @@
     private final int mPortNumber;
 
     /**
-     * Minimum size of packed message as sent through our ParcelFileDescriptor
-     * 8 bytes for timestamp and 1 to 3 bytes for message
+     * Maximum size of a packet that can pass through our ParcelFileDescriptor
      */
-    protected static final int MIN_PACKED_MESSAGE_SIZE = 9;
+    protected static final int MAX_PACKET_SIZE = 1024;
 
     /**
-     * Maximum size of packed message as sent through our ParcelFileDescriptor
-     * 8 bytes for timestamp and 1 to 3 bytes for message
+     * size of message timestamp in bytes
      */
-    protected static final int MAX_PACKED_MESSAGE_SIZE = 11;
+    private static final int TIMESTAMP_SIZE = 8;
+
+    /**
+     * Maximum amount of MIDI data that can be included in a packet
+     */
+    public static final int MAX_PACKET_DATA_SIZE = MAX_PACKET_SIZE - TIMESTAMP_SIZE;
 
 
   /* package */ MidiPort(int portNumber) {
@@ -76,49 +79,52 @@
      */
     protected static int packMessage(byte[] message, int offset, int size, long timestamp,
             byte[] dest) {
-        // pack variable length message first
+        if (size + TIMESTAMP_SIZE > MAX_PACKET_SIZE) {
+            size = MAX_PACKET_SIZE - TIMESTAMP_SIZE;
+        }
+        // message data goes first
         System.arraycopy(message, offset, dest, 0, size);
-        int destOffset = size;
-        // timestamp takes 8 bytes
-        for (int i = 0; i < 8; i++) {
-            dest[destOffset++] = (byte)timestamp;
+
+        // followed by timestamp
+        for (int i = 0; i < TIMESTAMP_SIZE; i++) {
+            dest[size++] = (byte)timestamp;
             timestamp >>= 8;
         }
 
-        return destOffset;
+        return size;
     }
 
     /**
-     * Utility function for unpacking a MIDI message to be sent through our ParcelFileDescriptor
-     * returns the offet of of MIDI message in packed buffer
+     * Utility function for unpacking a MIDI message received from our ParcelFileDescriptor
+     * returns the offset of the MIDI message in packed buffer
      */
     protected static int getMessageOffset(byte[] buffer, int bufferLength) {
-        // message is at start of buffer
+        // message is at the beginning
         return 0;
     }
 
     /**
-     * Utility function for unpacking a MIDI message to be sent through our ParcelFileDescriptor
-     * returns size of MIDI message in packed buffer
+     * Utility function for unpacking a MIDI message received from our ParcelFileDescriptor
+     * returns size of MIDI data in packed buffer
      */
     protected static int getMessageSize(byte[] buffer, int bufferLength) {
-        // message length is total buffer length minus size of the timestamp and port number
-        return bufferLength - 8 /* sizeof(timestamp) */;
+        // message length is total buffer length minus size of the timestamp
+        return bufferLength - TIMESTAMP_SIZE;
     }
 
     /**
-     * Utility function for unpacking a MIDI message to be sent through our ParcelFileDescriptor
+     * Utility function for unpacking a MIDI message received from our ParcelFileDescriptor
      * unpacks timestamp from packed buffer
      */
     protected static long getMessageTimeStamp(byte[] buffer, int bufferLength) {
+        // timestamp is at end of the packet
+        int offset = bufferLength;
         long timestamp = 0;
 
-        // timestamp follows variable length message data
-        int dataLength = getMessageSize(buffer, bufferLength);
-        for (int i = dataLength + 7; i >= dataLength; i--) {
-            int b = (int)buffer[i] & 0xFF;
+        for (int i = 0; i < TIMESTAMP_SIZE; i++) {
+            int b = (int)buffer[--offset] & 0xFF;
             timestamp = (timestamp << 8) | b;
         }
         return timestamp;
-     }
+    }
 }
diff --git a/core/java/android/midi/MidiReceiver.java b/core/java/android/midi/MidiReceiver.java
index 0b183cc..a4e1a10 100644
--- a/core/java/android/midi/MidiReceiver.java
+++ b/core/java/android/midi/MidiReceiver.java
@@ -30,6 +30,8 @@
      * NOTE: the msg array parameter is only valid within the context of this call.
      * The msg bytes should be copied by the receiver rather than retaining a reference
      * to this parameter.
+     * Also, modifying the contents of the msg array parameter may result in other receivers
+     * in the same application receiving incorrect values in their onPost() method.
      *
      * @param msg a byte array containing the MIDI message
      * @param offset the offset of the first byte of the message in the byte array
diff --git a/core/java/android/midi/MidiUtils.java b/core/java/android/midi/MidiUtils.java
deleted file mode 100644
index e60e2db..0000000
--- a/core/java/android/midi/MidiUtils.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.midi;
-
-import android.util.Log;
-
-/**
- * Class containing miscellaneous MIDI utilities.
- *
- * @hide
- */
-public final class MidiUtils {
-    private static final String TAG = "MidiUtils";
-
-    private MidiUtils() { }
-
-    /**
-     * Returns data size of a MIDI message based on the message's command byte
-     * @param b the message command byte
-     * @return the message's data length
-     */
-    public static int getMessageDataSize(byte b) {
-        switch (b & 0xF0) {
-            case 0x80:
-            case 0x90:
-            case 0xA0:
-            case 0xB0:
-            case 0xE0:
-                return 2;
-            case 0xC0:
-            case 0xD0:
-                return 1;
-            case 0xF0:
-                switch (b & 0x0F) {
-                    case 0x00:
-                        Log.e(TAG, "System Exclusive not supported yet");
-                        return -1;
-                    case 0x01:
-                    case 0x03:
-                        return 1;
-                    case 0x02:
-                        return 2;
-                    default:
-                        return 0;
-                }
-            default:
-                Log.e(TAG, "unknown MIDI command " + b);
-                return -1;
-        }
-    }
-}
diff --git a/core/java/android/net/StaticIpConfiguration.java b/core/java/android/net/StaticIpConfiguration.java
index 365f2b6..37ee961 100644
--- a/core/java/android/net/StaticIpConfiguration.java
+++ b/core/java/android/net/StaticIpConfiguration.java
@@ -188,6 +188,7 @@
         for (InetAddress dnsServer : dnsServers) {
             NetworkUtils.parcelInetAddress(dest, dnsServer, flags);
         }
+        dest.writeString(domains);
     }
 
     protected static void readFromParcel(StaticIpConfiguration s, Parcel in) {
@@ -198,5 +199,6 @@
         for (int i = 0; i < size; i++) {
             s.dnsServers.add(NetworkUtils.unparcelInetAddress(in));
         }
+        s.domains = in.readString();
     }
 }
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 2dfd919..e4b594a 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -597,6 +597,11 @@
          * Lollipop with an extra sugar coating on the outside!
          */
         public static final int LOLLIPOP_MR1 = 22;
+
+        /**
+         * M comes after L.
+         */
+        public static final int MNC = CUR_DEVELOPMENT;
     }
 
     /** The type of build, like "user" or "eng". */
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index 7b13e84..d08ab46 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -188,9 +188,6 @@
 
     void wallpaperCommandComplete(IBinder window, in Bundle result);
 
-    void setUniverseTransform(IBinder window, float alpha, float offx, float offy,
-            float dsdx, float dtdx, float dsdy, float dtdy);
-
     /**
      * Notifies that a rectangle on the screen has been requested.
      */
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index c3f679f..19c9271 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -4569,11 +4569,18 @@
     }
 
     /**
-     * Register a callback to be invoked when the scroll position of this view
-     * changed.
+     * Register a callback to be invoked when the scroll X or Y positions of
+     * this view change.
+     * <p>
+     * <b>Note:</b> Some views handle scrolling independently from View and may
+     * have their own separate listeners for scroll-type events. For example,
+     * {@link android.widget.ListView ListView} allows clients to register an
+     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
+     * to listen for changes in list scroll position.
      *
-     * @param l The callback that will run.
-     * @hide Only used internally.
+     * @param l The listener to notify when the scroll X or Y position changes.
+     * @see android.view.View#getScrollX()
+     * @see android.view.View#getScrollY()
      */
     public void setOnScrollChangeListener(OnScrollChangeListener l) {
         getListenerInfo().mOnScrollChangeListener = l;
@@ -5896,23 +5903,6 @@
         return true;
     }
 
-    /**
-     * Adds the clickable rectangles withing the bounds of this view. They
-     * may overlap. This method is intended for use only by the accessibility
-     * layer.
-     *
-     * @param outRects List to which to add clickable areas.
-     *
-     * @hide
-     */
-    public void addClickableRectsForAccessibility(List<RectF> outRects) {
-        if (isClickable() || isLongClickable()) {
-            RectF bounds = new RectF();
-            bounds.set(0, 0, getWidth(), getHeight());
-            outRects.add(bounds);
-        }
-    }
-
     static void offsetRects(List<RectF> rects, float offsetX, float offsetY) {
         final int rectCount = rects.size();
         for (int i = 0; i < rectCount; i++) {
@@ -9959,9 +9949,15 @@
 
     /**
      * Interface definition for a callback to be invoked when the scroll
-     * position of a view changes.
+     * X or Y positions of a view change.
+     * <p>
+     * <b>Note:</b> Some views handle scrolling independently from View and may
+     * have their own separate listeners for scroll-type events. For example,
+     * {@link android.widget.ListView ListView} allows clients to register an
+     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
+     * to listen for changes in list scroll position.
      *
-     * @hide Only used internally.
+     * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
      */
     public interface OnScrollChangeListener {
         /**
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index ee9845f..49e4efa 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -857,27 +857,11 @@
 
             // Compute the intersection between the child and the sibling.
             if (siblingBounds.intersect(bounds)) {
-                List<RectF> clickableRects = new ArrayList<>();
-                sibling.addClickableRectsForAccessibility(clickableRects);
-
-                final int clickableRectCount = clickableRects.size();
-                for (int j = 0; j < clickableRectCount; j++) {
-                    RectF clickableRect = clickableRects.get(j);
-
-                    // Translate the clickable rect to our coordinates.
-                    offsetChildRectToMyCoords(clickableRect, sibling);
-
-                    // Compute the intersection between the child and the clickable rects.
-                    if (clickableRect.intersect(bounds)) {
-                        // If a clickable rect completely covers the child, done.
-                        if (clickableRect.equals(bounds)) {
-                            releaseOrderedChildIterator();
-                            return false;
-                        }
-                        // Keep track of the intersection rectangle.
-                        intersections.add(clickableRect);
-                    }
-                }
+                // Conservatively we consider an overlapping sibling to be
+                // interactive and ignore it. This is not ideal as if the
+                // sibling completely covers the view despite handling no
+                // touch events we will not be able to click on the view.
+                intersections.add(siblingBounds);
             }
         }
 
@@ -892,54 +876,6 @@
         return true;
     }
 
-    /**
-     * @hide
-     */
-    @Override
-    public void addClickableRectsForAccessibility(List<RectF> outRects) {
-        int sizeBefore = outRects.size();
-
-        super.addClickableRectsForAccessibility(outRects);
-
-        // If we added ourselves, then no need to visit children.
-        if (outRects.size() > sizeBefore) {
-            return;
-        }
-
-        Iterator<View> iterator = obtainOrderedChildIterator();
-        while (iterator.hasNext()) {
-            View child = iterator.next();
-
-            // Cannot click on an invisible view.
-            if (!isVisible(child)) {
-                continue;
-            }
-
-            sizeBefore = outRects.size();
-
-            // Add clickable rects in the child bounds.
-            child.addClickableRectsForAccessibility(outRects);
-
-            // Offset the clickable rects for out children to our coordinates.
-            final int sizeAfter = outRects.size();
-            for (int j = sizeBefore; j < sizeAfter; j++) {
-                RectF rect = outRects.get(j);
-
-                // Translate the clickable rect to our coordinates.
-                offsetChildRectToMyCoords(rect, child);
-
-                // If a clickable rect fills the parent, done.
-                if ((int) rect.left == 0 && (int) rect.top == 0
-                        && (int) rect.right == mRight && (int) rect.bottom == mBottom) {
-                    releaseOrderedChildIterator();
-                    return;
-                }
-            }
-        }
-
-        releaseOrderedChildIterator();
-    }
-
     private void offsetChildRectToMyCoords(RectF rect, View child) {
         if (!child.hasIdentityMatrix()) {
             child.getMatrix().mapRect(rect);
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index f233c44..15e7060 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1330,6 +1330,11 @@
             }
         }
 
+        // Non-visible windows can't hold accessibility focus.
+        if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
+            host.clearAccessibilityFocus();
+        }
+
         // Execute enqueued actions on every traversal in case a detached view enqueued an action
         getRunQueue().executeActions(mAttachInfo.mHandler);
 
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 8cfe80c..740cb5d 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -501,13 +501,6 @@
         public static final int TYPE_NAVIGATION_BAR_PANEL = FIRST_SYSTEM_WINDOW+24;
 
         /**
-         * Window type: Behind the universe of the real windows.
-         * In multiuser systems shows on all users' windows.
-         * @hide
-         */
-        public static final int TYPE_UNIVERSE_BACKGROUND = FIRST_SYSTEM_WINDOW+25;
-
-        /**
          * Window type: Display overlay window.  Used to simulate secondary display devices.
          * In multiuser systems shows on all users' windows.
          * @hide
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index b8e94ee..ff1fde7 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -579,13 +579,6 @@
     public int getMaxWallpaperLayer();
 
     /**
-     * Return the window layer at which windows appear above the normal
-     * universe (that is no longer impacted by the universe background
-     * transform).
-     */
-    public int getAboveUniverseLayer();
-
-    /**
      * Return the display width available after excluding any screen
      * decorations that can never be removed.  That is, system bar or
      * button bar.
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index b5afdf7..6096d7d 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -721,7 +721,7 @@
      * @return Whether the refresh succeeded.
      */
     public boolean refresh() {
-        return refresh(false);
+        return refresh(true);
     }
 
     /**
diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java
index c6c979e..f1fa1b6 100644
--- a/core/java/android/widget/HorizontalScrollView.java
+++ b/core/java/android/widget/HorizontalScrollView.java
@@ -762,18 +762,6 @@
         awakenScrollBars();
     }
 
-    /**
-     * @hide
-     */
-    @Override
-    public void addClickableRectsForAccessibility(List<RectF> outRects) {
-        // This class always consumes touch events, therefore if it
-        // covers a view we do not want to send a click over it.
-        RectF bounds = new RectF();
-        bounds.set(0, 0, getWidth(), getHeight());
-        outRects.add(bounds);
-    }
-
     /** @hide */
     @Override
     public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index e8bf623..94fc9e9 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -665,6 +665,7 @@
         ColorStateList textColorLink = null;
         int textSize = 15;
         String fontFamily = null;
+        boolean fontFamilyExplicit = false;
         int typefaceIndex = -1;
         int styleIndex = -1;
         boolean allCaps = false;
@@ -1029,6 +1030,7 @@
 
             case com.android.internal.R.styleable.TextView_fontFamily:
                 fontFamily = a.getString(attr);
+                fontFamilyExplicit = true;
                 break;
 
             case com.android.internal.R.styleable.TextView_password:
@@ -1333,6 +1335,9 @@
             typefaceIndex = MONOSPACE;
         }
 
+        if (typefaceIndex != -1 && !fontFamilyExplicit) {
+            fontFamily = null;
+        }
         setTypefaceFromAttrs(fontFamily, typefaceIndex, styleIndex);
 
         if (shadowcolor != 0) {
diff --git a/core/java/android/widget/Toolbar.java b/core/java/android/widget/Toolbar.java
index 0f35e0d..c5325c4 100644
--- a/core/java/android/widget/Toolbar.java
+++ b/core/java/android/widget/Toolbar.java
@@ -1101,18 +1101,6 @@
      * @hide
      */
     @Override
-    public void addClickableRectsForAccessibility(List<RectF> outRects) {
-        // This class always consumes touch events, therefore if it
-        // covers a view we do not want to send a click over it.
-        RectF bounds = new RectF();
-        bounds.set(0, 0, getWidth(), getHeight());
-        outRects.add(bounds);
-    }
-
-    /**
-     * @hide
-     */
-    @Override
     protected void onSetLayoutParams(View child, ViewGroup.LayoutParams lp) {
         /*
          * Apps may set ActionBar.LayoutParams on their action bar custom views when
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index aba4bd0..0eb52cb 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -800,7 +800,12 @@
             if (args.niceName != null) {
                 String property = "wrap." + args.niceName;
                 if (property.length() > 31) {
-                    property = property.substring(0, 31);
+                    // Avoid creating an illegal property name when truncating.
+                    if (property.charAt(30) != '.') {
+                        property = property.substring(0, 31);
+                    } else {
+                        property = property.substring(0, 30);
+                    }
                 }
                 args.invokeWith = SystemProperties.get(property);
                 if (args.invokeWith != null && args.invokeWith.length() == 0) {
diff --git a/core/java/com/android/internal/widget/ActionBarContainer.java b/core/java/com/android/internal/widget/ActionBarContainer.java
index e8e2c8d..7937a95 100644
--- a/core/java/com/android/internal/widget/ActionBarContainer.java
+++ b/core/java/com/android/internal/widget/ActionBarContainer.java
@@ -227,18 +227,6 @@
         return true;
     }
 
-    /**
-     * @hide
-     */
-    @Override
-    public void addClickableRectsForAccessibility(List<RectF> outRects) {
-        // This class always consumes touch events, therefore if it
-        // covers a view we do not want to send a click over it.
-        RectF bounds = new RectF();
-        bounds.set(0, 0, getWidth(), getHeight());
-        outRects.add(bounds);
-    }
-
     @Override
     public boolean onHoverEvent(MotionEvent ev) {
         super.onHoverEvent(ev);
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index cb9b421..1dd10e1 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -87,6 +87,7 @@
     android_graphics_Canvas.cpp \
     android_graphics_Picture.cpp \
     android/graphics/AutoDecodeCancel.cpp \
+    android/graphics/AvoidXfermode.cpp \
     android/graphics/Bitmap.cpp \
     android/graphics/BitmapFactory.cpp \
     android/graphics/Camera.cpp \
diff --git a/core/jni/android/graphics/AvoidXfermode.cpp b/core/jni/android/graphics/AvoidXfermode.cpp
new file mode 100644
index 0000000..9ca1f26
--- /dev/null
+++ b/core/jni/android/graphics/AvoidXfermode.cpp
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "AvoidXfermode.h"
+#include "SkColorPriv.h"
+#include "SkReadBuffer.h"
+#include "SkWriteBuffer.h"
+#include "SkString.h"
+
+AvoidXfermode::AvoidXfermode(SkColor opColor, U8CPU tolerance, Mode mode) {
+    if (tolerance > 255) {
+        tolerance = 255;
+    }
+    fTolerance = SkToU8(tolerance);
+    fOpColor = opColor;
+    fDistMul = (256 << 14) / (tolerance + 1);
+    fMode = mode;
+}
+
+SkFlattenable* AvoidXfermode::CreateProc(SkReadBuffer& buffer) {
+    const SkColor color = buffer.readColor();
+    const unsigned tolerance = buffer.readUInt();
+    const unsigned mode = buffer.readUInt();
+    return Create(color, tolerance, (Mode)mode);
+}
+
+void AvoidXfermode::flatten(SkWriteBuffer& buffer) const {
+    buffer.writeColor(fOpColor);
+    buffer.writeUInt(fTolerance);
+    buffer.writeUInt(fMode);
+}
+
+// returns 0..31
+static unsigned color_dist16(uint16_t c, unsigned r, unsigned g, unsigned b) {
+    SkASSERT(r <= SK_R16_MASK);
+    SkASSERT(g <= SK_G16_MASK);
+    SkASSERT(b <= SK_B16_MASK);
+
+    unsigned dr = SkAbs32(SkGetPackedR16(c) - r);
+    unsigned dg = SkAbs32(SkGetPackedG16(c) - g) >> (SK_G16_BITS - SK_R16_BITS);
+    unsigned db = SkAbs32(SkGetPackedB16(c) - b);
+
+    return SkMax32(dr, SkMax32(dg, db));
+}
+
+// returns 0..255
+static unsigned color_dist32(SkPMColor c, U8CPU r, U8CPU g, U8CPU b) {
+    SkASSERT(r <= 0xFF);
+    SkASSERT(g <= 0xFF);
+    SkASSERT(b <= 0xFF);
+
+    unsigned dr = SkAbs32(SkGetPackedR32(c) - r);
+    unsigned dg = SkAbs32(SkGetPackedG32(c) - g);
+    unsigned db = SkAbs32(SkGetPackedB32(c) - b);
+
+    return SkMax32(dr, SkMax32(dg, db));
+}
+
+static int scale_dist_14(int dist, uint32_t mul, uint32_t sub) {
+    int tmp = dist * mul - sub;
+    int result = (tmp + (1 << 13)) >> 14;
+
+    return result;
+}
+
+static inline unsigned Accurate255To256(unsigned x) {
+    return x + (x >> 7);
+}
+
+void AvoidXfermode::xfer32(SkPMColor dst[], const SkPMColor src[], int count,
+                             const SkAlpha aa[]) const {
+    unsigned    opR = SkColorGetR(fOpColor);
+    unsigned    opG = SkColorGetG(fOpColor);
+    unsigned    opB = SkColorGetB(fOpColor);
+    uint32_t    mul = fDistMul;
+    uint32_t    sub = (fDistMul - (1 << 14)) << 8;
+
+    int MAX, mask;
+
+    if (kTargetColor_Mode == fMode) {
+        mask = -1;
+        MAX = 255;
+    } else {
+        mask = 0;
+        MAX = 0;
+    }
+
+    for (int i = 0; i < count; i++) {
+        int d = color_dist32(dst[i], opR, opG, opB);
+        // now reverse d if we need to
+        d = MAX + (d ^ mask) - mask;
+        SkASSERT((unsigned)d <= 255);
+        d = Accurate255To256(d);
+
+        d = scale_dist_14(d, mul, sub);
+        SkASSERT(d <= 256);
+
+        if (d > 0) {
+            if (aa) {
+                d = SkAlphaMul(d, Accurate255To256(*aa++));
+                if (0 == d) {
+                    continue;
+                }
+            }
+            dst[i] = SkFourByteInterp256(src[i], dst[i], d);
+        }
+    }
+}
+
+static inline U16CPU SkBlend3216(SkPMColor src, U16CPU dst, unsigned scale) {
+    SkASSERT(scale <= 32);
+    scale <<= 3;
+
+    return SkPackRGB16( SkAlphaBlend(SkPacked32ToR16(src), SkGetPackedR16(dst), scale),
+                        SkAlphaBlend(SkPacked32ToG16(src), SkGetPackedG16(dst), scale),
+                        SkAlphaBlend(SkPacked32ToB16(src), SkGetPackedB16(dst), scale));
+}
+
+void AvoidXfermode::xfer16(uint16_t dst[], const SkPMColor src[], int count,
+                             const SkAlpha aa[]) const {
+    unsigned    opR = SkColorGetR(fOpColor) >> (8 - SK_R16_BITS);
+    unsigned    opG = SkColorGetG(fOpColor) >> (8 - SK_G16_BITS);
+    unsigned    opB = SkColorGetB(fOpColor) >> (8 - SK_R16_BITS);
+    uint32_t    mul = fDistMul;
+    uint32_t    sub = (fDistMul - (1 << 14)) << SK_R16_BITS;
+
+    int MAX, mask;
+
+    if (kTargetColor_Mode == fMode) {
+        mask = -1;
+        MAX = 31;
+    } else {
+        mask = 0;
+        MAX = 0;
+    }
+
+    for (int i = 0; i < count; i++) {
+        int d = color_dist16(dst[i], opR, opG, opB);
+        // now reverse d if we need to
+        d = MAX + (d ^ mask) - mask;
+        SkASSERT((unsigned)d <= 31);
+        // convert from 0..31 to 0..32
+        d += d >> 4;
+        d = scale_dist_14(d, mul, sub);
+        SkASSERT(d <= 32);
+
+        if (d > 0) {
+            if (aa) {
+                d = SkAlphaMul(d, Accurate255To256(*aa++));
+                if (0 == d) {
+                    continue;
+                }
+            }
+            dst[i] = SkBlend3216(src[i], dst[i], d);
+        }
+    }
+}
+
+void AvoidXfermode::xferA8(SkAlpha dst[], const SkPMColor src[], int count,
+        const SkAlpha aa[]) const {
+}
+
+#ifndef SK_IGNORE_TO_STRING
+void AvoidXfermode::toString(SkString* str) const {
+    str->append("AvoidXfermode: opColor: ");
+    str->appendHex(fOpColor);
+    str->appendf("distMul: %d ", fDistMul);
+
+    static const char* gModeStrings[] = { "Avoid", "Target" };
+
+    str->appendf("mode: %s", gModeStrings[fMode]);
+}
+#endif
diff --git a/core/jni/android/graphics/AvoidXfermode.h b/core/jni/android/graphics/AvoidXfermode.h
new file mode 100644
index 0000000..318d7be
--- /dev/null
+++ b/core/jni/android/graphics/AvoidXfermode.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef AvoidXfermode_DEFINED
+#define AvoidXfermode_DEFINED
+
+#include "SkColor.h"
+#include "SkTypes.h"
+#include "SkXfermode.h"
+
+/** \class AvoidXfermode
+
+    This xfermode will draw the src everywhere except on top of the specified
+    color.
+*/
+class AvoidXfermode : public SkXfermode {
+public:
+    enum Mode {
+        kAvoidColor_Mode,   //!< draw everywhere except on the opColor
+        kTargetColor_Mode   //!< draw only on top of the opColor
+    };
+
+    /** This xfermode draws, or doesn't draw, based on the destination's
+        distance from an op-color.
+
+        There are two modes, and each mode interprets a tolerance value.
+
+        Avoid: In this mode, drawing is allowed only on destination pixels that
+               are different from the op-color.
+               Tolerance near 0: avoid any colors even remotely similar to the op-color
+               Tolerance near 255: avoid only colors nearly identical to the op-color
+
+        Target: In this mode, drawing only occurs on destination pixels that
+                are similar to the op-color
+                Tolerance near 0: draw only on colors that are nearly identical to the op-color
+                Tolerance near 255: draw on any colors even remotely similar to the op-color
+     */
+    static AvoidXfermode* Create(SkColor opColor, U8CPU tolerance, Mode mode) {
+        return SkNEW_ARGS(AvoidXfermode, (opColor, tolerance, mode));
+    }
+
+    // overrides from SkXfermode
+    void xfer32(SkPMColor dst[], const SkPMColor src[], int count,
+            const SkAlpha aa[]) const override;
+    void xfer16(uint16_t dst[], const SkPMColor src[], int count,
+            const SkAlpha aa[]) const override;
+    void xferA8(SkAlpha dst[], const SkPMColor src[], int count,
+            const SkAlpha aa[]) const override;
+
+    SK_TO_STRING_OVERRIDE()
+    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(AvoidXfermode)
+
+protected:
+    AvoidXfermode(SkColor opColor, U8CPU tolerance, Mode mode);
+    void flatten(SkWriteBuffer&) const override;
+
+private:
+    SkColor     fOpColor;
+    uint32_t    fDistMul;   // x.14 cached from fTolerance
+    uint8_t     fTolerance;
+    Mode        fMode;
+
+    typedef SkXfermode INHERITED;
+};
+
+#endif
diff --git a/core/jni/android/graphics/Camera.cpp b/core/jni/android/graphics/Camera.cpp
index b572604..036ece1 100644
--- a/core/jni/android/graphics/Camera.cpp
+++ b/core/jni/android/graphics/Camera.cpp
@@ -96,7 +96,7 @@
 }
 
 static void Camera_applyToCanvas(JNIEnv* env, jobject obj, jlong canvasHandle) {
-    SkCanvas* canvas = reinterpret_cast<android::Canvas*>(canvasHandle)->getSkCanvas();
+    SkCanvas* canvas = reinterpret_cast<android::Canvas*>(canvasHandle)->asSkCanvas();
     jlong viewHandle = env->GetLongField(obj, gNativeInstanceFieldID);
     Sk3DView* v = reinterpret_cast<Sk3DView*>(viewHandle);
     v->applyToCanvas(canvas);
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index 9996ce1..dde1393 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -366,7 +366,7 @@
     if (!canvasHandle) {
         return NULL;
     }
-    SkCanvas* c = reinterpret_cast<android::Canvas*>(canvasHandle)->getSkCanvas();
+    SkCanvas* c = reinterpret_cast<android::Canvas*>(canvasHandle)->asSkCanvas();
     SkASSERT(c);
     return c;
 }
@@ -511,18 +511,15 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-static bool computeAllocationSize(const SkImageInfo& info, size_t* size, size_t* rowBytes) {
-        int32_t rowBytes32 = SkToS32(info.minRowBytes());
-        int64_t bigSize = (int64_t)info.height() * rowBytes32;
-        if (rowBytes32 < 0 || !sk_64_isS32(bigSize)) {
-            return false; // allocation will be too large
-        }
+static bool computeAllocationSize(const SkBitmap& bitmap, size_t* size) {
+    int32_t rowBytes32 = SkToS32(bitmap.rowBytes());
+    int64_t bigSize = (int64_t)bitmap.height() * rowBytes32;
+    if (rowBytes32 < 0 || !sk_64_isS32(bigSize)) {
+        return false; // allocation will be too large
+    }
 
-        *size = sk_64_asS32(bigSize);
-        *rowBytes = rowBytes32;
-
-        SkASSERT(*size >= info.getSafeSize(*rowBytes));
-        return true;
+    *size = sk_64_asS32(bigSize);
+    return true;
 }
 
 jbyteArray GraphicsJNI::allocateJavaPixelRef(JNIEnv* env, SkBitmap* bitmap,
@@ -533,11 +530,15 @@
         return NULL;
     }
 
-    size_t size, rowBytes;
-    if (!computeAllocationSize(info, &size, &rowBytes)) {
+    size_t size;
+    if (!computeAllocationSize(*bitmap, &size)) {
         return NULL;
     }
 
+    // we must respect the rowBytes value already set on the bitmap instead of
+    // attempting to compute our own.
+    const size_t rowBytes = bitmap->rowBytes();
+
     jbyteArray arrayObj = (jbyteArray) env->CallObjectMethod(gVMRuntime,
                                                              gVMRuntime_newNonMovableArray,
                                                              gByte_class, size);
@@ -580,11 +581,15 @@
         return NULL;
     }
 
-    size_t size, rowBytes;
-    if (!computeAllocationSize(info, &size, &rowBytes)) {
+    size_t size;
+    if (!computeAllocationSize(*bitmap, &size)) {
         return false;
     }
 
+    // we must respect the rowBytes value already set on the bitmap instead of
+    // attempting to compute our own.
+    const size_t rowBytes = bitmap->rowBytes();
+
     void* addr = sk_malloc_flags(size, 0);
     if (NULL == addr) {
         return false;
diff --git a/core/jni/android/graphics/NinePatch.cpp b/core/jni/android/graphics/NinePatch.cpp
index 543323c..3f8bfe2 100644
--- a/core/jni/android/graphics/NinePatch.cpp
+++ b/core/jni/android/graphics/NinePatch.cpp
@@ -120,7 +120,7 @@
     static void drawF(JNIEnv* env, jobject, jlong canvasHandle, jobject boundsRectF,
             jlong bitmapHandle, jlong chunkHandle, jlong paintHandle,
             jint destDensity, jint srcDensity) {
-        SkCanvas* canvas       = reinterpret_cast<Canvas*>(canvasHandle)->getSkCanvas();
+        SkCanvas* canvas       = reinterpret_cast<Canvas*>(canvasHandle)->asSkCanvas();
         const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
         Res_png_9patch* chunk  = reinterpret_cast<Res_png_9patch*>(chunkHandle);
         const Paint* paint     = reinterpret_cast<Paint*>(paintHandle);
@@ -139,7 +139,7 @@
     static void drawI(JNIEnv* env, jobject, jlong canvasHandle, jobject boundsRect,
             jlong bitmapHandle, jlong chunkHandle, jlong paintHandle,
             jint destDensity, jint srcDensity) {
-        SkCanvas* canvas       = reinterpret_cast<Canvas*>(canvasHandle)->getSkCanvas();
+        SkCanvas* canvas       = reinterpret_cast<Canvas*>(canvasHandle)->asSkCanvas();
         const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
         Res_png_9patch* chunk  = reinterpret_cast<Res_png_9patch*>(chunkHandle);
         const Paint* paint     = reinterpret_cast<Paint*>(paintHandle);
diff --git a/core/jni/android/graphics/NinePatchPeeker.cpp b/core/jni/android/graphics/NinePatchPeeker.cpp
index 2644888..6c32a21 100644
--- a/core/jni/android/graphics/NinePatchPeeker.cpp
+++ b/core/jni/android/graphics/NinePatchPeeker.cpp
@@ -24,7 +24,9 @@
     if (!strcmp("npTc", tag) && length >= sizeof(Res_png_9patch)) {
         Res_png_9patch* patch = (Res_png_9patch*) data;
         size_t patchSize = patch->serializedSize();
-        assert(length == patchSize);
+        if (length != patchSize) {
+            return false;
+        }
         // You have to copy the data because it is owned by the png reader
         Res_png_9patch* patchNew = (Res_png_9patch*) malloc(patchSize);
         memcpy(patchNew, patch, patchSize);
diff --git a/core/jni/android/graphics/Picture.cpp b/core/jni/android/graphics/Picture.cpp
index c249012..12bfaa2 100644
--- a/core/jni/android/graphics/Picture.cpp
+++ b/core/jni/android/graphics/Picture.cpp
@@ -101,7 +101,7 @@
     }
     validate();
     if (NULL != mPicture.get()) {
-        mPicture.get()->playback(canvas->getSkCanvas());
+        mPicture.get()->playback(canvas->asSkCanvas());
     }
 }
 
diff --git a/core/jni/android/graphics/Xfermode.cpp b/core/jni/android/graphics/Xfermode.cpp
index 5a3883a..4a424ae 100644
--- a/core/jni/android/graphics/Xfermode.cpp
+++ b/core/jni/android/graphics/Xfermode.cpp
@@ -18,7 +18,7 @@
 #include "GraphicsJNI.h"
 #include "core_jni_helpers.h"
 
-#include "SkAvoidXfermode.h"
+#include "AvoidXfermode.h"
 #include "SkPixelXorXfermode.h"
 
 namespace android {
@@ -35,8 +35,8 @@
     static jlong avoid_create(JNIEnv* env, jobject, jint opColor,
                                 jint tolerance, jint modeHandle)
     {
-        SkAvoidXfermode::Mode mode = static_cast<SkAvoidXfermode::Mode>(modeHandle);
-        return reinterpret_cast<jlong>(SkAvoidXfermode::Create(opColor, tolerance, mode));
+        AvoidXfermode::Mode mode = static_cast<AvoidXfermode::Mode>(modeHandle);
+        return reinterpret_cast<jlong>(AvoidXfermode::Create(opColor, tolerance, mode));
     }
 
     static jlong pixelxor_create(JNIEnv* env, jobject, jint opColor)
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 085cc81..6094fd1 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -183,8 +183,6 @@
 
     <protected-broadcast android:name="android.intent.action.HEADSET_PLUG" />
     <protected-broadcast android:name="android.media.action.HDMI_AUDIO_PLUG" />
-    <protected-broadcast android:name="android.media.action.USB_AUDIO_ACCESSORY_PLUG" />
-    <protected-broadcast android:name="android.media.action.USB_AUDIO_DEVICE_PLUG" />
 
     <protected-broadcast android:name="android.media.AUDIO_BECOMING_NOISY" />
     <protected-broadcast android:name="android.media.RINGER_MODE_CHANGED" />
diff --git a/core/res/res/layout/dialog_custom_title_material.xml b/core/res/res/layout/dialog_custom_title_material.xml
index 248a05e..50ed910 100644
--- a/core/res/res/layout/dialog_custom_title_material.xml
+++ b/core/res/res/layout/dialog_custom_title_material.xml
@@ -27,6 +27,8 @@
         android:layout_weight="0"
         android:gravity="center_vertical|start"
         style="?attr/windowTitleBackgroundStyle" />
+    <View android:layout_width="match_parent"
+        android:layout_height="0dp" />
     <FrameLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
diff --git a/core/res/res/layout/dialog_title_icons_material.xml b/core/res/res/layout/dialog_title_icons_material.xml
index 62af096..3866ca7 100644
--- a/core/res/res/layout/dialog_title_icons_material.xml
+++ b/core/res/res/layout/dialog_title_icons_material.xml
@@ -48,6 +48,9 @@
             android:layout_marginStart="8dip" />
     </LinearLayout>
 
+    <View android:layout_width="match_parent"
+        android:layout_height="0dp" />
+
     <FrameLayout
         android:layout_width="match_parent" android:layout_height="wrap_content"
         android:layout_weight="1"
diff --git a/core/res/res/layout/dialog_title_material.xml b/core/res/res/layout/dialog_title_material.xml
index 339d569..1ea7f6e 100644
--- a/core/res/res/layout/dialog_title_material.xml
+++ b/core/res/res/layout/dialog_title_material.xml
@@ -32,6 +32,8 @@
         android:paddingStart="?attr/dialogPreferredPadding"
         android:paddingEnd="?attr/dialogPreferredPadding"
         android:paddingTop="@dimen/dialog_padding_top_material" />
+    <View android:layout_width="match_parent"
+        android:layout_height="0dp" />
     <FrameLayout
         android:layout_width="match_parent" android:layout_height="wrap_content"
         android:layout_weight="1"
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 68c1046..f2d9de8 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -424,6 +424,10 @@
     <!-- Integer indicating wpa_supplicant scan interval in milliseconds -->
     <integer translatable="false" name="config_wifi_supplicant_scan_interval">15000</integer>
 
+    <!-- Integer indicating amount of time failed networks areblacklisted for the purpose
+         of network switching in milliseconds -->
+    <integer translatable="false" name="config_wifi_network_switching_blacklist_time">172800000</integer>
+
     <!-- Integer indicating wpa_supplicant scan interval when p2p is connected in milliseconds -->
     <integer translatable="false" name="config_wifi_scan_interval_p2p_connected">60000</integer>
 
@@ -2021,4 +2025,7 @@
 
     <!-- Use ERI text for network name on CDMA LTE -->
     <bool name="config_LTE_eri_for_network_name">true</bool>
+
+    <!-- Whether to start in touch mode -->
+    <bool name="config_defaultInTouchMode">true</bool>
 </resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index f51e82c9..a32aa3e 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3397,6 +3397,7 @@
 
     <!-- This is used to express that something occurred within the last X days (e.g., Last 7 days). -->
     <plurals name="last_num_days">
+        <item quantity="one">Last <xliff:g id="count">%d</xliff:g> day</item>
         <item quantity="other">Last <xliff:g id="count">%d</xliff:g> days</item>
     </plurals>
 
@@ -3748,6 +3749,9 @@
         <xliff:g id="number" example="123">%1$d</xliff:g> of
         <xliff:g id="number" example="123">%2$d</xliff:g>.</string>
 
+    <!-- [CHAR LIMIT=NONE] Message shown in upgrading dialog for each .apk pre boot broadcast -->
+    <string name="android_preparing_apk">Preparing <xliff:g id="appname">%1$s</xliff:g>.</string>
+
     <!-- [CHAR LIMIT=NONE] Message to show in upgrading dialog when reached the point of starting apps. -->
     <string name="android_upgrading_starting_apps">Starting apps.</string>
 
@@ -5188,4 +5192,9 @@
     <string name="stk_cc_ss_to_ussd">SS request is modified to USSD request.</string>
     <string name="stk_cc_ss_to_ss">SS request is modified to new SS request.</string>
 
+    <!-- Manufacturer name for USB MIDI Peripheral port -->
+    <string name="usb_midi_peripheral_manufacturer_name">Android</string>
+    <!-- Model name for USB MIDI Peripheral port -->
+    <string name="usb_midi_peripheral_model_name">USB Peripheral Port</string>
+
 </resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 574c099..9c1fd07 100755
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -327,6 +327,7 @@
   <java-symbol type="integer" name="config_wifi_framework_scan_result_rssi_level_patchup_value" />
   <java-symbol type="integer" name="config_wifi_framework_current_network_boost" />
   <java-symbol type="string"  name="config_wifi_random_mac_oui" />
+  <java-symbol type="integer"  name="config_wifi_network_switching_blacklist_time" />
 
   <java-symbol type="bool" name="editable_voicemailnumber" />
 
@@ -1513,6 +1514,7 @@
   <java-symbol type="layout" name="screen_title" />
   <java-symbol type="layout" name="screen_title_icons" />
   <java-symbol type="string" name="system_ui_date_pattern" />
+  <java-symbol type="string" name="android_preparing_apk" />
   <java-symbol type="string" name="android_start_title" />
   <java-symbol type="string" name="android_upgrading_title" />
   <java-symbol type="string" name="bugreport_title" />
@@ -2154,4 +2156,8 @@
 
   <java-symbol type="bool" name="config_use_sim_language_file" />
   <java-symbol type="bool" name="config_LTE_eri_for_network_name" />
+  <java-symbol type="bool" name="config_defaultInTouchMode" />
+
+  <java-symbol type="string" name="usb_midi_peripheral_manufacturer_name" />
+  <java-symbol type="string" name="usb_midi_peripheral_model_name" />
 </resources>
diff --git a/docs/html/google/play-services/ads.jd b/docs/html/google/play-services/ads.jd
index e4f0b2c..2f915f3 100644
--- a/docs/html/google/play-services/ads.jd
+++ b/docs/html/google/play-services/ads.jd
@@ -98,10 +98,8 @@
     serve banner and interstitial ads using the Google Mobile Ads APIs.</p>
 
     <h4>3. Read the documentation</h4>
-    <p>Read the <a class="external-link" href="https://www.google.com/adsense/localized-terms">AdSense
-    Terms of Service</a> and the <a class="external-link"
-    href="https://support.google.com/admob/topic/1307235?hl=en&ref_topic=1307209">AdMob
-    publisher guidelines and policies</a>.</p>
+    <p>Your use of the Google Mobile Ads SDK is governed by the terms between you and Google that
+    govern your use of the Google product (AdSense/AdMob, AdX or DFP) with which you use the SDK.</p>
     <p>For quick access while developing your Android apps, the <a
     href="{@docRoot}reference/gms-packages.html">Google Mobile Ads API reference</a> is available here on
     developer.android.com.</p>
diff --git a/docs/html/images/transitions/transition_sample_video.mp4 b/docs/html/images/transitions/transition_sample_video.mp4
new file mode 100644
index 0000000..37ae685
--- /dev/null
+++ b/docs/html/images/transitions/transition_sample_video.mp4
Binary files differ
diff --git a/docs/html/images/transitions/transition_sample_video.ogv b/docs/html/images/transitions/transition_sample_video.ogv
new file mode 100644
index 0000000..5598814
--- /dev/null
+++ b/docs/html/images/transitions/transition_sample_video.ogv
Binary files differ
diff --git a/docs/html/images/transitions/transition_sample_video.webm b/docs/html/images/transitions/transition_sample_video.webm
new file mode 100644
index 0000000..346ba8c
--- /dev/null
+++ b/docs/html/images/transitions/transition_sample_video.webm
Binary files differ
diff --git a/docs/html/images/transitions/transitions_diagram.png b/docs/html/images/transitions/transitions_diagram.png
new file mode 100644
index 0000000..9363940
--- /dev/null
+++ b/docs/html/images/transitions/transitions_diagram.png
Binary files differ
diff --git a/docs/html/images/tv/app-browse.png b/docs/html/images/tv/app-browse.png
new file mode 100644
index 0000000..7670713
--- /dev/null
+++ b/docs/html/images/tv/app-browse.png
Binary files differ
diff --git a/docs/html/images/tv/card-view.png b/docs/html/images/tv/card-view.png
new file mode 100644
index 0000000..5e907de
--- /dev/null
+++ b/docs/html/images/tv/card-view.png
Binary files differ
diff --git a/docs/html/sdk/index.jd b/docs/html/sdk/index.jd
index e74d46a..af6f6b8 100644
--- a/docs/html/sdk/index.jd
+++ b/docs/html/sdk/index.jd
@@ -481,14 +481,14 @@
 
 <ul>
 <li>GNOME or KDE desktop</li>
-<li>GNU C Library (glibc) 2.11 or later</li>
+<li>GNU C Library (glibc) 2.15 or later</li>
 <li>2 GB RAM minimum, 4 GB RAM recommended</li>
 <li>400 MB hard disk space</li>
 <li>At least 1 GB for Android SDK, emulator system images, and caches</li>
 <li>1280 x 800 minimum screen resolution</li>
 <li>Oracle&reg;  Java Development Kit (JDK) 7 </li>
 </ul>
-<p>Tested on Ubuntu&reg;  12.04, Precise Pangolin (64-bit distribution capable of running
+<p>Tested on Ubuntu&reg;  14.04, Trusty Tahr (64-bit distribution capable of running
 32-bit applications).</p>
 
 
diff --git a/docs/html/tools/building/plugin-for-gradle.jd b/docs/html/tools/building/plugin-for-gradle.jd
index 77cbfda..54a03fd 100644
--- a/docs/html/tools/building/plugin-for-gradle.jd
+++ b/docs/html/tools/building/plugin-for-gradle.jd
@@ -321,7 +321,7 @@
 machine and on other machines where Android Studio is not installed.</p>
 
 <p class="caution"><strong>Caution:</strong> When you create a project, only use the Gradle wrapper
-scripts and JAR from a trusted source, such as those generated by Android Studio. /p>
+scripts and JAR from a trusted source, such as those generated by Android Studio. </p>
 
 
 <h2 id="buildVariants"> Build variants</h2>
diff --git a/docs/html/training/training_toc.cs b/docs/html/training/training_toc.cs
index 0fcfb9c..c59d8ff 100644
--- a/docs/html/training/training_toc.cs
+++ b/docs/html/training/training_toc.cs
@@ -437,6 +437,35 @@
           </li>
         </ul>
       </li>
+
+      <li class="nav-section">
+        <div class="nav-section-header">
+          <a href="<?cs var:toroot?>training/transitions/index.html"
+             description=
+             "How to animate state changes in a view hierarchy using transitions."
+            >Animating Views Using Scenes and Transitions</a>
+        </div>
+        <ul>
+          <li><a href="<?cs var:toroot ?>training/transitions/overview.html">
+            The Transitions Framework
+          </a>
+          </li>
+          <li><a href="<?cs var:toroot ?>training/transitions/scenes.html">
+            Creating a Scene
+          </a>
+          </li>
+          <li><a href="<?cs var:toroot ?>training/transitions/transitions.html">
+            Applying a Transition
+          </a>
+          </li>
+          <li><a href="<?cs var:toroot ?>training/transitions/custom-transitions.html">
+            Creating Custom Transitions
+          </a>
+          </li>
+
+        </ul>
+      </li>
+
       <li class="nav-section">
         <div class="nav-section-header"><a href="<?cs var:toroot ?>training/animation/index.html"
              description=
@@ -922,6 +951,10 @@
               Creating a Catalog Browser</a>
           </li>
           <li>
+            <a href="<?cs var:toroot ?>training/tv/playback/card.html">
+              Providing a Card View</a>
+          </li>
+          <li>
             <a href="<?cs var:toroot ?>training/tv/playback/details.html"
                ja-lang="詳細ビューをビルドする">
               Building a Details View</a>
@@ -1854,4 +1887,4 @@
     buildToggleLists();
     changeNavLang(getLangPref());
 //-->
-</script>
+</script>
\ No newline at end of file
diff --git a/docs/html/training/transitions/custom-transitions.jd b/docs/html/training/transitions/custom-transitions.jd
new file mode 100644
index 0000000..b64daaeb
--- /dev/null
+++ b/docs/html/training/transitions/custom-transitions.jd
@@ -0,0 +1,189 @@
+page.title=Creating Custom Transitions
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+<h2>This lesson teaches you to</h2>
+<ol>
+  <li><a href="#Extend">Extend the Transition Class</a></li>
+  <li><a href="#CaptureProperties">Capture View Property Values</a></li>
+  <li><a href="#CreateAnimator">Create a Custom Animator</a></li>
+  <li><a href="#Apply">Apply a Custom Transition</a></li>
+</ol>
+</div>
+</div>
+
+<p>A custom transition enables you to create an animation that is not available from any of
+the built-in transition classes. For example, you can define a custom transition that turns
+the foreground color of text and input fields to gray to indicate that the fields are disabled
+in the new screen. This type of change helps users see the fields you disabled.</p>
+
+<p>A custom transition, like one of the built-in transition types, applies animations to
+child views of both the starting and ending scenes. Unlike built-in transition types,
+however, you have to provide the code that captures property values and generates animations.
+You may also want to define a subset of target views for your animation.</p>
+
+<p>This lesson teaches you to capture property values and generate animations to create
+custom transitions.</p>
+
+
+
+<h2 id="Extend">Extend the Transition Class</h2>
+
+<p>To create a custom transition, add a class to your project that extends the {@link
+android.transition.Transition} class and override the methods shown in the following snippet:</p>
+
+<pre>
+public class CustomTransition extends Transition {
+
+    &#64;Override
+    public void captureStartValues(TransitionValues values) {}
+
+    &#64;Override
+    public void captureEndValues(TransitionValues values) {}
+
+    &#64;Override
+    public Animator createAnimator(ViewGroup sceneRoot,
+                                   TransitionValues startValues,
+                                   TransitionValues endValues) {}
+}
+</pre>
+
+<p>The following sections explain how to override these methods.</p>
+
+
+
+<h2 id="CaptureProperties">Capture View Property Values</h2>
+
+<p>Transition animations use the property animation system described in
+<a href="{@docRoot}guide/topics/graphics/prop-animation.html">Property Animation</a>. Property
+animations change a view property between a starting and ending value over a specified
+period of time, so the framework needs to have both the starting and ending value of
+the property to construct the animation.</p>
+
+<p>However, a property animation usually needs only a small subset of all the view's property
+values. For example, a color animation needs color property values, while a movement
+animation needs position property values. Since the property values needed for an animation
+are specific to a transition, the transitions framework does not provide every property value
+to a transition. Instead, the framework invokes callback methods that allow a transition to
+capture only the property values it needs and store them in the framework.</p>
+
+
+<h3 id="StartingValues">Capturing Starting Values</h3>
+
+<p>To pass the starting view values to the framework, implement the
+{@link android.transition.Transition#captureStartValues captureStartValues(transitionValues)}
+method. The framework calls this method for every view in the starting scene. The method
+argument is a {@link android.transition.TransitionValues} object that contains a reference
+to the view and a {@link java.util.Map} instance in which you can store the view values you
+want. In your implementation, retrieve these property values and pass them back to the
+framework by storing them in the map.</p>
+
+<p>To ensure that the key for a property value does not conflict with other {@link
+android.transition.TransitionValues} keys, use the following naming scheme:</p>
+
+<pre>
+package_name:transition_name:property_name
+</pre>
+
+<p>The following snippet shows an implementation of the {@link
+android.transition.Transition#captureStartValues captureStartValues()} method:</p>
+
+<pre>
+public class CustomTransition extends Transition {
+
+    // Define a key for storing a property value in
+    // TransitionValues.values with the syntax
+    // package_name:transition_class:property_name to avoid collisions
+    private static final String PROPNAME_BACKGROUND =
+            "com.example.android.customtransition:CustomTransition:background";
+
+    &#64;Override
+    public void captureStartValues(TransitionValues transitionValues) {
+        // Call the convenience method captureValues
+        captureValues(transitionValues);
+    }
+
+
+    // For the view in transitionValues.view, get the values you
+    // want and put them in transitionValues.values
+    private void captureValues(TransitionValues transitionValues) {
+        // Get a reference to the view
+        View view = transitionValues.view;
+        // Store its background property in the values map
+        transitionValues.values.put(PROPNAME_BACKGROUND, view.getBackground());
+    }
+    ...
+}
+</pre>
+
+
+<h3 id="EndingValues">Capture Ending Values</h3>
+
+<p>The framework calls the {@link android.transition.Transition#captureEndValues} method
+once for every target view in the ending scene. In all other respects, {@link
+android.transition.Transition#captureEndValues captureEndValues()} works the same as {@link
+android.transition.Transition#captureStartValues captureStartValues()}.</p>
+
+<p>The following code snippet shows an implementation of the {@link
+android.transition.Transition#captureEndValues captureEndValues()} method:</p>
+
+<pre>
+&#64;Override
+public void captureEndValues(TransitionValues transitionValues) {
+    captureValues(transitionValues);
+}
+</pre>
+
+<p>In this example, both the {@link android.transition.Transition#captureStartValues
+captureStartValues()} and {@link android.transition.Transition#captureEndValues captureEndValues()}
+methods invoke <code>captureValues()</code> to retrieve and store values. The view property
+that <code>captureValues()</code> retrieves is the same, but it has different values in the
+starting and ending scenes. The framework maintains separate maps for the starting and ending
+states of a view.</p>
+
+
+
+<h2 id="CreateAnimator">Create a Custom Animator</h2>
+
+<p>To animate the changes to a view between its state in the starting scene and its state in
+the ending scene, you provide an animator by overriding the {@link
+android.transition.Transition#createAnimator createAnimator()} method. When the
+framework calls this method, it passes in the scene root view and the {@link
+android.transition.TransitionValues} objects that contain the starting and ending values
+you captured.</p>
+
+<p>The number of times the framework calls the {@link
+android.transition.Transition#createAnimator createAnimator()} method depends on the changes that
+occur between the starting and ending scenes. For example, consider a fade out/fade in animation
+implemented as a custom transition. If the starting scene has five targets of which two are
+removed from the ending scene, and the ending scene has the three targets from the starting
+scene plus a new target, then the framework calls {@link
+android.transition.Transition#createAnimator createAnimator()} six times: three of the calls
+animate the fading out and fading in of the targets that stay in both scene objects; two more calls
+animate the fading out of the targets removed from the ending scene; and one call
+animates the fading in of the new target in the ending scene.</p>
+
+<p>For target views that exist on both the starting and ending scenes, the framework provides
+a {@link android.transition.TransitionValues} object for both the <code>startValues</code> and
+<code>endValues</code> arguments. For target views that only exist in the starting or the
+ending scene, the framework provides a {@link android.transition.TransitionValues} object
+for the corresponding argument and <code>null</code> for the other.</p>
+
+<p>To implement the {@link android.transition.Transition#createAnimator} method when you create
+a custom transition, use the view property values you captured to create an {@link
+android.animation.Animator} object and return it to the framework. For an example implementation,
+see the <a
+href="{@docRoot}samples/CustomTransition/src/com.example.android.customtransition/ChangeColor.html">
+<code>ChangeColor</code></a> class in the <a href="{@docRoot}samples/CustomTransition/index.html">
+CustomTransition</a> sample. For more information about property animators, see
+<a href="{@docRoot}guide/topics/graphics/prop-animation.html">Property Animation</a>.</p>
+
+
+
+<h2 id="Apply">Apply a Custom Transition</h2>
+
+<p>Custom transitions work the same as built-in transitions. You can apply a custom transition
+using a transition manager, as described in <a
+href="{@docRoot}training/transitions/transitions.html#Apply">Applying a Transition</a>.</p>
diff --git a/docs/html/training/transitions/index.jd b/docs/html/training/transitions/index.jd
new file mode 100644
index 0000000..53faa01
--- /dev/null
+++ b/docs/html/training/transitions/index.jd
@@ -0,0 +1,80 @@
+page.title=Animating Views Using Scenes and Transitions
+
+@jd:body
+
+<!-- Sidebox -->
+<div id="tb-wrapper">
+<div id="tb">
+  <h2>Dependencies and Prerequisites</h2>
+  <ul>
+    <li>Android 4.4.2 (API level 19) or higher</li>
+  </ul>
+  <h2>You should also read</h2>
+  <ul>
+    <li><a href="{@docRoot}guide/topics/ui/how-android-draws.html">
+        How Android Draws Views</a></li>
+  </ul>
+  <h2>Try it out</h2>
+  <ul>
+    <li><a href="{@docRoot}samples/BasicTransition/index.html">BasicTransition</a> sample</li>
+    <li><a href="{@docRoot}samples/CustomTransition/index.html">CustomTransition</a> sample</li>
+  </ul>
+</div>
+</div>
+
+<!-- Video box -->
+<a class="notice-developers-video wide" href="http://www.youtube.com/watch?v=S3H7nJ4QaD8">
+<div>
+  <h3>Video</h3>
+  <p>DevBytes: Android 4.4 Transitions</p>
+</div>
+</a>
+
+<p>The user interface of an activity often changes in response to user input and other events.
+For example, an activity that contains a form where users can type search queries can hide
+the form when the user submits it and show a list of search results in its place.</p>
+
+<p>To provide visual continuity in these situations, you can animate changes between
+different view hierarchies in your user interface. These animations give users feedback on
+their actions and help them learn how your app works.</p>
+
+<p>Android includes the <em>transitions framework</em>, which enables you to easily
+animate changes between two view hierarchies. The framework animates the views at runtime by
+changing some of their property values over time. The framework includes built-in animations
+for common effects and lets you create custom animations and transition lifecycle callbacks.</p>
+
+<p>This class teaches you to use the built-in animations in the transitions framework to
+animate changes between view hierarchies. This class also covers how to create custom
+animations.</p>
+
+<p class="note"><strong>Note:</strong> For Android versions earlier than 4.4.2 (API level 19)
+but greater than or equal to Android 4.0 (API level 14), use the <code>animateLayoutChanges</code>
+attribute to animate layouts. To learn more, see
+<a href="{@docRoot}guide/topics/graphics/prop-animation.html">Property Animation</a> and
+<a href="{@docRoot}training/animation/layout.html">Animating Layout Changes</a>.</p>
+
+
+<h2>Lessons</h2>
+
+<dl>
+<dt><a href="{@docRoot}training/transitions/overview.html">
+The Transitions Framework</a></dt>
+<dd>
+  Learn the main features and components of the transitions framework.
+</dd>
+<dt><a href="{@docRoot}training/transitions/scenes.html">
+Creating a Scene</a></dt>
+<dd>
+  Learn how to create a scene to store the state of a view hierarchy.
+</dd>
+<dt><a href="{@docRoot}training/transitions/transitions.html">
+Applying a Transition</a></dt>
+<dd>
+  Learn how to apply a transition between two scenes of a view hierarchy.
+</dd>
+<dt><a href="{@docRoot}training/transitions/custom-transitions.html">
+Creating Custom Transitions</a></dt>
+<dd>
+  Learn how to create other animation effects not included in the transitions framework.
+</dd>
+</dl>
diff --git a/docs/html/training/transitions/overview.jd b/docs/html/training/transitions/overview.jd
new file mode 100644
index 0000000..044cf16
--- /dev/null
+++ b/docs/html/training/transitions/overview.jd
@@ -0,0 +1,165 @@
+page.title=The Transitions Framework
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+<h2>This lesson covers</h2>
+<ol>
+  <li><a href="#Overview">Overview</a></li>
+  <li><a href="#Scenes">Scenes</a></li>
+  <li><a href="#Transitions">Transitions</a></li>
+  <li><a href="#Limitations">Limitations</a></li>
+</ol>
+</div>
+</div>
+
+<p>Animating your app's user interface provides more than just visual appeal. Animations
+highlight changes and provide visual cues that help users learn how your app works.</p>
+
+<p>To help you animate a change between one view hierarchy and another, Android provides the
+transitions framework. This framework applies one or more animations to all the views in the
+hierarchies as it changes between them.</p>
+
+<p>The framework has the following features:</p>
+
+<dl>
+<dt><em>Group-level animations</em></dt>
+<dd>Applies one or more animation effects to all of the views in a view hierarchy.</dd>
+<dt><em>Transition-based animation</em></dt>
+<dd>Runs animations based on the changes between starting and ending view property values.</dd>
+<dt><em>Built-in animations</em></dt>
+<dd>Includes predefined animations for common effects such as fade out or movement.</dd>
+
+<!-- Figure 1 - Transitions video -->
+<div style="float:right;margin-left:30px;margin-top:10px">
+<div class="framed-nexus5-port-span-5" style="clear:left;">
+<video class="play-on-hover" height="442" autoplay="" poster="">
+<source src="{@docRoot}images/transitions/transition_sample_video.mp4" type="video/mp4">
+<source src="{@docRoot}images/transitions/transition_sample_video.ogv" type="video/ogg">
+<source src="{@docRoot}images/transitions/transition_sample_video.webm" type="video/webm">
+</video>
+</div>
+<p class="img-caption" style="margin-top:7px;margin-bottom:0px">
+<strong>Figure 1.</strong> Visual cues using user interface animation.</p>
+<div style="margin-top:5px;margin-bottom:20px;font-size:10pt" class="video-instructions">&nbsp;</div>
+</div>
+
+<dt><em>Resource file support</em></dt>
+<dd>Loads view hierarchies and built-in animations from layout resource files.</dd>
+<dt><em>Lifecycle callbacks</em></dt>
+<dd>Defines callbacks that provide finer control over the animation and hierarchy change
+process.</dd>
+</dl>
+
+
+
+<h2 id="Overview">Overview</h2>
+
+<p>The example in Figure 1 shows how an animation provides visual cues to help the user. As the
+app changes from its search entry screen to its search results screen, it fades out views that
+are no longer in use and fades in new views.</p>
+
+<p>This animation is an example of using the transitions framework. The framework
+animates changes to all the views in two view hierarchies. A view hierarchy can be as simple
+as a single view or as complex as a {@link android.view.ViewGroup} containing an elaborate
+tree of views. The framework animates each view by changing one or more of its property values
+over time between the initial or <em>starting</em> view hierarchy and the final or <em>ending</em>
+view hierarchy.</p>
+
+<p>The transitions framework works in parallel with view hierarchies and animations. The
+purpose of the framework is to store the state of view hierarchies, change between these
+hierarchies in order to modify the appearance of the device screen, and animate the change by
+storing and applying animation definitions.</p>
+
+<p>The diagram in Figure 2 illustrates the relationship between view hierarchies, framework
+objects, and animations:</p>
+
+<!-- Figure 2 - diagram -->
+<img src="{@docRoot}images/transitions/transitions_diagram.png"
+     width="506" height="234" alt="" style="margin-top:7px" />
+<p class="img-caption"><strong>Figure 2.</strong> Relationships in the transitions framework.</p>
+
+<p>The transitions framework provides abstractions for scenes, transitions, and transition
+managers. These are described in detail in the following sections. To use the framework, you
+create scenes for the view hierarchies in your app that you plan to change between. Next, you
+create a transition for each animation you want to use. To start the animation between two
+view hierarchies, you use a transition manager specifying the transition to use and the ending
+scene. This procedure is described in detail in the remaining lessons in this class.</p>
+
+
+
+<h2 id="Scenes">Scenes</h2>
+
+<p>A scene stores the state of a view hierarchy, including all its views and their property
+values. A view hierarchy can be a simple view or a complex tree of views and child layouts.
+Storing the view hierarchy state in a scene enables you to transition into that state from
+another scene. The framework provides the {@link android.transition.Scene} class to represent
+a scene.</p>
+
+<p>The transitions framework lets you create scenes from layout resource files or from
+{@link android.view.ViewGroup} objects in your code. Creating a scene in your code is useful
+if you generated a view hierarchy dynamically or if you are modifying it at runtime.</p>
+
+<p>In most cases, you do not create a starting scene explicitly. If you have applied a
+transition, the framework uses the previous ending scene as the starting scene for any
+subsequent transitions. If you have not applied a transition, the framework collects information
+about the views from the current state of the screen.</p>
+
+<p>A scene can also define its own actions that run when you make a scene change. For example,
+this feature is useful for cleaning up view settings after you transition to a scene.</p>
+
+<p>In addition to the view hierarchy and its property values, a scene also stores a reference
+to the parent of the view hierarchy. This root view is called a <strong>scene root</strong>.
+Changes to the scene and animations that affect the scene occur within the scene root.</p>
+
+<p>To learn how to create scenes, see
+<a href="{@docRoot}training/transitions/scenes.html">Creating a Scene</a>.</p>
+
+
+
+<h2 id="Transitions">Transitions</h2>
+
+<p>In the transitions framework, animations create a series of frames that depict a change
+between the view hierarchies in the starting and ending scenes. Information about the animation
+is stored in a {@link android.transition.Transition} object. To run the animation, you apply the
+transition using a {@link android.transition.TransitionManager} instance. The framework can
+transition between two different scenes or transition to a different state for the current
+scene.</p>
+
+<p>The framework includes a set of built-in transitions for commonly-used animation effects,
+such as fading and resizing views. You can also define your own custom transitions to create
+an animation effect using the APIs in the animations framework. The transitions framework also
+enables you to combine different animation effects in a transition set that contains a group
+of individual built-in or custom transitions.</p>
+
+<p>The transition lifecycle is similar to the activity lifecycle, and it represents the
+transition states that the framework monitors between the start and the completion of an
+animation. At important lifecycle states, the framework invokes callback methods that you can
+implement to make adjustments to your user interface at different phases of the transition.</p>
+
+<p>To learn more about transitions, see
+<a href="{@docRoot}training/transitions/transitions.html">Applying a Transition</a> and
+<a href="{@docRoot}training/transitions/custom-transitions.html">Creating Custom
+Transitions</a>.</p>
+
+
+
+<h2 id="Limitations">Limitations</h2>
+
+<p>This section lists some known limitations of the transitions framework:</p>
+
+<ul>
+<li>Animations applied to a {@link android.view.SurfaceView} may not appear correctly.
+{@link android.view.SurfaceView} instances are updated from a non-UI thread, so the updates
+may be out of sync with the animations of other views.</li>
+<li>Some specific transition types may not produce the desired animation effect when applied
+to a {@link android.view.TextureView}.</li>
+<li>Classes that extend {@link android.widget.AdapterView}, such as
+{@link android.widget.ListView}, manage their child views in ways that are incompatible with
+the transitions framework. If you try to animate a view based on
+{@link android.widget.AdapterView}, the device display may hang.</li>
+<li>If you try to resize a {@link android.widget.TextView} with an animation, the text will
+pop to a new location before the object has completely resized. To avoid this problem, do not
+animate the resizing of views that contain text.</li>
+</ul>
diff --git a/docs/html/training/transitions/scenes.jd b/docs/html/training/transitions/scenes.jd
new file mode 100644
index 0000000..4bf7d0e
--- /dev/null
+++ b/docs/html/training/transitions/scenes.jd
@@ -0,0 +1,211 @@
+page.title=Creating a Scene
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+<h2>This lesson teaches you to</h2>
+<ol>
+  <li><a href="#FromLayout">Create a Scene From a Layout Resource</a></li>
+  <li><a href="#FromCode">Create a Scene in Your Code</a></li>
+  <li><a href="#Actions">Create Scene Actions</a></li>
+</ol>
+</div>
+</div>
+
+<p>Scenes store the state of a view hierarchy, including all its views and their property
+values. The transitions framework can run animations between a starting and an ending scene.
+The starting scene is often determined automatically from the current state of the user
+interface. For the ending scene, the framework enables you to create a scene from a layout
+resource file or from a group of views in your code.</p>
+
+<p>This lesson shows you how to create scenes in your app and how to define scene actions.
+The next lesson shows you how to transition between two scenes.</p>
+
+<p class="note"><strong>Note:</strong> The framework can animate changes in a single view
+hierarchy without using scenes, as described in
+<a href="{@docRoot}training/transitions/transitions.html#NoScenes">Apply a Transition Without
+Scenes</a>. However, understanding this lesson is essential to work with transitions.</p>
+
+
+
+<h2 id="FromLayout">Create a Scene From a Layout Resource</h2>
+
+<p>You can create a {@link android.transition.Scene} instance directly from a layout resource
+file. Use this technique when the view hierarchy in the file is mostly static. The resulting
+scene represents the state of the view hierarchy at the time you created the
+{@link android.transition.Scene} instance. If you change the view hierarchy, you have to
+recreate the scene. The framework creates the scene from the entire view hierarchy in the
+file; you can not create a scene from part of a layout file.</p>
+
+<p>To create a {@link android.transition.Scene} instance from a layout resource file, retrieve
+the scene root from your layout as a {@link android.view.ViewGroup} instance and then call the
+{@link android.transition.Scene#getSceneForLayout Scene.getSceneForLayout()} method with the
+scene root and the resource ID of the layout file that contains the view hierarchy for the
+scene.</p>
+
+<h3>Define Layouts for Scenes</h3>
+
+<p>The code snippets in the rest of this section show you how to create two different scenes
+with the same scene root element. The snippets also demonstrate that you can load multiple
+unrelated {@link android.transition.Scene} objects without implying that they are related to
+each other.</p>
+
+<p>The example consists of the following layout definitions:</p>
+
+<ul>
+<li>The main layout of an activity with a text label and a child layout.</li>
+<li>A relative layout for the first scene with two text fields.</li>
+<li>A relative layout for the second scene with the same two text fields in different order.</li>
+</ul>
+
+<p>The example is designed so that all of the animation occurs within the child layout of the
+main layout for the activity. The text label in the main layout remains static.</p>
+
+<p>The main layout for the activity is defined as follows:</p>
+
+<p class="code-caption">res/layout/activity_main.xml</p>
+
+<pre>
+&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/master_layout">
+    &lt;TextView
+        android:id="@+id/title"
+        ...
+        android:text="Title"/>
+    &lt;FrameLayout
+        android:id="@+id/scene_root">
+        &lt;include layout="@layout/a_scene" />
+    &lt;/FrameLayout>
+&lt;/LinearLayout>
+</pre>
+
+<p>This layout definition contains a text field and a child layout for the scene root. The
+layout for the first scene is included in the main layout file. This allows the app to display
+it as part of the initial user interface and also to load it into a scene, since the framework
+can load only a whole layout file into a scene.</p>
+
+<p>The layout for the first scene is defined as follows:</p>
+
+<p class="code-caption">res/layout/a_scene.xml</p>
+
+<pre>
+&lt;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/scene_container"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent" >
+    &lt;TextView
+        android:id="@+id/text_view1
+        android:text="Text Line 1" />
+    &lt;TextView
+        android:id="@+id/text_view2
+        android:text="Text Line 2" />
+&lt;/RelativeLayout>
+</pre>
+
+<p>The layout for the second scene contains the same two text fields (with the same IDs)
+placed in a different order and is defined as follows:</p>
+
+<p class="code-caption">res/layout/another_scene.xml</p>
+
+<pre>
+&lt;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/scene_container"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent" >
+    &lt;TextView
+        android:id="@+id/text_view2
+        android:text="Text Line 2" />
+    &lt;TextView
+        android:id="@+id/text_view1
+        android:text="Text Line 1" />
+&lt;/RelativeLayout>
+</pre>
+
+<h3>Generate Scenes from Layouts</h3>
+
+<p>After you create definitions for the two relative layouts, you can obtain an scene for
+each of them. This enables you to later transition between the two UI configurations.
+To obtain a scene, you need a reference to the scene root and the layout resource ID.</p>
+
+<p>The following code snippet shows you how to get a reference to the scene root and create
+two {@link android.transition.Scene} objects from the layout files:</p>
+
+<pre>
+Scene mAScene;
+Scene mAnotherScene;
+
+// Create the scene root for the scenes in this app
+mSceneRoot = (ViewGroup) findViewById(R.id.scene_root);
+
+// Create the scenes
+mAScene = Scene.getSceneForLayout(mSceneRoot, R.layout.a_scene, this);
+mAnotherScene =
+    Scene.getSceneForLayout(mSceneRoot, R.layout.another_scene, this);
+</pre>
+
+<p>In the app, there are now two {@link android.transition.Scene} objects based on view
+hierarchies. Both scenes use the scene root defined by the
+{@link android.widget.FrameLayout} element in <code>res/layout/activity_main.xml</code>.</p>
+
+
+
+<h2 id="FromCode">Create a Scene in Your Code</h2>
+
+<p>You can also create a {@link android.transition.Scene} instance in your code from a
+{@link android.view.ViewGroup} object. Use this technique when you modify the view hierarchies
+directly in your code or when you generate them dynamically.</p>
+
+<p>To create a scene from a view hierarchy in your code, use the
+{@link android.transition.Scene#Scene(android.view.ViewGroup, android.view.View) Scene(sceneRoot, viewHierarchy)}
+constructor. Calling this constructor is equivalent to calling the
+{@link android.transition.Scene#getSceneForLayout Scene.getSceneForLayout()} method when you
+have already inflated a layout file.</p>
+
+<p>The following code snippet demonstrates how to create a {@link android.transition.Scene}
+instance from the scene root element and the view hierarchy for the scene in your code:</p>
+
+<pre>
+Scene mScene;
+
+// Obtain the scene root element
+mSceneRoot = (ViewGroup) mSomeLayoutElement;
+
+// Obtain the view hierarchy to add as a child of
+// the scene root when this scene is entered
+mViewHierarchy = (ViewGroup) someOtherLayoutElement;
+
+// Create a scene
+mScene = new Scene(mSceneRoot, mViewHierarchy);
+</pre>
+
+
+
+<h2 id="Actions">Create Scene Actions</h2>
+
+<p>The framework enables you to define custom scene actions that the system runs when entering
+or exiting a scene. In many cases, defining custom scene actions is not necessary, since the
+framework animates the change between scenes automatically.</p>
+
+<p>Scene actions are useful for handling these cases:</p>
+
+<ul>
+<li>Animate views that are not in the same hierarchy. You can animate views for both the
+starting and ending scenes using exit and entry scene actions.</li>
+<li>Animate views that the transitions framework cannot animate automatically, such as
+{@link android.widget.ListView} objects. For more information, see
+<a href="{@docRoot}training/transitions/overview.html#Limitations">Limitations</a>.</li>
+</ul>
+
+<p>To provide custom scene actions, define your actions as {@link java.lang.Runnable} objects
+and pass them to the {@link android.transition.Scene#setExitAction Scene.setExitAction()} or
+{@link android.transition.Scene#setEnterAction Scene.setEnterAction()} methods. The framework
+calls the {@link android.transition.Scene#setExitAction setExitAction()} method on the starting
+scene before running the transition animation and the {@link
+android.transition.Scene#setEnterAction setEnterAction()} method on the ending scene after
+running the transition animation.</p>
+
+<p class="note"><strong>Note:</strong> Do not use scene actions to pass data between views in
+the starting and ending scenes. For more information, see
+<a href="{@docRoot}training/transitions/transitions.html#Callbacks">Defining Transition
+Lifecycle Callbacks</a>.</p>
diff --git a/docs/html/training/transitions/transitions.jd b/docs/html/training/transitions/transitions.jd
new file mode 100644
index 0000000..489e291
--- /dev/null
+++ b/docs/html/training/transitions/transitions.jd
@@ -0,0 +1,315 @@
+page.title=Applying a Transition
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+<h2>This lesson teaches you to</h2>
+<ol>
+  <li><a href="#Create">Create a Transition</a></li>
+  <li><a href="#Apply">Apply a Transition</a></li>
+  <li><a href="#Targets">Choose Specific Target Views</a></li>
+  <li><a href="#Multiple">Specify Multiple Transitions</a></li>
+  <li><a href="#NoScenes">Apply a Transition Without Scenes</a></li>
+  <li><a href="#Callbacks">Define Transition Lifecycle Callbacks</a></li>
+</ol>
+</div>
+</div>
+
+<p>In the transitions framework, animations create a series of frames that depict a change
+between the view hierarchies in the starting and ending scenes. The framework represents
+these animations as transition objects, which contain information about an animation. To
+run an animation, you provide the transition to use and the ending scene to a transition
+manager.</p>
+
+<p>This lesson teaches you run an animation between two scenes using built-in transitions
+to move, resize, and fade views. The next lesson shows you how to define custom transitions.</p>
+
+
+
+<h2 id="Create">Create a Transition</h2>
+
+<p>In the previous lesson, you learned how to create scenes that represent the state of
+different view hierarchies. Once you have defined the starting scene and the ending scene you
+want to change between, you need to create a {@link android.transition.Transition} object
+that defines an animation. The framework enables you to specify a built-in transition in a
+resource file and inflate it in your code or to create an instance of a built-in transition
+directly in your code.</p>
+
+<!-- Built in transition table -->
+<p class="table-caption" id="table1"><strong>Table 1.</strong> Built-in transition types.</p>
+<table>
+<tr>
+  <th scope="col">Class</th>
+  <th scope="col">Tag</th>
+  <th scope="col">Attributes</th>
+  <th scope="col">Effect</th>
+</tr>
+<tr>
+  <td><code><a href="/reference/android/transition/AutoTransition.html">AutoTransition</a></code></td>
+  <td>&lt;autoTransition/&gt;</td>
+  <td style="text-align=center;"> - </td>
+  <td>Default transition. Fade out, move and resize, and fade in views, in that order.</td>
+</tr>
+<tr>
+  <td><code><a href="/reference/android/transition/Fade.html">Fade</a></code></td>
+  <td>&lt;fade/&gt;</td>
+  <td><code>android:fadingMode="[fade_in |<br> fade_out |<br> fade_in_out]"</code></td>
+  <td>
+    <code>fade_in</code> fades in views<br>
+    <code>fade_out</code> fades out views<br>
+    <code>fade_in_out</code> (default) does a <code>fade_out</code> followed by a <code>fade_in</code>.
+  </td>
+</tr>
+<tr>
+  <td><code><a href="/reference/android/transition/ChangeBounds.html">ChangeBounds</a></code></td>
+  <td>&lt;changeBounds/&gt;</td>
+  <td style="text-align=center;"> - </td>
+  <td>Moves and resizes views.</td>
+</tr>
+</table>
+
+
+<h3 id="FromFile">Create a transition instance from a resource file</h3>
+
+<p>This technique enables you to modify your transition definition without having to change
+the code of your activity. This technique is also useful to separate complex transition
+definitions from your application code, as shown in <a href="#Multiple">Specify Multiple
+Transitions</a>.</p>
+
+<p>To specify a built-in transition in a resource file, follow these steps:</p>
+
+<ol>
+<li>Add the <code>res/transition/</code> directory to your project.</li>
+<li>Create a new XML resource file inside this directory.</li>
+<li>Add an XML node for one of the built-in transitions.</li>
+</ol>
+
+<p>For example, the following resource file specifies the {@link android.transition.Fade}
+transition:</p>
+
+<p class="code-caption">res/transition/fade_transition.xml</p>
+
+<pre>
+&lt;fade xmlns:android="http://schemas.android.com/apk/res/android" />
+</pre>
+
+<p>The following code snippet shows how to inflate a {@link android.transition.Transition}
+instance inside your activity from a resource file:</p>
+
+<pre>
+Transition mFadeTransition =
+        TransitionInflater.from(this).
+        inflateTransition(R.transition.fade_transition);
+</pre>
+
+
+<h3 id="FromCode">Create a transition instance in your code</h3>
+
+<p>This technique is useful for creating transition objects dynamically if you modify the user
+interface in your code, and to create simple built-in transition instances with few or
+no parameters.</p>
+
+<p>To create an instance of a built-in transition, invoke one of the public constructors in
+the subclasses of the {@link android.transition.Transition} class. For example, the following
+code snippet creates an instance of the {@link android.transition.Fade} transition:</p>
+
+<pre>
+Transition mFadeTransition = new Fade();
+</pre>
+
+
+
+<h2 id="Apply">Apply a Transition</h2>
+
+<p>You typically apply a transition to change between different view hierarchies in response
+to an event, such as a user action. For example, consider a search app: when the user enters
+a search term and clicks the search button, the app changes to the scene that represents the
+results layout while applying a transition that fades out the search button and fades in the
+search results.</p>
+
+<p>To make a scene change while applying a transition in response to some event in your
+activity, call the {@link android.transition.TransitionManager#go TransitionManager.go()}
+static method with the ending scene and the transition instance to use for the animation,
+as shown in the following snippet:</p>
+
+<pre>
+TransitionManager.go(mEndingScene, mFadeTransition);
+</pre>
+
+<p>The framework changes the view hierarchy inside the scene root with the view hierarchy
+from the ending scene while running the animation specified by the transition instance. The
+starting scene is the ending scene from the last transition. If there was no previous
+transition, the starting scene is determined automatically from the current state of the
+user interface.</p>
+
+<p>If you do not specify a transition instance, the transition manager can apply an automatic
+transition that does something reasonable for most situations. For more information, see the
+API reference for the {@link android.transition.TransitionManager} class.</p>
+
+
+
+<h2 id="Targets">Choose Specific Target Views</h2>
+
+<p>The framework applies transitions to all views in the starting and ending scenes by
+default. In some cases, you may only want  to apply an animation to a subset of views in a
+scene. For example, the framework does not support animating changes to
+{@link android.widget.ListView} objects, so you should not try to animate them during a
+transition. The framework enables you to select specific views you want to animate.</p>
+
+<p>Each view that the transition animates is called a <em>target</em>. You can only
+select targets that are part of the view hierarchy associated with a scene.</p>
+
+<p>To remove one or more views from the list of targets, call the {@link
+android.transition.Transition#removeTarget removeTarget()} method before starting
+the transition. To add only the views you specify to the list of targets, call the
+{@link android.transition.Transition#addTarget addTarget()} method. For more
+information, see the API reference for the {@link android.transition.Transition} class.</p>
+
+
+
+<h2 id="Multiple">Specify Multiple Transitions</h2>
+
+<p>To get the most impact from an animation, you should match it to the type of changes
+that occur between the scenes. For example, if you are removing some views and adding others
+between scenes, a fade out/fade in animation provides a noticeable indication that some views
+are no longer available. If you are moving views to different points on the screen, a better
+choice would be to animate the movement so that users notice the new location of the views.</p>
+
+<p>You do not have to choose only one animation, since the transitions framework enables you
+to combine animation effects in a transition set that contains a group of individual built-in
+or custom transitions.</p>
+
+<p>To define a transition set from a collection of transitions in XML, create a resource file
+in the <code>res/transitions/</code> directory and list the transitions under the
+<code>transitionSet</code> element. For example, the following snippet shows how to specify a
+transition set that has the same behaviour as the {@link android.transition.AutoTransition}
+class:</p>
+
+<pre>
+&lt;transitionSet xmlns:android="http://schemas.android.com/apk/res/android"
+    android:transitionOrdering="sequential">
+    &lt;fade android:fadingMode="fade_out" />
+    &lt;changeBounds />
+    &lt;fade android:fadingMode="fade_in" />
+&lt;/transitionSet>
+</pre>
+
+<p>To inflate the transition set into a {@link android.transition.TransitionSet} object in
+your code, call the {@link android.transition.TransitionInflater#from TransitionInflater.from()}
+method in your activity. The {@link android.transition.TransitionSet} class extends from the
+{@link android.transition.Transition} class, so you can use it with a transition manager just
+like any other {@link android.transition.Transition} instance.</p>
+
+
+
+<h2 id="NoScenes">Apply a Transition Without Scenes</h2>
+
+<p>Changing view hierarchies is not the only way to modify your user interface. You can also
+make changes by adding, modifying, and removing child views within the current hierarchy. For
+example, you can implement a search interaction with just a single layout. Start with the
+layout showing a search entry field and a search icon. To change the user interface to show
+the results, remove the search button when the user clicks it by calling the {@link
+android.view.ViewGroup#removeView ViewGroup.removeView()} method, and add the search results by
+calling {@link android.view.ViewGroup#addView ViewGroup.addView()} method.</p>
+
+<p>You may want to use this approach if the alternative is to have two hierarchies that are
+nearly identical. Rather than having to create and maintain two separate layout files for a
+minor difference in the user interface, you can have one layout file containing a view
+hierarchy that you modify in code.</p>
+
+<p>If you make changes within the current view hierarchy in this fashion, you do not need to
+create a scene. Instead, you can create and apply a transition between two states of a view
+hierarchy using a <em>delayed transition</em>. This feature of the transitions framework
+starts with the current view hierarchy state, records changes you make to its views, and applies
+a transition that animates the changes when the system redraws the user interface.</p>
+
+<p>To create a delayed transition within a single view hierarchy, follow these steps:</p>
+
+<ol>
+<li>When the event that triggers the transition occurs, call the {@link
+android.transition.TransitionManager#beginDelayedTransition
+TransitionManager.beginDelayedTransition()} method providing the parent view of all the views
+you want to change and the transition to use. The framework stores the current state of the
+child views and their property values.</li>
+<li>Make changes to the child views as required by your use case. The framework records
+the changes you make to the child views and their properties.</li>
+<li>When the system redraws the user interface according to your changes, the framework
+animates the changes between the original state and the new state.</li>
+</ol>
+
+<p>The following example shows how to animate the addition of a text view to a view hierarchy
+using a delayed transition. The first snippet shows the layout definition file:</p>
+
+<p class="code-caption">res/layout/activity_main.xml</p>
+
+<pre>
+&lt;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/mainLayout"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent" >
+    &lt;EditText
+        android:id="@+id/inputText"
+        android:layout_alignParentLeft="true"
+        android:layout_alignParentTop="true"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content" />
+    ...
+&lt;/RelativeLayout>
+</pre>
+
+<p>The next snippet shows the code that animates the addition of the text view:</p>
+
+<p class="code-caption">MainActivity.java</p>
+
+<pre>
+private TextView mLabelText;
+private Fade mFade;
+private ViewGroup mRootView;
+...
+
+// Load the layout
+this.setContentView(R.layout.activity_main);
+...
+
+// Create a new TextView and set some View properties
+mLabelText = new TextView();
+mLabelText.setText("Label").setId("1");
+
+// Get the root view and create a transition
+mRootView = (ViewGroup) findViewById(R.id.mainLayout);
+mFade = new Fade(IN);
+
+// Start recording changes to the view hierarchy
+TransitionManager.beginDelayedTransition(mRootView, mFade);
+
+// Add the new TextView to the view hierarchy
+mRootView.addView(mLabelText);
+
+// When the system redraws the screen to show this update,
+// the framework will animate the addition as a fade in
+</pre>
+
+
+
+<h2 id="Callbacks">Define Transition Lifecycle Callbacks</h2>
+
+<p>The transition lifecycle is similar to the activity lifecycle. It represents the transition
+states that the framework monitors during the time between a call to the {@link
+android.transition.TransitionManager#go TransitionManager.go()} method and the completion of
+the animation. At important lifecycle states, the framework invokes callbacks defined by
+the {@link android.transition.Transition.TransitionListener TransitionListener}
+interface.</p>
+
+<p>Transition lifecycle callbacks are useful, for example, for copying a view property value
+from the starting view hierarchy to the ending view hierarchy during a scene change. You
+cannot simply copy the value from its starting view to the view in the ending view hierarchy,
+because the ending view hierarchy is not inflated until the transition is completed.
+Instead, you need to store the value in a variable and then copy it into the ending view
+hierarchy when the framework has finished the transition. To get notified when the transition
+is completed, you can implement the {@link
+android.transition.Transition.TransitionListener#onTransitionEnd
+TransitionListener.onTransitionEnd()} method in your activity.</p>
+
+<p>For more information, see the API reference for the {@link
+android.transition.Transition.TransitionListener TransitionListener} class.</p>
diff --git a/docs/html/training/tv/playback/card.jd b/docs/html/training/tv/playback/card.jd
new file mode 100644
index 0000000..8ac75fd
--- /dev/null
+++ b/docs/html/training/tv/playback/card.jd
@@ -0,0 +1,156 @@
+page.title=Providing a Card View
+page.tags="card"
+
+trainingnavtop=true
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+  <h2>This lesson teaches you to</h2>
+  <ol>
+    <li><a href="#presenter">Create a Card Presenter</a></li>
+    <li><a href="#card-view">Create a Card View</a></li>
+  </ol>
+  <h2>Try it out</h2>
+  <ul>
+    <li><a class="external-link" href="https://github.com/googlesamples/androidtv-Leanback">Android
+    Leanback sample app</a></li>
+  </ul>
+</div>
+</div>
+
+<p>In the previous lesson, you created a catalog browser, implemented in a browse fragment, that
+displays a list of media items. In this lesson, you create the card views for your media items and
+present them in the browse fragment.</p>
+
+<p>The {@link android.support.v17.leanback.widget.BaseCardView} class and subclasses display the meta
+data associated with a media item. The {@link android.support.v17.leanback.widget.ImageCardView}
+class used in this lesson displays an image for the content along with the media item's title.</p>
+
+<p>This lesson describes code from the <a href="https://github.com/googlesamples/androidtv-Leanback">
+Android Leanback sample app</a>, available on GitHub. Use this sample code to start your own
+app.</p>
+
+<img itemprop="image" src="{@docRoot}images/tv/app-browse.png" alt="App main screen"/>
+<p class="img-caption"><b>Figure 1.</b> The <a href="https://github.com/googlesamples/androidtv-Leanback">
+Leanback sample app</a> browse fragment with a card presenter displaying card view objects.</p>
+
+<h2 id="presenter">Create a Card Presenter</h2>
+
+<p>A {@link android.support.v17.leanback.widget.Presenter} generates views and binds objects to them
+on demand. In the browse fragment where your app presents its content to the user, you create a
+{@link android.support.v17.leanback.widget.Presenter} for the content cards and pass it to the adapter
+that adds the content to the screen. In the following code, the <code>CardPresenter</code> is created
+in the {@link android.support.v4.app.LoaderManager.LoaderCallbacks#onLoadFinished(android.support.v4.content.Loader, java.lang.Object) onLoadFinished()}
+callback of the {@link android.support.v4.app.LoaderManager}.</p>
+
+<pre>
+&#64;Override
+public void onLoadFinished(Loader&lt;HashMap&lt;String, List&lt;Movie&gt;&gt;&gt; arg0,
+                           HashMap&lt;String, List&lt;Movie&gt;&gt; data) {
+
+    mRowsAdapter = new ArrayObjectAdapter(new ListRowPresenter());
+    CardPresenter cardPresenter = new CardPresenter();
+
+    int i = 0;
+
+    for (Map.Entry&lt;String, List&lt;Movie&gt;&gt; entry : data.entrySet()) {
+        ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(cardPresenter);
+        List&lt;Movie&gt; list = entry.getValue();
+
+        for (int j = 0; j &lt; list.size(); j++) {
+            listRowAdapter.add(list.get(j));
+        }
+        HeaderItem header = new HeaderItem(i, entry.getKey(), null);
+        i++;
+        mRowsAdapter.add(new ListRow(header, listRowAdapter));
+    }
+
+    HeaderItem gridHeader = new HeaderItem(i, getString(R.string.more_samples),
+            null);
+
+    GridItemPresenter gridPresenter = new GridItemPresenter();
+    ArrayObjectAdapter gridRowAdapter = new ArrayObjectAdapter(gridPresenter);
+    gridRowAdapter.add(getString(R.string.grid_view));
+    gridRowAdapter.add(getString(R.string.error_fragment));
+    gridRowAdapter.add(getString(R.string.personal_settings));
+    mRowsAdapter.add(new ListRow(gridHeader, gridRowAdapter));
+
+    setAdapter(mRowsAdapter);
+
+    updateRecommendations();
+}
+</pre>
+
+<h2 id="card-view">Create a Card View</h2>
+
+<p>In this step, you build the card presenter with a view holder for the card view that describes
+your media content items. Note that each presenter must only create one view type. If you have two
+different card view types then you need two different card presenters.</p>
+
+<p>In the {@link android.support.v17.leanback.widget.Presenter}, implement an
+{@link android.support.v17.leanback.widget.Presenter#onCreateViewHolder(android.view.ViewGroup) onCreateViewHolder()}
+callback that creates a view holder that can be used to display a content item.</p>
+
+<pre>
+&#64;Override
+public class CardPresenter extends Presenter {
+
+    private Context mContext;
+    private static int CARD_WIDTH = 313;
+    private static int CARD_HEIGHT = 176;
+    private Drawable mDefaultCardImage;
+
+    &#64;Override
+    public ViewHolder onCreateViewHolder(ViewGroup parent) {
+        mContext = parent.getContext();
+        mDefaultCardImage = mContext.getResources().getDrawable(R.drawable.movie);
+...
+</pre>
+
+<p>In the {@link android.support.v17.leanback.widget.Presenter#onCreateViewHolder(android.view.ViewGroup)
+onCreateViewHolder()} method, create a card view for content items. The sample below uses an
+{@link android.support.v17.leanback.widget.ImageCardView}.</p>
+
+<p>When a card is selected, the default behavior expands it to a larger size. If you want to designate
+a different color for the selected card, call {@link android.support.v17.leanback.widget.BaseCardView#setSelected(boolean)
+setSelected()}
+as shown here.</p>
+
+<pre>
+...
+    ImageCardView cardView = new ImageCardView(mContext) {
+        &#64;Override
+        public void setSelected(boolean selected) {
+            int selected_background = mContext.getResources().getColor(R.color.detail_background);
+            int default_background = mContext.getResources().getColor(R.color.default_background);
+            int color = selected ? selected_background : default_background;
+            findViewById(R.id.info_field).setBackgroundColor(color);
+            super.setSelected(selected);
+        }
+    };
+...
+</pre>
+
+<p>When the user opens your app, the {@link android.support.v17.leanback.widget.Presenter.ViewHolder}
+displays the <code>CardView</code> objects for your content items. You need to set these to receive
+focus from the D-pad controller by calling {@link android.view.View#setFocusable(boolean) setFocusable(true)}
+and {@link android.view.View#setFocusableInTouchMode(boolean) setFocusableInTouchMode(true)}.</p>
+
+<pre>
+...
+    cardView.setFocusable(true);
+    cardView.setFocusableInTouchMode(true);
+    return new ViewHolder(cardView);
+}
+</pre>
+
+<p>When the user selects the {@link android.support.v17.leanback.widget.ImageCardView}, it expands
+to reveal its text area with the background color you specify, as shown in figure 2.</p>
+
+<img itemprop="image" src="{@docRoot}images/tv/card-view.png" alt="App card view"/>
+<p class="img-caption"><b>Figure 2.</b> The <a href="https://github.com/googlesamples/androidtv-Leanback">
+Leanback sample app</a> image card view when selected.</p>
+
+
diff --git a/docs/html/training/tv/playback/index.jd b/docs/html/training/tv/playback/index.jd
index 5427d48..0e9c5ec 100644
--- a/docs/html/training/tv/playback/index.jd
+++ b/docs/html/training/tv/playback/index.jd
@@ -56,6 +56,9 @@
     <dd>Learn how to use the Leanback support library to build a browsing interface for media
       catalogs.</dd>
 
+  <dt><b><a href="details.html">Providing a Card View</a></b></dt>
+    <dd>Learn how to use the Leanback support library to build a card view for content items.</dd>
+
   <dt><b><a href="details.html">Building a Details View</a></b></dt>
     <dd>Learn how to use the Leanback support library to build a details page for media items.</dd>
 
diff --git a/docs/html/training/tv/start/layouts.jd b/docs/html/training/tv/start/layouts.jd
index 177ea7a..a378096 100644
--- a/docs/html/training/tv/start/layouts.jd
+++ b/docs/html/training/tv/start/layouts.jd
@@ -119,8 +119,8 @@
 
 <p>
   Avoid screen elements being clipped due to overscan and by incorporating a 10% margin
-  on all sides of your layout. This translates into a 27dp margin on the left and right edges and
-  a 48dp margin on the top and bottom of your base layouts for activities. The following
+  on all sides of your layout. This translates into a 48dp margin on the left and right edges and
+  a 27dp margin on the top and bottom of your base layouts for activities. The following
   example layout demonstrates how to set these margins in the root layout for a TV app:
 </p>
 
diff --git a/graphics/java/android/graphics/AvoidXfermode.java b/graphics/java/android/graphics/AvoidXfermode.java
index 206c959..48ee6fa 100644
--- a/graphics/java/android/graphics/AvoidXfermode.java
+++ b/graphics/java/android/graphics/AvoidXfermode.java
@@ -23,7 +23,7 @@
 @Deprecated
 public class AvoidXfermode extends Xfermode {
 
-    // these need to match the enum in SkAvoidXfermode.h on the native side
+    // these need to match the enum in AvoidXfermode.h on the native side
     public enum Mode {
         AVOID   (0),    //!< draw everywhere except on the opColor
         TARGET  (1);    //!< draw only on top of the opColor
diff --git a/graphics/java/android/graphics/drawable/InsetDrawable.java b/graphics/java/android/graphics/drawable/InsetDrawable.java
index 8b70a08..488ee4c 100644
--- a/graphics/java/android/graphics/drawable/InsetDrawable.java
+++ b/graphics/java/android/graphics/drawable/InsetDrawable.java
@@ -34,7 +34,6 @@
 import android.graphics.Outline;
 import android.graphics.PixelFormat;
 import android.graphics.PorterDuff.Mode;
-import android.graphics.drawable.Drawable.ConstantState;
 import android.graphics.Rect;
 import android.util.AttributeSet;
 
@@ -60,28 +59,49 @@
 public class InsetDrawable extends Drawable implements Drawable.Callback {
     private final Rect mTmpRect = new Rect();
 
-    private final InsetState mState;
+    private InsetState mState;
+    private Drawable mDrawable;
 
     private boolean mMutated;
 
-    /*package*/ InsetDrawable() {
-        this(null, null);
+    /**
+     * No-arg constructor used by drawable inflation.
+     */
+    InsetDrawable() {
+        this(new InsetState(), null);
     }
 
+    /**
+     * Creates a new inset drawable with the specified inset.
+     *
+     * @param drawable The drawable to inset.
+     * @param inset Inset in pixels around the drawable.
+     */
     public InsetDrawable(Drawable drawable, int inset) {
         this(drawable, inset, inset, inset, inset);
     }
 
-    public InsetDrawable(Drawable drawable, int insetLeft, int insetTop,
-                         int insetRight, int insetBottom) {
-        this(null, null);
+    /**
+     * Creates a new inset drawable with the specified insets.
+     *
+     * @param drawable The drawable to inset.
+     * @param insetLeft Left inset in pixels.
+     * @param insetTop Top inset in pixels.
+     * @param insetRight Right inset in pixels.
+     * @param insetBottom Bottom inset in pixels.
+     */
+    public InsetDrawable(Drawable drawable, int insetLeft, int insetTop,int insetRight,
+            int insetBottom) {
+        this(new InsetState(), null);
 
-        mState.mDrawable = drawable;
+        mState.mDrawableState = drawable == null ? null : drawable.getConstantState();
         mState.mInsetLeft = insetLeft;
         mState.mInsetTop = insetTop;
         mState.mInsetRight = insetRight;
         mState.mInsetBottom = insetBottom;
 
+        mDrawable = drawable;
+
         if (drawable != null) {
             drawable.setCallback(this);
         }
@@ -93,10 +113,6 @@
         final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.InsetDrawable);
         super.inflateWithAttributes(r, parser, a, R.styleable.InsetDrawable_visible);
 
-        // Reset mDrawable to preserve old multiple-inflate behavior. This is
-        // silly, but we have CTS tests that rely on it.
-        mState.mDrawable = null;
-
         updateStateFromTypedArray(a);
         inflateChildElements(r, parser, attrs, theme);
         verifyRequiredAttributes(a);
@@ -106,25 +122,26 @@
     private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs,
             Theme theme) throws XmlPullParserException, IOException {
         // Load inner XML elements.
-        if (mState.mDrawable == null) {
+        if (mDrawable == null) {
             int type;
             while ((type=parser.next()) == XmlPullParser.TEXT) {
             }
             if (type != XmlPullParser.START_TAG) {
-                throw new XmlPullParserException(
-                        parser.getPositionDescription()
-                                + ": <inset> tag requires a 'drawable' attribute or "
-                                + "child tag defining a drawable");
+                throw new XmlPullParserException(parser.getPositionDescription()
+                        + ": <inset> tag requires a 'drawable' attribute or "
+                        + "child tag defining a drawable");
             }
+
             final Drawable dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
-            mState.mDrawable = dr;
+            mState.mDrawableState = dr.getConstantState();
+            mDrawable = dr;
             dr.setCallback(this);
         }
     }
 
     private void verifyRequiredAttributes(TypedArray a) throws XmlPullParserException {
         // If we're not waiting on a theme, verify required attributes.
-        if (mState.mDrawable == null && (mState.mThemeAttrs == null
+        if (mDrawable == null && (mState.mThemeAttrs == null
                 || mState.mThemeAttrs[R.styleable.InsetDrawable_drawable] == 0)) {
             throw new XmlPullParserException(a.getPositionDescription()
                     + ": <inset> tag requires a 'drawable' attribute or "
@@ -148,7 +165,8 @@
                 case R.styleable.InsetDrawable_drawable:
                     final Drawable dr = a.getDrawable(attr);
                     if (dr != null) {
-                        state.mDrawable = dr;
+                        mState.mDrawableState = dr.getConstantState();
+                        mDrawable = dr;
                         dr.setCallback(this);
                     }
                     break;
@@ -198,8 +216,8 @@
             }
         }
 
-        if (state.mDrawable != null && state.mDrawable.canApplyTheme()) {
-            state.mDrawable.applyTheme(t);
+        if (mDrawable != null && mDrawable.canApplyTheme()) {
+            mDrawable.applyTheme(t);
         }
     }
 
@@ -234,27 +252,27 @@
 
     @Override
     public void draw(Canvas canvas) {
-        mState.mDrawable.draw(canvas);
+        mDrawable.draw(canvas);
     }
 
     @Override
     public int getChangingConfigurations() {
         return super.getChangingConfigurations()
                 | mState.mChangingConfigurations
-                | mState.mDrawable.getChangingConfigurations();
+                | mDrawable.getChangingConfigurations();
     }
 
     @Override
     public boolean getPadding(Rect padding) {
-        boolean pad = mState.mDrawable.getPadding(padding);
+        final boolean pad = mDrawable.getPadding(padding);
 
         padding.left += mState.mInsetLeft;
         padding.right += mState.mInsetRight;
         padding.top += mState.mInsetTop;
         padding.bottom += mState.mInsetBottom;
 
-        return pad || (mState.mInsetLeft | mState.mInsetRight |
-                mState.mInsetTop | mState.mInsetBottom) != 0;
+        return pad || (mState.mInsetLeft | mState.mInsetRight
+                | mState.mInsetTop | mState.mInsetBottom) != 0;
     }
 
     /** @hide */
@@ -269,61 +287,61 @@
 
     @Override
     public void setHotspot(float x, float y) {
-        mState.mDrawable.setHotspot(x, y);
+        mDrawable.setHotspot(x, y);
     }
 
     @Override
     public void setHotspotBounds(int left, int top, int right, int bottom) {
-        mState.mDrawable.setHotspotBounds(left, top, right, bottom);
+        mDrawable.setHotspotBounds(left, top, right, bottom);
     }
 
     /** @hide */
     @Override
     public void getHotspotBounds(Rect outRect) {
-        mState.mDrawable.getHotspotBounds(outRect);
+        mDrawable.getHotspotBounds(outRect);
     }
 
     @Override
     public boolean setVisible(boolean visible, boolean restart) {
-        mState.mDrawable.setVisible(visible, restart);
+        mDrawable.setVisible(visible, restart);
         return super.setVisible(visible, restart);
     }
 
     @Override
     public void setAlpha(int alpha) {
-        mState.mDrawable.setAlpha(alpha);
+        mDrawable.setAlpha(alpha);
     }
 
     @Override
     public int getAlpha() {
-        return mState.mDrawable.getAlpha();
+        return mDrawable.getAlpha();
     }
 
     @Override
     public void setColorFilter(ColorFilter cf) {
-        mState.mDrawable.setColorFilter(cf);
+        mDrawable.setColorFilter(cf);
     }
 
     @Override
     public void setTintList(ColorStateList tint) {
-        mState.mDrawable.setTintList(tint);
+        mDrawable.setTintList(tint);
     }
 
     @Override
     public void setTintMode(Mode tintMode) {
-        mState.mDrawable.setTintMode(tintMode);
+        mDrawable.setTintMode(tintMode);
     }
 
     /** {@hide} */
     @Override
     public void setLayoutDirection(int layoutDirection) {
-        mState.mDrawable.setLayoutDirection(layoutDirection);
+        mDrawable.setLayoutDirection(layoutDirection);
     }
 
     @Override
     public int getOpacity() {
         final InsetState state = mState;
-        final int opacity = state.mDrawable.getOpacity();
+        final int opacity = mDrawable.getOpacity();
         if (opacity == PixelFormat.OPAQUE && (state.mInsetLeft > 0 || state.mInsetTop > 0
                 || state.mInsetRight > 0 || state.mInsetBottom > 0)) {
             return PixelFormat.TRANSLUCENT;
@@ -333,19 +351,19 @@
 
     @Override
     public boolean isStateful() {
-        return mState.mDrawable.isStateful();
+        return mDrawable.isStateful();
     }
 
     @Override
     protected boolean onStateChange(int[] state) {
-        boolean changed = mState.mDrawable.setState(state);
+        final boolean changed = mDrawable.setState(state);
         onBoundsChange(getBounds());
         return changed;
     }
 
     @Override
     protected boolean onLevelChange(int level) {
-        return mState.mDrawable.setLevel(level);
+        return mDrawable.setLevel(level);
     }
 
     @Override
@@ -358,24 +376,22 @@
         r.right -= mState.mInsetRight;
         r.bottom -= mState.mInsetBottom;
 
-        mState.mDrawable.setBounds(r.left, r.top, r.right, r.bottom);
+        mDrawable.setBounds(r.left, r.top, r.right, r.bottom);
     }
 
     @Override
     public int getIntrinsicWidth() {
-        return mState.mDrawable.getIntrinsicWidth()
-                + mState.mInsetLeft + mState.mInsetRight;
+        return mDrawable.getIntrinsicWidth() + mState.mInsetLeft + mState.mInsetRight;
     }
 
     @Override
     public int getIntrinsicHeight() {
-        return mState.mDrawable.getIntrinsicHeight()
-                + mState.mInsetTop + mState.mInsetBottom;
+        return mDrawable.getIntrinsicHeight() + mState.mInsetTop + mState.mInsetBottom;
     }
 
     @Override
     public void getOutline(@NonNull Outline outline) {
-        mState.mDrawable.getOutline(outline);
+        mDrawable.getOutline(outline);
     }
 
     @Override
@@ -390,7 +406,8 @@
     @Override
     public Drawable mutate() {
         if (!mMutated && super.mutate() == this) {
-            mState.mDrawable.mutate();
+            mState = new InsetState(mState);
+            mDrawable.mutate();
             mMutated = true;
         }
         return this;
@@ -401,7 +418,7 @@
      */
     public void clearMutated() {
         super.clearMutated();
-        mState.mDrawable.clearMutated();
+        mDrawable.clearMutated();
         mMutated = false;
     }
 
@@ -409,51 +426,53 @@
      * Returns the drawable wrapped by this InsetDrawable. May be null.
      */
     public Drawable getDrawable() {
-        return mState.mDrawable;
+        return mDrawable;
     }
 
-    final static class InsetState extends ConstantState {
+    private static final class InsetState extends ConstantState {
         int[] mThemeAttrs;
         int mChangingConfigurations;
 
-        Drawable mDrawable;
+        ConstantState mDrawableState;
 
         int mInsetLeft = 0;
         int mInsetTop = 0;
         int mInsetRight = 0;
         int mInsetBottom = 0;
 
-        private boolean mCheckedConstantState;
-        private boolean mCanConstantState;
+        public InsetState() {
+            // Empty constructor.
+        }
 
-        InsetState(InsetState orig, InsetDrawable owner, Resources res) {
+        public InsetState(InsetState orig) {
             if (orig != null) {
                 mThemeAttrs = orig.mThemeAttrs;
                 mChangingConfigurations = orig.mChangingConfigurations;
-                if (res != null) {
-                    mDrawable = orig.mDrawable.getConstantState().newDrawable(res);
-                } else {
-                    mDrawable = orig.mDrawable.getConstantState().newDrawable();
-                }
-                mDrawable.setCallback(owner);
-                mDrawable.setLayoutDirection(orig.mDrawable.getLayoutDirection());
-                mDrawable.setBounds(orig.mDrawable.getBounds());
-                mDrawable.setLevel(orig.mDrawable.getLevel());
+                mDrawableState = orig.mDrawableState;
                 mInsetLeft = orig.mInsetLeft;
                 mInsetTop = orig.mInsetTop;
                 mInsetRight = orig.mInsetRight;
                 mInsetBottom = orig.mInsetBottom;
-                mCheckedConstantState = mCanConstantState = true;
             }
         }
 
         @Override
         public boolean canApplyTheme() {
-            return mThemeAttrs != null || (mDrawable != null && mDrawable.canApplyTheme())
+            return mThemeAttrs != null
+                    || (mDrawableState != null && mDrawableState.canApplyTheme())
                     || super.canApplyTheme();
         }
 
         @Override
+        public int addAtlasableBitmaps(Collection<Bitmap> atlasList) {
+            final ConstantState state = mDrawableState;
+            if (state != null) {
+                return state.addAtlasableBitmaps(atlasList);
+            }
+            return 0;
+        }
+
+        @Override
         public Drawable newDrawable() {
             return new InsetDrawable(this, null);
         }
@@ -468,27 +487,30 @@
             return mChangingConfigurations;
         }
 
-        boolean canConstantState() {
-            if (!mCheckedConstantState) {
-                mCanConstantState = mDrawable.getConstantState() != null;
-                mCheckedConstantState = true;
-            }
-
-            return mCanConstantState;
-        }
-
-        @Override
-        public int addAtlasableBitmaps(Collection<Bitmap> atlasList) {
-            final ConstantState state = mDrawable.getConstantState();
-            if (state != null) {
-                return state.addAtlasableBitmaps(atlasList);
-            }
-            return 0;
+        public boolean canConstantState() {
+            return mDrawableState != null;
         }
     }
 
+    /**
+     * The one constructor to rule them all. This is called by all public
+     * constructors to set the state and initialize local properties.
+     */
     private InsetDrawable(InsetState state, Resources res) {
-        mState = new InsetState(state, this, res);
+        mState = state;
+
+        updateLocalState(res);
+    }
+
+    /**
+     * Initializes local dynamic properties from state. This should be called
+     * after significant state changes, e.g. from the One True Constructor and
+     * after inflating or applying a theme.
+     */
+    private void updateLocalState(Resources res) {
+        if (mState.mDrawableState != null) {
+            mDrawable = mState.mDrawableState.newDrawable(res);
+        }
     }
 }
 
diff --git a/include/androidfw/ResourceTypes.h b/include/androidfw/ResourceTypes.h
index 421c5c1..8673219 100644
--- a/include/androidfw/ResourceTypes.h
+++ b/include/androidfw/ResourceTypes.h
@@ -118,9 +118,9 @@
                        yDivsOffset(0), colorsOffset(0) { }
 
     int8_t wasDeserialized;
-    int8_t numXDivs;
-    int8_t numYDivs;
-    int8_t numColors;
+    uint8_t numXDivs;
+    uint8_t numYDivs;
+    uint8_t numColors;
 
     // The offset (from the start of this structure) to the xDivs & yDivs
     // array for this 9patch. To get a pointer to this array, call
diff --git a/libs/hwui/Android.common.mk b/libs/hwui/Android.common.mk
index b1673fe..7c1a724 100644
--- a/libs/hwui/Android.common.mk
+++ b/libs/hwui/Android.common.mk
@@ -5,12 +5,24 @@
     -Wno-gnu-static-float-init
 
 LOCAL_SRC_FILES := \
+    font/CacheTexture.cpp \
+    font/Font.cpp \
+    renderstate/MeshState.cpp \
+    renderstate/PixelBufferState.cpp \
+    renderstate/RenderState.cpp \
+    renderstate/Scissor.cpp \
+    renderstate/Stencil.cpp \
+    renderthread/CanvasContext.cpp \
+    renderthread/DrawFrameTask.cpp \
+    renderthread/EglManager.cpp \
+    renderthread/RenderProxy.cpp \
+    renderthread/RenderTask.cpp \
+    renderthread/RenderThread.cpp \
+    renderthread/TimeLord.cpp \
+    thread/TaskManager.cpp \
     utils/Blur.cpp \
     utils/GLUtils.cpp \
     utils/SortedListImpl.cpp \
-    thread/TaskManager.cpp \
-    font/CacheTexture.cpp \
-    font/Font.cpp \
     AmbientShadow.cpp \
     AnimationContext.cpp \
     Animator.cpp \
@@ -48,29 +60,17 @@
     RenderBufferCache.cpp \
     RenderNode.cpp \
     RenderProperties.cpp \
-    RenderState.cpp \
     ResourceCache.cpp \
     ShadowTessellator.cpp \
     SkiaCanvas.cpp \
     SkiaShader.cpp \
     Snapshot.cpp \
     SpotShadow.cpp \
-    Stencil.cpp \
     TessellationCache.cpp \
     Texture.cpp \
     TextureCache.cpp \
     TextDropShadowCache.cpp
 
-# RenderThread stuff
-LOCAL_SRC_FILES += \
-    renderthread/CanvasContext.cpp \
-    renderthread/DrawFrameTask.cpp \
-    renderthread/EglManager.cpp \
-    renderthread/RenderProxy.cpp \
-    renderthread/RenderTask.cpp \
-    renderthread/RenderThread.cpp \
-    renderthread/TimeLord.cpp
-
 intermediates := $(call intermediates-dir-for,STATIC_LIBRARIES,libRS,TARGET,)
 
 LOCAL_C_INCLUDES += \
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index 107eb08..1fb8092 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -16,24 +16,23 @@
 
 #define LOG_TAG "OpenGLRenderer"
 
+#include "Caches.h"
+
+#include "DisplayListRenderer.h"
+#include "GammaFontRenderer.h"
+#include "LayerRenderer.h"
+#include "Properties.h"
+#include "renderstate/RenderState.h"
+#include "ShadowTessellator.h"
+
 #include <utils/Log.h>
 #include <utils/String8.h>
 
-#include "Caches.h"
-#include "DisplayListRenderer.h"
-#include "GammaFontRenderer.h"
-#include "Properties.h"
-#include "LayerRenderer.h"
-#include "ShadowTessellator.h"
-#include "RenderState.h"
-
 namespace android {
-
-using namespace uirenderer;
-ANDROID_SINGLETON_STATIC_INSTANCE(Caches);
-
 namespace uirenderer {
 
+Caches* Caches::sInstance = nullptr;
+
 ///////////////////////////////////////////////////////////////////////////////
 // Macros
 ///////////////////////////////////////////////////////////////////////////////
@@ -48,8 +47,12 @@
 // Constructors/destructor
 ///////////////////////////////////////////////////////////////////////////////
 
-Caches::Caches(): Singleton<Caches>(),
-        mExtensions(Extensions::getInstance()), mInitialized(false), mRenderState(nullptr) {
+Caches::Caches(RenderState& renderState)
+        : patchCache(renderState)
+        , mRenderState(&renderState)
+        , mExtensions(Extensions::getInstance())
+        , mInitialized(false) {
+    INIT_LOGD("Creating OpenGL renderer caches");
     init();
     initFont();
     initConstraints();
@@ -59,7 +62,8 @@
     initTempProperties();
 
     mDebugLevel = readDebugLevel();
-    ALOGD("Enabling debug mode %d", mDebugLevel);
+    ALOGD_IF(mDebugLevel != kDebugDisabled,
+            "Enabling debug mode %d", mDebugLevel);
 }
 
 bool Caches::init() {
@@ -67,29 +71,10 @@
 
     ATRACE_NAME("Caches::init");
 
-    glGenBuffers(1, &meshBuffer);
-    glBindBuffer(GL_ARRAY_BUFFER, meshBuffer);
-    glBufferData(GL_ARRAY_BUFFER, sizeof(gMeshVertices), gMeshVertices, GL_STATIC_DRAW);
-
-    mCurrentBuffer = meshBuffer;
-    mCurrentIndicesBuffer = 0;
-    mCurrentPositionPointer = this;
-    mCurrentPositionStride = 0;
-    mCurrentTexCoordsPointer = this;
-    mCurrentPixelBuffer = 0;
-
-    mTexCoordsArrayEnabled = false;
-
-    glDisable(GL_SCISSOR_TEST);
-    scissorEnabled = false;
-    mScissorX = mScissorY = mScissorWidth = mScissorHeight = 0;
-
     glActiveTexture(gTextureUnits[0]);
     mTextureUnit = 0;
 
     mRegionMesh = nullptr;
-    mMeshIndices = 0;
-    mShadowStripsIndices = 0;
     blend = false;
     lastSrcMode = GL_ZERO;
     lastDstMode = GL_ZERO;
@@ -101,11 +86,12 @@
     debugOverdraw = false;
     debugStencilClip = kStencilHide;
 
-    patchCache.init(*this);
+    patchCache.init();
 
     mInitialized = true;
 
     resetBoundTextures();
+    mPixelBufferState.reset(new PixelBufferState());
 
     return true;
 }
@@ -219,17 +205,8 @@
 
 void Caches::terminate() {
     if (!mInitialized) return;
-
-    glDeleteBuffers(1, &meshBuffer);
-    mCurrentBuffer = 0;
-
-    glDeleteBuffers(1, &mMeshIndices);
-    mMeshIndices = 0;
     mRegionMesh.release();
 
-    glDeleteBuffers(1, &mShadowStripsIndices);
-    mShadowStripsIndices = 0;
-
     fboCache.clear();
 
     programCache.clear();
@@ -239,6 +216,8 @@
 
     clearGarbage();
 
+    mPixelBufferState.release();
+
     mInitialized = false;
 }
 
@@ -271,7 +250,7 @@
             layerCache.getSize(), layerCache.getMaxSize(), layerCache.getCount());
     if (mRenderState) {
         int memused = 0;
-        for (std::set<const Layer*>::iterator it = mRenderState->mActiveLayers.begin();
+        for (std::set<Layer*>::iterator it = mRenderState->mActiveLayers.begin();
                 it != mRenderState->mActiveLayers.end(); it++) {
             const Layer* layer = *it;
             log.appendFormat("    Layer size %dx%d; isTextureLayer()=%d; texid=%u fbo=%u; refs=%d\n",
@@ -369,155 +348,9 @@
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-// VBO
+// Textures
 ///////////////////////////////////////////////////////////////////////////////
 
-bool Caches::bindMeshBuffer() {
-    return bindMeshBuffer(meshBuffer);
-}
-
-bool Caches::bindMeshBuffer(const GLuint buffer) {
-    if (mCurrentBuffer != buffer) {
-        glBindBuffer(GL_ARRAY_BUFFER, buffer);
-        mCurrentBuffer = buffer;
-        return true;
-    }
-    return false;
-}
-
-bool Caches::unbindMeshBuffer() {
-    if (mCurrentBuffer) {
-        glBindBuffer(GL_ARRAY_BUFFER, 0);
-        mCurrentBuffer = 0;
-        return true;
-    }
-    return false;
-}
-
-bool Caches::bindIndicesBufferInternal(const GLuint buffer) {
-    if (mCurrentIndicesBuffer != buffer) {
-        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
-        mCurrentIndicesBuffer = buffer;
-        return true;
-    }
-    return false;
-}
-
-bool Caches::bindQuadIndicesBuffer() {
-    if (!mMeshIndices) {
-        std::unique_ptr<uint16_t[]> regionIndices(new uint16_t[gMaxNumberOfQuads * 6]);
-        for (uint32_t i = 0; i < gMaxNumberOfQuads; i++) {
-            uint16_t quad = i * 4;
-            int index = i * 6;
-            regionIndices[index    ] = quad;       // top-left
-            regionIndices[index + 1] = quad + 1;   // top-right
-            regionIndices[index + 2] = quad + 2;   // bottom-left
-            regionIndices[index + 3] = quad + 2;   // bottom-left
-            regionIndices[index + 4] = quad + 1;   // top-right
-            regionIndices[index + 5] = quad + 3;   // bottom-right
-        }
-
-        glGenBuffers(1, &mMeshIndices);
-        bool force = bindIndicesBufferInternal(mMeshIndices);
-        glBufferData(GL_ELEMENT_ARRAY_BUFFER, gMaxNumberOfQuads * 6 * sizeof(uint16_t),
-                regionIndices.get(), GL_STATIC_DRAW);
-        return force;
-    }
-
-    return bindIndicesBufferInternal(mMeshIndices);
-}
-
-bool Caches::bindShadowIndicesBuffer() {
-    if (!mShadowStripsIndices) {
-        std::unique_ptr<uint16_t[]> shadowIndices(new uint16_t[MAX_SHADOW_INDEX_COUNT]);
-        ShadowTessellator::generateShadowIndices(shadowIndices.get());
-        glGenBuffers(1, &mShadowStripsIndices);
-        bool force = bindIndicesBufferInternal(mShadowStripsIndices);
-        glBufferData(GL_ELEMENT_ARRAY_BUFFER, MAX_SHADOW_INDEX_COUNT * sizeof(uint16_t),
-            shadowIndices.get(), GL_STATIC_DRAW);
-        return force;
-    }
-
-    return bindIndicesBufferInternal(mShadowStripsIndices);
-}
-
-bool Caches::unbindIndicesBuffer() {
-    if (mCurrentIndicesBuffer) {
-        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
-        mCurrentIndicesBuffer = 0;
-        return true;
-    }
-    return false;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// PBO
-///////////////////////////////////////////////////////////////////////////////
-
-bool Caches::bindPixelBuffer(const GLuint buffer) {
-    if (mCurrentPixelBuffer != buffer) {
-        glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer);
-        mCurrentPixelBuffer = buffer;
-        return true;
-    }
-    return false;
-}
-
-bool Caches::unbindPixelBuffer() {
-    if (mCurrentPixelBuffer) {
-        glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
-        mCurrentPixelBuffer = 0;
-        return true;
-    }
-    return false;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Meshes and textures
-///////////////////////////////////////////////////////////////////////////////
-
-void Caches::bindPositionVertexPointer(bool force, const GLvoid* vertices, GLsizei stride) {
-    if (force || vertices != mCurrentPositionPointer || stride != mCurrentPositionStride) {
-        GLuint slot = currentProgram->position;
-        glVertexAttribPointer(slot, 2, GL_FLOAT, GL_FALSE, stride, vertices);
-        mCurrentPositionPointer = vertices;
-        mCurrentPositionStride = stride;
-    }
-}
-
-void Caches::bindTexCoordsVertexPointer(bool force, const GLvoid* vertices, GLsizei stride) {
-    if (force || vertices != mCurrentTexCoordsPointer || stride != mCurrentTexCoordsStride) {
-        GLuint slot = currentProgram->texCoords;
-        glVertexAttribPointer(slot, 2, GL_FLOAT, GL_FALSE, stride, vertices);
-        mCurrentTexCoordsPointer = vertices;
-        mCurrentTexCoordsStride = stride;
-    }
-}
-
-void Caches::resetVertexPointers() {
-    mCurrentPositionPointer = this;
-    mCurrentTexCoordsPointer = this;
-}
-
-void Caches::resetTexCoordsVertexPointer() {
-    mCurrentTexCoordsPointer = this;
-}
-
-void Caches::enableTexCoordsVertexArray() {
-    if (!mTexCoordsArrayEnabled) {
-        glEnableVertexAttribArray(Program::kBindingTexCoords);
-        mCurrentTexCoordsPointer = this;
-        mTexCoordsArrayEnabled = true;
-    }
-}
-
-void Caches::disableTexCoordsVertexArray() {
-    if (mTexCoordsArrayEnabled) {
-        glDisableVertexAttribArray(Program::kBindingTexCoords);
-        mTexCoordsArrayEnabled = false;
-    }
-}
-
 void Caches::activeTexture(GLuint textureUnit) {
     if (mTextureUnit != textureUnit) {
         glActiveTexture(gTextureUnits[textureUnit]);
@@ -579,71 +412,6 @@
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-// Scissor
-///////////////////////////////////////////////////////////////////////////////
-
-bool Caches::setScissor(GLint x, GLint y, GLint width, GLint height) {
-    if (scissorEnabled && (x != mScissorX || y != mScissorY ||
-            width != mScissorWidth || height != mScissorHeight)) {
-
-        if (x < 0) {
-            width += x;
-            x = 0;
-        }
-        if (y < 0) {
-            height += y;
-            y = 0;
-        }
-        if (width < 0) {
-            width = 0;
-        }
-        if (height < 0) {
-            height = 0;
-        }
-        glScissor(x, y, width, height);
-
-        mScissorX = x;
-        mScissorY = y;
-        mScissorWidth = width;
-        mScissorHeight = height;
-
-        return true;
-    }
-    return false;
-}
-
-bool Caches::enableScissor() {
-    if (!scissorEnabled) {
-        glEnable(GL_SCISSOR_TEST);
-        scissorEnabled = true;
-        resetScissor();
-        return true;
-    }
-    return false;
-}
-
-bool Caches::disableScissor() {
-    if (scissorEnabled) {
-        glDisable(GL_SCISSOR_TEST);
-        scissorEnabled = false;
-        return true;
-    }
-    return false;
-}
-
-void Caches::setScissorEnabled(bool enabled) {
-    if (scissorEnabled != enabled) {
-        if (enabled) glEnable(GL_SCISSOR_TEST);
-        else glDisable(GL_SCISSOR_TEST);
-        scissorEnabled = enabled;
-    }
-}
-
-void Caches::resetScissor() {
-    mScissorX = mScissorY = mScissorWidth = mScissorHeight = 0;
-}
-
-///////////////////////////////////////////////////////////////////////////////
 // Tiling
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -682,7 +450,7 @@
 TextureVertex* Caches::getRegionMesh() {
     // Create the mesh, 2 triangles and 4 vertices per rectangle in the region
     if (!mRegionMesh) {
-        mRegionMesh.reset(new TextureVertex[gMaxNumberOfQuads * 4]);
+        mRegionMesh.reset(new TextureVertex[kMaxNumberOfQuads * 4]);
     }
 
     return mRegionMesh.get();
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index b0eebd7..8d23833 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -21,7 +21,27 @@
     #define LOG_TAG "OpenGLRenderer"
 #endif
 
+
+#include "AssetAtlas.h"
+#include "Dither.h"
+#include "Extensions.h"
+#include "FboCache.h"
+#include "GradientCache.h"
+#include "LayerCache.h"
+#include "PatchCache.h"
+#include "ProgramCache.h"
+#include "PathCache.h"
+#include "RenderBufferCache.h"
+#include "renderstate/PixelBufferState.h"
+#include "ResourceCache.h"
+#include "TessellationCache.h"
+#include "TextDropShadowCache.h"
+#include "TextureCache.h"
+#include "thread/TaskProcessor.h"
+#include "thread/TaskManager.h"
+
 #include <vector>
+#include <memory>
 
 #include <GLES3/gl3.h>
 
@@ -33,25 +53,6 @@
 
 #include <SkPath.h>
 
-#include "thread/TaskProcessor.h"
-#include "thread/TaskManager.h"
-
-#include "AssetAtlas.h"
-#include "Extensions.h"
-#include "TextureCache.h"
-#include "LayerCache.h"
-#include "RenderBufferCache.h"
-#include "GradientCache.h"
-#include "PatchCache.h"
-#include "ProgramCache.h"
-#include "PathCache.h"
-#include "TessellationCache.h"
-#include "TextDropShadowCache.h"
-#include "FboCache.h"
-#include "ResourceCache.h"
-#include "Stencil.h"
-#include "Dither.h"
-
 namespace android {
 namespace uirenderer {
 
@@ -64,29 +65,6 @@
 // GL ES 2.0 defines that at least 16 texture units must be supported
 #define REQUIRED_TEXTURE_UNITS_COUNT 3
 
-// Maximum number of quads that pre-allocated meshes can draw
-static const uint32_t gMaxNumberOfQuads = 2048;
-
-// Generates simple and textured vertices
-#define FV(x, y, u, v) { x, y, u, v }
-
-// This array is never used directly but used as a memcpy source in the
-// OpenGLRenderer constructor
-static const TextureVertex gMeshVertices[] = {
-        FV(0.0f, 0.0f, 0.0f, 0.0f),
-        FV(1.0f, 0.0f, 1.0f, 0.0f),
-        FV(0.0f, 1.0f, 0.0f, 1.0f),
-        FV(1.0f, 1.0f, 1.0f, 1.0f)
-};
-static const GLsizei gMeshStride = sizeof(TextureVertex);
-static const GLsizei gVertexStride = sizeof(Vertex);
-static const GLsizei gAlphaVertexStride = sizeof(AlphaVertex);
-static const GLsizei gMeshTextureOffset = 2 * sizeof(float);
-static const GLsizei gVertexAlphaOffset = 2 * sizeof(float);
-static const GLsizei gVertexAAWidthOffset = 2 * sizeof(float);
-static const GLsizei gVertexAALengthOffset = 3 * sizeof(float);
-static const GLsizei gMeshCount = 4;
-
 // Must define as many texture units as specified by REQUIRED_TEXTURE_UNITS_COUNT
 static const GLenum gTextureUnits[] = {
     GL_TEXTURE0,
@@ -95,28 +73,31 @@
 };
 
 ///////////////////////////////////////////////////////////////////////////////
-// Debug
-///////////////////////////////////////////////////////////////////////////////
-
-struct CacheLogger {
-    CacheLogger() {
-        INIT_LOGD("Creating OpenGL renderer caches");
-    }
-}; // struct CacheLogger
-
-///////////////////////////////////////////////////////////////////////////////
 // Caches
 ///////////////////////////////////////////////////////////////////////////////
 
 class RenderNode;
 class RenderState;
 
-class ANDROID_API Caches: public Singleton<Caches> {
-    Caches();
+class ANDROID_API Caches {
+public:
+    static Caches& createInstance(RenderState& renderState) {
+        LOG_ALWAYS_FATAL_IF(sInstance, "double create of Caches attempted");
+        sInstance = new Caches(renderState);
+        return *sInstance;
+    }
 
-    friend class Singleton<Caches>;
+    static Caches& getInstance() {
+        LOG_ALWAYS_FATAL_IF(!sInstance, "instance not yet created");
+        return *sInstance;
+    }
 
-    CacheLogger mLogger;
+    static bool hasInstance() {
+        return sInstance != 0;
+    }
+private:
+    Caches(RenderState& renderState);
+    static Caches* sInstance;
 
 public:
     enum FlushMode {
@@ -135,8 +116,6 @@
      */
     bool initProperties();
 
-    void setRenderState(RenderState* renderState) { mRenderState = renderState; }
-
     /**
      * Flush the cache.
      *
@@ -175,59 +154,6 @@
      */
     void deleteLayerDeferred(Layer* layer);
 
-    /**
-     * Binds the VBO used to render simple textured quads.
-     */
-    bool bindMeshBuffer();
-
-    /**
-     * Binds the specified VBO if needed.
-     */
-    bool bindMeshBuffer(const GLuint buffer);
-
-    /**
-     * Unbinds the VBO used to render simple textured quads.
-     */
-    bool unbindMeshBuffer();
-
-    /**
-     * Binds a global indices buffer that can draw up to
-     * gMaxNumberOfQuads quads.
-     */
-    bool bindQuadIndicesBuffer();
-    bool bindShadowIndicesBuffer();
-    bool unbindIndicesBuffer();
-
-    /**
-     * Binds the specified buffer as the current GL unpack pixel buffer.
-     */
-    bool bindPixelBuffer(const GLuint buffer);
-
-    /**
-     * Resets the current unpack pixel buffer to 0 (default value.)
-     */
-    bool unbindPixelBuffer();
-
-    /**
-     * Binds an attrib to the specified float vertex pointer.
-     * Assumes a stride of gMeshStride and a size of 2.
-     */
-    void bindPositionVertexPointer(bool force, const GLvoid* vertices, GLsizei stride = gMeshStride);
-
-    /**
-     * Binds an attrib to the specified float vertex pointer.
-     * Assumes a stride of gMeshStride and a size of 2.
-     */
-    void bindTexCoordsVertexPointer(bool force, const GLvoid* vertices, GLsizei stride = gMeshStride);
-
-    /**
-     * Resets the vertex pointers.
-     */
-    void resetVertexPointers();
-    void resetTexCoordsVertexPointer();
-
-    void enableTexCoordsVertexArray();
-    void disableTexCoordsVertexArray();
 
     /**
      * Activate the specified texture unit. The texture unit must
@@ -272,20 +198,6 @@
      */
     void unbindTexture(GLuint texture);
 
-    /**
-     * Sets the scissor for the current surface.
-     */
-    bool setScissor(GLint x, GLint y, GLint width, GLint height);
-
-    /**
-     * Resets the scissor state.
-     */
-    void resetScissor();
-
-    bool enableScissor();
-    bool disableScissor();
-    void setScissorEnabled(bool enabled);
-
     void startTiling(GLuint x, GLuint y, GLuint width, GLuint height, bool discard);
     void endTiling();
 
@@ -310,14 +222,10 @@
     GLenum lastSrcMode;
     GLenum lastDstMode;
     Program* currentProgram;
-    bool scissorEnabled;
 
     bool drawDeferDisabled;
     bool drawReorderDisabled;
 
-    // VBO to draw with
-    GLuint meshBuffer;
-
     // Misc
     GLint maxTextureSize;
 
@@ -348,7 +256,6 @@
     TaskManager tasks;
 
     Dither dither;
-    Stencil stencil;
 
     bool gpuPixelBuffersEnabled;
 
@@ -371,6 +278,8 @@
     int propertyAmbientShadowStrength;
     int propertySpotShadowStrength;
 
+    PixelBufferState& pixelBuffer() { return *mPixelBufferState; }
+
 private:
     enum OverdrawColorSet {
         kColorSet_Default = 0,
@@ -382,8 +291,6 @@
     void initConstraints();
     void initStaticProperties();
 
-    bool bindIndicesBufferInternal(const GLuint buffer);
-
     static void eventMarkNull(GLsizei length, const GLchar* marker) { }
     static void startMarkNull(GLsizei length, const GLchar* marker) { }
     static void endMarkNull() { }
@@ -396,32 +303,17 @@
         if (label) *label = '\0';
     }
 
-    GLuint mCurrentBuffer;
-    GLuint mCurrentIndicesBuffer;
-    GLuint mCurrentPixelBuffer;
-    const void* mCurrentPositionPointer;
-    GLsizei mCurrentPositionStride;
-    const void* mCurrentTexCoordsPointer;
-    GLsizei mCurrentTexCoordsStride;
+    RenderState* mRenderState;
 
-    bool mTexCoordsArrayEnabled;
+    std::unique_ptr<PixelBufferState> mPixelBufferState; // TODO: move to RenderState
 
     GLuint mTextureUnit;
 
-    GLint mScissorX;
-    GLint mScissorY;
-    GLint mScissorWidth;
-    GLint mScissorHeight;
-
     Extensions& mExtensions;
 
     // Used to render layers
     std::unique_ptr<TextureVertex[]> mRegionMesh;
 
-    // Global index buffer
-    GLuint mMeshIndices;
-    GLuint mShadowStripsIndices;
-
     mutable Mutex mGarbageLock;
     Vector<Layer*> mLayerGarbage;
 
@@ -434,8 +326,6 @@
     GLuint mBoundTextures[REQUIRED_TEXTURE_UNITS_COUNT];
 
     OverdrawColorSet mOverdrawDebugColorSet;
-
-    RenderState* mRenderState;
 }; // class Caches
 
 }; // namespace uirenderer
diff --git a/libs/hwui/Canvas.h b/libs/hwui/Canvas.h
index f9c8620..45dc03a 100644
--- a/libs/hwui/Canvas.h
+++ b/libs/hwui/Canvas.h
@@ -50,7 +50,7 @@
     //       moved within this interface! Further, the return value should
     //       NOT be unref'd and is valid until this canvas is destroyed or a
     //       new bitmap is set.
-    virtual SkCanvas* getSkCanvas() = 0;
+    virtual SkCanvas* asSkCanvas() = 0;
 
     virtual void setBitmap(SkBitmap* bitmap, bool copyState) = 0;
 
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 36c14c4..d128ffe 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -17,13 +17,6 @@
 #ifndef ANDROID_HWUI_DISPLAY_OPERATION_H
 #define ANDROID_HWUI_DISPLAY_OPERATION_H
 
-#include <SkColor.h>
-#include <SkPath.h>
-#include <SkPathOps.h>
-#include <SkXfermode.h>
-
-#include <private/hwui/DrawGlInfo.h>
-
 #include "OpenGLRenderer.h"
 #include "AssetAtlas.h"
 #include "DeferredDisplayList.h"
@@ -31,11 +24,18 @@
 #include "GammaFontRenderer.h"
 #include "Patch.h"
 #include "RenderNode.h"
-#include "RenderState.h"
+#include "renderstate/RenderState.h"
 #include "UvMapper.h"
 #include "utils/LinearAllocator.h"
 #include "utils/PaintUtils.h"
 
+#include <SkColor.h>
+#include <SkPath.h>
+#include <SkPathOps.h>
+#include <SkXfermode.h>
+
+#include <private/hwui/DrawGlInfo.h>
+
 // Use OP_LOG for logging with arglist, OP_LOGS if just printing char*
 #define OP_LOGS(s) OP_LOG("%s", (s))
 #define OP_LOG(s, ...) ALOGD( "%*s" s, level * 2, "", __VA_ARGS__ )
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index d2b3ead..527a0e5 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -136,7 +136,7 @@
 // ----------------------------------------------------------------------------
 // android/graphics/Canvas interface
 // ----------------------------------------------------------------------------
-    virtual SkCanvas* getSkCanvas() override {
+    virtual SkCanvas* asSkCanvas() override {
         LOG_ALWAYS_FATAL("DisplayListRenderer has no SkCanvas");
         return nullptr;
     }
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index a0bc7b0..193474f 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -14,7 +14,17 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "OpenGLRenderer"
+#include "FontRenderer.h"
+
+#include "Caches.h"
+#include "Debug.h"
+#include "Extensions.h"
+#include "OpenGLRenderer.h"
+#include "PixelBuffer.h"
+#include "Rect.h"
+#include "renderstate/RenderState.h"
+#include "utils/Blur.h"
+#include "utils/Timing.h"
 
 #include <SkGlyph.h>
 #include <SkUtils.h>
@@ -27,17 +37,6 @@
 #include <RenderScript.h>
 #endif
 
-#include "utils/Blur.h"
-#include "utils/Timing.h"
-
-#include "Caches.h"
-#include "Debug.h"
-#include "Extensions.h"
-#include "FontRenderer.h"
-#include "OpenGLRenderer.h"
-#include "PixelBuffer.h"
-#include "Rect.h"
-
 namespace android {
 namespace uirenderer {
 
@@ -47,9 +46,7 @@
 ///////////////////////////////////////////////////////////////////////////////
 // TextSetupFunctor
 ///////////////////////////////////////////////////////////////////////////////
-status_t TextSetupFunctor::operator ()(int what, void* data) {
-    Data* typedData = reinterpret_cast<Data*>(data);
-    GLenum glyphFormat = typedData ? typedData->glyphFormat : GL_ALPHA;
+status_t TextSetupFunctor::setup(GLenum glyphFormat) {
 
     renderer->setupDraw();
     renderer->setupDrawTextGamma(paint);
@@ -397,7 +394,7 @@
 
 CacheTexture* FontRenderer::createCacheTexture(int width, int height, GLenum format,
         bool allocate) {
-    CacheTexture* cacheTexture = new CacheTexture(width, height, format, gMaxNumberOfQuads);
+    CacheTexture* cacheTexture = new CacheTexture(width, height, format, kMaxNumberOfQuads);
 
     if (allocate) {
         Caches::getInstance().activeTexture(0);
@@ -473,7 +470,7 @@
     checkTextureUpdateForCache(caches, mRGBACacheTextures, resetPixelStore, lastTextureId);
 
     // Unbind any PBO we might have used to update textures
-    caches.unbindPixelBuffer();
+    caches.pixelBuffer().unbind();
 
     // Reset to default unpack row length to avoid affecting texture
     // uploads in other parts of the renderer
@@ -485,26 +482,29 @@
 }
 
 void FontRenderer::issueDrawCommand(Vector<CacheTexture*>& cacheTextures) {
-    Caches& caches = Caches::getInstance();
+    if (!mFunctor) return;
+
+    Caches& caches = mFunctor->renderer->getCaches();
+    RenderState& renderState = mFunctor->renderer->renderState();
+
     bool first = true;
-    bool force = false;
+    bool forceRebind = false;
     for (uint32_t i = 0; i < cacheTextures.size(); i++) {
         CacheTexture* texture = cacheTextures[i];
         if (texture->canDraw()) {
             if (first) {
                 if (mFunctor) {
-                    TextSetupFunctor::Data functorData(texture->getFormat());
-                    (*mFunctor)(0, &functorData);
+                    mFunctor->setup(texture->getFormat());
                 }
 
                 checkTextureUpdate();
-                caches.bindQuadIndicesBuffer();
+                renderState.meshState().bindQuadIndicesBuffer();
 
                 if (!mDrawn) {
                     // If returns true, a VBO was bound and we must
                     // rebind our vertex attrib pointers even if
                     // they have the same values as the current pointers
-                    force = caches.unbindMeshBuffer();
+                    forceRebind = renderState.meshState().unbindMeshBuffer();
                 }
 
                 caches.activeTexture(0);
@@ -515,14 +515,16 @@
             texture->setLinearFiltering(mLinearFiltering, false);
 
             TextureVertex* mesh = texture->mesh();
-            caches.bindPositionVertexPointer(force, &mesh[0].x);
-            caches.bindTexCoordsVertexPointer(force, &mesh[0].u);
-            force = false;
+            MeshState& meshState = renderState.meshState();
+            Program* program = caches.currentProgram;
+            meshState.bindPositionVertexPointer(program, forceRebind, &mesh[0].x);
+            meshState.bindTexCoordsVertexPointer(program, forceRebind, &mesh[0].u);
 
             glDrawElements(GL_TRIANGLES, texture->meshElementCount(),
                     GL_UNSIGNED_SHORT, texture->indices());
 
             texture->resetMesh();
+            forceRebind = false;
         }
     }
 }
@@ -647,7 +649,7 @@
                 Font::BITMAP, dataBuffer, paddedWidth, paddedHeight, nullptr, positions);
 
         // Unbind any PBO we might have used
-        Caches::getInstance().unbindPixelBuffer();
+        Caches::getInstance().pixelBuffer().unbind();
 
         blurImage(&dataBuffer, paddedWidth, paddedHeight, radius);
     }
@@ -661,7 +663,7 @@
     return image;
 }
 
-void FontRenderer::initRender(const Rect* clip, Rect* bounds, Functor* functor) {
+void FontRenderer::initRender(const Rect* clip, Rect* bounds, TextSetupFunctor* functor) {
     checkInit();
 
     mDrawn = false;
@@ -689,7 +691,7 @@
 
 bool FontRenderer::renderPosText(const SkPaint* paint, const Rect* clip, const char *text,
         uint32_t startIndex, uint32_t len, int numGlyphs, int x, int y,
-        const float* positions, Rect* bounds, Functor* functor, bool forceFinish) {
+        const float* positions, Rect* bounds, TextSetupFunctor* functor, bool forceFinish) {
     if (!mCurrentFont) {
         ALOGE("No font set");
         return false;
@@ -707,7 +709,7 @@
 
 bool FontRenderer::renderTextOnPath(const SkPaint* paint, const Rect* clip, const char *text,
         uint32_t startIndex, uint32_t len, int numGlyphs, const SkPath* path,
-        float hOffset, float vOffset, Rect* bounds, Functor* functor) {
+        float hOffset, float vOffset, Rect* bounds, TextSetupFunctor* functor) {
     if (!mCurrentFont) {
         ALOGE("No font set");
         return false;
diff --git a/libs/hwui/FontRenderer.h b/libs/hwui/FontRenderer.h
index 668ee64..cb63684 100644
--- a/libs/hwui/FontRenderer.h
+++ b/libs/hwui/FontRenderer.h
@@ -17,7 +17,12 @@
 #ifndef ANDROID_HWUI_FONT_RENDERER_H
 #define ANDROID_HWUI_FONT_RENDERER_H
 
-#include <utils/Functor.h>
+#include "font/FontUtil.h"
+#include "font/CacheTexture.h"
+#include "font/CachedGlyphInfo.h"
+#include "font/Font.h"
+#include "utils/SortedList.h"
+
 #include <utils/LruCache.h>
 #include <utils/Vector.h>
 #include <utils/StrongPointer.h>
@@ -26,12 +31,6 @@
 
 #include <GLES2/gl2.h>
 
-#include "font/FontUtil.h"
-#include "font/CacheTexture.h"
-#include "font/CachedGlyphInfo.h"
-#include "font/Font.h"
-#include "utils/SortedList.h"
-
 #ifdef ANDROID_ENABLE_RENDERSCRIPT
 #include "RenderScript.h"
 namespace RSC {
@@ -47,26 +46,20 @@
 
 class OpenGLRenderer;
 
-///////////////////////////////////////////////////////////////////////////////
-// TextSetupFunctor
-///////////////////////////////////////////////////////////////////////////////
-class TextSetupFunctor: public Functor {
+class TextSetupFunctor {
 public:
-    struct Data {
-        Data(GLenum glyphFormat) : glyphFormat(glyphFormat) {
-        }
-
-        GLenum glyphFormat;
-    };
-
     TextSetupFunctor(OpenGLRenderer* renderer, float x, float y, bool pureTranslate,
-            int alpha, SkXfermode::Mode mode, const SkPaint* paint): Functor(),
-            renderer(renderer), x(x), y(y), pureTranslate(pureTranslate),
-            alpha(alpha), mode(mode), paint(paint) {
+            int alpha, SkXfermode::Mode mode, const SkPaint* paint)
+        : renderer(renderer)
+        , x(x)
+        , y(y)
+        , pureTranslate(pureTranslate)
+        , alpha(alpha)
+        , mode(mode)
+        , paint(paint) {
     }
-    ~TextSetupFunctor() { }
 
-    status_t operator ()(int what, void* data) override;
+    status_t setup(GLenum glyphFormat);
 
     OpenGLRenderer* renderer;
     float x;
@@ -77,10 +70,6 @@
     const SkPaint* paint;
 };
 
-///////////////////////////////////////////////////////////////////////////////
-// FontRenderer
-///////////////////////////////////////////////////////////////////////////////
-
 class FontRenderer {
 public:
     FontRenderer();
@@ -101,22 +90,14 @@
     // bounds is an out parameter
     bool renderPosText(const SkPaint* paint, const Rect* clip, const char *text,
             uint32_t startIndex, uint32_t len, int numGlyphs, int x, int y, const float* positions,
-            Rect* bounds, Functor* functor, bool forceFinish = true);
+            Rect* bounds, TextSetupFunctor* functor, bool forceFinish = true);
 
     // bounds is an out parameter
     bool renderTextOnPath(const SkPaint* paint, const Rect* clip, const char *text,
             uint32_t startIndex, uint32_t len, int numGlyphs, const SkPath* path,
-            float hOffset, float vOffset, Rect* bounds, Functor* functor);
+            float hOffset, float vOffset, Rect* bounds, TextSetupFunctor* functor);
 
     struct DropShadow {
-        DropShadow() { };
-
-        DropShadow(const DropShadow& dropShadow):
-            width(dropShadow.width), height(dropShadow.height),
-            image(dropShadow.image), penX(dropShadow.penX),
-            penY(dropShadow.penY) {
-        }
-
         uint32_t width;
         uint32_t height;
         uint8_t* image;
@@ -152,7 +133,7 @@
     void flushAllAndInvalidate();
 
     void checkInit();
-    void initRender(const Rect* clip, Rect* bounds, Functor* functor);
+    void initRender(const Rect* clip, Rect* bounds, TextSetupFunctor* functor);
     void finishRender();
 
     void issueDrawCommand(Vector<CacheTexture*>& cacheTextures);
@@ -193,7 +174,7 @@
 
     bool mUploadTexture;
 
-    Functor* mFunctor;
+    TextSetupFunctor* mFunctor;
     const Rect* mClip;
     Rect* mBounds;
     bool mDrawn;
diff --git a/libs/hwui/GradientCache.h b/libs/hwui/GradientCache.h
index 9176c76..1714e6d 100644
--- a/libs/hwui/GradientCache.h
+++ b/libs/hwui/GradientCache.h
@@ -17,6 +17,8 @@
 #ifndef ANDROID_HWUI_GRADIENT_CACHE_H
 #define ANDROID_HWUI_GRADIENT_CACHE_H
 
+#include <memory>
+
 #include <GLES3/gl3.h>
 
 #include <SkShader.h>
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index 7388e3c..7a4b830 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -16,17 +16,18 @@
 
 #define LOG_TAG "OpenGLRenderer"
 
-#include <utils/Log.h>
+#include "Layer.h"
 
 #include "Caches.h"
 #include "DeferredDisplayList.h"
-#include "Layer.h"
 #include "LayerRenderer.h"
 #include "OpenGLRenderer.h"
 #include "RenderNode.h"
-#include "RenderState.h"
+#include "renderstate/RenderState.h"
 #include "utils/TraceUtils.h"
 
+#include <utils/Log.h>
+
 #define ATRACE_LAYER_WORK(label) \
     ATRACE_FORMAT("%s HW Layer DisplayList %s %ux%u", \
             label, \
@@ -67,15 +68,23 @@
 }
 
 Layer::~Layer() {
-    renderState.requireGLContext();
     renderState.unregisterLayer(this);
     SkSafeUnref(colorFilter);
-    removeFbo();
-    deleteTexture();
+
+    if (stencil || fbo || texture.id) {
+        renderState.requireGLContext();
+        removeFbo();
+        deleteTexture();
+    }
 
     delete[] mesh;
 }
 
+void Layer::onGlContextLost() {
+    removeFbo();
+    deleteTexture();
+}
+
 uint32_t Layer::computeIdealWidth(uint32_t layerWidth) {
     return uint32_t(ceilf(layerWidth / float(LAYER_SIZE)) * LAYER_SIZE);
 }
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index 3b4f293..84ff021 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -288,6 +288,12 @@
     void postDecStrong();
 
     /**
+     * Lost the GL context but the layer is still around, mark it invalid internally
+     * so the dtor knows not to do any GL work
+     */
+    void onGlContextLost();
+
+    /**
      * Bounds of the layer.
      */
     Rect layer;
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index 6ad1b197..076251f 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -17,18 +17,19 @@
 #define LOG_TAG "OpenGLRenderer"
 #define ATRACE_TAG ATRACE_TAG_VIEW
 
-#include <ui/Rect.h>
-
-#include <private/hwui/DrawGlInfo.h>
-
-#include "RenderState.h"
 #include "LayerCache.h"
 #include "LayerRenderer.h"
 #include "Matrix.h"
 #include "Properties.h"
 #include "Rect.h"
+#include "renderstate/RenderState.h"
 #include "utils/TraceUtils.h"
 
+#include <ui/Rect.h>
+
+#include <private/hwui/DrawGlInfo.h>
+
+
 namespace android {
 namespace uirenderer {
 
@@ -48,7 +49,7 @@
         bool opaque) {
     LAYER_RENDERER_LOGD("Rendering into layer, fbo = %d", mLayer->getFbo());
 
-    renderState().bindFramebuffer(mLayer->getFbo());
+    mRenderState.bindFramebuffer(mLayer->getFbo());
 
     const float width = mLayer->layer.getWidth();
     const float height = mLayer->layer.getHeight();
@@ -70,10 +71,10 @@
 
 void LayerRenderer::clear(float left, float top, float right, float bottom, bool opaque) {
     if (mLayer->isDirty()) {
-        getCaches().disableScissor();
+        mRenderState.scissor().setEnabled(false);
         glClear(GL_COLOR_BUFFER_BIT);
 
-        getCaches().resetScissor();
+        mRenderState.scissor().reset();
         mLayer->setDirty(false);
     } else {
         OpenGLRenderer::clear(left, top, right, bottom, opaque);
@@ -436,7 +437,7 @@
             renderer.OpenGLRenderer::prepareDirty(0.0f, 0.0f,
                     bitmap->width(), bitmap->height(), !layer->isBlend());
 
-            caches.disableScissor();
+            renderState.scissor().setEnabled(false);
             renderer.translate(0.0f, bitmap->height());
             renderer.scale(1.0f, -1.0f);
 
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 82f6ddd..42b246c 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -16,6 +16,25 @@
 
 #define LOG_TAG "OpenGLRenderer"
 
+#include "OpenGLRenderer.h"
+
+#include "DeferredDisplayList.h"
+#include "DisplayListRenderer.h"
+#include "Fence.h"
+#include "GammaFontRenderer.h"
+#include "Patch.h"
+#include "PathTessellator.h"
+#include "Properties.h"
+#include "RenderNode.h"
+#include "renderstate/RenderState.h"
+#include "ShadowTessellator.h"
+#include "SkiaShader.h"
+#include "Vector.h"
+#include "VertexBuffer.h"
+#include "utils/GLUtils.h"
+#include "utils/PaintUtils.h"
+#include "utils/TraceUtils.h"
+
 #include <stdlib.h>
 #include <stdint.h>
 #include <sys/types.h>
@@ -32,24 +51,6 @@
 
 #include <ui/Rect.h>
 
-#include "OpenGLRenderer.h"
-#include "DeferredDisplayList.h"
-#include "DisplayListRenderer.h"
-#include "Fence.h"
-#include "GammaFontRenderer.h"
-#include "Patch.h"
-#include "PathTessellator.h"
-#include "Properties.h"
-#include "RenderNode.h"
-#include "RenderState.h"
-#include "ShadowTessellator.h"
-#include "SkiaShader.h"
-#include "Vector.h"
-#include "VertexBuffer.h"
-#include "utils/GLUtils.h"
-#include "utils/PaintUtils.h"
-#include "utils/TraceUtils.h"
-
 #if DEBUG_DETAILED_EVENTS
     #define EVENT_LOGD(...) eventMarkDEBUG(__VA_ARGS__)
 #else
@@ -135,10 +136,10 @@
 
 OpenGLRenderer::OpenGLRenderer(RenderState& renderState)
         : mState(*this)
-        , mFrameStarted(false)
         , mCaches(Caches::getInstance())
         , mExtensions(Extensions::getInstance())
         , mRenderState(renderState)
+        , mFrameStarted(false)
         , mScissorOptimizationDisabled(false)
         , mSuppressTiling(false)
         , mFirstFrameAfterResize(true)
@@ -151,7 +152,7 @@
     memset(&mDrawModifiers, 0, sizeof(mDrawModifiers));
     mDrawModifiers.mOverrideLayerAlpha = 1.0f;
 
-    memcpy(mMeshVertices, gMeshVertices, sizeof(gMeshVertices));
+    memcpy(mMeshVertices, kMeshVertices, sizeof(kMeshVertices));
 }
 
 OpenGLRenderer::~OpenGLRenderer() {
@@ -256,14 +257,14 @@
 
 void OpenGLRenderer::clear(float left, float top, float right, float bottom, bool opaque) {
     if (!opaque) {
-        mCaches.enableScissor();
-        mCaches.setScissor(left, getViewportHeight() - bottom, right - left, bottom - top);
+        mRenderState.scissor().setEnabled(true);
+        mRenderState.scissor().set(left, getViewportHeight() - bottom, right - left, bottom - top);
         glClear(GL_COLOR_BUFFER_BIT);
         mDirty = true;
         return;
     }
 
-    mCaches.resetScissor();
+    mRenderState.scissor().reset();
 }
 
 void OpenGLRenderer::syncState() {
@@ -347,7 +348,7 @@
     mRenderState.bindFramebuffer(currentSnapshot()->fbo);
     debugOverdraw(true, false);
 
-    mCaches.resetScissor();
+    mRenderState.scissor().reset();
     dirtyClip();
 }
 
@@ -378,7 +379,7 @@
     if (mState.getDirtyClip()) {
         setStencilFromClip(); // can issue draws, so must precede enableScissor()/interrupt()
     }
-    if (mCaches.enableScissor() || prevDirtyClip) {
+    if (mRenderState.scissor().setEnabled(true) || prevDirtyClip) {
         setScissorFromClip();
     }
 
@@ -428,27 +429,29 @@
     if (mCaches.debugOverdraw && onGetTargetFbo() == 0) {
         const Rect* clip = &mTilingClip;
 
-        mCaches.enableScissor();
-        mCaches.setScissor(clip->left, mState.firstSnapshot()->getViewportHeight() - clip->bottom,
-                clip->right - clip->left, clip->bottom - clip->top);
+        mRenderState.scissor().setEnabled(true);
+        mRenderState.scissor().set(clip->left,
+                mState.firstSnapshot()->getViewportHeight() - clip->bottom,
+                clip->right - clip->left,
+                clip->bottom - clip->top);
 
         // 1x overdraw
-        mCaches.stencil.enableDebugTest(2);
+        mRenderState.stencil().enableDebugTest(2);
         drawColor(mCaches.getOverdrawColor(1), SkXfermode::kSrcOver_Mode);
 
         // 2x overdraw
-        mCaches.stencil.enableDebugTest(3);
+        mRenderState.stencil().enableDebugTest(3);
         drawColor(mCaches.getOverdrawColor(2), SkXfermode::kSrcOver_Mode);
 
         // 3x overdraw
-        mCaches.stencil.enableDebugTest(4);
+        mRenderState.stencil().enableDebugTest(4);
         drawColor(mCaches.getOverdrawColor(3), SkXfermode::kSrcOver_Mode);
 
         // 4x overdraw and higher
-        mCaches.stencil.enableDebugTest(4, true);
+        mRenderState.stencil().enableDebugTest(4, true);
         drawColor(mCaches.getOverdrawColor(4), SkXfermode::kSrcOver_Mode);
 
-        mCaches.stencil.disable();
+        mRenderState.stencil().disable();
     }
 }
 
@@ -835,8 +838,8 @@
     startTilingCurrentClip(true, true);
 
     // Clear the FBO, expand the clear region by 1 to get nice bilinear filtering
-    mCaches.enableScissor();
-    mCaches.setScissor(clip.left - 1.0f, bounds.getHeight() - clip.bottom - 1.0f,
+    mRenderState.scissor().setEnabled(true);
+    mRenderState.scissor().set(clip.left - 1.0f, bounds.getHeight() - clip.bottom - 1.0f,
             clip.getWidth() + 2.0f, clip.getHeight() + 2.0f);
     glClear(GL_COLOR_BUFFER_BIT);
 
@@ -863,7 +866,7 @@
     bool clipRequired = false;
     mState.calculateQuickRejectForScissor(rect.left, rect.top, rect.right, rect.bottom,
             &clipRequired, nullptr, false); // safely ignore return, should never be rejected
-    mCaches.setScissorEnabled(mScissorOptimizationDisabled || clipRequired);
+    mRenderState.scissor().setEnabled(mScissorOptimizationDisabled || clipRequired);
 
     if (fboLayer) {
         endTiling();
@@ -891,7 +894,7 @@
         layer->setAlpha(255);
     }
 
-    mCaches.unbindMeshBuffer();
+    mRenderState.meshState().unbindMeshBuffer();
 
     mCaches.activeTexture(0);
 
@@ -960,7 +963,7 @@
     setupDrawTextureTransformUniforms(layer->getTexTransform());
     setupDrawMesh(&mMeshVertices[0].x, &mMeshVertices[0].u);
 
-    glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
+    glDrawArrays(GL_TRIANGLE_STRIP, 0, kMeshCount);
 }
 
 void OpenGLRenderer::composeLayerRect(Layer* layer, const Rect& rect, bool swap) {
@@ -1002,7 +1005,7 @@
         drawTextureMesh(x, y, x + rect.getWidth(), y + rect.getHeight(),
                 layer->getTexture(), &layerPaint, blend,
                 &mMeshVertices[0].x, &mMeshVertices[0].u,
-                GL_TRIANGLE_STRIP, gMeshCount, swap, swap || simpleTransform);
+                GL_TRIANGLE_STRIP, kMeshCount, swap, swap || simpleTransform);
 
         resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f);
     }
@@ -1168,7 +1171,7 @@
 
         numQuads++;
 
-        if (numQuads >= gMaxNumberOfQuads) {
+        if (numQuads >= kMaxNumberOfQuads) {
             DRAW_DOUBLE_STENCIL(glDrawElements(GL_TRIANGLES, numQuads * 6,
                     GL_UNSIGNED_SHORT, nullptr));
             numQuads = 0;
@@ -1261,7 +1264,7 @@
 void OpenGLRenderer::issueIndexedQuadDraw(Vertex* mesh, GLsizei quadsCount) {
     GLsizei elementsCount = quadsCount * 6;
     while (elementsCount > 0) {
-        GLsizei drawCount = min(elementsCount, (GLsizei) gMaxNumberOfQuads * 6);
+        GLsizei drawCount = min(elementsCount, (GLsizei) kMaxNumberOfQuads * 6);
 
         setupDrawIndexedVertices(&mesh[0].x);
         glDrawElements(GL_TRIANGLES, drawCount, GL_UNSIGNED_SHORT, nullptr);
@@ -1286,7 +1289,7 @@
         // The list contains bounds that have already been clipped
         // against their initial clip rect, and the current clip
         // is likely different so we need to disable clipping here
-        bool scissorChanged = mCaches.disableScissor();
+        bool scissorChanged = mRenderState.scissor().setEnabled(false);
 
         Vertex mesh[count * 4];
         Vertex* vertex = mesh;
@@ -1317,7 +1320,7 @@
 
         issueIndexedQuadDraw(&mesh[0], count);
 
-        if (scissorChanged) mCaches.enableScissor();
+        if (scissorChanged) mRenderState.scissor().setEnabled(true);
     } else {
         mLayers.clear();
     }
@@ -1406,7 +1409,8 @@
         writableSnapshot()->setClip(0, 0, mState.getWidth(), mState.getHeight());
     }
     dirtyClip();
-    mCaches.setScissorEnabled(clipRect != nullptr || mScissorOptimizationDisabled);
+    bool enableScissor = (clipRect != nullptr) || mScissorOptimizationDisabled;
+    mRenderState.scissor().setEnabled(enableScissor);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1417,7 +1421,7 @@
     Rect clip(mState.currentClipRect());
     clip.snapToPixelBoundaries();
 
-    if (mCaches.setScissor(clip.left, getViewportHeight() - clip.bottom,
+    if (mRenderState.scissor().set(clip.left, getViewportHeight() - clip.bottom,
             clip.getWidth(), clip.getHeight())) {
         mState.setDirtyClip(false);
     }
@@ -1491,7 +1495,7 @@
         }
     }
 
-    mCaches.setScissor(scissorBox.left, getViewportHeight() - scissorBox.bottom,
+    mRenderState.scissor().set(scissorBox.left, getViewportHeight() - scissorBox.bottom,
             scissorBox.getWidth(), scissorBox.getHeight());
 
     const SkPaint* paint = nullptr;
@@ -1533,17 +1537,17 @@
                 incrementThreshold = 0;
             }
 
-            mCaches.stencil.enableWrite(incrementThreshold);
+            mRenderState.stencil().enableWrite(incrementThreshold);
 
             // Clean and update the stencil, but first make sure we restrict drawing
             // to the region's bounds
-            bool resetScissor = mCaches.enableScissor();
+            bool resetScissor = mRenderState.scissor().setEnabled(true);
             if (resetScissor) {
                 // The scissor was not set so we now need to update it
                 setScissorFromClip();
             }
 
-            mCaches.stencil.clear();
+            mRenderState.stencil().clear();
 
             // stash and disable the outline clip state, since stencil doesn't account for outline
             bool storedSkipOutlineClip = mSkipOutlineClip;
@@ -1564,10 +1568,10 @@
                 // so we don't want to dirty the current layer, if any
                 drawRegionRects(clipArea.getClipRegion(), paint, false);
             }
-            if (resetScissor) mCaches.disableScissor();
+            if (resetScissor) mRenderState.scissor().setEnabled(false);
             mSkipOutlineClip = storedSkipOutlineClip;
 
-            mCaches.stencil.enableTest(incrementThreshold);
+            mRenderState.stencil().enableTest(incrementThreshold);
 
             // Draw the region used to generate the stencil if the appropriate debug
             // mode is enabled
@@ -1580,7 +1584,7 @@
             }
         } else {
             EVENT_LOGD("setStencilFromClip - disabling");
-            mCaches.stencil.disable();
+            mRenderState.stencil().disable();
         }
     }
 }
@@ -1611,7 +1615,7 @@
     }
 
     // not quick rejected, so enable the scissor if clipRequired
-    mCaches.setScissorEnabled(mScissorOptimizationDisabled || clipRequired);
+    mRenderState.scissor().setEnabled(mScissorOptimizationDisabled || clipRequired);
     mSkipOutlineClip = !roundRectClipRequired;
     return false;
 }
@@ -1638,7 +1642,7 @@
     // Make sure setScissor & setStencil happen at the beginning of
     // this method
     if (mState.getDirtyClip()) {
-        if (mCaches.scissorEnabled) {
+        if (mRenderState.scissor().isEnabled()) {
             setScissorFromClip();
         }
 
@@ -1657,7 +1661,7 @@
     // the stencil buffer and if stencil highlight debugging is on
     mDescription.hasDebugHighlight = !mCaches.debugOverdraw &&
             mCaches.debugStencilClip == Caches::kStencilShowHighlight &&
-            mCaches.stencil.isTestEnabled();
+            mRenderState.stencil().isTestEnabled();
 }
 
 void OpenGLRenderer::setupDrawWithTexture(bool isAlpha8) {
@@ -1676,7 +1680,7 @@
 }
 
 void OpenGLRenderer::setupDrawNoTexture() {
-    mCaches.disableTexCoordsVertexArray();
+    mRenderState.meshState().disableTexCoordsVertexArray();
 }
 
 void OpenGLRenderer::setupDrawVertexAlpha(bool useShadowAlphaInterp) {
@@ -1888,21 +1892,21 @@
 }
 
 void OpenGLRenderer::setupDrawSimpleMesh() {
-    bool force = mCaches.bindMeshBuffer();
-    mCaches.bindPositionVertexPointer(force, nullptr);
-    mCaches.unbindIndicesBuffer();
+    bool force = mRenderState.meshState().bindMeshBuffer();
+    mRenderState.meshState().bindPositionVertexPointer(mCaches.currentProgram, force, nullptr);
+    mRenderState.meshState().unbindIndicesBuffer();
 }
 
 void OpenGLRenderer::setupDrawTexture(GLuint texture) {
     if (texture) bindTexture(texture);
     mTextureUnit++;
-    mCaches.enableTexCoordsVertexArray();
+    mRenderState.meshState().enableTexCoordsVertexArray();
 }
 
 void OpenGLRenderer::setupDrawExternalTexture(GLuint texture) {
     bindExternalTexture(texture);
     mTextureUnit++;
-    mCaches.enableTexCoordsVertexArray();
+    mRenderState.meshState().enableTexCoordsVertexArray();
 }
 
 void OpenGLRenderer::setupDrawTextureTransform() {
@@ -1918,27 +1922,29 @@
         const GLvoid* texCoords, GLuint vbo) {
     bool force = false;
     if (!vertices || vbo) {
-        force = mCaches.bindMeshBuffer(vbo == 0 ? mCaches.meshBuffer : vbo);
+        force = mRenderState.meshState().bindMeshBuffer(vbo);
     } else {
-        force = mCaches.unbindMeshBuffer();
+        force = mRenderState.meshState().unbindMeshBuffer();
     }
 
-    mCaches.bindPositionVertexPointer(force, vertices);
+    mRenderState.meshState().bindPositionVertexPointer(mCaches.currentProgram, force, vertices);
     if (mCaches.currentProgram->texCoords >= 0) {
-        mCaches.bindTexCoordsVertexPointer(force, texCoords);
+        mRenderState.meshState().bindTexCoordsVertexPointer(mCaches.currentProgram, force, texCoords);
     }
 
-    mCaches.unbindIndicesBuffer();
+    mRenderState.meshState().unbindIndicesBuffer();
 }
 
 void OpenGLRenderer::setupDrawMesh(const GLvoid* vertices,
         const GLvoid* texCoords, const GLvoid* colors) {
-    bool force = mCaches.unbindMeshBuffer();
+    bool force = mRenderState.meshState().unbindMeshBuffer();
     GLsizei stride = sizeof(ColorTextureVertex);
 
-    mCaches.bindPositionVertexPointer(force, vertices, stride);
+    mRenderState.meshState().bindPositionVertexPointer(mCaches.currentProgram, force,
+            vertices, stride);
     if (mCaches.currentProgram->texCoords >= 0) {
-        mCaches.bindTexCoordsVertexPointer(force, texCoords, stride);
+        mRenderState.meshState().bindTexCoordsVertexPointer(mCaches.currentProgram, force,
+                texCoords, stride);
     }
     int slot = mCaches.currentProgram->getAttrib("colors");
     if (slot >= 0) {
@@ -1946,7 +1952,7 @@
         glVertexAttribPointer(slot, 4, GL_FLOAT, GL_FALSE, stride, colors);
     }
 
-    mCaches.unbindIndicesBuffer();
+    mRenderState.meshState().unbindIndicesBuffer();
 }
 
 void OpenGLRenderer::setupDrawMeshIndices(const GLvoid* vertices,
@@ -1954,24 +1960,26 @@
     bool force = false;
     // If vbo is != 0 we want to treat the vertices parameter as an offset inside
     // a VBO. However, if vertices is set to NULL and vbo == 0 then we want to
-    // use the default VBO found in Caches
+    // use the default VBO found in RenderState
     if (!vertices || vbo) {
-        force = mCaches.bindMeshBuffer(vbo == 0 ? mCaches.meshBuffer : vbo);
+        force = mRenderState.meshState().bindMeshBuffer(vbo);
     } else {
-        force = mCaches.unbindMeshBuffer();
+        force = mRenderState.meshState().unbindMeshBuffer();
     }
-    mCaches.bindQuadIndicesBuffer();
+    mRenderState.meshState().bindQuadIndicesBuffer();
 
-    mCaches.bindPositionVertexPointer(force, vertices);
+    mRenderState.meshState().bindPositionVertexPointer(mCaches.currentProgram, force, vertices);
     if (mCaches.currentProgram->texCoords >= 0) {
-        mCaches.bindTexCoordsVertexPointer(force, texCoords);
+        mRenderState.meshState().bindTexCoordsVertexPointer(mCaches.currentProgram,
+                force, texCoords);
     }
 }
 
 void OpenGLRenderer::setupDrawIndexedVertices(GLvoid* vertices) {
-    bool force = mCaches.unbindMeshBuffer();
-    mCaches.bindQuadIndicesBuffer();
-    mCaches.bindPositionVertexPointer(force, vertices, gVertexStride);
+    bool force = mRenderState.meshState().unbindMeshBuffer();
+    mRenderState.meshState().bindQuadIndicesBuffer();
+    mRenderState.meshState().bindPositionVertexPointer(mCaches.currentProgram, force,
+            vertices, kVertexStride);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -2030,8 +2038,8 @@
     // No need to check for a UV mapper on the texture object, only ARGB_8888
     // bitmaps get packed in the atlas
     drawAlpha8TextureMesh(x, y, x + texture->width, y + texture->height, texture->id,
-            paint, (GLvoid*) nullptr, (GLvoid*) gMeshTextureOffset,
-            GL_TRIANGLE_STRIP, gMeshCount, ignoreTransform);
+            paint, (GLvoid*) nullptr, (GLvoid*) kMeshTextureOffset,
+            GL_TRIANGLE_STRIP, kMeshCount, ignoreTransform);
 }
 
 /**
@@ -2094,7 +2102,7 @@
     }
 
     // TODO: use quickReject on bounds from vertices
-    mCaches.enableScissor();
+    mRenderState.scissor().setEnabled(true);
 
     float left = FLT_MAX;
     float top = FLT_MAX;
@@ -2224,7 +2232,7 @@
 
     getMapper(texture).map(u1, v1, u2, v2);
 
-    mCaches.unbindMeshBuffer();
+    mRenderState.meshState().unbindMeshBuffer();
     resetDrawTextureTexCoords(u1, v1, u2, v2);
 
     texture->setWrap(GL_CLAMP_TO_EDGE, true);
@@ -2271,12 +2279,12 @@
         drawAlpha8TextureMesh(dstLeft, dstTop, dstRight, dstBottom,
                 texture->id, paint,
                 &mMeshVertices[0].x, &mMeshVertices[0].u,
-                GL_TRIANGLE_STRIP, gMeshCount, ignoreTransform);
+                GL_TRIANGLE_STRIP, kMeshCount, ignoreTransform);
     } else {
         drawTextureMesh(dstLeft, dstTop, dstRight, dstBottom,
                 texture->id, paint, texture->blend,
                 &mMeshVertices[0].x, &mMeshVertices[0].u,
-                GL_TRIANGLE_STRIP, gMeshCount, false, ignoreTransform);
+                GL_TRIANGLE_STRIP, kMeshCount, false, ignoreTransform);
     }
 
     if (CC_UNLIKELY(useScaleTransform)) {
@@ -2408,33 +2416,34 @@
     setupDrawShaderUniforms(getShader(paint));
 
     const void* vertices = vertexBuffer.getBuffer();
-    mCaches.unbindMeshBuffer();
-    mCaches.bindPositionVertexPointer(true, vertices, isAA ? gAlphaVertexStride : gVertexStride);
-    mCaches.resetTexCoordsVertexPointer();
+    mRenderState.meshState().unbindMeshBuffer();
+    mRenderState.meshState().bindPositionVertexPointer(mCaches.currentProgram,
+            true, vertices, isAA ? kAlphaVertexStride : kVertexStride);
+    mRenderState.meshState().resetTexCoordsVertexPointer();
 
     int alphaSlot = -1;
     if (isAA) {
-        void* alphaCoords = ((GLbyte*) vertices) + gVertexAlphaOffset;
+        void* alphaCoords = ((GLbyte*) vertices) + kVertexAlphaOffset;
         alphaSlot = mCaches.currentProgram->getAttrib("vtxAlpha");
         // TODO: avoid enable/disable in back to back uses of the alpha attribute
         glEnableVertexAttribArray(alphaSlot);
-        glVertexAttribPointer(alphaSlot, 1, GL_FLOAT, GL_FALSE, gAlphaVertexStride, alphaCoords);
+        glVertexAttribPointer(alphaSlot, 1, GL_FLOAT, GL_FALSE, kAlphaVertexStride, alphaCoords);
     }
 
     const VertexBuffer::Mode mode = vertexBuffer.getMode();
     if (mode == VertexBuffer::kStandard) {
-        mCaches.unbindIndicesBuffer();
+        mRenderState.meshState().unbindIndicesBuffer();
         glDrawArrays(GL_TRIANGLE_STRIP, 0, vertexBuffer.getVertexCount());
     } else if (mode == VertexBuffer::kOnePolyRingShadow) {
-        mCaches.bindShadowIndicesBuffer();
+        mRenderState.meshState().bindShadowIndicesBuffer();
         glDrawElements(GL_TRIANGLE_STRIP, ONE_POLY_RING_SHADOW_INDEX_COUNT,
                 GL_UNSIGNED_SHORT, nullptr);
     } else if (mode == VertexBuffer::kTwoPolyRingShadow) {
-        mCaches.bindShadowIndicesBuffer();
+        mRenderState.meshState().bindShadowIndicesBuffer();
         glDrawElements(GL_TRIANGLE_STRIP, TWO_POLY_RING_SHADOW_INDEX_COUNT,
                 GL_UNSIGNED_SHORT, nullptr);
     } else if (mode == VertexBuffer::kIndices) {
-        mCaches.unbindIndicesBuffer();
+        mRenderState.meshState().unbindIndicesBuffer();
         glDrawElements(GL_TRIANGLE_STRIP, vertexBuffer.getIndexCount(),
                 GL_UNSIGNED_SHORT, vertexBuffer.getIndices());
     }
@@ -2716,9 +2725,9 @@
     setupDrawPureColorUniforms();
     setupDrawColorFilterUniforms(getColorFilter(paint));
     setupDrawShaderUniforms(getShader(paint));
-    setupDrawMesh(nullptr, (GLvoid*) gMeshTextureOffset);
+    setupDrawMesh(nullptr, (GLvoid*) kMeshTextureOffset);
 
-    glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
+    glDrawArrays(GL_TRIANGLE_STRIP, 0, kMeshCount);
 }
 
 bool OpenGLRenderer::canSkipText(const SkPaint* paint) const {
@@ -2738,7 +2747,7 @@
         return;
     }
 
-    mCaches.enableScissor();
+    mRenderState.scissor().setEnabled(true);
 
     float x = 0.0f;
     float y = 0.0f;
@@ -2868,8 +2877,6 @@
     mState.setClippingRoundRect(allocator, rect, radius, highPriority);
 }
 
-
-
 void OpenGLRenderer::drawText(const char* text, int bytesCount, int count, float x, float y,
         const float* positions, const SkPaint* paint, float totalAdvance, const Rect& bounds,
         DrawOpMode drawOpMode) {
@@ -2964,7 +2971,7 @@
     }
 
     // TODO: avoid scissor by calculating maximum bounds using path bounds + font metrics
-    mCaches.enableScissor();
+    mRenderState.scissor().setEnabled(true);
 
     FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(paint);
     fontRenderer.setFont(paint, SkMatrix::I());
@@ -3038,7 +3045,7 @@
 
     updateLayer(layer, true);
 
-    mCaches.setScissorEnabled(mScissorOptimizationDisabled || clipRequired);
+    mRenderState.scissor().setEnabled(mScissorOptimizationDisabled || clipRequired);
     mCaches.activeTexture(0);
 
     if (CC_LIKELY(!layer->region.isEmpty())) {
@@ -3074,7 +3081,7 @@
             GLsizei elementsCount = layer->meshElementCount;
 
             while (elementsCount > 0) {
-                GLsizei drawCount = min(elementsCount, (GLsizei) gMaxNumberOfQuads * 6);
+                GLsizei drawCount = min(elementsCount, (GLsizei) kMaxNumberOfQuads * 6);
 
                 setupDrawMeshIndices(&mesh[0].x, &mesh[0].u);
                 DRAW_DOUBLE_STENCIL_IF(!layer->hasDrawnSinceUpdate,
@@ -3152,9 +3159,9 @@
     setupDrawPureColorUniforms();
     setupDrawColorFilterUniforms(getColorFilter(paint));
     setupDrawShaderUniforms(getShader(paint));
-    setupDrawMesh(nullptr, (GLvoid*) gMeshTextureOffset);
+    setupDrawMesh(nullptr, (GLvoid*) kMeshTextureOffset);
 
-    glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
+    glDrawArrays(GL_TRIANGLE_STRIP, 0, kMeshCount);
 }
 
 // Same values used by Skia
@@ -3220,7 +3227,7 @@
     if (mState.currentlyIgnored()) return;
 
     // TODO: use quickRejectWithScissor. For now, always force enable scissor.
-    mCaches.enableScissor();
+    mRenderState.scissor().setEnabled(true);
 
     SkPaint paint;
     paint.setAntiAlias(true); // want to use AlphaVertex
@@ -3333,7 +3340,7 @@
     setupDrawColorFilterUniforms(getColorFilter(paint));
     setupDrawSimpleMesh();
 
-    glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
+    glDrawArrays(GL_TRIANGLE_STRIP, 0, kMeshCount);
 }
 
 void OpenGLRenderer::drawTextureRect(float left, float top, float right, float bottom,
@@ -3341,7 +3348,7 @@
     texture->setWrap(GL_CLAMP_TO_EDGE, true);
 
     GLvoid* vertices = (GLvoid*) nullptr;
-    GLvoid* texCoords = (GLvoid*) gMeshTextureOffset;
+    GLvoid* texCoords = (GLvoid*) kMeshTextureOffset;
 
     if (texture->uvMapper) {
         vertices = &mMeshVertices[0].x;
@@ -3360,11 +3367,11 @@
         texture->setFilter(GL_NEAREST, true);
         drawTextureMesh(x, y, x + texture->width, y + texture->height, texture->id,
                 paint, texture->blend, vertices, texCoords,
-                GL_TRIANGLE_STRIP, gMeshCount, false, true);
+                GL_TRIANGLE_STRIP, kMeshCount, false, true);
     } else {
         texture->setFilter(getFilter(paint), true);
         drawTextureMesh(left, top, right, bottom, texture->id, paint,
-                texture->blend, vertices, texCoords, GL_TRIANGLE_STRIP, gMeshCount);
+                texture->blend, vertices, texCoords, GL_TRIANGLE_STRIP, kMeshCount);
     }
 
     if (texture->uvMapper) {
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 76ad6ce..94054ff 100755
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -222,6 +222,10 @@
         return mCaches;
     }
 
+    RenderState& renderState() {
+        return mRenderState;
+    }
+
     int getViewportWidth() { return mState.getViewportWidth(); }
     int getViewportHeight() { return mState.getViewportHeight(); }
 
@@ -523,9 +527,10 @@
         return false;
     }
 
-    inline RenderState& renderState() { return mRenderState; }
-
     CanvasState mState;
+    Caches& mCaches;
+    Extensions& mExtensions; // TODO: move to RenderState
+    RenderState& mRenderState;
 
 private:
     /**
@@ -1027,11 +1032,6 @@
     DrawModifiers mDrawModifiers;
     SkPaint mFilteredPaint;
 
-    // Various caches
-    Caches& mCaches;
-    Extensions& mExtensions;
-    RenderState& mRenderState;
-
     // List of rectangles to clear after saveLayer() is invoked
     std::vector<Rect> mLayers;
     // List of layers to update at the beginning of a frame
diff --git a/libs/hwui/PatchCache.cpp b/libs/hwui/PatchCache.cpp
index eb88bc0..af403b4 100644
--- a/libs/hwui/PatchCache.cpp
+++ b/libs/hwui/PatchCache.cpp
@@ -23,6 +23,7 @@
 #include "Patch.h"
 #include "PatchCache.h"
 #include "Properties.h"
+#include "renderstate/RenderState.h"
 
 namespace android {
 namespace uirenderer {
@@ -31,9 +32,13 @@
 // Constructors/destructor
 ///////////////////////////////////////////////////////////////////////////////
 
-PatchCache::PatchCache():
-        mSize(0), mCache(LruCache<PatchDescription, Patch*>::kUnlimitedCapacity),
-        mMeshBuffer(0), mFreeBlocks(nullptr), mGenerationId(0) {
+PatchCache::PatchCache(RenderState& renderState)
+        : mRenderState(renderState)
+        , mSize(0)
+        , mCache(LruCache<PatchDescription, Patch*>::kUnlimitedCapacity)
+        , mMeshBuffer(0)
+        , mFreeBlocks(nullptr)
+        , mGenerationId(0) {
     char property[PROPERTY_VALUE_MAX];
     if (property_get(PROPERTY_PATCH_CACHE_SIZE, property, nullptr) > 0) {
         INIT_LOGD("  Setting patch cache size to %skB", property);
@@ -48,15 +53,15 @@
     clear();
 }
 
-void PatchCache::init(Caches& caches) {
+void PatchCache::init() {
     bool created = false;
     if (!mMeshBuffer) {
         glGenBuffers(1, &mMeshBuffer);
         created = true;
     }
 
-    caches.bindMeshBuffer(mMeshBuffer);
-    caches.resetVertexPointers();
+    mRenderState.meshState().bindMeshBuffer(mMeshBuffer);
+    mRenderState.meshState().resetVertexPointers();
 
     if (created) {
         createVertexBuffer();
@@ -85,7 +90,7 @@
     clearCache();
 
     if (mMeshBuffer) {
-        Caches::getInstance().unbindMeshBuffer();
+        mRenderState.meshState().unbindMeshBuffer();
         glDeleteBuffers(1, &mMeshBuffer);
         mMeshBuffer = 0;
         mSize = 0;
@@ -187,7 +192,7 @@
  */
 void PatchCache::setupMesh(Patch* newMesh, TextureVertex* vertices) {
     // This call ensures the VBO exists and that it is bound
-    init(Caches::getInstance());
+    init();
 
     // If we're running out of space, let's clear the entire cache
     uint32_t size = newMesh->getSize();
@@ -219,7 +224,7 @@
 
     // Copy the 9patch mesh in the VBO
     newMesh->offset = (GLintptr) (block->offset);
-    newMesh->textureOffset = newMesh->offset + gMeshTextureOffset;
+    newMesh->textureOffset = newMesh->offset + kMeshTextureOffset;
     glBufferSubData(GL_ARRAY_BUFFER, newMesh->offset, size, vertices);
 
     // Remove the block since we've used it entirely
diff --git a/libs/hwui/PatchCache.h b/libs/hwui/PatchCache.h
index 4cb5338..e038720 100644
--- a/libs/hwui/PatchCache.h
+++ b/libs/hwui/PatchCache.h
@@ -51,9 +51,9 @@
 
 class PatchCache {
 public:
-    PatchCache();
+    PatchCache(RenderState& renderState);
     ~PatchCache();
-    void init(Caches& caches);
+    void init();
 
     const Patch* get(const AssetAtlas::Entry* entry,
             const uint32_t bitmapWidth, const uint32_t bitmapHeight,
@@ -168,6 +168,7 @@
     void dumpFreeBlocks(const char* prefix);
 #endif
 
+    RenderState& mRenderState;
     uint32_t mMaxSize;
     uint32_t mSize;
 
diff --git a/libs/hwui/PathCache.cpp b/libs/hwui/PathCache.cpp
index c564b87..cc7f88d 100644
--- a/libs/hwui/PathCache.cpp
+++ b/libs/hwui/PathCache.cpp
@@ -31,7 +31,6 @@
 #include "PathCache.h"
 
 #include "thread/Signal.h"
-#include "thread/Task.h"
 #include "thread/TaskProcessor.h"
 
 namespace android {
diff --git a/libs/hwui/PathCache.h b/libs/hwui/PathCache.h
index ecd3712..7378018 100644
--- a/libs/hwui/PathCache.h
+++ b/libs/hwui/PathCache.h
@@ -17,21 +17,22 @@
 #ifndef ANDROID_HWUI_PATH_CACHE_H
 #define ANDROID_HWUI_PATH_CACHE_H
 
-#include <GLES2/gl2.h>
+#include "Debug.h"
+#include "Texture.h"
+#include "thread/Task.h"
+#include "thread/TaskProcessor.h"
+#include "utils/Macros.h"
+#include "utils/Pair.h"
 
+#include <GLES2/gl2.h>
+#include <SkPath.h>
 #include <utils/LruCache.h>
 #include <utils/Mutex.h>
 #include <utils/Vector.h>
 
-#include "Debug.h"
-#include "Texture.h"
-#include "utils/Macros.h"
-#include "utils/Pair.h"
-
 class SkBitmap;
 class SkCanvas;
 class SkPaint;
-class SkPath;
 struct SkRect;
 
 namespace android {
diff --git a/libs/hwui/PixelBuffer.cpp b/libs/hwui/PixelBuffer.cpp
index efa271e..62eb68c 100644
--- a/libs/hwui/PixelBuffer.cpp
+++ b/libs/hwui/PixelBuffer.cpp
@@ -16,13 +16,14 @@
 
 #define LOG_TAG "OpenGLRenderer"
 
-#include <utils/Log.h>
+#include "PixelBuffer.h"
 
-#include "Caches.h"
 #include "Debug.h"
 #include "Extensions.h"
-#include "PixelBuffer.h"
 #include "Properties.h"
+#include "renderstate/RenderState.h"
+
+#include <utils/Log.h>
 
 namespace android {
 namespace uirenderer {
@@ -93,14 +94,16 @@
     Caches& mCaches;
 };
 
-GpuPixelBuffer::GpuPixelBuffer(GLenum format, uint32_t width, uint32_t height)
+GpuPixelBuffer::GpuPixelBuffer(GLenum format,
+        uint32_t width, uint32_t height)
         : PixelBuffer(format, width, height)
         , mMappedPointer(nullptr)
-        , mCaches(Caches::getInstance()) {
+        , mCaches(Caches::getInstance()){
     glGenBuffers(1, &mBuffer);
-    mCaches.bindPixelBuffer(mBuffer);
+
+    mCaches.pixelBuffer().bind(mBuffer);
     glBufferData(GL_PIXEL_UNPACK_BUFFER, getSize(), nullptr, GL_DYNAMIC_DRAW);
-    mCaches.unbindPixelBuffer();
+    mCaches.pixelBuffer().unbind();
 }
 
 GpuPixelBuffer::~GpuPixelBuffer() {
@@ -109,7 +112,7 @@
 
 uint8_t* GpuPixelBuffer::map(AccessMode mode) {
     if (mAccessMode == kAccessMode_None) {
-        mCaches.bindPixelBuffer(mBuffer);
+        mCaches.pixelBuffer().bind(mBuffer);
         mMappedPointer = (uint8_t*) glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, getSize(), mode);
 #if DEBUG_OPENGL
         if (!mMappedPointer) {
@@ -128,7 +131,7 @@
 void GpuPixelBuffer::unmap() {
     if (mAccessMode != kAccessMode_None) {
         if (mMappedPointer) {
-            mCaches.bindPixelBuffer(mBuffer);
+            mCaches.pixelBuffer().bind(mBuffer);
             GLboolean status = glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
             if (status == GL_FALSE) {
                 ALOGE("Corrupted GPU pixel buffer");
@@ -145,7 +148,7 @@
 
 void GpuPixelBuffer::upload(uint32_t x, uint32_t y, uint32_t width, uint32_t height, int offset) {
     // If the buffer is not mapped, unmap() will not bind it
-    mCaches.bindPixelBuffer(mBuffer);
+    mCaches.pixelBuffer().bind(mBuffer);
     unmap();
     glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, mFormat,
             GL_UNSIGNED_BYTE, reinterpret_cast<void*>(offset));
@@ -155,7 +158,8 @@
 // Factory
 ///////////////////////////////////////////////////////////////////////////////
 
-PixelBuffer* PixelBuffer::create(GLenum format, uint32_t width, uint32_t height, BufferType type) {
+PixelBuffer* PixelBuffer::create(GLenum format,
+        uint32_t width, uint32_t height, BufferType type) {
     if (type == kBufferType_Auto && Caches::getInstance().gpuPixelBuffersEnabled) {
         return new GpuPixelBuffer(format, width, height);
     }
diff --git a/libs/hwui/PixelBuffer.h b/libs/hwui/PixelBuffer.h
index 04225a2..aac5ec4 100644
--- a/libs/hwui/PixelBuffer.h
+++ b/libs/hwui/PixelBuffer.h
@@ -18,6 +18,7 @@
 #define ANDROID_HWUI_PIXEL_BUFFER_H
 
 #include <GLES3/gl3.h>
+#include <cutils/log.h>
 
 namespace android {
 namespace uirenderer {
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index 7fdbf9a..efbb709 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -46,82 +46,87 @@
         canvas->ref();
     }
 
-    virtual SkCanvas* getSkCanvas() {
+    virtual SkCanvas* asSkCanvas() override {
         return mCanvas.get();
     }
 
-    virtual void setBitmap(SkBitmap* bitmap, bool copyState);
+    virtual void setBitmap(SkBitmap* bitmap, bool copyState) override;
 
-    virtual bool isOpaque();
-    virtual int width();
-    virtual int height();
+    virtual bool isOpaque() override;
+    virtual int width() override;
+    virtual int height() override;
 
-    virtual int getSaveCount() const;
-    virtual int save(SkCanvas::SaveFlags flags);
-    virtual void restore();
-    virtual void restoreToCount(int saveCount);
+    virtual int getSaveCount() const override;
+    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);
+                const SkPaint* paint, SkCanvas::SaveFlags flags) override;
     virtual int saveLayerAlpha(float left, float top, float right, float bottom,
-            int alpha, SkCanvas::SaveFlags flags);
+            int alpha, SkCanvas::SaveFlags flags) override;
 
-    virtual void getMatrix(SkMatrix* outMatrix) const;
-    virtual void setMatrix(const SkMatrix& matrix);
-    virtual void concat(const SkMatrix& matrix);
-    virtual void rotate(float degrees);
-    virtual void scale(float sx, float sy);
-    virtual void skew(float sx, float sy);
-    virtual void translate(float dx, float dy);
+    virtual void getMatrix(SkMatrix* outMatrix) const override;
+    virtual void setMatrix(const SkMatrix& matrix) override;
+    virtual void concat(const SkMatrix& matrix) override;
+    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;
 
-    virtual bool getClipBounds(SkRect* outRect) const;
-    virtual bool quickRejectRect(float left, float top, float right, float bottom) const;
-    virtual bool quickRejectPath(const SkPath& path) const;
-    virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
-    virtual bool clipPath(const SkPath* path, SkRegion::Op op);
-    virtual bool clipRegion(const SkRegion* region, SkRegion::Op op);
+    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;
 
-    virtual SkDrawFilter* getDrawFilter();
-    virtual void setDrawFilter(SkDrawFilter* drawFilter);
+    virtual SkDrawFilter* getDrawFilter() override;
+    virtual void setDrawFilter(SkDrawFilter* drawFilter) override;
 
-    virtual void drawColor(int color, SkXfermode::Mode mode);
-    virtual void drawPaint(const SkPaint& paint);
+    virtual void drawColor(int color, SkXfermode::Mode mode) override;
+    virtual void drawPaint(const SkPaint& paint) override;
 
-    virtual void drawPoint(float x, float y, const SkPaint& paint);
-    virtual void drawPoints(const float* points, int count, const SkPaint& paint);
+    virtual void drawPoint(float x, float y, const SkPaint& paint) override;
+    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);
-    virtual void drawLines(const float* points, int count, const SkPaint& paint);
-    virtual void drawRect(float left, float top, float right, float bottom, const SkPaint& paint);
+            const SkPaint& paint) override;
+    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 drawRoundRect(float left, float top, float right, float bottom,
-            float rx, float ry, const SkPaint& paint);
-    virtual void drawCircle(float x, float y, float radius, const SkPaint& paint);
-    virtual void drawOval(float left, float top, float right, float bottom, const SkPaint& paint);
+            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);
-    virtual void drawPath(const SkPath& path, const SkPaint& paint);
+            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);
+            const uint16_t* indices, int indexCount, const SkPaint& paint) override;
 
-    virtual void drawBitmap(const SkBitmap& bitmap, float left, float top, const SkPaint* paint);
-    virtual void drawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix, const SkPaint* paint);
+    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);
+            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);
+            const float* vertices, const int* colors, const SkPaint* paint) override;
 
     virtual void drawText(const uint16_t* text, const float* positions, int count,
             const SkPaint& paint, float x, float y,
             float boundsLeft, float boundsTop, float boundsRight, float boundsBottom,
-            float totalAdvance);
+            float totalAdvance) override;
     virtual void drawPosText(const uint16_t* text, const float* positions, int count,
-            int posCount, const SkPaint& paint);
+            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);
+            float hOffset, float vOffset, const SkPaint& paint) override;
 
-    virtual bool drawTextAbsolutePos() const { return true; }
+    virtual bool drawTextAbsolutePos() const  override { return true; }
 
 private:
     struct SaveRec {
diff --git a/libs/hwui/Vector.h b/libs/hwui/Vector.h
index aa6acc9..7c3f2fd 100644
--- a/libs/hwui/Vector.h
+++ b/libs/hwui/Vector.h
@@ -17,6 +17,9 @@
 #ifndef ANDROID_HWUI_VECTOR_H
 #define ANDROID_HWUI_VECTOR_H
 
+#include <math.h>
+#include <utils/Log.h>
+
 namespace android {
 namespace uirenderer {
 
diff --git a/libs/hwui/renderstate/MeshState.cpp b/libs/hwui/renderstate/MeshState.cpp
new file mode 100644
index 0000000..7820a66
--- /dev/null
+++ b/libs/hwui/renderstate/MeshState.cpp
@@ -0,0 +1,192 @@
+/*
+ * 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 "renderstate/MeshState.h"
+
+#include "Program.h"
+
+#include "ShadowTessellator.h"
+
+namespace android {
+namespace uirenderer {
+
+MeshState::MeshState()
+        : mCurrentPositionPointer(this)
+        , mCurrentPositionStride(0)
+        , mCurrentTexCoordsPointer(this)
+        , mCurrentTexCoordsStride(0)
+        , mTexCoordsArrayEnabled(false) {
+
+    glGenBuffers(1, &meshBuffer);
+    glBindBuffer(GL_ARRAY_BUFFER, meshBuffer);
+    glBufferData(GL_ARRAY_BUFFER, sizeof(kMeshVertices), kMeshVertices, GL_STATIC_DRAW);
+
+    mCurrentBuffer = meshBuffer;
+    mCurrentIndicesBuffer = 0;
+    mCurrentPixelBuffer = 0;
+
+    mQuadListIndices = 0;
+    mShadowStripsIndices = 0;
+}
+
+MeshState::~MeshState() {
+    glDeleteBuffers(1, &meshBuffer);
+    mCurrentBuffer = 0;
+
+    glDeleteBuffers(1, &mQuadListIndices);
+    mQuadListIndices = 0;
+
+    glDeleteBuffers(1, &mShadowStripsIndices);
+    mShadowStripsIndices = 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Buffer Objects
+///////////////////////////////////////////////////////////////////////////////
+
+bool MeshState::bindMeshBuffer() {
+    return bindMeshBuffer(meshBuffer);
+}
+
+bool MeshState::bindMeshBuffer(GLuint buffer) {
+    if (!buffer) buffer = meshBuffer;
+    if (mCurrentBuffer != buffer) {
+        glBindBuffer(GL_ARRAY_BUFFER, buffer);
+        mCurrentBuffer = buffer;
+        return true;
+    }
+    return false;
+}
+
+bool MeshState::unbindMeshBuffer() {
+    if (mCurrentBuffer) {
+        glBindBuffer(GL_ARRAY_BUFFER, 0);
+        mCurrentBuffer = 0;
+        return true;
+    }
+    return false;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Vertices
+///////////////////////////////////////////////////////////////////////////////
+
+void MeshState::bindPositionVertexPointer(const Program* currentProgram, bool force,
+        const GLvoid* vertices, GLsizei stride) {
+    if (force || vertices != mCurrentPositionPointer || stride != mCurrentPositionStride) {
+        GLuint slot = currentProgram->position;
+        glVertexAttribPointer(slot, 2, GL_FLOAT, GL_FALSE, stride, vertices);
+        mCurrentPositionPointer = vertices;
+        mCurrentPositionStride = stride;
+    }
+}
+
+void MeshState::bindTexCoordsVertexPointer(const Program* currentProgram, bool force,
+        const GLvoid* vertices, GLsizei stride) {
+    if (force || vertices != mCurrentTexCoordsPointer || stride != mCurrentTexCoordsStride) {
+        GLuint slot = currentProgram->texCoords;
+        glVertexAttribPointer(slot, 2, GL_FLOAT, GL_FALSE, stride, vertices);
+        mCurrentTexCoordsPointer = vertices;
+        mCurrentTexCoordsStride = stride;
+    }
+}
+
+void MeshState::resetVertexPointers() {
+    mCurrentPositionPointer = this;
+    mCurrentTexCoordsPointer = this;
+}
+
+void MeshState::resetTexCoordsVertexPointer() {
+    mCurrentTexCoordsPointer = this;
+}
+
+void MeshState::enableTexCoordsVertexArray() {
+    if (!mTexCoordsArrayEnabled) {
+        glEnableVertexAttribArray(Program::kBindingTexCoords);
+        mCurrentTexCoordsPointer = this;
+        mTexCoordsArrayEnabled = true;
+    }
+}
+
+void MeshState::disableTexCoordsVertexArray() {
+    if (mTexCoordsArrayEnabled) {
+        glDisableVertexAttribArray(Program::kBindingTexCoords);
+        mTexCoordsArrayEnabled = false;
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Indices
+///////////////////////////////////////////////////////////////////////////////
+
+bool MeshState::bindIndicesBufferInternal(const GLuint buffer) {
+    if (mCurrentIndicesBuffer != buffer) {
+        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
+        mCurrentIndicesBuffer = buffer;
+        return true;
+    }
+    return false;
+}
+
+bool MeshState::bindQuadIndicesBuffer() {
+    if (!mQuadListIndices) {
+        std::unique_ptr<uint16_t[]> regionIndices(new uint16_t[kMaxNumberOfQuads * 6]);
+        for (uint32_t i = 0; i < kMaxNumberOfQuads; i++) {
+            uint16_t quad = i * 4;
+            int index = i * 6;
+            regionIndices[index    ] = quad;       // top-left
+            regionIndices[index + 1] = quad + 1;   // top-right
+            regionIndices[index + 2] = quad + 2;   // bottom-left
+            regionIndices[index + 3] = quad + 2;   // bottom-left
+            regionIndices[index + 4] = quad + 1;   // top-right
+            regionIndices[index + 5] = quad + 3;   // bottom-right
+        }
+
+        glGenBuffers(1, &mQuadListIndices);
+        bool force = bindIndicesBufferInternal(mQuadListIndices);
+        glBufferData(GL_ELEMENT_ARRAY_BUFFER, kMaxNumberOfQuads * 6 * sizeof(uint16_t),
+                regionIndices.get(), GL_STATIC_DRAW);
+        return force;
+    }
+
+    return bindIndicesBufferInternal(mQuadListIndices);
+}
+
+bool MeshState::bindShadowIndicesBuffer() {
+    if (!mShadowStripsIndices) {
+        std::unique_ptr<uint16_t[]> shadowIndices(new uint16_t[MAX_SHADOW_INDEX_COUNT]);
+        ShadowTessellator::generateShadowIndices(shadowIndices.get());
+        glGenBuffers(1, &mShadowStripsIndices);
+        bool force = bindIndicesBufferInternal(mShadowStripsIndices);
+        glBufferData(GL_ELEMENT_ARRAY_BUFFER, MAX_SHADOW_INDEX_COUNT * sizeof(uint16_t),
+            shadowIndices.get(), GL_STATIC_DRAW);
+        return force;
+    }
+
+    return bindIndicesBufferInternal(mShadowStripsIndices);
+}
+
+bool MeshState::unbindIndicesBuffer() {
+    if (mCurrentIndicesBuffer) {
+        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+        mCurrentIndicesBuffer = 0;
+        return true;
+    }
+    return false;
+}
+
+} /* namespace uirenderer */
+} /* namespace android */
+
diff --git a/libs/hwui/renderstate/MeshState.h b/libs/hwui/renderstate/MeshState.h
new file mode 100644
index 0000000..76f73d4
--- /dev/null
+++ b/libs/hwui/renderstate/MeshState.h
@@ -0,0 +1,139 @@
+/*
+ * 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 RENDERSTATE_MESHSTATE_H
+#define RENDERSTATE_MESHSTATE_H
+
+#include "Vertex.h"
+
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#include <memory>
+
+namespace android {
+namespace uirenderer {
+
+class Program;
+
+// Maximum number of quads that pre-allocated meshes can draw
+const uint32_t kMaxNumberOfQuads = 2048;
+
+// This array is never used directly but used as a memcpy source in the
+// OpenGLRenderer constructor
+const TextureVertex kMeshVertices[] = {
+        { 0, 0, 0, 0 },
+        { 1, 0, 1, 0 },
+        { 0, 1, 0, 1 },
+        { 1, 1, 1, 1 },
+};
+
+const GLsizei kVertexStride = sizeof(Vertex);
+const GLsizei kAlphaVertexStride = sizeof(AlphaVertex);
+const GLsizei kTextureVertexStride = sizeof(TextureVertex);
+
+const GLsizei kMeshTextureOffset = 2 * sizeof(float);
+const GLsizei kVertexAlphaOffset = 2 * sizeof(float);
+const GLsizei kVertexAAWidthOffset = 2 * sizeof(float);
+const GLsizei kVertexAALengthOffset = 3 * sizeof(float);
+const GLsizei kMeshCount = 4;
+
+class MeshState {
+private:
+    friend class RenderState;
+
+public:
+    ~MeshState();
+    ///////////////////////////////////////////////////////////////////////////////
+    // Buffer objects
+    ///////////////////////////////////////////////////////////////////////////////
+    /**
+     * Binds the VBO used to render simple textured quads.
+     */
+    bool bindMeshBuffer();
+
+    /**
+     * Binds the specified VBO if needed. If buffer == 0, binds default simple textured quad.
+     */
+    bool bindMeshBuffer(GLuint buffer);
+
+    /**
+     * Unbinds the VBO used to render simple textured quads.
+     */
+    bool unbindMeshBuffer();
+
+    ///////////////////////////////////////////////////////////////////////////////
+    // Vertices
+    ///////////////////////////////////////////////////////////////////////////////
+    /**
+     * Binds an attrib to the specified float vertex pointer.
+     * Assumes a stride of gTextureVertexStride and a size of 2.
+     */
+    void bindPositionVertexPointer(const Program* currentProgram, bool force,
+            const GLvoid* vertices, GLsizei stride = kTextureVertexStride);
+
+    /**
+     * Binds an attrib to the specified float vertex pointer.
+     * Assumes a stride of gTextureVertexStride and a size of 2.
+     */
+    void bindTexCoordsVertexPointer(const Program* currentProgram, bool force,
+            const GLvoid* vertices, GLsizei stride = kTextureVertexStride);
+
+    /**
+     * Resets the vertex pointers.
+     */
+    void resetVertexPointers();
+    void resetTexCoordsVertexPointer();
+
+    void enableTexCoordsVertexArray();
+    void disableTexCoordsVertexArray();
+
+    ///////////////////////////////////////////////////////////////////////////////
+    // Indices
+    ///////////////////////////////////////////////////////////////////////////////
+    /**
+     * Binds a global indices buffer that can draw up to
+     * gMaxNumberOfQuads quads.
+     */
+    bool bindQuadIndicesBuffer();
+    bool bindShadowIndicesBuffer();
+    bool unbindIndicesBuffer();
+
+private:
+    MeshState();
+    bool bindIndicesBufferInternal(const GLuint buffer);
+
+    // VBO to draw with
+    GLuint meshBuffer;
+
+    GLuint mCurrentBuffer;
+    GLuint mCurrentIndicesBuffer;
+    GLuint mCurrentPixelBuffer;
+
+    const void* mCurrentPositionPointer;
+    GLsizei mCurrentPositionStride;
+    const void* mCurrentTexCoordsPointer;
+    GLsizei mCurrentTexCoordsStride;
+
+    bool mTexCoordsArrayEnabled;
+
+    // Global index buffer
+    GLuint mQuadListIndices;
+    GLuint mShadowStripsIndices;
+};
+
+} /* namespace uirenderer */
+} /* namespace android */
+
+#endif // RENDERSTATE_MESHSTATE_H
diff --git a/libs/hwui/renderstate/PixelBufferState.cpp b/libs/hwui/renderstate/PixelBufferState.cpp
new file mode 100644
index 0000000..c23af52
--- /dev/null
+++ b/libs/hwui/renderstate/PixelBufferState.cpp
@@ -0,0 +1,45 @@
+/*
+ * 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 "renderstate/PixelBufferState.h"
+
+namespace android {
+namespace uirenderer {
+
+PixelBufferState::PixelBufferState()
+        : mCurrentPixelBuffer(0) {
+}
+
+bool PixelBufferState::bind(GLuint buffer) {
+    if (mCurrentPixelBuffer != buffer) {
+        glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer);
+        mCurrentPixelBuffer = buffer;
+        return true;
+    }
+    return false;
+}
+
+bool PixelBufferState::unbind() {
+    if (mCurrentPixelBuffer) {
+        glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
+        mCurrentPixelBuffer = 0;
+        return true;
+    }
+    return false;
+}
+
+} /* namespace uirenderer */
+} /* namespace android */
+
diff --git a/libs/hwui/renderstate/PixelBufferState.h b/libs/hwui/renderstate/PixelBufferState.h
new file mode 100644
index 0000000..8dab21d
--- /dev/null
+++ b/libs/hwui/renderstate/PixelBufferState.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef RENDERSTATE_PIXELBUFFERSTATE_H
+#define RENDERSTATE_PIXELBUFFERSTATE_H
+
+#include <GLES3/gl3.h>
+
+namespace android {
+namespace uirenderer {
+
+class PixelBufferState {
+    friend class Caches; // TODO: move to RenderState
+public:
+    bool bind(GLuint buffer);
+    bool unbind();
+private:
+    PixelBufferState();
+    GLuint mCurrentPixelBuffer;
+};
+
+} /* namespace uirenderer */
+} /* namespace android */
+
+#endif // RENDERSTATE_PIXELBUFFERSTATE_H
diff --git a/libs/hwui/RenderState.cpp b/libs/hwui/renderstate/RenderState.cpp
similarity index 81%
rename from libs/hwui/RenderState.cpp
rename to libs/hwui/renderstate/RenderState.cpp
index 45a97fb..e4c8745 100644
--- a/libs/hwui/RenderState.cpp
+++ b/libs/hwui/renderstate/RenderState.cpp
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#include "RenderState.h"
+#include "renderstate/RenderState.h"
 
 #include "renderthread/CanvasContext.h"
 #include "renderthread/EglManager.h"
@@ -24,6 +24,9 @@
 RenderState::RenderState(renderthread::RenderThread& thread)
         : mRenderThread(thread)
         , mCaches(nullptr)
+        , mMeshState(nullptr)
+        , mScissor(nullptr)
+        , mStencil(nullptr)
         , mViewportWidth(0)
         , mViewportHeight(0)
         , mFramebuffer(0) {
@@ -31,16 +34,27 @@
 }
 
 RenderState::~RenderState() {
+    LOG_ALWAYS_FATAL_IF(mMeshState || mScissor || mStencil,
+            "State object lifecycle not managed correctly");
 }
 
 void RenderState::onGLContextCreated() {
+    LOG_ALWAYS_FATAL_IF(mMeshState || mScissor || mStencil,
+            "State object lifecycle not managed correctly");
+    mMeshState = new MeshState();
+    mScissor = new Scissor();
+    mStencil = new Stencil();
+
     // This is delayed because the first access of Caches makes GL calls
-    mCaches = &Caches::getInstance();
+    mCaches = &Caches::createInstance(*this);
     mCaches->init();
-    mCaches->setRenderState(this);
     mCaches->textureCache.setAssetAtlas(&mAssetAtlas);
 }
 
+static void layerLostGlContext(Layer* layer) {
+    layer->onGlContextLost();
+}
+
 void RenderState::onGLContextDestroyed() {
 /*
     size_t size = mActiveLayers.size();
@@ -73,7 +87,17 @@
         LOG_ALWAYS_FATAL("%d layers have survived gl context destruction", size);
     }
 */
+
+    // TODO: reset all cached state in state objects
+    std::for_each(mActiveLayers.begin(), mActiveLayers.end(), layerLostGlContext);
     mAssetAtlas.terminate();
+
+    delete mMeshState;
+    mMeshState = nullptr;
+    delete mScissor;
+    mScissor = nullptr;
+    delete mStencil;
+    mStencil = nullptr;
 }
 
 void RenderState::setViewport(GLsizei width, GLsizei height) {
@@ -109,10 +133,10 @@
         }
     }
     mCaches->resetActiveTexture();
-    mCaches->unbindMeshBuffer();
-    mCaches->unbindIndicesBuffer();
-    mCaches->resetVertexPointers();
-    mCaches->disableTexCoordsVertexArray();
+    meshState().unbindMeshBuffer();
+    meshState().unbindIndicesBuffer();
+    meshState().resetVertexPointers();
+    meshState().disableTexCoordsVertexArray();
     debugOverdraw(false, false);
 }
 
@@ -123,9 +147,7 @@
 
     glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
 
-    mCaches->scissorEnabled = glIsEnabled(GL_SCISSOR_TEST);
-    mCaches->enableScissor();
-    mCaches->resetScissor();
+    scissor().invalidate();
 
     mCaches->activeTexture(0);
     mCaches->resetBoundTextures();
@@ -139,13 +161,13 @@
 void RenderState::debugOverdraw(bool enable, bool clear) {
     if (mCaches->debugOverdraw && mFramebuffer == 0) {
         if (clear) {
-            mCaches->disableScissor();
-            mCaches->stencil.clear();
+            scissor().setEnabled(false);
+            stencil().clear();
         }
         if (enable) {
-            mCaches->stencil.enableDebugWrite();
+            stencil().enableDebugWrite();
         } else {
-            mCaches->stencil.disable();
+            stencil().disable();
         }
     }
 }
diff --git a/libs/hwui/RenderState.h b/libs/hwui/renderstate/RenderState.h
similarity index 85%
rename from libs/hwui/RenderState.h
rename to libs/hwui/renderstate/RenderState.h
index 629fe0d..d1ee64a 100644
--- a/libs/hwui/RenderState.h
+++ b/libs/hwui/renderstate/RenderState.h
@@ -27,6 +27,10 @@
 
 #include "AssetAtlas.h"
 #include "Caches.h"
+#include "renderstate/MeshState.h"
+#include "renderstate/PixelBufferState.h"
+#include "renderstate/Scissor.h"
+#include "renderstate/Stencil.h"
 #include "utils/Macros.h"
 
 namespace android {
@@ -58,10 +62,10 @@
 
     void debugOverdraw(bool enable, bool clear);
 
-    void registerLayer(const Layer* layer) {
+    void registerLayer(Layer* layer) {
         mActiveLayers.insert(layer);
     }
-    void unregisterLayer(const Layer* layer) {
+    void unregisterLayer(Layer* layer) {
         mActiveLayers.erase(layer);
     }
 
@@ -80,7 +84,9 @@
     void postDecStrong(VirtualLightRefBase* object);
 
     AssetAtlas& assetAtlas() { return mAssetAtlas; }
-
+    MeshState& meshState() { return *mMeshState; }
+    Scissor& scissor() { return *mScissor; }
+    Stencil& stencil() { return *mStencil; }
 private:
     friend class renderthread::RenderThread;
     friend class Caches;
@@ -92,10 +98,16 @@
     RenderState(renderthread::RenderThread& thread);
     ~RenderState();
 
+
     renderthread::RenderThread& mRenderThread;
     Caches* mCaches;
+
+    MeshState* mMeshState;
+    Scissor* mScissor;
+    Stencil* mStencil;
+
     AssetAtlas mAssetAtlas;
-    std::set<const Layer*> mActiveLayers;
+    std::set<Layer*> mActiveLayers;
     std::set<renderthread::CanvasContext*> mRegisteredContexts;
 
     GLsizei mViewportWidth;
diff --git a/libs/hwui/renderstate/Scissor.cpp b/libs/hwui/renderstate/Scissor.cpp
new file mode 100644
index 0000000..66c31a2
--- /dev/null
+++ b/libs/hwui/renderstate/Scissor.cpp
@@ -0,0 +1,84 @@
+/*
+ * 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 "renderstate/Scissor.h"
+
+namespace android {
+namespace uirenderer {
+
+Scissor::Scissor()
+    : mEnabled(false)
+    , mScissorX(0)
+    , mScissorY(0)
+    , mScissorWidth(0)
+    , mScissorHeight(0) {
+}
+
+bool Scissor::setEnabled(bool enabled) {
+    if (mEnabled != enabled) {
+        if (enabled) {
+            glEnable(GL_SCISSOR_TEST);
+        } else {
+            glDisable(GL_SCISSOR_TEST);
+        }
+        mEnabled = enabled;
+        return true;
+    }
+    return false;
+}
+
+bool Scissor::set(GLint x, GLint y, GLint width, GLint height) {
+    if (mEnabled && (x != mScissorX || y != mScissorY
+            || width != mScissorWidth || height != mScissorHeight)) {
+
+        if (x < 0) {
+            width += x;
+            x = 0;
+        }
+        if (y < 0) {
+            height += y;
+            y = 0;
+        }
+        if (width < 0) {
+            width = 0;
+        }
+        if (height < 0) {
+            height = 0;
+        }
+        glScissor(x, y, width, height);
+
+        mScissorX = x;
+        mScissorY = y;
+        mScissorWidth = width;
+        mScissorHeight = height;
+
+        return true;
+    }
+    return false;
+}
+
+void Scissor::reset() {
+    mScissorX = mScissorY = mScissorWidth = mScissorHeight = 0;
+}
+
+void Scissor::invalidate() {
+    mEnabled = glIsEnabled(GL_SCISSOR_TEST);
+    setEnabled(true);
+    reset();
+}
+
+} /* namespace uirenderer */
+} /* namespace android */
+
diff --git a/libs/hwui/renderstate/Scissor.h b/libs/hwui/renderstate/Scissor.h
new file mode 100644
index 0000000..cc8b3dd
--- /dev/null
+++ b/libs/hwui/renderstate/Scissor.h
@@ -0,0 +1,45 @@
+/*
+ * 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 RENDERSTATE_SCISSOR_H
+#define RENDERSTATE_SCISSOR_H
+
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+namespace android {
+namespace uirenderer {
+
+class Scissor {
+    friend class RenderState;
+public:
+    bool setEnabled(bool enabled);
+    bool set(GLint x, GLint y, GLint width, GLint height);
+    void reset();
+    bool isEnabled() { return mEnabled; }
+private:
+    Scissor();
+    void invalidate();
+    bool mEnabled;
+    GLint mScissorX;
+    GLint mScissorY;
+    GLint mScissorWidth;
+    GLint mScissorHeight;
+};
+
+} /* namespace uirenderer */
+} /* namespace android */
+
+#endif // RENDERSTATE_SCISSOR_H
diff --git a/libs/hwui/Stencil.cpp b/libs/hwui/renderstate/Stencil.cpp
similarity index 98%
rename from libs/hwui/Stencil.cpp
rename to libs/hwui/renderstate/Stencil.cpp
index f56a02e..acbed14 100644
--- a/libs/hwui/Stencil.cpp
+++ b/libs/hwui/renderstate/Stencil.cpp
@@ -17,7 +17,7 @@
 #include "Debug.h"
 #include "Extensions.h"
 #include "Properties.h"
-#include "Stencil.h"
+#include "renderstate/Stencil.h"
 
 #include <GLES2/gl2ext.h>
 
diff --git a/libs/hwui/Stencil.h b/libs/hwui/renderstate/Stencil.h
similarity index 100%
rename from libs/hwui/Stencil.h
rename to libs/hwui/renderstate/Stencil.h
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 71ecba5..6346479 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -16,19 +16,19 @@
 
 #include "CanvasContext.h"
 
-#include <algorithm>
-#include <private/hwui/DrawGlInfo.h>
-#include <strings.h>
-
 #include "EglManager.h"
 #include "RenderThread.h"
 #include "../AnimationContext.h"
 #include "../Caches.h"
 #include "../DeferredLayerUpdater.h"
-#include "../RenderState.h"
+#include "../renderstate/RenderState.h"
+#include "../renderstate/Stencil.h"
 #include "../LayerRenderer.h"
 #include "../OpenGLRenderer.h"
-#include "../Stencil.h"
+
+#include <algorithm>
+#include <private/hwui/DrawGlInfo.h>
+#include <strings.h>
 
 #define TRIM_MEMORY_COMPLETE 80
 #define TRIM_MEMORY_UI_HIDDEN 20
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index 0aa0439..c4feb41 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -16,13 +16,13 @@
 
 #include "EglManager.h"
 
+#include "../Caches.h"
+#include "../renderstate/RenderState.h"
+#include "RenderThread.h"
+
 #include <cutils/log.h>
 #include <cutils/properties.h>
 
-#include "../Caches.h"
-#include "../RenderState.h"
-#include "RenderThread.h"
-
 #define PROPERTY_RENDER_DIRTY_REGIONS "debug.hwui.render_dirty_regions"
 #define GLES_VERSION 2
 
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index a2f0625..9a0fbad 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -16,17 +16,15 @@
 
 #include "RenderThread.h"
 
-#if defined(HAVE_PTHREADS)
-#include <sys/resource.h>
-#endif
-#include <gui/DisplayEventReceiver.h>
-#include <utils/Log.h>
-
-#include "../RenderState.h"
+#include "../renderstate/RenderState.h"
 #include "CanvasContext.h"
 #include "EglManager.h"
 #include "RenderProxy.h"
 
+#include <gui/DisplayEventReceiver.h>
+#include <sys/resource.h>
+#include <utils/Log.h>
+
 namespace android {
 using namespace uirenderer::renderthread;
 ANDROID_SINGLETON_STATIC_INSTANCE(RenderThread);
@@ -250,9 +248,7 @@
 }
 
 bool RenderThread::threadLoop() {
-#if defined(HAVE_PTHREADS)
     setpriority(PRIO_PROCESS, 0, PRIORITY_DISPLAY);
-#endif
     initThreadLocals();
 
     int timeoutMillis = -1;
diff --git a/libs/hwui/thread/TaskManager.cpp b/libs/hwui/thread/TaskManager.cpp
index cb5401c..3c30aab 100644
--- a/libs/hwui/thread/TaskManager.cpp
+++ b/libs/hwui/thread/TaskManager.cpp
@@ -14,10 +14,8 @@
  * limitations under the License.
  */
 
-#include <sys/sysinfo.h>
-#if defined(HAVE_PTHREADS)
 #include <sys/resource.h>
-#endif
+#include <sys/sysinfo.h>
 
 #include "TaskManager.h"
 #include "Task.h"
@@ -83,9 +81,7 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 status_t TaskManager::WorkerThread::readyToRun() {
-#if defined(HAVE_PTHREADS)
     setpriority(PRIO_PROCESS, 0, PRIORITY_FOREGROUND);
-#endif
     return NO_ERROR;
 }
 
diff --git a/libs/hwui/utils/Macros.h b/libs/hwui/utils/Macros.h
index 5b7c87c..fe43fdb 100644
--- a/libs/hwui/utils/Macros.h
+++ b/libs/hwui/utils/Macros.h
@@ -18,8 +18,8 @@
 
 #define PREVENT_COPY_AND_ASSIGN(Type) \
     private: \
-        Type(const Type&); \
-        void operator=(const Type&)
+        Type(const Type&) = delete; \
+        void operator=(const Type&) = delete
 
 #define DESCRIPTION_TYPE(Type) \
         int compare(const Type& rhs) const { return memcmp(this, &rhs, sizeof(Type));} \
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 766a837..0ffa5fc 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -4711,7 +4711,7 @@
             synchronized (mLastDeviceConnectMsgTime) {
                 long time = SystemClock.uptimeMillis();
                 if (mLastDeviceConnectMsgTime > time) {
-                    delay = (int)(mLastDeviceConnectMsgTime - time);
+                    delay = (int)(mLastDeviceConnectMsgTime - time) + 30;
                 }
             }
         }
diff --git a/media/java/android/media/Image.java b/media/java/android/media/Image.java
index 0d6b91a..53ab264 100644
--- a/media/java/android/media/Image.java
+++ b/media/java/android/media/Image.java
@@ -214,6 +214,11 @@
          * the underlying data could be mapped as a pointer in JNI without doing
          * any copies with {@code GetDirectBufferAddress}.</p>
          *
+         * <p>For raw formats, each plane is only guaranteed to contain data
+         * up to the last pixel in the last row. In other words, the stride
+         * after the last row may not be mapped into the buffer. This is a
+         * necessary requirement for any interleaved format.</p>
+         *
          * @return the byte buffer containing the image data for this plane.
          */
         public abstract ByteBuffer getBuffer();
diff --git a/media/java/android/media/SoundPool.java b/media/java/android/media/SoundPool.java
index 4f74bdd..32d5b82 100644
--- a/media/java/android/media/SoundPool.java
+++ b/media/java/android/media/SoundPool.java
@@ -543,11 +543,6 @@
 
         public int load(String path, int priority)
         {
-            // pass network streams to player
-            if (path.startsWith("http:"))
-                return _load(path, priority);
-
-            // try local path
             int id = 0;
             try {
                 File f = new File(path);
@@ -562,6 +557,7 @@
             return id;
         }
 
+        @Override
         public int load(Context context, int resId, int priority) {
             AssetFileDescriptor afd = context.getResources().openRawResourceFd(resId);
             int id = 0;
@@ -576,6 +572,7 @@
             return id;
         }
 
+        @Override
         public int load(AssetFileDescriptor afd, int priority) {
             if (afd != null) {
                 long len = afd.getLength();
@@ -588,16 +585,17 @@
             }
         }
 
+        @Override
         public int load(FileDescriptor fd, long offset, long length, int priority) {
             return _load(fd, offset, length, priority);
         }
 
-        private native final int _load(String uri, int priority);
-
         private native final int _load(FileDescriptor fd, long offset, long length, int priority);
 
+        @Override
         public native final boolean unload(int soundID);
 
+        @Override
         public final int play(int soundID, float leftVolume, float rightVolume,
                 int priority, int loop, float rate) {
             if (isRestricted()) {
@@ -620,16 +618,22 @@
             }
         }
 
+        @Override
         public native final void pause(int streamID);
 
+        @Override
         public native final void resume(int streamID);
 
+        @Override
         public native final void autoPause();
 
+        @Override
         public native final void autoResume();
 
+        @Override
         public native final void stop(int streamID);
 
+        @Override
         public final void setVolume(int streamID, float leftVolume, float rightVolume) {
             if (isRestricted()) {
                 return;
@@ -639,16 +643,21 @@
 
         private native final void _setVolume(int streamID, float leftVolume, float rightVolume);
 
+        @Override
         public void setVolume(int streamID, float volume) {
             setVolume(streamID, volume, volume);
         }
 
+        @Override
         public native final void setPriority(int streamID, int priority);
 
+        @Override
         public native final void setLoop(int streamID, int loop);
 
+        @Override
         public native final void setRate(int streamID, float rate);
 
+        @Override
         public void setOnLoadCompleteListener(SoundPool.OnLoadCompleteListener listener)
         {
             synchronized(mLock) {
@@ -729,52 +738,69 @@
             return 0;
         }
 
+        @Override
         public int load(Context context, int resId, int priority) {
             return 0;
         }
 
+        @Override
         public int load(AssetFileDescriptor afd, int priority) {
             return 0;
         }
 
+        @Override
         public int load(FileDescriptor fd, long offset, long length, int priority) {
             return 0;
         }
 
+        @Override
         public final boolean unload(int soundID) {
             return true;
         }
 
+        @Override
         public final int play(int soundID, float leftVolume, float rightVolume,
                 int priority, int loop, float rate) {
             return 0;
         }
 
+        @Override
         public final void pause(int streamID) { }
 
+        @Override
         public final void resume(int streamID) { }
 
+        @Override
         public final void autoPause() { }
 
+        @Override
         public final void autoResume() { }
 
+        @Override
         public final void stop(int streamID) { }
 
+        @Override
         public final void setVolume(int streamID,
                 float leftVolume, float rightVolume) { }
 
+        @Override
         public void setVolume(int streamID, float volume) {
         }
 
+        @Override
         public final void setPriority(int streamID, int priority) { }
 
+        @Override
         public final void setLoop(int streamID, int loop) { }
 
+        @Override
         public final void setRate(int streamID, float rate) { }
 
+        @Override
         public void setOnLoadCompleteListener(SoundPool.OnLoadCompleteListener listener) {
         }
 
+        @Override
         public final void release() { }
     }
 }
diff --git a/media/java/android/media/browse/MediaBrowser.java b/media/java/android/media/browse/MediaBrowser.java
index e82567c..ef8d169 100644
--- a/media/java/android/media/browse/MediaBrowser.java
+++ b/media/java/android/media/browse/MediaBrowser.java
@@ -33,6 +33,7 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.RemoteException;
+import android.os.ResultReceiver;
 import android.service.media.MediaBrowserService;
 import android.service.media.IMediaBrowserService;
 import android.service.media.IMediaBrowserServiceCallbacks;
@@ -347,8 +348,8 @@
      */
     public void unsubscribe(@NonNull String parentId) {
         // Check arguments.
-        if (parentId == null) {
-            throw new IllegalArgumentException("parentId is null");
+        if (TextUtils.isEmpty(parentId)) {
+            throw new IllegalArgumentException("parentId is empty.");
         }
 
         // Remove from our list.
@@ -367,6 +368,60 @@
     }
 
     /**
+     * Retrieves a specific {@link MediaItem} from the connected service. Not
+     * all services may support this, so falling back to subscribing to the
+     * parent's id should be used when unavailable.
+     *
+     * @param mediaId The id of the item to retrieve.
+     * @param cb The callback to receive the result on.
+     */
+    public void getMediaItem(@NonNull String mediaId, @NonNull final MediaItemCallback cb) {
+        if (TextUtils.isEmpty(mediaId)) {
+            throw new IllegalArgumentException("mediaId is empty.");
+        }
+        if (cb == null) {
+            throw new IllegalArgumentException("cb is null.");
+        }
+        if (mState != CONNECT_STATE_CONNECTED) {
+            Log.i(TAG, "Not connected, unable to retrieve the MediaItem.");
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    cb.onError();
+                }
+            });
+            return;
+        }
+        ResultReceiver receiver = new ResultReceiver(mHandler) {
+            @Override
+            protected void onReceiveResult(int resultCode, Bundle resultData) {
+                if (resultCode != 0 || resultData == null
+                        || !resultData.containsKey(MediaBrowserService.KEY_MEDIA_ITEM)) {
+                    cb.onError();
+                    return;
+                }
+                Parcelable item = resultData.getParcelable(MediaBrowserService.KEY_MEDIA_ITEM);
+                if (!(item instanceof MediaItem)) {
+                    cb.onError();
+                }
+                cb.onMediaItemLoaded((MediaItem) resultData.getParcelable(
+                        MediaBrowserService.KEY_MEDIA_ITEM));
+            }
+        };
+        try {
+            mServiceBinder.getMediaItem(mediaId, receiver);
+        } catch (RemoteException e) {
+            Log.i(TAG, "Remote error getting media item.");
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    cb.onError();
+                }
+            });
+        }
+    }
+
+    /**
      * For debugging.
      */
     private static String getStateLabel(int state) {
@@ -690,6 +745,27 @@
     }
 
     /**
+     * Callback for receiving the result of {@link #getMediaItem}.
+     */
+    public static abstract class MediaItemCallback {
+
+        /**
+         * Called when the item has been returned by the browser service.
+         *
+         * @param item The item that was returned or null if it doesn't exist.
+         */
+        public void onMediaItemLoaded(MediaItem item) {
+        }
+
+        /**
+         * Called when the id doesn't exist or there was an error retrieving the
+         * item.
+         */
+        public void onError() {
+        }
+    }
+
+    /**
      * ServiceConnection to the other app.
      */
     private class MediaServiceConnection implements ServiceConnection {
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index 8c478ed..f29be0d 100644
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -310,7 +310,9 @@
                 public void run() {
                     try {
                         if (DEBUG) Log.d(TAG, "notifySessionEvent(" + eventType + ")");
-                        mSessionCallback.onSessionEvent(eventType, eventArgs);
+                        if (mSessionCallback != null) {
+                            mSessionCallback.onSessionEvent(eventType, eventArgs);
+                        }
                     } catch (RemoteException e) {
                         Log.w(TAG, "error in sending event (event=" + eventType + ")");
                     }
@@ -329,7 +331,9 @@
                 public void run() {
                     try {
                         if (DEBUG) Log.d(TAG, "notifyChannelRetuned");
-                        mSessionCallback.onChannelRetuned(channelUri);
+                        if (mSessionCallback != null) {
+                            mSessionCallback.onChannelRetuned(channelUri);
+                        }
                     } catch (RemoteException e) {
                         Log.w(TAG, "error in notifyChannelRetuned");
                     }
@@ -366,7 +370,9 @@
                 public void run() {
                     try {
                         if (DEBUG) Log.d(TAG, "notifyTracksChanged");
-                        mSessionCallback.onTracksChanged(tracks);
+                        if (mSessionCallback != null) {
+                            mSessionCallback.onTracksChanged(tracks);
+                        }
                     } catch (RemoteException e) {
                         Log.w(TAG, "error in notifyTracksChanged");
                     }
@@ -394,7 +400,9 @@
                 public void run() {
                     try {
                         if (DEBUG) Log.d(TAG, "notifyTrackSelected");
-                        mSessionCallback.onTrackSelected(type, trackId);
+                        if (mSessionCallback != null) {
+                            mSessionCallback.onTrackSelected(type, trackId);
+                        }
                     } catch (RemoteException e) {
                         Log.w(TAG, "error in notifyTrackSelected");
                     }
@@ -415,7 +423,9 @@
                 public void run() {
                     try {
                         if (DEBUG) Log.d(TAG, "notifyVideoAvailable");
-                        mSessionCallback.onVideoAvailable();
+                        if (mSessionCallback != null) {
+                            mSessionCallback.onVideoAvailable();
+                        }
                     } catch (RemoteException e) {
                         Log.w(TAG, "error in notifyVideoAvailable");
                     }
@@ -447,7 +457,9 @@
                 public void run() {
                     try {
                         if (DEBUG) Log.d(TAG, "notifyVideoUnavailable");
-                        mSessionCallback.onVideoUnavailable(reason);
+                        if (mSessionCallback != null) {
+                            mSessionCallback.onVideoUnavailable(reason);
+                        }
                     } catch (RemoteException e) {
                         Log.w(TAG, "error in notifyVideoUnavailable");
                     }
@@ -486,7 +498,9 @@
                 public void run() {
                     try {
                         if (DEBUG) Log.d(TAG, "notifyContentAllowed");
-                        mSessionCallback.onContentAllowed();
+                        if (mSessionCallback != null) {
+                            mSessionCallback.onContentAllowed();
+                        }
                     } catch (RemoteException e) {
                         Log.w(TAG, "error in notifyContentAllowed");
                     }
@@ -526,7 +540,9 @@
                 public void run() {
                     try {
                         if (DEBUG) Log.d(TAG, "notifyContentBlocked");
-                        mSessionCallback.onContentBlocked(rating.flattenToString());
+                        if (mSessionCallback != null) {
+                            mSessionCallback.onContentBlocked(rating.flattenToString());
+                        }
                     } catch (RemoteException e) {
                         Log.w(TAG, "error in notifyContentBlocked");
                     }
@@ -557,7 +573,9 @@
                     try {
                         if (DEBUG) Log.d(TAG, "layoutSurface (l=" + left + ", t=" + top + ", r="
                                 + right + ", b=" + bottom + ",)");
-                        mSessionCallback.onLayoutSurface(left, top, right, bottom);
+                        if (mSessionCallback != null) {
+                            mSessionCallback.onLayoutSurface(left, top, right, bottom);
+                        }
                     } catch (RemoteException e) {
                         Log.w(TAG, "error in layoutSurface");
                     }
diff --git a/media/java/android/service/media/IMediaBrowserService.aidl b/media/java/android/service/media/IMediaBrowserService.aidl
index 01285ee..f01fc07 100644
--- a/media/java/android/service/media/IMediaBrowserService.aidl
+++ b/media/java/android/service/media/IMediaBrowserService.aidl
@@ -6,6 +6,7 @@
 import android.service.media.IMediaBrowserServiceCallbacks;
 import android.net.Uri;
 import android.os.Bundle;
+import android.os.ResultReceiver;
 
 /**
  * Media API allows clients to browse through hierarchy of a user’s media collection,
@@ -18,4 +19,5 @@
 
     void addSubscription(String uri, IMediaBrowserServiceCallbacks callbacks);
     void removeSubscription(String uri, IMediaBrowserServiceCallbacks callbacks);
+    void getMediaItem(String uri, in ResultReceiver cb);
 }
\ No newline at end of file
diff --git a/media/java/android/service/media/MediaBrowserService.java b/media/java/android/service/media/MediaBrowserService.java
index 47cb94b..8287344 100644
--- a/media/java/android/service/media/MediaBrowserService.java
+++ b/media/java/android/service/media/MediaBrowserService.java
@@ -32,8 +32,10 @@
 import android.os.IBinder;
 import android.os.Handler;
 import android.os.RemoteException;
+import android.os.ResultReceiver;
 import android.service.media.IMediaBrowserService;
 import android.service.media.IMediaBrowserServiceCallbacks;
+import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.Log;
 
@@ -74,6 +76,13 @@
     @SdkConstant(SdkConstantType.SERVICE_ACTION)
     public static final String SERVICE_INTERFACE = "android.media.browse.MediaBrowserService";
 
+    /**
+     * A key for passing the MediaItem to the ResultReceiver in getMediaItem.
+     *
+     * @hide
+     */
+    public static final String KEY_MEDIA_ITEM = "media_item";
+
     private final ArrayMap<IBinder, ConnectionRecord> mConnections = new ArrayMap();
     private final Handler mHandler = new Handler();
     private ServiceBinder mBinder;
@@ -261,6 +270,33 @@
                 }
             });
         }
+
+        @Override
+        public void getMediaItem(final String mediaId, final ResultReceiver receiver) {
+            if (TextUtils.isEmpty(mediaId) || receiver == null) {
+                return;
+            }
+
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    final Result<MediaBrowser.MediaItem> result
+                            = new Result<MediaBrowser.MediaItem>(mediaId) {
+                        @Override
+                        void onResultSent(MediaBrowser.MediaItem item) {
+                            Bundle bundle = new Bundle();
+                            bundle.putParcelable(KEY_MEDIA_ITEM, item);
+                            receiver.send(0, bundle);
+                        }
+                    };
+                    try {
+                        MediaBrowserService.this.getMediaItem(mediaId, result);
+                    } catch (UnsupportedOperationException e) {
+                        receiver.send(-1, null);
+                    }
+                }
+            });
+        }
     }
 
     @Override
@@ -284,20 +320,21 @@
     /**
      * Called to get the root information for browsing by a particular client.
      * <p>
-     * The implementation should verify that the client package has
-     * permission to access browse media information before returning
-     * the root id; it should return null if the client is not
-     * allowed to access this information.
+     * The implementation should verify that the client package has permission
+     * to access browse media information before returning the root id; it
+     * should return null if the client is not allowed to access this
+     * information.
      * </p>
      *
-     * @param clientPackageName The package name of the application
-     * which is requesting access to browse media.
-     * @param clientUid The uid of the application which is requesting
-     * access to browse media.
+     * @param clientPackageName The package name of the application which is
+     *            requesting access to browse media.
+     * @param clientUid The uid of the application which is requesting access to
+     *            browse media.
      * @param rootHints An optional bundle of service-specific arguments to send
-     * to the media browse service when connecting and retrieving the root id
-     * for browsing, or null if none.  The contents of this bundle may affect
-     * the information returned when browsing.
+     *            to the media browse service when connecting and retrieving the
+     *            root id for browsing, or null if none. The contents of this
+     *            bundle may affect the information returned when browsing.
+     * @return The {@link BrowserRoot} for accessing this app's content or null.
      */
     public abstract @Nullable BrowserRoot onGetRoot(@NonNull String clientPackageName,
             int clientUid, @Nullable Bundle rootHints);
@@ -305,24 +342,51 @@
     /**
      * Called to get information about the children of a media item.
      * <p>
-     * Implementations must call result.{@link Result#sendResult result.sendResult} with the list
-     * of children. If loading the children will be an expensive operation that should be performed
-     * on another thread, result.{@link Result#detach result.detach} may be called before returning
-     * from this function, and then {@link Result#sendResult result.sendResult} called when
-     * the loading is complete.
+     * Implementations must call {@link Result#sendResult result.sendResult}
+     * with the list of children. If loading the children will be an expensive
+     * operation that should be performed on another thread,
+     * {@link Result#detach result.detach} may be called before returning from
+     * this function, and then {@link Result#sendResult result.sendResult}
+     * called when the loading is complete.
      *
-     * @param parentId The id of the parent media item whose
-     * children are to be queried.
-     * @return The list of children, or null if the id is invalid.
+     * @param parentId The id of the parent media item whose children are to be
+     *            queried.
+     * @param result The Result to send the list of children to, or null if the
+     *            id is invalid.
      */
     public abstract void onLoadChildren(@NonNull String parentId,
             @NonNull Result<List<MediaBrowser.MediaItem>> result);
 
     /**
+     * Called to get a specific media item. The mediaId should be the same id
+     * that would be returned for this item when it is in a list of child items.
+     * <p>
+     * Implementations must call {@link Result#sendResult result.sendResult}. If
+     * loading the item will be an expensive operation {@link Result#detach
+     * result.detach} may be called before returning from this function, and
+     * then {@link Result#sendResult result.sendResult} called when the item has
+     * been loaded.
+     * <p>
+     * The default implementation throws an exception.
+     *
+     * @param mediaId The id for the specific
+     *            {@link android.media.browse.MediaBrowser.MediaItem}.
+     * @param result The Result to send the item to, or null if the id is
+     *            invalid.
+     * @throws UnsupportedOperationException
+     */
+    public void getMediaItem(String mediaId, Result<MediaBrowser.MediaItem> result)
+            throws UnsupportedOperationException {
+        throw new UnsupportedOperationException("getMediaItem is not supported.");
+    }
+
+    /**
      * Call to set the media session.
      * <p>
      * This should be called as soon as possible during the service's startup.
      * It may only be called once.
+     *
+     * @param token The token for the service's {@link MediaSession}.
      */
     public void setSessionToken(final MediaSession.Token token) {
         if (token == null) {
diff --git a/media/jni/android_media_ImageReader.cpp b/media/jni/android_media_ImageReader.cpp
index 7e68c78..5406130 100644
--- a/media/jni/android_media_ImageReader.cpp
+++ b/media/jni/android_media_ImageReader.cpp
@@ -351,7 +351,7 @@
     int bytesPerPixel = 0;
 
     dataSize = ySize = cSize = cStride = 0;
-    int32_t fmt = buffer->format;
+    int32_t fmt = buffer->flexFormat;
 
     bool usingRGBAOverride = usingRGBAToJpegOverride(fmt, readerFormat);
     fmt = applyFormatOverrides(fmt, readerFormat);
@@ -363,18 +363,21 @@
                 (idx == 1) ?
                     buffer->dataCb :
                 buffer->dataCr;
+            // only map until last pixel
             if (idx == 0) {
-                dataSize = buffer->stride * buffer->height;
+                dataSize = buffer->stride * (buffer->height - 1) + buffer->width;
             } else {
-                dataSize = buffer->chromaStride * buffer->height / 2;
+                dataSize = buffer->chromaStride * (buffer->height / 2 - 1) +
+                        buffer->chromaStep * (buffer->width / 2 - 1) + 1;
             }
             break;
         // NV21
         case HAL_PIXEL_FORMAT_YCrCb_420_SP:
             cr = buffer->data + (buffer->stride * buffer->height);
             cb = cr + 1;
-            ySize = buffer->width * buffer->height;
-            cSize = buffer->width * buffer->height / 2;
+            // only map until last pixel
+            ySize = buffer->width * (buffer->height - 1) + buffer->width;
+            cSize = buffer->width * (buffer->height / 2 - 1) + buffer->width - 1;
 
             pData =
                 (idx == 0) ?
@@ -488,7 +491,7 @@
     int pixelStride = 0;
     ALOG_ASSERT(buffer != NULL, "buffer is NULL");
 
-    int32_t fmt = buffer->format;
+    int32_t fmt = buffer->flexFormat;
 
     fmt = applyFormatOverrides(fmt, readerFormat);
 
@@ -548,7 +551,7 @@
     int rowStride = 0;
     ALOG_ASSERT(buffer != NULL, "buffer is NULL");
 
-    int32_t fmt = buffer->format;
+    int32_t fmt = buffer->flexFormat;
 
     fmt = applyFormatOverrides(fmt, readerFormat);
 
@@ -796,7 +799,7 @@
         return ACQUIRE_NO_BUFFERS;
     }
 
-    if (buffer->format == HAL_PIXEL_FORMAT_YCrCb_420_SP) {
+    if (buffer->flexFormat == HAL_PIXEL_FORMAT_YCrCb_420_SP) {
         jniThrowException(env, "java/lang/UnsupportedOperationException",
                 "NV21 format is not supported by ImageReader");
         return -1;
@@ -825,8 +828,10 @@
     }
 
     int bufFmt = buffer->format;
+    if (imgReaderFmt == HAL_PIXEL_FORMAT_YCbCr_420_888) {
+        bufFmt = buffer->flexFormat;
+    }
     if (imgReaderFmt != bufFmt) {
-
         if (imgReaderFmt == HAL_PIXEL_FORMAT_YCbCr_420_888 && (bufFmt ==
                 HAL_PIXEL_FORMAT_YCrCb_420_SP || bufFmt == HAL_PIXEL_FORMAT_YV12)) {
             // Special casing for when producer switches to a format compatible with flexible YUV
@@ -848,7 +853,7 @@
             String8 msg;
             msg.appendFormat("The producer output buffer format 0x%x doesn't "
                     "match the ImageReader's configured buffer format 0x%x.",
-                    buffer->format, ctx->getBufferFormat());
+                    bufFmt, ctx->getBufferFormat());
             jniThrowException(env, "java/lang/UnsupportedOperationException",
                     msg.string());
             return -1;
diff --git a/media/jni/soundpool/Android.mk b/media/jni/soundpool/Android.mk
index 3382512..71ab013 100644
--- a/media/jni/soundpool/Android.mk
+++ b/media/jni/soundpool/Android.mk
@@ -2,7 +2,9 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:= \
-    android_media_SoundPool_SoundPoolImpl.cpp
+    android_media_SoundPool_SoundPoolImpl.cpp \
+    SoundPool.cpp \
+    SoundPoolThread.cpp
 
 LOCAL_SHARED_LIBRARIES := \
     liblog \
@@ -10,7 +12,9 @@
     libutils \
     libandroid_runtime \
     libnativehelper \
-    libmedia
+    libmedia \
+    libmediandk \
+    libbinder
 
 LOCAL_MODULE:= libsoundpool
 
diff --git a/media/jni/soundpool/SoundPool.cpp b/media/jni/soundpool/SoundPool.cpp
new file mode 100644
index 0000000..a8b91d2
--- /dev/null
+++ b/media/jni/soundpool/SoundPool.cpp
@@ -0,0 +1,1018 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "SoundPool"
+
+#include <inttypes.h>
+
+#include <utils/Log.h>
+
+#define USE_SHARED_MEM_BUFFER
+
+#include <media/AudioTrack.h>
+#include <media/IMediaHTTPService.h>
+#include <media/mediaplayer.h>
+#include <media/stagefright/MediaExtractor.h>
+#include "SoundPool.h"
+#include "SoundPoolThread.h"
+#include <media/AudioPolicyHelper.h>
+#include <ndk/NdkMediaCodec.h>
+#include <ndk/NdkMediaExtractor.h>
+#include <ndk/NdkMediaFormat.h>
+
+namespace android
+{
+
+int kDefaultBufferCount = 4;
+uint32_t kMaxSampleRate = 48000;
+uint32_t kDefaultSampleRate = 44100;
+uint32_t kDefaultFrameCount = 1200;
+size_t kDefaultHeapSize = 1024 * 1024; // 1MB
+
+
+SoundPool::SoundPool(int maxChannels, const audio_attributes_t* pAttributes)
+{
+    ALOGV("SoundPool constructor: maxChannels=%d, attr.usage=%d, attr.flags=0x%x, attr.tags=%s",
+            maxChannels, pAttributes->usage, pAttributes->flags, pAttributes->tags);
+
+    // check limits
+    mMaxChannels = maxChannels;
+    if (mMaxChannels < 1) {
+        mMaxChannels = 1;
+    }
+    else if (mMaxChannels > 32) {
+        mMaxChannels = 32;
+    }
+    ALOGW_IF(maxChannels != mMaxChannels, "App requested %d channels", maxChannels);
+
+    mQuit = false;
+    mDecodeThread = 0;
+    memcpy(&mAttributes, pAttributes, sizeof(audio_attributes_t));
+    mAllocated = 0;
+    mNextSampleID = 0;
+    mNextChannelID = 0;
+
+    mCallback = 0;
+    mUserData = 0;
+
+    mChannelPool = new SoundChannel[mMaxChannels];
+    for (int i = 0; i < mMaxChannels; ++i) {
+        mChannelPool[i].init(this);
+        mChannels.push_back(&mChannelPool[i]);
+    }
+
+    // start decode thread
+    startThreads();
+}
+
+SoundPool::~SoundPool()
+{
+    ALOGV("SoundPool destructor");
+    mDecodeThread->quit();
+    quit();
+
+    Mutex::Autolock lock(&mLock);
+
+    mChannels.clear();
+    if (mChannelPool)
+        delete [] mChannelPool;
+    // clean up samples
+    ALOGV("clear samples");
+    mSamples.clear();
+
+    if (mDecodeThread)
+        delete mDecodeThread;
+}
+
+void SoundPool::addToRestartList(SoundChannel* channel)
+{
+    Mutex::Autolock lock(&mRestartLock);
+    if (!mQuit) {
+        mRestart.push_back(channel);
+        mCondition.signal();
+    }
+}
+
+void SoundPool::addToStopList(SoundChannel* channel)
+{
+    Mutex::Autolock lock(&mRestartLock);
+    if (!mQuit) {
+        mStop.push_back(channel);
+        mCondition.signal();
+    }
+}
+
+int SoundPool::beginThread(void* arg)
+{
+    SoundPool* p = (SoundPool*)arg;
+    return p->run();
+}
+
+int SoundPool::run()
+{
+    mRestartLock.lock();
+    while (!mQuit) {
+        mCondition.wait(mRestartLock);
+        ALOGV("awake");
+        if (mQuit) break;
+
+        while (!mStop.empty()) {
+            SoundChannel* channel;
+            ALOGV("Getting channel from stop list");
+            List<SoundChannel* >::iterator iter = mStop.begin();
+            channel = *iter;
+            mStop.erase(iter);
+            mRestartLock.unlock();
+            if (channel != 0) {
+                Mutex::Autolock lock(&mLock);
+                channel->stop();
+            }
+            mRestartLock.lock();
+            if (mQuit) break;
+        }
+
+        while (!mRestart.empty()) {
+            SoundChannel* channel;
+            ALOGV("Getting channel from list");
+            List<SoundChannel*>::iterator iter = mRestart.begin();
+            channel = *iter;
+            mRestart.erase(iter);
+            mRestartLock.unlock();
+            if (channel != 0) {
+                Mutex::Autolock lock(&mLock);
+                channel->nextEvent();
+            }
+            mRestartLock.lock();
+            if (mQuit) break;
+        }
+    }
+
+    mStop.clear();
+    mRestart.clear();
+    mCondition.signal();
+    mRestartLock.unlock();
+    ALOGV("goodbye");
+    return 0;
+}
+
+void SoundPool::quit()
+{
+    mRestartLock.lock();
+    mQuit = true;
+    mCondition.signal();
+    mCondition.wait(mRestartLock);
+    ALOGV("return from quit");
+    mRestartLock.unlock();
+}
+
+bool SoundPool::startThreads()
+{
+    createThreadEtc(beginThread, this, "SoundPool");
+    if (mDecodeThread == NULL)
+        mDecodeThread = new SoundPoolThread(this);
+    return mDecodeThread != NULL;
+}
+
+SoundChannel* SoundPool::findChannel(int channelID)
+{
+    for (int i = 0; i < mMaxChannels; ++i) {
+        if (mChannelPool[i].channelID() == channelID) {
+            return &mChannelPool[i];
+        }
+    }
+    return NULL;
+}
+
+SoundChannel* SoundPool::findNextChannel(int channelID)
+{
+    for (int i = 0; i < mMaxChannels; ++i) {
+        if (mChannelPool[i].nextChannelID() == channelID) {
+            return &mChannelPool[i];
+        }
+    }
+    return NULL;
+}
+
+int SoundPool::load(int fd, int64_t offset, int64_t length, int priority __unused)
+{
+    ALOGV("load: fd=%d, offset=%" PRId64 ", length=%" PRId64 ", priority=%d",
+            fd, offset, length, priority);
+    Mutex::Autolock lock(&mLock);
+    sp<Sample> sample = new Sample(++mNextSampleID, fd, offset, length);
+    mSamples.add(sample->sampleID(), sample);
+    doLoad(sample);
+    return sample->sampleID();
+}
+
+void SoundPool::doLoad(sp<Sample>& sample)
+{
+    ALOGV("doLoad: loading sample sampleID=%d", sample->sampleID());
+    sample->startLoad();
+    mDecodeThread->loadSample(sample->sampleID());
+}
+
+bool SoundPool::unload(int sampleID)
+{
+    ALOGV("unload: sampleID=%d", sampleID);
+    Mutex::Autolock lock(&mLock);
+    return mSamples.removeItem(sampleID);
+}
+
+int SoundPool::play(int sampleID, float leftVolume, float rightVolume,
+        int priority, int loop, float rate)
+{
+    ALOGV("play sampleID=%d, leftVolume=%f, rightVolume=%f, priority=%d, loop=%d, rate=%f",
+            sampleID, leftVolume, rightVolume, priority, loop, rate);
+    sp<Sample> sample;
+    SoundChannel* channel;
+    int channelID;
+
+    Mutex::Autolock lock(&mLock);
+
+    if (mQuit) {
+        return 0;
+    }
+    // is sample ready?
+    sample = findSample(sampleID);
+    if ((sample == 0) || (sample->state() != Sample::READY)) {
+        ALOGW("  sample %d not READY", sampleID);
+        return 0;
+    }
+
+    dump();
+
+    // allocate a channel
+    channel = allocateChannel_l(priority);
+
+    // no channel allocated - return 0
+    if (!channel) {
+        ALOGV("No channel allocated");
+        return 0;
+    }
+
+    channelID = ++mNextChannelID;
+
+    ALOGV("play channel %p state = %d", channel, channel->state());
+    channel->play(sample, channelID, leftVolume, rightVolume, priority, loop, rate);
+    return channelID;
+}
+
+SoundChannel* SoundPool::allocateChannel_l(int priority)
+{
+    List<SoundChannel*>::iterator iter;
+    SoundChannel* channel = NULL;
+
+    // allocate a channel
+    if (!mChannels.empty()) {
+        iter = mChannels.begin();
+        if (priority >= (*iter)->priority()) {
+            channel = *iter;
+            mChannels.erase(iter);
+            ALOGV("Allocated active channel");
+        }
+    }
+
+    // update priority and put it back in the list
+    if (channel) {
+        channel->setPriority(priority);
+        for (iter = mChannels.begin(); iter != mChannels.end(); ++iter) {
+            if (priority < (*iter)->priority()) {
+                break;
+            }
+        }
+        mChannels.insert(iter, channel);
+    }
+    return channel;
+}
+
+// move a channel from its current position to the front of the list
+void SoundPool::moveToFront_l(SoundChannel* channel)
+{
+    for (List<SoundChannel*>::iterator iter = mChannels.begin(); iter != mChannels.end(); ++iter) {
+        if (*iter == channel) {
+            mChannels.erase(iter);
+            mChannels.push_front(channel);
+            break;
+        }
+    }
+}
+
+void SoundPool::pause(int channelID)
+{
+    ALOGV("pause(%d)", channelID);
+    Mutex::Autolock lock(&mLock);
+    SoundChannel* channel = findChannel(channelID);
+    if (channel) {
+        channel->pause();
+    }
+}
+
+void SoundPool::autoPause()
+{
+    ALOGV("autoPause()");
+    Mutex::Autolock lock(&mLock);
+    for (int i = 0; i < mMaxChannels; ++i) {
+        SoundChannel* channel = &mChannelPool[i];
+        channel->autoPause();
+    }
+}
+
+void SoundPool::resume(int channelID)
+{
+    ALOGV("resume(%d)", channelID);
+    Mutex::Autolock lock(&mLock);
+    SoundChannel* channel = findChannel(channelID);
+    if (channel) {
+        channel->resume();
+    }
+}
+
+void SoundPool::autoResume()
+{
+    ALOGV("autoResume()");
+    Mutex::Autolock lock(&mLock);
+    for (int i = 0; i < mMaxChannels; ++i) {
+        SoundChannel* channel = &mChannelPool[i];
+        channel->autoResume();
+    }
+}
+
+void SoundPool::stop(int channelID)
+{
+    ALOGV("stop(%d)", channelID);
+    Mutex::Autolock lock(&mLock);
+    SoundChannel* channel = findChannel(channelID);
+    if (channel) {
+        channel->stop();
+    } else {
+        channel = findNextChannel(channelID);
+        if (channel)
+            channel->clearNextEvent();
+    }
+}
+
+void SoundPool::setVolume(int channelID, float leftVolume, float rightVolume)
+{
+    Mutex::Autolock lock(&mLock);
+    SoundChannel* channel = findChannel(channelID);
+    if (channel) {
+        channel->setVolume(leftVolume, rightVolume);
+    }
+}
+
+void SoundPool::setPriority(int channelID, int priority)
+{
+    ALOGV("setPriority(%d, %d)", channelID, priority);
+    Mutex::Autolock lock(&mLock);
+    SoundChannel* channel = findChannel(channelID);
+    if (channel) {
+        channel->setPriority(priority);
+    }
+}
+
+void SoundPool::setLoop(int channelID, int loop)
+{
+    ALOGV("setLoop(%d, %d)", channelID, loop);
+    Mutex::Autolock lock(&mLock);
+    SoundChannel* channel = findChannel(channelID);
+    if (channel) {
+        channel->setLoop(loop);
+    }
+}
+
+void SoundPool::setRate(int channelID, float rate)
+{
+    ALOGV("setRate(%d, %f)", channelID, rate);
+    Mutex::Autolock lock(&mLock);
+    SoundChannel* channel = findChannel(channelID);
+    if (channel) {
+        channel->setRate(rate);
+    }
+}
+
+// call with lock held
+void SoundPool::done_l(SoundChannel* channel)
+{
+    ALOGV("done_l(%d)", channel->channelID());
+    // if "stolen", play next event
+    if (channel->nextChannelID() != 0) {
+        ALOGV("add to restart list");
+        addToRestartList(channel);
+    }
+
+    // return to idle state
+    else {
+        ALOGV("move to front");
+        moveToFront_l(channel);
+    }
+}
+
+void SoundPool::setCallback(SoundPoolCallback* callback, void* user)
+{
+    Mutex::Autolock lock(&mCallbackLock);
+    mCallback = callback;
+    mUserData = user;
+}
+
+void SoundPool::notify(SoundPoolEvent event)
+{
+    Mutex::Autolock lock(&mCallbackLock);
+    if (mCallback != NULL) {
+        mCallback(event, this, mUserData);
+    }
+}
+
+void SoundPool::dump()
+{
+    for (int i = 0; i < mMaxChannels; ++i) {
+        mChannelPool[i].dump();
+    }
+}
+
+
+Sample::Sample(int sampleID, int fd, int64_t offset, int64_t length)
+{
+    init();
+    mSampleID = sampleID;
+    mFd = dup(fd);
+    mOffset = offset;
+    mLength = length;
+    ALOGV("create sampleID=%d, fd=%d, offset=%" PRId64 " length=%" PRId64,
+        mSampleID, mFd, mLength, mOffset);
+}
+
+void Sample::init()
+{
+    mSize = 0;
+    mRefCount = 0;
+    mSampleID = 0;
+    mState = UNLOADED;
+    mFd = -1;
+    mOffset = 0;
+    mLength = 0;
+}
+
+Sample::~Sample()
+{
+    ALOGV("Sample::destructor sampleID=%d, fd=%d", mSampleID, mFd);
+    if (mFd > 0) {
+        ALOGV("close(%d)", mFd);
+        ::close(mFd);
+    }
+}
+
+static status_t decode(int fd, int64_t offset, int64_t length,
+        uint32_t *rate, int *numChannels, audio_format_t *audioFormat,
+        sp<MemoryHeapBase> heap, size_t *memsize) {
+
+    ALOGV("fd %d, offset %" PRId64 ", size %" PRId64, fd, offset, length);
+    AMediaExtractor *ex = AMediaExtractor_new();
+    status_t err = AMediaExtractor_setDataSourceFd(ex, fd, offset, length);
+
+    if (err != AMEDIA_OK) {
+        return err;
+    }
+
+    *audioFormat = AUDIO_FORMAT_PCM_16_BIT;
+
+    size_t numTracks = AMediaExtractor_getTrackCount(ex);
+    for (size_t i = 0; i < numTracks; i++) {
+        AMediaFormat *format = AMediaExtractor_getTrackFormat(ex, i);
+        const char *mime;
+        if (!AMediaFormat_getString(format, AMEDIAFORMAT_KEY_MIME, &mime)) {
+            AMediaExtractor_delete(ex);
+            AMediaFormat_delete(format);
+            return UNKNOWN_ERROR;
+        }
+        if (strncmp(mime, "audio/", 6) == 0) {
+
+            AMediaCodec *codec = AMediaCodec_createDecoderByType(mime);
+            if (AMediaCodec_configure(codec, format,
+                    NULL /* window */, NULL /* drm */, 0 /* flags */) != AMEDIA_OK
+                || AMediaCodec_start(codec) != AMEDIA_OK
+                || AMediaExtractor_selectTrack(ex, i) != AMEDIA_OK) {
+                AMediaExtractor_delete(ex);
+                AMediaCodec_delete(codec);
+                AMediaFormat_delete(format);
+                return UNKNOWN_ERROR;
+            }
+
+            bool sawInputEOS = false;
+            bool sawOutputEOS = false;
+            uint8_t* writePos = static_cast<uint8_t*>(heap->getBase());
+            size_t available = heap->getSize();
+            size_t written = 0;
+
+            AMediaFormat_delete(format);
+            format = AMediaCodec_getOutputFormat(codec);
+
+            while (!sawOutputEOS) {
+                if (!sawInputEOS) {
+                    ssize_t bufidx = AMediaCodec_dequeueInputBuffer(codec, 5000);
+                    ALOGV("input buffer %zd", bufidx);
+                    if (bufidx >= 0) {
+                        size_t bufsize;
+                        uint8_t *buf = AMediaCodec_getInputBuffer(codec, bufidx, &bufsize);
+                        int sampleSize = AMediaExtractor_readSampleData(ex, buf, bufsize);
+                        ALOGV("read %d", sampleSize);
+                        if (sampleSize < 0) {
+                            sampleSize = 0;
+                            sawInputEOS = true;
+                            ALOGV("EOS");
+                        }
+                        int64_t presentationTimeUs = AMediaExtractor_getSampleTime(ex);
+
+                        AMediaCodec_queueInputBuffer(codec, bufidx,
+                                0 /* offset */, sampleSize, presentationTimeUs,
+                                sawInputEOS ? AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM : 0);
+                        AMediaExtractor_advance(ex);
+                    }
+                }
+
+                AMediaCodecBufferInfo info;
+                int status = AMediaCodec_dequeueOutputBuffer(codec, &info, 1);
+                ALOGV("dequeueoutput returned: %d", status);
+                if (status >= 0) {
+                    if (info.flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM) {
+                        ALOGV("output EOS");
+                        sawOutputEOS = true;
+                    }
+                    ALOGV("got decoded buffer size %d", info.size);
+
+                    uint8_t *buf = AMediaCodec_getOutputBuffer(codec, status, NULL /* out_size */);
+                    size_t dataSize = info.size;
+                    if (dataSize > available) {
+                        dataSize = available;
+                    }
+                    memcpy(writePos, buf + info.offset, dataSize);
+                    writePos += dataSize;
+                    written += dataSize;
+                    available -= dataSize;
+                    AMediaCodec_releaseOutputBuffer(codec, status, false /* render */);
+                    if (available == 0) {
+                        // there might be more data, but there's no space for it
+                        sawOutputEOS = true;
+                    }
+                } else if (status == AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED) {
+                    ALOGV("output buffers changed");
+                } else if (status == AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED) {
+                    AMediaFormat_delete(format);
+                    format = AMediaCodec_getOutputFormat(codec);
+                    ALOGV("format changed to: %s", AMediaFormat_toString(format));
+                } else if (status == AMEDIACODEC_INFO_TRY_AGAIN_LATER) {
+                    ALOGV("no output buffer right now");
+                } else {
+                    ALOGV("unexpected info code: %d", status);
+                }
+            }
+
+            AMediaCodec_stop(codec);
+            AMediaCodec_delete(codec);
+            AMediaExtractor_delete(ex);
+            if (!AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_SAMPLE_RATE, (int32_t*) rate) ||
+                    !AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_CHANNEL_COUNT, numChannels)) {
+                AMediaFormat_delete(format);
+                return UNKNOWN_ERROR;
+            }
+            AMediaFormat_delete(format);
+            *memsize = written;
+            return OK;
+        }
+        AMediaFormat_delete(format);
+    }
+    AMediaExtractor_delete(ex);
+    return UNKNOWN_ERROR;
+}
+
+status_t Sample::doLoad()
+{
+    uint32_t sampleRate;
+    int numChannels;
+    audio_format_t format;
+    status_t status;
+    mHeap = new MemoryHeapBase(kDefaultHeapSize);
+
+    ALOGV("Start decode");
+    status = decode(mFd, mOffset, mLength, &sampleRate, &numChannels, &format,
+                                 mHeap, &mSize);
+    ALOGV("close(%d)", mFd);
+    ::close(mFd);
+    mFd = -1;
+    if (status != NO_ERROR) {
+        ALOGE("Unable to load sample");
+        goto error;
+    }
+    ALOGV("pointer = %p, size = %zu, sampleRate = %u, numChannels = %d",
+          mHeap->getBase(), mSize, sampleRate, numChannels);
+
+    if (sampleRate > kMaxSampleRate) {
+       ALOGE("Sample rate (%u) out of range", sampleRate);
+       status = BAD_VALUE;
+       goto error;
+    }
+
+    if ((numChannels < 1) || (numChannels > 2)) {
+        ALOGE("Sample channel count (%d) out of range", numChannels);
+        status = BAD_VALUE;
+        goto error;
+    }
+
+    mData = new MemoryBase(mHeap, 0, mSize);
+    mSampleRate = sampleRate;
+    mNumChannels = numChannels;
+    mFormat = format;
+    mState = READY;
+    return NO_ERROR;
+
+error:
+    mHeap.clear();
+    return status;
+}
+
+
+void SoundChannel::init(SoundPool* soundPool)
+{
+    mSoundPool = soundPool;
+}
+
+// call with sound pool lock held
+void SoundChannel::play(const sp<Sample>& sample, int nextChannelID, float leftVolume,
+        float rightVolume, int priority, int loop, float rate)
+{
+    sp<AudioTrack> oldTrack;
+    sp<AudioTrack> newTrack;
+    status_t status;
+
+    { // scope for the lock
+        Mutex::Autolock lock(&mLock);
+
+        ALOGV("SoundChannel::play %p: sampleID=%d, channelID=%d, leftVolume=%f, rightVolume=%f,"
+                " priority=%d, loop=%d, rate=%f",
+                this, sample->sampleID(), nextChannelID, leftVolume, rightVolume,
+                priority, loop, rate);
+
+        // if not idle, this voice is being stolen
+        if (mState != IDLE) {
+            ALOGV("channel %d stolen - event queued for channel %d", channelID(), nextChannelID);
+            mNextEvent.set(sample, nextChannelID, leftVolume, rightVolume, priority, loop, rate);
+            stop_l();
+            return;
+        }
+
+        // initialize track
+        size_t afFrameCount;
+        uint32_t afSampleRate;
+        audio_stream_type_t streamType = audio_attributes_to_stream_type(mSoundPool->attributes());
+        if (AudioSystem::getOutputFrameCount(&afFrameCount, streamType) != NO_ERROR) {
+            afFrameCount = kDefaultFrameCount;
+        }
+        if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) {
+            afSampleRate = kDefaultSampleRate;
+        }
+        int numChannels = sample->numChannels();
+        uint32_t sampleRate = uint32_t(float(sample->sampleRate()) * rate + 0.5);
+        size_t frameCount = 0;
+
+        if (loop) {
+            frameCount = sample->size()/numChannels/
+                ((sample->format() == AUDIO_FORMAT_PCM_16_BIT) ? sizeof(int16_t) : sizeof(uint8_t));
+        }
+
+#ifndef USE_SHARED_MEM_BUFFER
+        uint32_t totalFrames = (kDefaultBufferCount * afFrameCount * sampleRate) / afSampleRate;
+        // Ensure minimum audio buffer size in case of short looped sample
+        if(frameCount < totalFrames) {
+            frameCount = totalFrames;
+        }
+#endif
+
+        // mToggle toggles each time a track is started on a given channel.
+        // The toggle is concatenated with the SoundChannel address and passed to AudioTrack
+        // as callback user data. This enables the detection of callbacks received from the old
+        // audio track while the new one is being started and avoids processing them with
+        // wrong audio audio buffer size  (mAudioBufferSize)
+        unsigned long toggle = mToggle ^ 1;
+        void *userData = (void *)((unsigned long)this | toggle);
+        audio_channel_mask_t channelMask = audio_channel_out_mask_from_count(numChannels);
+
+        // do not create a new audio track if current track is compatible with sample parameters
+#ifdef USE_SHARED_MEM_BUFFER
+        newTrack = new AudioTrack(streamType, sampleRate, sample->format(),
+                channelMask, sample->getIMemory(), AUDIO_OUTPUT_FLAG_FAST, callback, userData);
+#else
+        uint32_t bufferFrames = (totalFrames + (kDefaultBufferCount - 1)) / kDefaultBufferCount;
+        newTrack = new AudioTrack(streamType, sampleRate, sample->format(),
+                channelMask, frameCount, AUDIO_OUTPUT_FLAG_FAST, callback, userData,
+                bufferFrames);
+#endif
+        oldTrack = mAudioTrack;
+        status = newTrack->initCheck();
+        if (status != NO_ERROR) {
+            ALOGE("Error creating AudioTrack");
+            goto exit;
+        }
+        ALOGV("setVolume %p", newTrack.get());
+        newTrack->setVolume(leftVolume, rightVolume);
+        newTrack->setLoop(0, frameCount, loop);
+
+        // From now on, AudioTrack callbacks received with previous toggle value will be ignored.
+        mToggle = toggle;
+        mAudioTrack = newTrack;
+        mPos = 0;
+        mSample = sample;
+        mChannelID = nextChannelID;
+        mPriority = priority;
+        mLoop = loop;
+        mLeftVolume = leftVolume;
+        mRightVolume = rightVolume;
+        mNumChannels = numChannels;
+        mRate = rate;
+        clearNextEvent();
+        mState = PLAYING;
+        mAudioTrack->start();
+        mAudioBufferSize = newTrack->frameCount()*newTrack->frameSize();
+    }
+
+exit:
+    ALOGV("delete oldTrack %p", oldTrack.get());
+    if (status != NO_ERROR) {
+        mAudioTrack.clear();
+    }
+}
+
+void SoundChannel::nextEvent()
+{
+    sp<Sample> sample;
+    int nextChannelID;
+    float leftVolume;
+    float rightVolume;
+    int priority;
+    int loop;
+    float rate;
+
+    // check for valid event
+    {
+        Mutex::Autolock lock(&mLock);
+        nextChannelID = mNextEvent.channelID();
+        if (nextChannelID  == 0) {
+            ALOGV("stolen channel has no event");
+            return;
+        }
+
+        sample = mNextEvent.sample();
+        leftVolume = mNextEvent.leftVolume();
+        rightVolume = mNextEvent.rightVolume();
+        priority = mNextEvent.priority();
+        loop = mNextEvent.loop();
+        rate = mNextEvent.rate();
+    }
+
+    ALOGV("Starting stolen channel %d -> %d", channelID(), nextChannelID);
+    play(sample, nextChannelID, leftVolume, rightVolume, priority, loop, rate);
+}
+
+void SoundChannel::callback(int event, void* user, void *info)
+{
+    SoundChannel* channel = static_cast<SoundChannel*>((void *)((unsigned long)user & ~1));
+
+    channel->process(event, info, (unsigned long)user & 1);
+}
+
+void SoundChannel::process(int event, void *info, unsigned long toggle)
+{
+    //ALOGV("process(%d)", mChannelID);
+
+    Mutex::Autolock lock(&mLock);
+
+    AudioTrack::Buffer* b = NULL;
+    if (event == AudioTrack::EVENT_MORE_DATA) {
+       b = static_cast<AudioTrack::Buffer *>(info);
+    }
+
+    if (mToggle != toggle) {
+        ALOGV("process wrong toggle %p channel %d", this, mChannelID);
+        if (b != NULL) {
+            b->size = 0;
+        }
+        return;
+    }
+
+    sp<Sample> sample = mSample;
+
+//    ALOGV("SoundChannel::process event %d", event);
+
+    if (event == AudioTrack::EVENT_MORE_DATA) {
+
+        // check for stop state
+        if (b->size == 0) return;
+
+        if (mState == IDLE) {
+            b->size = 0;
+            return;
+        }
+
+        if (sample != 0) {
+            // fill buffer
+            uint8_t* q = (uint8_t*) b->i8;
+            size_t count = 0;
+
+            if (mPos < (int)sample->size()) {
+                uint8_t* p = sample->data() + mPos;
+                count = sample->size() - mPos;
+                if (count > b->size) {
+                    count = b->size;
+                }
+                memcpy(q, p, count);
+//              ALOGV("fill: q=%p, p=%p, mPos=%u, b->size=%u, count=%d", q, p, mPos, b->size,
+//                      count);
+            } else if (mPos < mAudioBufferSize) {
+                count = mAudioBufferSize - mPos;
+                if (count > b->size) {
+                    count = b->size;
+                }
+                memset(q, 0, count);
+//              ALOGV("fill extra: q=%p, mPos=%u, b->size=%u, count=%d", q, mPos, b->size, count);
+            }
+
+            mPos += count;
+            b->size = count;
+            //ALOGV("buffer=%p, [0]=%d", b->i16, b->i16[0]);
+        }
+    } else if (event == AudioTrack::EVENT_UNDERRUN || event == AudioTrack::EVENT_BUFFER_END) {
+        ALOGV("process %p channel %d event %s",
+              this, mChannelID, (event == AudioTrack::EVENT_UNDERRUN) ? "UNDERRUN" :
+                      "BUFFER_END");
+        mSoundPool->addToStopList(this);
+    } else if (event == AudioTrack::EVENT_LOOP_END) {
+        ALOGV("End loop %p channel %d", this, mChannelID);
+    } else if (event == AudioTrack::EVENT_NEW_IAUDIOTRACK) {
+        ALOGV("process %p channel %d NEW_IAUDIOTRACK", this, mChannelID);
+    } else {
+        ALOGW("SoundChannel::process unexpected event %d", event);
+    }
+}
+
+
+// call with lock held
+bool SoundChannel::doStop_l()
+{
+    if (mState != IDLE) {
+        setVolume_l(0, 0);
+        ALOGV("stop");
+        mAudioTrack->stop();
+        mSample.clear();
+        mState = IDLE;
+        mPriority = IDLE_PRIORITY;
+        return true;
+    }
+    return false;
+}
+
+// call with lock held and sound pool lock held
+void SoundChannel::stop_l()
+{
+    if (doStop_l()) {
+        mSoundPool->done_l(this);
+    }
+}
+
+// call with sound pool lock held
+void SoundChannel::stop()
+{
+    bool stopped;
+    {
+        Mutex::Autolock lock(&mLock);
+        stopped = doStop_l();
+    }
+
+    if (stopped) {
+        mSoundPool->done_l(this);
+    }
+}
+
+//FIXME: Pause is a little broken right now
+void SoundChannel::pause()
+{
+    Mutex::Autolock lock(&mLock);
+    if (mState == PLAYING) {
+        ALOGV("pause track");
+        mState = PAUSED;
+        mAudioTrack->pause();
+    }
+}
+
+void SoundChannel::autoPause()
+{
+    Mutex::Autolock lock(&mLock);
+    if (mState == PLAYING) {
+        ALOGV("pause track");
+        mState = PAUSED;
+        mAutoPaused = true;
+        mAudioTrack->pause();
+    }
+}
+
+void SoundChannel::resume()
+{
+    Mutex::Autolock lock(&mLock);
+    if (mState == PAUSED) {
+        ALOGV("resume track");
+        mState = PLAYING;
+        mAutoPaused = false;
+        mAudioTrack->start();
+    }
+}
+
+void SoundChannel::autoResume()
+{
+    Mutex::Autolock lock(&mLock);
+    if (mAutoPaused && (mState == PAUSED)) {
+        ALOGV("resume track");
+        mState = PLAYING;
+        mAutoPaused = false;
+        mAudioTrack->start();
+    }
+}
+
+void SoundChannel::setRate(float rate)
+{
+    Mutex::Autolock lock(&mLock);
+    if (mAudioTrack != NULL && mSample != 0) {
+        uint32_t sampleRate = uint32_t(float(mSample->sampleRate()) * rate + 0.5);
+        mAudioTrack->setSampleRate(sampleRate);
+        mRate = rate;
+    }
+}
+
+// call with lock held
+void SoundChannel::setVolume_l(float leftVolume, float rightVolume)
+{
+    mLeftVolume = leftVolume;
+    mRightVolume = rightVolume;
+    if (mAudioTrack != NULL)
+        mAudioTrack->setVolume(leftVolume, rightVolume);
+}
+
+void SoundChannel::setVolume(float leftVolume, float rightVolume)
+{
+    Mutex::Autolock lock(&mLock);
+    setVolume_l(leftVolume, rightVolume);
+}
+
+void SoundChannel::setLoop(int loop)
+{
+    Mutex::Autolock lock(&mLock);
+    if (mAudioTrack != NULL && mSample != 0) {
+        uint32_t loopEnd = mSample->size()/mNumChannels/
+            ((mSample->format() == AUDIO_FORMAT_PCM_16_BIT) ? sizeof(int16_t) : sizeof(uint8_t));
+        mAudioTrack->setLoop(0, loopEnd, loop);
+        mLoop = loop;
+    }
+}
+
+SoundChannel::~SoundChannel()
+{
+    ALOGV("SoundChannel destructor %p", this);
+    {
+        Mutex::Autolock lock(&mLock);
+        clearNextEvent();
+        doStop_l();
+    }
+    // do not call AudioTrack destructor with mLock held as it will wait for the AudioTrack
+    // callback thread to exit which may need to execute process() and acquire the mLock.
+    mAudioTrack.clear();
+}
+
+void SoundChannel::dump()
+{
+    ALOGV("mState = %d mChannelID=%d, mNumChannels=%d, mPos = %d, mPriority=%d, mLoop=%d",
+            mState, mChannelID, mNumChannels, mPos, mPriority, mLoop);
+}
+
+void SoundEvent::set(const sp<Sample>& sample, int channelID, float leftVolume,
+            float rightVolume, int priority, int loop, float rate)
+{
+    mSample = sample;
+    mChannelID = channelID;
+    mLeftVolume = leftVolume;
+    mRightVolume = rightVolume;
+    mPriority = priority;
+    mLoop = loop;
+    mRate =rate;
+}
+
+} // end namespace android
diff --git a/media/jni/soundpool/SoundPool.h b/media/jni/soundpool/SoundPool.h
new file mode 100644
index 0000000..9d9cbdf
--- /dev/null
+++ b/media/jni/soundpool/SoundPool.h
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2007 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 SOUNDPOOL_H_
+#define SOUNDPOOL_H_
+
+#include <utils/threads.h>
+#include <utils/List.h>
+#include <utils/Vector.h>
+#include <utils/KeyedVector.h>
+#include <media/AudioTrack.h>
+#include <binder/MemoryHeapBase.h>
+#include <binder/MemoryBase.h>
+
+namespace android {
+
+static const int IDLE_PRIORITY = -1;
+
+// forward declarations
+class SoundEvent;
+class SoundPoolThread;
+class SoundPool;
+
+// for queued events
+class SoundPoolEvent {
+public:
+    SoundPoolEvent(int msg, int arg1=0, int arg2=0) :
+        mMsg(msg), mArg1(arg1), mArg2(arg2) {}
+    int         mMsg;
+    int         mArg1;
+    int         mArg2;
+    enum MessageType { INVALID, SAMPLE_LOADED };
+};
+
+// callback function prototype
+typedef void SoundPoolCallback(SoundPoolEvent event, SoundPool* soundPool, void* user);
+
+// tracks samples used by application
+class Sample  : public RefBase {
+public:
+    enum sample_state { UNLOADED, LOADING, READY, UNLOADING };
+    Sample(int sampleID, int fd, int64_t offset, int64_t length);
+    ~Sample();
+    int sampleID() { return mSampleID; }
+    int numChannels() { return mNumChannels; }
+    int sampleRate() { return mSampleRate; }
+    audio_format_t format() { return mFormat; }
+    size_t size() { return mSize; }
+    int state() { return mState; }
+    uint8_t* data() { return static_cast<uint8_t*>(mData->pointer()); }
+    status_t doLoad();
+    void startLoad() { mState = LOADING; }
+    sp<IMemory> getIMemory() { return mData; }
+
+private:
+    void init();
+
+    size_t              mSize;
+    volatile int32_t    mRefCount;
+    uint16_t            mSampleID;
+    uint16_t            mSampleRate;
+    uint8_t             mState : 3;
+    uint8_t             mNumChannels : 2;
+    audio_format_t      mFormat;
+    int                 mFd;
+    int64_t             mOffset;
+    int64_t             mLength;
+    sp<IMemory>         mData;
+    sp<MemoryHeapBase>  mHeap;
+};
+
+// stores pending events for stolen channels
+class SoundEvent
+{
+public:
+    SoundEvent() : mChannelID(0), mLeftVolume(0), mRightVolume(0),
+            mPriority(IDLE_PRIORITY), mLoop(0), mRate(0) {}
+    void set(const sp<Sample>& sample, int channelID, float leftVolume,
+            float rightVolume, int priority, int loop, float rate);
+    sp<Sample>      sample() { return mSample; }
+    int             channelID() { return mChannelID; }
+    float           leftVolume() { return mLeftVolume; }
+    float           rightVolume() { return mRightVolume; }
+    int             priority() { return mPriority; }
+    int             loop() { return mLoop; }
+    float           rate() { return mRate; }
+    void            clear() { mChannelID = 0; mSample.clear(); }
+
+protected:
+    sp<Sample>      mSample;
+    int             mChannelID;
+    float           mLeftVolume;
+    float           mRightVolume;
+    int             mPriority;
+    int             mLoop;
+    float           mRate;
+};
+
+// for channels aka AudioTracks
+class SoundChannel : public SoundEvent {
+public:
+    enum state { IDLE, RESUMING, STOPPING, PAUSED, PLAYING };
+    SoundChannel() : mState(IDLE), mNumChannels(1),
+            mPos(0), mToggle(0), mAutoPaused(false) {}
+    ~SoundChannel();
+    void init(SoundPool* soundPool);
+    void play(const sp<Sample>& sample, int channelID, float leftVolume, float rightVolume,
+            int priority, int loop, float rate);
+    void setVolume_l(float leftVolume, float rightVolume);
+    void setVolume(float leftVolume, float rightVolume);
+    void stop_l();
+    void stop();
+    void pause();
+    void autoPause();
+    void resume();
+    void autoResume();
+    void setRate(float rate);
+    int state() { return mState; }
+    void setPriority(int priority) { mPriority = priority; }
+    void setLoop(int loop);
+    int numChannels() { return mNumChannels; }
+    void clearNextEvent() { mNextEvent.clear(); }
+    void nextEvent();
+    int nextChannelID() { return mNextEvent.channelID(); }
+    void dump();
+
+private:
+    static void callback(int event, void* user, void *info);
+    void process(int event, void *info, unsigned long toggle);
+    bool doStop_l();
+
+    SoundPool*          mSoundPool;
+    sp<AudioTrack>      mAudioTrack;
+    SoundEvent          mNextEvent;
+    Mutex               mLock;
+    int                 mState;
+    int                 mNumChannels;
+    int                 mPos;
+    int                 mAudioBufferSize;
+    unsigned long       mToggle;
+    bool                mAutoPaused;
+};
+
+// application object for managing a pool of sounds
+class SoundPool {
+    friend class SoundPoolThread;
+    friend class SoundChannel;
+public:
+    SoundPool(int maxChannels, const audio_attributes_t* pAttributes);
+    ~SoundPool();
+    int load(int fd, int64_t offset, int64_t length, int priority);
+    bool unload(int sampleID);
+    int play(int sampleID, float leftVolume, float rightVolume, int priority,
+            int loop, float rate);
+    void pause(int channelID);
+    void autoPause();
+    void resume(int channelID);
+    void autoResume();
+    void stop(int channelID);
+    void setVolume(int channelID, float leftVolume, float rightVolume);
+    void setPriority(int channelID, int priority);
+    void setLoop(int channelID, int loop);
+    void setRate(int channelID, float rate);
+    const audio_attributes_t* attributes() { return &mAttributes; }
+
+    // called from SoundPoolThread
+    void sampleLoaded(int sampleID);
+
+    // called from AudioTrack thread
+    void done_l(SoundChannel* channel);
+
+    // callback function
+    void setCallback(SoundPoolCallback* callback, void* user);
+    void* getUserData() { return mUserData; }
+
+private:
+    SoundPool() {} // no default constructor
+    bool startThreads();
+    void doLoad(sp<Sample>& sample);
+    sp<Sample> findSample(int sampleID) { return mSamples.valueFor(sampleID); }
+    SoundChannel* findChannel (int channelID);
+    SoundChannel* findNextChannel (int channelID);
+    SoundChannel* allocateChannel_l(int priority);
+    void moveToFront_l(SoundChannel* channel);
+    void notify(SoundPoolEvent event);
+    void dump();
+
+    // restart thread
+    void addToRestartList(SoundChannel* channel);
+    void addToStopList(SoundChannel* channel);
+    static int beginThread(void* arg);
+    int run();
+    void quit();
+
+    Mutex                   mLock;
+    Mutex                   mRestartLock;
+    Condition               mCondition;
+    SoundPoolThread*        mDecodeThread;
+    SoundChannel*           mChannelPool;
+    List<SoundChannel*>     mChannels;
+    List<SoundChannel*>     mRestart;
+    List<SoundChannel*>     mStop;
+    DefaultKeyedVector< int, sp<Sample> >   mSamples;
+    int                     mMaxChannels;
+    audio_attributes_t      mAttributes;
+    int                     mAllocated;
+    int                     mNextSampleID;
+    int                     mNextChannelID;
+    bool                    mQuit;
+
+    // callback
+    Mutex                   mCallbackLock;
+    SoundPoolCallback*      mCallback;
+    void*                   mUserData;
+};
+
+} // end namespace android
+
+#endif /*SOUNDPOOL_H_*/
diff --git a/media/jni/soundpool/SoundPoolThread.cpp b/media/jni/soundpool/SoundPoolThread.cpp
new file mode 100644
index 0000000..ba3b482
--- /dev/null
+++ b/media/jni/soundpool/SoundPoolThread.cpp
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "SoundPoolThread"
+#include "utils/Log.h"
+
+#include "SoundPoolThread.h"
+
+namespace android {
+
+void SoundPoolThread::write(SoundPoolMsg msg) {
+    Mutex::Autolock lock(&mLock);
+    while (mMsgQueue.size() >= maxMessages) {
+        mCondition.wait(mLock);
+    }
+
+    // if thread is quitting, don't add to queue
+    if (mRunning) {
+        mMsgQueue.push(msg);
+        mCondition.signal();
+    }
+}
+
+const SoundPoolMsg SoundPoolThread::read() {
+    Mutex::Autolock lock(&mLock);
+    while (mMsgQueue.size() == 0) {
+        mCondition.wait(mLock);
+    }
+    SoundPoolMsg msg = mMsgQueue[0];
+    mMsgQueue.removeAt(0);
+    mCondition.signal();
+    return msg;
+}
+
+void SoundPoolThread::quit() {
+    Mutex::Autolock lock(&mLock);
+    if (mRunning) {
+        mRunning = false;
+        mMsgQueue.clear();
+        mMsgQueue.push(SoundPoolMsg(SoundPoolMsg::KILL, 0));
+        mCondition.signal();
+        mCondition.wait(mLock);
+    }
+    ALOGV("return from quit");
+}
+
+SoundPoolThread::SoundPoolThread(SoundPool* soundPool) :
+    mSoundPool(soundPool)
+{
+    mMsgQueue.setCapacity(maxMessages);
+    if (createThreadEtc(beginThread, this, "SoundPoolThread")) {
+        mRunning = true;
+    }
+}
+
+SoundPoolThread::~SoundPoolThread()
+{
+    quit();
+}
+
+int SoundPoolThread::beginThread(void* arg) {
+    ALOGV("beginThread");
+    SoundPoolThread* soundPoolThread = (SoundPoolThread*)arg;
+    return soundPoolThread->run();
+}
+
+int SoundPoolThread::run() {
+    ALOGV("run");
+    for (;;) {
+        SoundPoolMsg msg = read();
+        ALOGV("Got message m=%d, mData=%d", msg.mMessageType, msg.mData);
+        switch (msg.mMessageType) {
+        case SoundPoolMsg::KILL:
+            ALOGV("goodbye");
+            return NO_ERROR;
+        case SoundPoolMsg::LOAD_SAMPLE:
+            doLoadSample(msg.mData);
+            break;
+        default:
+            ALOGW("run: Unrecognized message %d\n",
+                    msg.mMessageType);
+            break;
+        }
+    }
+}
+
+void SoundPoolThread::loadSample(int sampleID) {
+    write(SoundPoolMsg(SoundPoolMsg::LOAD_SAMPLE, sampleID));
+}
+
+void SoundPoolThread::doLoadSample(int sampleID) {
+    sp <Sample> sample = mSoundPool->findSample(sampleID);
+    status_t status = -1;
+    if (sample != 0) {
+        status = sample->doLoad();
+    }
+    mSoundPool->notify(SoundPoolEvent(SoundPoolEvent::SAMPLE_LOADED, sampleID, status));
+}
+
+} // end namespace android
diff --git a/media/jni/soundpool/SoundPoolThread.h b/media/jni/soundpool/SoundPoolThread.h
new file mode 100644
index 0000000..d388388
--- /dev/null
+++ b/media/jni/soundpool/SoundPoolThread.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2007 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 SOUNDPOOLTHREAD_H_
+#define SOUNDPOOLTHREAD_H_
+
+#include <utils/threads.h>
+#include <utils/Vector.h>
+#include <media/AudioTrack.h>
+
+#include "SoundPool.h"
+
+namespace android {
+
+class SoundPoolMsg {
+public:
+    enum MessageType { INVALID, KILL, LOAD_SAMPLE };
+    SoundPoolMsg() : mMessageType(INVALID), mData(0) {}
+    SoundPoolMsg(MessageType MessageType, int data) :
+        mMessageType(MessageType), mData(data) {}
+    uint16_t         mMessageType;
+    uint16_t         mData;
+};
+
+/*
+ * This class handles background requests from the SoundPool
+ */
+class SoundPoolThread {
+public:
+    SoundPoolThread(SoundPool* SoundPool);
+    ~SoundPoolThread();
+    void loadSample(int sampleID);
+    void quit();
+    void write(SoundPoolMsg msg);
+
+private:
+    static const size_t maxMessages = 5;
+
+    static int beginThread(void* arg);
+    int run();
+    void doLoadSample(int sampleID);
+    const SoundPoolMsg read();
+
+    Mutex                   mLock;
+    Condition               mCondition;
+    Vector<SoundPoolMsg>    mMsgQueue;
+    SoundPool*              mSoundPool;
+    bool                    mRunning;
+};
+
+} // end namespace android
+
+#endif /*SOUNDPOOLTHREAD_H_*/
diff --git a/media/jni/soundpool/android_media_SoundPool_SoundPoolImpl.cpp b/media/jni/soundpool/android_media_SoundPool_SoundPoolImpl.cpp
index baf61d5..b2333f8 100644
--- a/media/jni/soundpool/android_media_SoundPool_SoundPoolImpl.cpp
+++ b/media/jni/soundpool/android_media_SoundPool_SoundPoolImpl.cpp
@@ -23,7 +23,7 @@
 #include <nativehelper/jni.h>
 #include <nativehelper/JNIHelp.h>
 #include <android_runtime/AndroidRuntime.h>
-#include <media/SoundPool.h>
+#include "SoundPool.h"
 
 using namespace android;
 
@@ -45,20 +45,6 @@
 static audio_attributes_fields_t javaAudioAttrFields;
 
 // ----------------------------------------------------------------------------
-static jint
-android_media_SoundPool_SoundPoolImpl_load_URL(JNIEnv *env, jobject thiz, jstring path, jint priority)
-{
-    ALOGV("android_media_SoundPool_SoundPoolImpl_load_URL");
-    SoundPool *ap = MusterSoundPool(env, thiz);
-    if (path == NULL) {
-        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
-        return 0;
-    }
-    const char* s = env->GetStringUTFChars(path, NULL);
-    int id = ap->load(s, priority);
-    env->ReleaseStringUTFChars(path, s);
-    return (jint) id;
-}
 
 static jint
 android_media_SoundPool_SoundPoolImpl_load_FD(JNIEnv *env, jobject thiz, jobject fileDescriptor,
@@ -249,10 +235,6 @@
 // Dalvik VM type signatures
 static JNINativeMethod gMethods[] = {
     {   "_load",
-        "(Ljava/lang/String;I)I",
-        (void *)android_media_SoundPool_SoundPoolImpl_load_URL
-    },
-    {   "_load",
         "(Ljava/io/FileDescriptor;JJI)I",
         (void *)android_media_SoundPool_SoundPoolImpl_load_FD
     },
diff --git a/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java b/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java
index c2bb90c..0b7b99f 100644
--- a/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java
+++ b/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java
@@ -29,7 +29,8 @@
 import android.os.ServiceManager;
 import android.os.storage.IMountService;
 import android.os.storage.StorageManager;
-import android.util.Log;
+import android.text.Editable;
+import android.text.TextWatcher;
 import android.util.Slog;
 import android.view.View;
 import android.widget.Button;
@@ -180,20 +181,6 @@
         mEncPassword = (TextView) findViewById(R.id.enc_password);
         TextView curPwDesc = (TextView) findViewById(R.id.password_desc);
 
-        // We vary the password prompt depending on whether one is predefined, and whether
-        // the device is encrypted.
-        mIsEncrypted = deviceIsEncrypted();
-        if (!haveBackupPassword()) {
-            curPwDesc.setVisibility(View.GONE);
-            mCurPassword.setVisibility(View.GONE);
-            if (layoutId == R.layout.confirm_backup) {
-                TextView encPwDesc = (TextView) findViewById(R.id.enc_password_desc);
-                encPwDesc.setText(mIsEncrypted
-                                  ? R.string.backup_enc_password_required
-                                  : R.string.backup_enc_password_optional);
-            }
-        }
-
         mAllowButton.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
@@ -209,6 +196,7 @@
                 sendAcknowledgement(mToken, false, mObserver);
                 mAllowButton.setEnabled(false);
                 mDenyButton.setEnabled(false);
+                finish();
             }
         });
 
@@ -218,6 +206,39 @@
             mAllowButton.setEnabled(!mDidAcknowledge);
             mDenyButton.setEnabled(!mDidAcknowledge);
         }
+
+        // We vary the password prompt depending on whether one is predefined, and whether
+        // the device is encrypted.
+        mIsEncrypted = deviceIsEncrypted();
+        if (!haveBackupPassword()) {
+            curPwDesc.setVisibility(View.GONE);
+            mCurPassword.setVisibility(View.GONE);
+            if (layoutId == R.layout.confirm_backup) {
+                TextView encPwDesc = (TextView) findViewById(R.id.enc_password_desc);
+                if (mIsEncrypted) {
+                    encPwDesc.setText(R.string.backup_enc_password_required);
+                    monitorEncryptionPassword();
+                } else {
+                    encPwDesc.setText(R.string.backup_enc_password_optional);
+                }
+            }
+        }
+    }
+
+    private void monitorEncryptionPassword() {
+        mAllowButton.setEnabled(false);
+        mEncPassword.addTextChangedListener(new TextWatcher() {
+            @Override
+            public void onTextChanged(CharSequence s, int start, int before, int count) { }
+
+            @Override
+            public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
+
+            @Override
+            public void afterTextChanged(Editable s) {
+                mAllowButton.setEnabled(mEncPassword.getText().length() > 0);
+            }
+        });
     }
 
     // Preserve the restore observer callback binder across activity relaunch
diff --git a/packages/FusedLocation/src/com/android/location/fused/FusionEngine.java b/packages/FusedLocation/src/com/android/location/fused/FusionEngine.java
index 7cee066..5e9ec10 100644
--- a/packages/FusedLocation/src/com/android/location/fused/FusionEngine.java
+++ b/packages/FusedLocation/src/com/android/location/fused/FusionEngine.java
@@ -97,14 +97,18 @@
 
     /** Called on mLooper thread */
     public void enable() {
-        mEnabled = true;
-        updateRequirements();
+        if (!mEnabled) {
+            mEnabled = true;
+            updateRequirements();
+        }
     }
 
     /** Called on mLooper thread */
     public void disable() {
-        mEnabled = false;
-        updateRequirements();
+        if (mEnabled) {
+            mEnabled = false;
+            updateRequirements();
+        }
     }
 
     /** Called on mLooper thread */
@@ -131,16 +135,14 @@
     private void enableProvider(String name, long minTime) {
         ProviderStats stats = mStats.get(name);
 
-        if (stats.available) {
-            if (!stats.requested) {
-                stats.requestTime = SystemClock.elapsedRealtime();
-                stats.requested = true;
-                stats.minTime = minTime;
-                mLocationManager.requestLocationUpdates(name, minTime, 0, this, mLooper);
-            } else if (stats.minTime != minTime) {
-                stats.minTime = minTime;
-                mLocationManager.requestLocationUpdates(name, minTime, 0, this, mLooper);
-            }
+        if (!stats.requested) {
+            stats.requestTime = SystemClock.elapsedRealtime();
+            stats.requested = true;
+            stats.minTime = minTime;
+            mLocationManager.requestLocationUpdates(name, minTime, 0, this, mLooper);
+        } else if (stats.minTime != minTime) {
+            stats.minTime = minTime;
+            mLocationManager.requestLocationUpdates(name, minTime, 0, this, mLooper);
         }
     }
 
diff --git a/packages/Keyguard/res/values-zh-rCN/strings.xml b/packages/Keyguard/res/values-zh-rCN/strings.xml
index c5d61ac..9f9f970 100644
--- a/packages/Keyguard/res/values-zh-rCN/strings.xml
+++ b/packages/Keyguard/res/values-zh-rCN/strings.xml
@@ -34,7 +34,7 @@
     <string name="keyguard_low_battery" msgid="8143808018719173859">"请连接充电器。"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="1332288268600329841">"按“菜单”键解锁。"</string>
     <string name="keyguard_network_locked_message" msgid="9169717779058037168">"网络已锁定"</string>
-    <string name="keyguard_missing_sim_message_short" msgid="494980561304211931">"无SIM卡"</string>
+    <string name="keyguard_missing_sim_message_short" msgid="494980561304211931">"无 SIM 卡"</string>
     <string name="keyguard_missing_sim_message" product="tablet" msgid="1445849005909260039">"平板电脑中没有SIM卡。"</string>
     <string name="keyguard_missing_sim_message" product="default" msgid="3481110395508637643">"手机中没有SIM卡。"</string>
     <string name="keyguard_missing_sim_instructions" msgid="5210891509995942250">"请插入SIM卡。"</string>
diff --git a/packages/PrintSpooler/res/values-ca/arrays.xml b/packages/PrintSpooler/res/values-ca/arrays.xml
new file mode 100644
index 0000000..c1b149c
--- /dev/null
+++ b/packages/PrintSpooler/res/values-ca/arrays.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<resources>
+
+    <string-array name="pdf_printer_media_sizes" translatable="false">
+        <item>NA_LETTER</item>
+        <item>NA_GOVT_LETTER</item>
+        <item>NA_LEGAL</item>
+        <item>NA_JUNIOR_LEGAL</item>
+        <item>NA_LEDGER</item>
+        <item>NA_TABLOID</item>
+        <item>NA_INDEX_3X5</item>
+        <item>NA_INDEX_4X6</item>
+        <item>NA_INDEX_5X8</item>
+        <item>NA_MONARCH</item>
+        <item>NA_QUARTO</item>
+        <item>NA_FOOLSCAP</item>
+    </string-array>
+
+</resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index c18757d..e57c5f4 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -159,8 +159,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> አስወግድ።"</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ተሰናብቷል::"</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"ሁሉም የቅርብ ጊዜ ማመልከቻዎች ተሰናብተዋል።"</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> በመጀመር ላይ።"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"ማሳወቂያ ተወግዷል።"</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"የማሳወቂያ ጥላ።"</string>
@@ -282,8 +281,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ማያ ገጽ መሰካት"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"ፈልግ"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g>ን መጀመር አልተቻለም።"</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"ሁሉንም ማመልከቻዎች አሰናብት"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"ባትሪ ሞልቷል"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"ኃይል በመሙላት ላይ"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> እስኪሞላ ድረስ"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index a011911..7fc379c 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -159,8 +159,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Отхвърляне на <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Приложението <xliff:g id="APP">%s</xliff:g> е отхвърлено."</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Всички скорошни приложения са отхвърлени."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> се стартира."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Известието е отхвърлено."</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Падащ панел с известия."</string>
@@ -282,8 +281,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"фиксиране на екрана"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"търсене"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> не можа да стартира."</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Отхвърляне на всички приложения"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Заредена"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Зарежда се"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> до пълно зареждане"</string>
diff --git a/packages/SystemUI/res/values-bn-rBD/strings.xml b/packages/SystemUI/res/values-bn-rBD/strings.xml
index 8d33282..1110310 100644
--- a/packages/SystemUI/res/values-bn-rBD/strings.xml
+++ b/packages/SystemUI/res/values-bn-rBD/strings.xml
@@ -159,8 +159,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> খারিজ করুন।"</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> খারিজ করা হয়েছে৷"</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"সমস্ত সাম্প্রতিক অ্যাপ্লিকেশন খারিজ করা হয়েছে।"</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> তারাঙ্কিত করা হচ্ছে।"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"বিজ্ঞপ্তি খারিজ করা হয়েছে৷"</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"বিজ্ঞপ্তি শেড৷"</string>
@@ -282,8 +281,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"স্ক্রীন পিন করা"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"অনুসন্ধান"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> শুরু করা যায়নি৷"</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"সমস্ত অ্যাপ্লিকেশন খারিজ করুন"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"চার্জ হয়েছে"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"চার্জ হচ্ছে"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"পূর্ণ হতে <xliff:g id="CHARGING_TIME">%s</xliff:g> সময় লাগবে"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index e33c49d..ef5986b 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -161,8 +161,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Descarta <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"S\'ha omès <xliff:g id="APP">%s</xliff:g>."</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"S\'han descartat totes les aplicacions recents."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"S\'està iniciant <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notificació omesa."</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Àrea de notificacions"</string>
@@ -284,8 +283,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"fixació de pantalla"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"cerca"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"No s\'ha pogut iniciar <xliff:g id="APP">%s</xliff:g>."</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Descarta totes les aplicacions"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Carregada"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"S\'està carregant"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> per completar la càrrega"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index c8907c7..6235eb1 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -161,8 +161,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Zavřít aplikaci <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Aplikace <xliff:g id="APP">%s</xliff:g> byla odebrána."</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Všechny naposledy použité aplikace byly odstraněny."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Spouštění aplikace <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Oznámení je zavřeno."</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Panel oznámení."</string>
@@ -284,8 +283,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"připnutí obrazovky"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"vyhledat"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Aplikaci <xliff:g id="APP">%s</xliff:g> nelze spustit."</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Odstranit všechny aplikace"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Nabito"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Nabíjení"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> do plného nabití"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index f442472..3153d3f 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -159,8 +159,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Afvis <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> er annulleret."</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Alle de seneste applikationer er lukket."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> startes."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Underretningen er annulleret."</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Underretningspanel."</string>
@@ -282,8 +281,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"bliv i app"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"søg"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> kunne ikke startes."</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Luk alle applikationer"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Opladet"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Oplader"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> indtil fuld opladet"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index f3349d2..3165a3c 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -161,8 +161,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> beenden"</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> entfernt"</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Alle kürzlich verwendeten Apps wurden entfernt."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> wird gestartet."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Benachrichtigung geschlossen"</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Benachrichtigungsleiste"</string>
@@ -284,8 +283,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"Bildschirmfixierung"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"Suche"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> konnte nicht gestartet werden."</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Alle Apps entfernen"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Aufgeladen"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Wird aufgeladen"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"Voll in <xliff:g id="CHARGING_TIME">%s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 04c4fe8..e6ea177 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -161,8 +161,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Παράβλεψη <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Απορρίφθηκαν <xliff:g id="APP">%s</xliff:g>."</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Έγινε παράβλεψη όλων των πρόσφατων εφαρμογών."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Έναρξη <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Η ειδοποίηση έχει απορριφθεί."</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Πλαίσιο σκίασης ειδοποιήσεων."</string>
@@ -284,8 +283,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"καρφίτσωμα οθόνης"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"αναζήτηση"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Δεν ήταν δυνατή η εκκίνηση της εφαρμογής <xliff:g id="APP">%s</xliff:g>."</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Παράβλεψη όλων των εφαρμογών"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Φορτίστηκε"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Φόρτιση"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> για πλήρη φόρτιση"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 7cf20ba..c788677 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -161,8 +161,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Rechazar <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> descartada."</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Se descartaron todas las aplicaciones recientes."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Iniciando <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notificación ignorada"</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Pantalla de notificaciones"</string>
@@ -284,8 +283,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"Fijar pantalla"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"buscar"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"No se pudo iniciar <xliff:g id="APP">%s</xliff:g>."</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Descartar todas las aplicaciones"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Cargada"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Cargando"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> para completarse"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 82fe2bd..3f2fa15 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -159,8 +159,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Ignorar <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Se ha eliminado <xliff:g id="APP">%s</xliff:g>."</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Se han ignorado todas las aplicaciones recientes."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Iniciando <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notificación ignorada"</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Pantalla de notificaciones"</string>
@@ -282,8 +281,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"fijación de pantalla"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"buscar"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"No se ha podido iniciar <xliff:g id="APP">%s</xliff:g>."</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Ignorar todas las aplicaciones"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Cargada"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Cargando"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> para completarse"</string>
diff --git a/packages/SystemUI/res/values-et-rEE/strings.xml b/packages/SystemUI/res/values-et-rEE/strings.xml
index f8ce386..9c05158 100644
--- a/packages/SystemUI/res/values-et-rEE/strings.xml
+++ b/packages/SystemUI/res/values-et-rEE/strings.xml
@@ -159,8 +159,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Rakendusest <xliff:g id="APP">%s</xliff:g> loobumine."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Loobusite rakendusest <xliff:g id="APP">%s</xliff:g>."</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Kõikidest hiljutistest rakendustest on loobutud"</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Rakenduse <xliff:g id="APP">%s</xliff:g> käivitamine."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Märguandest on loobutud."</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Märguande vari."</string>
@@ -282,8 +281,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ekraanikuva kinnitamine"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"otsing"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Rakendust <xliff:g id="APP">%s</xliff:g> ei saanud käivitada."</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Loobu kõikidest rakendustest"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Laetud"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Laadimine"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"Täislaadimiseks kulub <xliff:g id="CHARGING_TIME">%s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-eu-rES/strings.xml b/packages/SystemUI/res/values-eu-rES/strings.xml
index b456bee..e2a81e9 100644
--- a/packages/SystemUI/res/values-eu-rES/strings.xml
+++ b/packages/SystemUI/res/values-eu-rES/strings.xml
@@ -159,8 +159,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Baztertu <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> baztertu da."</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Azken aplikazioen atala garbitu da."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> hasten."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Jakinarazpena baztertu da."</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Jakinarazpenen panela."</string>
@@ -282,8 +281,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"pantaila-ainguratzea"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"bilatu"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Ezin izan da hasi <xliff:g id="APP">%s</xliff:g>."</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Garbitu aplikazio guztiak"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Kargatuta"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Kargatzen"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> falta zaizkio guztiz kargatzeko"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index b8b2d65..3208b1b 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -159,8 +159,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Hylätään <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> hylättiin."</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Kaikki viimeisimmät sovellukset on hylätty."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Käynnistetään <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Ilmoitus hylätty."</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Ilmoitusalue."</string>
@@ -282,8 +281,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"näytön kiinnitys"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"haku"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Sovelluksen <xliff:g id="APP">%s</xliff:g> käynnistäminen epäonnistui."</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Hylkää kaikki sovellukset"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Ladattu"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Ladataan"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> kunnes täynnä"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 156e4a7..e6bd1f6 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -161,8 +161,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Supprimer <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Application \"<xliff:g id="APP">%s</xliff:g>\" ignorée."</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Toutes les applications récentes ont été supprimées."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Lancement de <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notification masquée"</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Volet des notifications"</string>
@@ -284,8 +283,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"épinglage d\'écran"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"rechercher"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Impossible de lancer <xliff:g id="APP">%s</xliff:g>."</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Supprimer toutes les applications"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Chargée"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Charge en cours..."</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"Chargée dans <xliff:g id="CHARGING_TIME">%s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 31ef4ef..1d91c8a 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -161,8 +161,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Supprimer <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Application \"<xliff:g id="APP">%s</xliff:g>\" ignorée."</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Toutes les applications récentes ont été supprimées."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Lancement de <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notification masquée"</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Volet des notifications"</string>
@@ -284,8 +283,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"épinglage d\'écran"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"rechercher"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Impossible de lancer <xliff:g id="APP">%s</xliff:g>."</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Supprimer toutes les applications"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Chargé"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"En charge"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"Chargé dans <xliff:g id="CHARGING_TIME">%s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-gl-rES/strings.xml b/packages/SystemUI/res/values-gl-rES/strings.xml
index 4c40a5a..78a5fbb 100644
--- a/packages/SystemUI/res/values-gl-rES/strings.xml
+++ b/packages/SystemUI/res/values-gl-rES/strings.xml
@@ -161,8 +161,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Rexeitar <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Rexeitouse <xliff:g id="APP">%s</xliff:g>."</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Rexeitáronse todas as aplicacións recentes."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Iniciando <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notificación rexeitada"</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Sombra de notificación"</string>
@@ -284,8 +283,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"fixación de pantalla"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"buscar"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Non foi posible iniciar <xliff:g id="APP">%s</xliff:g>."</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Rexeitar todas as aplicacións"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Cargada"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Cargando"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> para completar a carga"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 50ef47a..411e3c3 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -159,8 +159,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> को ख़ारिज करें."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> खा़रिज कर दिया गया."</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"हाल ही के सभी ऐप्लिकेशन ख़ारिज कर दिए गए."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> प्रारंभ हो रहा है."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"नोटिफिकेशन खारिज की गई."</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"नोटिफिकेशन शेड."</string>
@@ -282,8 +281,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"स्क्रीन पिन करना"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"खोज"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> प्रारंभ नहीं किया जा सका."</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"सभी ऐप्लिकेशन ख़ारिज करें"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"चार्ज हो गई है"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"चार्ज हो रही है"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"पूर्ण होने में <xliff:g id="CHARGING_TIME">%s</xliff:g> शेष"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 3fb20a9..1e42832 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -159,8 +159,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Odbacivanje aplikacije <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Aplikacija <xliff:g id="APP">%s</xliff:g> odbačena je."</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Odbačene su sve nedavne aplikacije."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Pokretanje aplikacije <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Obavijest je odbačena."</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Zaslon obavijesti."</string>
@@ -282,8 +281,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"prikvačivanje zaslona"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"pretraži"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Aplikacija <xliff:g id="APP">%s</xliff:g> nije pokrenuta."</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Odbaci sve aplikacije"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Napunjeno"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Punjenje"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> do napunjenosti"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 8787599..ed105d0 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -159,8 +159,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"A(z) <xliff:g id="APP">%s</xliff:g> elvetése."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> eltávolítva."</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Az összes alkalmazás eltávolítva a nemrég használtak közül."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"A(z) <xliff:g id="APP">%s</xliff:g> indítása."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Értesítés elvetve."</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Értesítési felület."</string>
@@ -282,8 +281,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"képernyő rögzítése"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"keresés"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Nem lehet elindítani a következőt: <xliff:g id="APP">%s</xliff:g>."</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Összes alkalmazás elvetése"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Feltöltve"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Töltés"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> a teljes töltöttségig"</string>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml
index c0f8776..6432060 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings.xml
+++ b/packages/SystemUI/res/values-hy-rAM/strings.xml
@@ -159,8 +159,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Անտեսել <xliff:g id="APP">%s</xliff:g>-ը:"</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g>-ը անտեսված է:"</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Բոլոր վերջին հավելվածները հեռացվել են ցուցակից:"</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Մեկնարկել <xliff:g id="APP">%s</xliff:g>-ը:"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Ծանուցումը անտեսվեց:"</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Ծանուցումների վահանակ:"</string>
@@ -282,8 +281,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"էկրանի ամրակցում"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"որոնել"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Հնարավոր չէ գործարկել <xliff:g id="APP">%s</xliff:g>-ը:"</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Հեռացնել բոլոր հավելվածները"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Լիցքավորված է"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Լիցքավորվում է"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"Լրիվ լիցքավորմանը մնաց <xliff:g id="CHARGING_TIME">%s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 025bdbe..bd0a99f 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -159,8 +159,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Menyingkirkan <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> disingkirkan."</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Semua aplikasi terbaru ditutup."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Memulai <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Pemberitahuan disingkirkan."</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Bayangan pemberitahuan."</string>
@@ -282,8 +281,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"pin ke layar"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"telusuri"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Tidak dapat memulai <xliff:g id="APP">%s</xliff:g>."</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Tutup semua aplikasi"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Terisi"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Mengisi daya"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> sampai penuh"</string>
diff --git a/packages/SystemUI/res/values-is-rIS/strings.xml b/packages/SystemUI/res/values-is-rIS/strings.xml
index 87fb619..adcda3f 100644
--- a/packages/SystemUI/res/values-is-rIS/strings.xml
+++ b/packages/SystemUI/res/values-is-rIS/strings.xml
@@ -159,8 +159,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Hunsa <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> vísað frá."</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Öll nýleg forrit fjarlægð."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Ræsir <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Tilkynningu lokað."</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Tilkynningasvæði."</string>
@@ -282,8 +281,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"skjáfesting"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"leita"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Ekki var hægt að ræsa <xliff:g id="APP">%s</xliff:g>."</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Fjarlægja öll forrit"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Fullhlaðin"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Í hleðslu"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> þar til fullri hleðslu er náð"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 8144bc0..21a483f 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -161,8 +161,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Elimina <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> eliminata."</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Tutte le applicazioni recenti sono state rimosse."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Avvio di <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notifica eliminata."</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Area notifiche."</string>
@@ -284,8 +283,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"blocco su schermo"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"cerca"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Impossibile avviare <xliff:g id="APP">%s</xliff:g>."</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Rimuovi tutte le applicazioni"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Carica"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"In carica"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> al termine della carica"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 0183e21..5b68f86 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -161,8 +161,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g>を削除します。"</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g>は削除されました。"</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"最近のアプリケーションをすべて消去しました。"</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g>を開始しています。"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"通知が削除されました。"</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"通知シェード"</string>
@@ -284,8 +283,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"画面固定"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"検索"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g>を開始できません。"</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"すべてのアプリケーションを消去"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"充電が完了しました"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"充電しています"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"充電完了まで<xliff:g id="CHARGING_TIME">%s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-ka-rGE/strings.xml b/packages/SystemUI/res/values-ka-rGE/strings.xml
index 42fdfe9..b6650d0 100644
--- a/packages/SystemUI/res/values-ka-rGE/strings.xml
+++ b/packages/SystemUI/res/values-ka-rGE/strings.xml
@@ -159,8 +159,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g>-ის უგულებელყოფა."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ამოშლილია სიიდან."</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"ყველა ბოლო აპლიკაცია გაუქმდა."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> იწყება."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"შეტყობინება წაიშალა."</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"შეტყობინებების ფარდა"</string>
@@ -282,8 +281,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ეკრანზე ჩამაგრება"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"ძიება"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g>-ის გამოძახება ვერ მოხერხდა."</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"ყველა აპლიკაციის გაუქმება"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"დატენილია"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"მიმდინარეობს დატენვა"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> სრულად დატენვამდე"</string>
diff --git a/packages/SystemUI/res/values-kk-rKZ/strings.xml b/packages/SystemUI/res/values-kk-rKZ/strings.xml
index 7190aa2..15c4584 100644
--- a/packages/SystemUI/res/values-kk-rKZ/strings.xml
+++ b/packages/SystemUI/res/values-kk-rKZ/strings.xml
@@ -159,8 +159,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> қолданбасынан бас тарту."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> алынып тасталған."</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Барлық жақындағы қабылданбаған қолданбалар."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> іске қосылуда."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Хабар алынып тасталды."</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Хабарландыру тақтасы"</string>
@@ -282,8 +281,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"экранды бекіту"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"іздеу"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> іске қосу мүмкін болмады."</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Барлық қолданбаларды қабылдамау"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Зарядталды"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Зарядталуда"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"Толғанға дейін <xliff:g id="CHARGING_TIME">%s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml
index e88deb7..28d586a 100644
--- a/packages/SystemUI/res/values-km-rKH/strings.xml
+++ b/packages/SystemUI/res/values-km-rKH/strings.xml
@@ -159,8 +159,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"បោះបង់ <xliff:g id="APP">%s</xliff:g> ។"</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> បដិសេធ។"</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"កម្មវិធីថ្មីៗទាំងអស់ត្រូវបានបោះបង់។"</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"ចាប់ផ្ដើម <xliff:g id="APP">%s</xliff:g> ។"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"បាន​បដិសេធ​ការ​ជូនដំណឹង"</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"ពណ៌​ការ​ជូន​ដំណឹង"</string>
@@ -282,8 +281,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ការ​ភ្ជាប់​អេក្រង់"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"ស្វែងរក"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"មិន​អាច​ចាប់ផ្ដើម <xliff:g id="APP">%s</xliff:g> ទេ។"</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"បោះបង់កម្មវិធីទាំងអស់"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"បាន​បញ្ចូល​ថ្ម​​"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"កំពុង​បញ្ចូល​ថ្ម"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> រហូត​ដល់ពេញ"</string>
diff --git a/packages/SystemUI/res/values-kn-rIN/strings.xml b/packages/SystemUI/res/values-kn-rIN/strings.xml
index 5b7738b..4134c11 100644
--- a/packages/SystemUI/res/values-kn-rIN/strings.xml
+++ b/packages/SystemUI/res/values-kn-rIN/strings.xml
@@ -159,8 +159,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> ವಜಾಗೊಳಿಸು."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ವಜಾಗೊಳಿಸಲಾಗಿದೆ."</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"ಇತ್ತೀಚಿನ ಎಲ್ಲಾ ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ವಜಾಗೊಳಿಸಲಾಗಿದೆ."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> ಪ್ರಾರಂಭಿಸಲಾಗುತ್ತಿದೆ."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"ಅಧಿಸೂಚನೆ ವಜಾಗೊಂಡಿದೆ."</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"ಅಧಿಸೂಚನೆಯ ಛಾಯೆ."</string>
@@ -282,8 +281,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ಸ್ಕ್ರೀನ್ ಪಿನ್ನಿಂಗ್"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"ಹುಡುಕಾಟ"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> ಪ್ರಾರಂಭಿಸಲು ಸಾದ್ಯವಿಲ್ಲ."</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"ಎಲ್ಲಾ ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ವಜಾಗೊಳಿಸಿ"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"ಚಾರ್ಜ್ ಆಗಿದೆ"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> ಪೂರ್ಣಗೊಳ್ಳುವವರೆಗೆ"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 906ba2b..549da84 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -159,8 +159,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g>을(를) 숨깁니다."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g>이(가) 제거되었습니다."</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"최근 사용한 애플리케이션을 모두 닫았습니다."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g>을(를) 시작하는 중입니다."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"알림이 제거되었습니다."</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"알림 세부정보"</string>
@@ -282,8 +281,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"화면 고정"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"검색"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g>을(를) 시작할 수 없습니다."</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"모든 애플리케이션 닫기"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"충전됨"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"충전 중"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"완충까지 <xliff:g id="CHARGING_TIME">%s</xliff:g> 남음"</string>
diff --git a/packages/SystemUI/res/values-ky-rKG/strings.xml b/packages/SystemUI/res/values-ky-rKG/strings.xml
index 30e5c97..960541a 100644
--- a/packages/SystemUI/res/values-ky-rKG/strings.xml
+++ b/packages/SystemUI/res/values-ky-rKG/strings.xml
@@ -184,8 +184,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> этибарга албоо."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> жок болду."</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Акыркы колдонмолордун баары көз жаздымда калтырылды."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> иштеп баштоодо."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Эскертме жок кылынды."</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Эскертмелер көшөгөсү."</string>
@@ -307,8 +306,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"экран кадоо"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"издөө"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> баштай алган жок."</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Бардык колдонмолорду көз жаздымда калтыруу"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Кубатталды"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Кубатталууда"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> толгонго чейин"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 49f38b9..f7a8c00 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -159,8 +159,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Atsisakyti <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Atsisakyta programos „<xliff:g id="APP">%s</xliff:g>“."</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Atsisakyta visų naujausių programų."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Paleidžiama <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Pranešimo atsisakyta."</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Pranešimų gaubtas."</string>
@@ -282,8 +281,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ekrano prisegimas"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"paieška"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Nepavyko paleisti <xliff:g id="APP">%s</xliff:g>."</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Atsisakyti visų programų"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Įkrautas"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Kraunamas"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> iki visiško įkrovimo"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index a0f7b20..a9f7110 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -159,8 +159,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Nerādīt lietotni <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Lietotne <xliff:g id="APP">%s</xliff:g> vairs netiek rādīta."</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Visas nesen izmantotās lietojumprogrammas tika noņemtas."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Notiek lietotnes <xliff:g id="APP">%s</xliff:g> palaišana."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Paziņojums netiek rādīts."</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Paziņojumu panelis"</string>
@@ -282,8 +281,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"Piespraust ekrānu"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"Meklēt"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Nevarēja palaist lietotni <xliff:g id="APP">%s</xliff:g>."</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Noņemt visas lietojumprogrammas"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Akumulators uzlādēts"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Notiek uzlāde"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> līdz pilnam akumulatoram"</string>
diff --git a/packages/SystemUI/res/values-mk-rMK/strings.xml b/packages/SystemUI/res/values-mk-rMK/strings.xml
index 67314c0..4686ba5 100644
--- a/packages/SystemUI/res/values-mk-rMK/strings.xml
+++ b/packages/SystemUI/res/values-mk-rMK/strings.xml
@@ -161,8 +161,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Отфрли <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> е отфрлена."</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Сите неодамнешни апликации се отфрлени."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Се стартува <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Известувањето е отфрлено."</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Панел за известување"</string>
@@ -284,8 +283,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"прикачување екран"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"пребарај"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> не може да се вклучи."</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Отфрли ги сите апликации"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Наполнета"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Се полни"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> додека не се наполни"</string>
diff --git a/packages/SystemUI/res/values-ml-rIN/strings.xml b/packages/SystemUI/res/values-ml-rIN/strings.xml
index 41e5ef8..41f5923 100644
--- a/packages/SystemUI/res/values-ml-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ml-rIN/strings.xml
@@ -159,8 +159,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> നിരസിക്കുക."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> നിരസിച്ചു."</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"അടുത്തിടെയുള്ള എല്ലാ അപ്ലിക്കേഷനും നിരസിച്ചു."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> ആരംഭിക്കുന്നു."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"അറിയിപ്പ് നിരസിച്ചു."</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"അറിയിപ്പ് ഷെയ്‌ഡ്."</string>
@@ -282,8 +281,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"സ്ക്രീൻ പിൻ ചെയ്യൽ"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"തിരയുക"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> ആരംഭിക്കാനായില്ല."</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"എല്ലാ അപ്ലിക്കേഷനുകളും നിരസിക്കുക"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"ചാർജ്ജുചെയ്‌തു"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"ചാർജ്ജുചെയ്യുന്നു"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"പൂർണ്ണമായും ചാർജ്ജാകുന്നതിന്, <xliff:g id="CHARGING_TIME">%s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-mn-rMN/strings.xml b/packages/SystemUI/res/values-mn-rMN/strings.xml
index ea80976..8f81367 100644
--- a/packages/SystemUI/res/values-mn-rMN/strings.xml
+++ b/packages/SystemUI/res/values-mn-rMN/strings.xml
@@ -159,8 +159,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g>-г хаах."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> байхгүй."</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Хамгийн сүүлийн бүх програмыг арилгасан байна."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g>-г эхлүүлж байна."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Мэдэгдэл хаагдсан."</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Мэдэгдлийн хураангуй самбар"</string>
@@ -282,8 +281,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"дэлгэц тогтоох"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"хайх"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g>-г эхлүүлж чадсангүй."</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Бүх програмыг арилгах"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Цэнэглэгдсэн"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Цэнэглэж байна"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"дүүргэхэд <xliff:g id="CHARGING_TIME">%s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-mr-rIN/strings.xml b/packages/SystemUI/res/values-mr-rIN/strings.xml
index e8f3a98..bf7c5a6 100644
--- a/packages/SystemUI/res/values-mr-rIN/strings.xml
+++ b/packages/SystemUI/res/values-mr-rIN/strings.xml
@@ -159,8 +159,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> डिसमिस करा."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> डिसमिस केला."</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"अलीकडील सर्व अनुप्रयोग डिसमिस झाले."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> प्रारंभ करीत आहे."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"सूचना डिसमिस केल्या."</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"सूचना शेड."</string>
@@ -282,8 +281,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"स्‍क्रीन पिन करणे"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"शोधा"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> प्रारंभ करणे शक्य झाले नाही."</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"सर्व अनुप्रयोग डिसमिस करा"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"चार्ज झाली"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"चार्ज होत आहे"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> पूर्ण होईपर्यंत"</string>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml
index 7b89c1c..5845d59 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings.xml
@@ -159,8 +159,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Ketepikan <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ditolak."</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Semua aplikasi terbaharu diketepikan."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Memulakan <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Pemberitahuan diketepikan."</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Bidai pemberitahuan."</string>
@@ -282,8 +281,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"penyematan skrin"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"cari"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Tidak dapat memulakan <xliff:g id="APP">%s</xliff:g>."</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Ketepikan semua aplikasi"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Sudah dicas"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Mengecas"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"Lagi <xliff:g id="CHARGING_TIME">%s</xliff:g> untuk penuh"</string>
diff --git a/packages/SystemUI/res/values-my-rMM/strings.xml b/packages/SystemUI/res/values-my-rMM/strings.xml
index 86e4729..c8f4c55 100644
--- a/packages/SystemUI/res/values-my-rMM/strings.xml
+++ b/packages/SystemUI/res/values-my-rMM/strings.xml
@@ -159,8 +159,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g>ကို ပယ်လိုက်ရန်"</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ထုတ်ထားသည်။"</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"မကြာသေးမီက အပလီကေးရှင်းများအားလုံး ဖယ်ထုတ်ပြီးပါပြီ။"</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g>ကို စတင်နေသည်။"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"အကြောင်းကြားချက်ကိုဖယ်ရှားပြီး"</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"အ​ကြောင်းကြားစာအကွက်"</string>
@@ -282,8 +281,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"မျက်နှာပြင် ပင်ထိုးမှု"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"ရှာဖွေရန်"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> ကို မစနိုင်ပါ။"</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"အပလီကေးရှင်းများအားလုံး ဖယ်ထုတ်မည်"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"အားသွင်းပြီး"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"အားသွင်းနေ"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> ပြည်သည့် အထိ"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 7ac8a69..60e27ee 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -159,8 +159,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Avvis <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> avvist."</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Alle nylig brukte apper er avvist."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Starter <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Varselet ble skjult."</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Varselskygge."</string>
@@ -282,8 +281,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"én-appsmodus"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"Søk"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Kunne ikke starte <xliff:g id="APP">%s</xliff:g>."</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Avvis alle apper"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Oppladet"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Lader"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"Fulladet om <xliff:g id="CHARGING_TIME">%s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-ne-rNP/strings.xml b/packages/SystemUI/res/values-ne-rNP/strings.xml
index d1d19af..87cbb6f 100644
--- a/packages/SystemUI/res/values-ne-rNP/strings.xml
+++ b/packages/SystemUI/res/values-ne-rNP/strings.xml
@@ -159,8 +159,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> खारेज गर्नुहोस्।"</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> खारेज गरिएको छ।"</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"सबै हालका अनुप्रयोगहरू खारेज गरियो।"</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g>सुरु गर्दै।"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"सूचना खारेज।"</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"सूचना कक्ष।"</string>
@@ -282,8 +281,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"स्क्रिन पिन गर्दै"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"खोजी गर्नुहोस्"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"सुरु गर्न सकिएन <xliff:g id="APP">%s</xliff:g>।"</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"सबै अनुप्रयोगहरू खारेज गर्नुहोस्"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"चार्ज भयो"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"चार्ज हुँदै"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> पूर्ण नभएसम्म"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 451ff9a..6786a74 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -159,8 +159,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> sluiten."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> verwijderd."</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Alle recente apps gesloten."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> starten."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Melding verwijderd."</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Meldingenpaneel."</string>
@@ -282,8 +281,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"scherm vastzetten"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"zoeken"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Kan <xliff:g id="APP">%s</xliff:g> niet starten."</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Alle apps sluiten"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Opgeladen"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Opladen"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> tot volledig opgeladen"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 81e22ca..3f2c7fd 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -159,8 +159,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Usuń stąd <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g>: zamknięto."</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Wszystkie ostatnie aplikacje zostały zamknięte."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Uruchamiam <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Zamknięto powiadomienie."</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Obszar powiadomień."</string>
@@ -282,8 +281,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"przypinanie ekranu"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"szukaj"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Nie udało się uruchomić aplikacji <xliff:g id="APP">%s</xliff:g>."</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Zamknij wszystkie aplikacje"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Naładowana"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Ładowanie"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> do pełnego naładowania"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index ae7b551..b5b2650 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -159,8 +159,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Ignorar <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ignorado."</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Todas as aplicações recentes foram ignoradas."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"A iniciar <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notificação ignorada."</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Painel de notificações."</string>
@@ -282,8 +281,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"fixação no ecrã"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"pesquisar"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Não foi possível iniciar o <xliff:g id="APP">%s</xliff:g>."</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Ignorar todas as aplicações"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Carregada"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"A carregar"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> até ficar completa"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 7887e06..c914a50 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -161,8 +161,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Descartar <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> descartado."</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Todos os apps recentes foram dispensados."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Iniciando <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notificação dispensada."</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Aba de notificações."</string>
@@ -284,8 +283,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"fixação de tela"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"pesquisar"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Não foi possível iniciar <xliff:g id="APP">%s</xliff:g>."</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Dispensar todos os apps"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Carregada"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Carregando"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> até concluir"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 0c1b4ec..c84b96f 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -159,8 +159,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Închideți <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> a fost eliminată."</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Toate aplicațiile recente au fost închise."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Se inițiază <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notificarea a fost închisă."</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Fereastră pentru notificări."</string>
@@ -282,8 +281,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"fixare pe ecran"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"căutare"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> nu a putut porni."</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Închideți toate aplicațiile"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"S-a încărcat"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Se încarcă"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> până la încărcare completă"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 8425cb4..cd00556 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -19,7 +19,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="7164937344850004466">"Графический интерфейс системы"</string>
+    <string name="app_label" msgid="7164937344850004466">"Интерфейс системы"</string>
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Очистить"</string>
     <string name="status_bar_recent_remove_item_title" msgid="6026395868129852968">"Удалить из списка"</string>
     <string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"О приложении"</string>
@@ -161,8 +161,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Удаление приложения <xliff:g id="APP">%s</xliff:g> из списка."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Приложение \"<xliff:g id="APP">%s</xliff:g>\" удалено из списка."</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Все недавние приложения закрыты."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Запуск приложения <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Уведомление закрыто"</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Панель уведомлений"</string>
@@ -284,8 +283,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"Заблокировать в приложении"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"поиск"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Не удалось запустить приложение \"<xliff:g id="APP">%s</xliff:g>\""</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Закрыть все приложения"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Батарея заряжена"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Зарядка батареи"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> до полной зарядки"</string>
diff --git a/packages/SystemUI/res/values-si-rLK/strings.xml b/packages/SystemUI/res/values-si-rLK/strings.xml
index 760e49d..0a54324 100644
--- a/packages/SystemUI/res/values-si-rLK/strings.xml
+++ b/packages/SystemUI/res/values-si-rLK/strings.xml
@@ -159,8 +159,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> ඉවතලන්න."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> අස් කර ඇත."</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"සියලු මෑත යෙඳුම් අස් කෙරිණි"</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> ආරම්භ කරමින්."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"දැනුම්දීම නිෂ්ප්‍රභා කරඇත."</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"දැනුම්දීම් ආවරණය."</string>
@@ -282,8 +281,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"තිර ඇමිණීම"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"සෙවීම"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> ආරම්භ කළ නොහැක."</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"සියලු යෙදුම් අස් කරන්න"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"අරෝපිතයි"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"ආරෝපණය වෙමින්"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> සම්පූර්ණ වන තෙක්"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index b20d8f9..9fbd73e4 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -161,8 +161,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Zrušiť aplikáciu <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Aplikácia <xliff:g id="APP">%s</xliff:g> bola zrušená."</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Všetky nedávne aplikácie boli odmietnuté."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Spúšťa sa aplikácia <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Upozornenie bolo zrušené."</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Panel upozornení."</string>
@@ -284,8 +283,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"pripnutie k obrazovke"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"hľadať"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Aplikáciu <xliff:g id="APP">%s</xliff:g> sa nepodarilo spustiť"</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Odmietnuť všetky aplikácie"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Nabitá"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Nabíja sa"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"Úplné nabitie o <xliff:g id="CHARGING_TIME">%s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 1981bfd..e4a2016 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -159,8 +159,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Opusti aplikacijo <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Aplikacija <xliff:g id="APP">%s</xliff:g> je bila odstranjena."</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Vse nedavne aplikacije so bile opuščene."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Zaganjanje aplikacije <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Obvestilo je bilo odstranjeno."</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Zaslon z obvestili."</string>
@@ -282,8 +281,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"pripenjanje zaslona"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"iskanje"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Aplikacije <xliff:g id="APP">%s</xliff:g> ni bilo mogoče zagnati."</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Opusti vse aplikacije"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Akumulator napolnjen"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Polnjenje"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> do napolnjenosti"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index fc4dd64..f3d7da0 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -159,8 +159,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Одбаците <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Апликација <xliff:g id="APP">%s</xliff:g> је одбачена."</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Све недавно коришћене апликације су одбачене."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Покрећемо <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Обавештење је одбачено."</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Прозор са обавештењима."</string>
@@ -282,8 +281,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"качење екрана"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"претражи"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Покретање апликације <xliff:g id="APP">%s</xliff:g> није успело."</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Одбаци све апликације"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Напуњена је"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Пуњење"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> док се не напуни"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 6cc5ad0..0e9879a 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -159,8 +159,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Ta bort <xliff:g id="APP">%s</xliff:g> från listan."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> togs bort permanent."</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Alla appar har tagits bort från listan Senaste."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Startar <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Meddelandet ignorerades."</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Meddelandepanel."</string>
@@ -282,8 +281,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"fästa skärmen"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"sök"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Det gick inte att starta appen <xliff:g id="APP">%s</xliff:g>."</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Ta bort alla appar"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Laddat"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Laddar"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> tills batteriet är fulladdat"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 3b539b9..05cd74a 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -159,8 +159,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Ondoa <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> imeondolewa."</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Programu za hivi majuzi zimeondolewa."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Inaanzisha <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Arifa imetupwa."</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Kivuli cha arifa."</string>
@@ -282,8 +281,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"kudumisha programu moja"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"tafuta"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Haikuweza kuanzisha <xliff:g id="APP">%s</xliff:g>."</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Ondoa programu zote"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Betri imejaa"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Inachaji"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"Imebakisha <xliff:g id="CHARGING_TIME">%s</xliff:g> ijae"</string>
diff --git a/packages/SystemUI/res/values-ta-rIN/strings.xml b/packages/SystemUI/res/values-ta-rIN/strings.xml
index bf163f6..7556c7b 100644
--- a/packages/SystemUI/res/values-ta-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ta-rIN/strings.xml
@@ -159,8 +159,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> ஐ நிராகரி."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> விலக்கப்பட்டது."</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"எல்லா சமீபத்திய பயன்பாடுகளும் விலக்கப்பட்டன."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> ஐத் தொடங்குகிறது."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"அறிவிப்பு நிராகரிக்கப்பட்டது."</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"அறிவிப்பு விவரம்."</string>
@@ -282,8 +281,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"திரையை பின் செய்தல்"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"தேடு"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g>ஐத் தொடங்க முடியவில்லை."</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"எல்லா பயன்பாடுகளையும் விலக்கு"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"சார்ஜ் செய்யப்பட்டது"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"சார்ஜாகிறது"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"முழுவதும் சார்ஜாக <xliff:g id="CHARGING_TIME">%s</xliff:g> ஆகும்"</string>
diff --git a/packages/SystemUI/res/values-te-rIN/strings.xml b/packages/SystemUI/res/values-te-rIN/strings.xml
index 04616c9..7704e85 100644
--- a/packages/SystemUI/res/values-te-rIN/strings.xml
+++ b/packages/SystemUI/res/values-te-rIN/strings.xml
@@ -159,8 +159,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g>ని తీసివేయండి."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> తీసివేయబడింది."</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"అన్ని ఇటీవలి అనువర్తనాలు తీసివేయబడ్డాయి."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g>ని ప్రారంభిస్తోంది."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"నోటిఫికేషన్ తీసివేయబడింది."</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"నోటిఫికేషన్ షేడ్."</string>
@@ -282,8 +281,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"స్క్రీన్ పిన్నింగ్"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"శోధించు"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g>ని ప్రారంభించడం సాధ్యపడలేదు."</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"అన్ని అనువర్తనాలను తీసివేయి"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"ఛార్జ్ చేయబడింది"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"ఛార్జ్ అవుతోంది"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"పూర్తిగా నిండటానికి <xliff:g id="CHARGING_TIME">%s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 5b51a87..d591d0a 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -159,8 +159,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"ยกเลิก <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ถูกลบไปแล้ว"</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"ปิดแอปพลิเคชันล่าสุดทั้งหมดแล้ว"</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"กำลังเริ่มต้น <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"ปิดการแจ้งเตือนแล้ว"</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"หน้าต่างแจ้งเตือน"</string>
@@ -282,8 +281,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"การตรึงหน้าจอ"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"ค้นหา"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"ไม่สามารถเริ่มใช้ <xliff:g id="APP">%s</xliff:g>"</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"ปิดแอปพลิเคชันทั้งหมด"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"ชาร์จแล้ว"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"กำลังชาร์จ"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"อีก <xliff:g id="CHARGING_TIME">%s</xliff:g> จึงจะเต็ม"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 2367762..abe7b53 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -159,8 +159,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"I-dismiss ang <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Hindi pinansin ang <xliff:g id="APP">%s</xliff:g>."</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Na-dismiss ang lahat ng kamakailang application."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Sinisimulan ang <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Na-dismiss ang notification."</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Notification shade."</string>
@@ -282,8 +281,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"pagpi-pin sa screen"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"maghanap"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Hindi masimulan <xliff:g id="APP">%s</xliff:g>."</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"I-dismiss ang lahat ng application"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Nasingil na"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Nagcha-charge"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> hanggang mapuno"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 2b7f059..9bcdc27 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -159,8 +159,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> uygulamasını kapat."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> kaldırıldı."</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Tüm son uygulamalar kapatıldı."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> başlatılıyor."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Bildirim kapatıldı."</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Bildirim gölgesi."</string>
@@ -282,8 +281,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ekran sabitleme"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"ara"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> başlatılamadı."</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Tüm uygulamaları kapat"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Ödeme alındı"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Şarj oluyor"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"Tam şarj olmasına <xliff:g id="CHARGING_TIME">%s</xliff:g> kaldı"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 1f086ff..68f7daa 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -159,8 +159,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Видалити додаток <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Програму <xliff:g id="APP">%s</xliff:g> закрито."</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Усі останні додатки закрито."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Запуск додатка <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Сповіщення відхилено."</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Панель сповіщень."</string>
@@ -282,8 +281,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"закріпити екран"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"пошук"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Не вдалося запустити <xliff:g id="APP">%s</xliff:g>."</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Закрити всі додатки"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Заряджено"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Заряджається"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"До повного зарядження <xliff:g id="CHARGING_TIME">%s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-ur-rPK/strings.xml b/packages/SystemUI/res/values-ur-rPK/strings.xml
index cb6f3f0..bc3dbc2 100644
--- a/packages/SystemUI/res/values-ur-rPK/strings.xml
+++ b/packages/SystemUI/res/values-ur-rPK/strings.xml
@@ -159,8 +159,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> کو مسترد کریں۔"</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> کو ہٹا دیا گیا۔"</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"سبھی حالیہ ایپلیکیشنز کو برخاست کر دیا گیا۔"</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> شروع ہو رہی ہے۔"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"اطلاع مسترد ہوگئی۔"</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"اطلاعاتی شیڈ۔"</string>
@@ -282,8 +281,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"اسکرین کو پن کرنا"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"تلاش کریں"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> کو شروع نہیں کیا جا سکا۔"</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"سبھی ایپلیکیشنز کو برخاست کریں"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"چارج ہوگئی"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"چارج ہو رہی ہے"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> مکمل ہونے تک"</string>
diff --git a/packages/SystemUI/res/values-uz-rUZ/strings.xml b/packages/SystemUI/res/values-uz-rUZ/strings.xml
index 58bf477..86ad17e 100644
--- a/packages/SystemUI/res/values-uz-rUZ/strings.xml
+++ b/packages/SystemUI/res/values-uz-rUZ/strings.xml
@@ -159,8 +159,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Olib tashlash: <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> olib tashlangan."</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Yaqinda ishlatilgan barcha ilovalar olib tashlandi."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> ishga tushirilmoqda."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Xabarnoma e‘tiborsiz qoldirildi."</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Xabarnoma soyasi."</string>
@@ -282,8 +281,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ekranni qadab qo‘yish"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"qidirish"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"“<xliff:g id="APP">%s</xliff:g>” ilovasini ishga tushirib bo‘lmadi."</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Barcha ilovalarni olib tashlash"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Batareya quvvati to‘ldi"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Quvvat olmoqda"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g>da to‘ladi"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index c34d0ed..506c60a 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -159,8 +159,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"Xóa bỏ <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> đã bị loại bỏ."</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"Đã loại bỏ tất cả các ứng dụng gần đây."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"Bắt đầu <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Đã loại bỏ thông báo."</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Bóng thông báo."</string>
@@ -282,8 +281,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"khóa màn hình"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"tìm kiếm"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"Không thể khởi động <xliff:g id="APP">%s</xliff:g>."</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"Loại bỏ tất cả các ứng dụng"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Đã sạc"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"Đang sạc"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> cho đến khi đầy"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 49fe785..4b39f65 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -143,7 +143,7 @@
     <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"漫游中"</string>
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"EDGE"</string>
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"WLAN"</string>
-    <string name="accessibility_no_sim" msgid="8274017118472455155">"无SIM卡。"</string>
+    <string name="accessibility_no_sim" msgid="8274017118472455155">"无 SIM 卡。"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"蓝牙网络共享。"</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"飞行模式。"</string>
     <!-- String.format failed for translation -->
@@ -161,8 +161,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"移除<xliff:g id="APP">%s</xliff:g>。"</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"已删除<xliff:g id="APP">%s</xliff:g>"</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"已关闭所有最近用过的应用。"</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"正在启动<xliff:g id="APP">%s</xliff:g>。"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"已关闭通知。"</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"通知栏。"</string>
@@ -284,8 +283,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"固定屏幕"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"搜索"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"无法启动<xliff:g id="APP">%s</xliff:g>。"</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"关闭所有应用"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"充电完成"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"正在充电"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"还需<xliff:g id="CHARGING_TIME">%s</xliff:g>充满"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 22e0ed1..50d8489 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -161,8 +161,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"關閉「<xliff:g id="APP">%s</xliff:g>」。"</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"「<xliff:g id="APP">%s</xliff:g>」已關閉。"</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"所有最近使用的應用程式已關閉。"</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"正在啟動「<xliff:g id="APP">%s</xliff:g>」。"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"通知已關閉。"</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"通知欄。"</string>
@@ -284,8 +283,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"螢幕固定"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"搜尋"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"無法啟動「<xliff:g id="APP">%s</xliff:g>」。"</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"關閉所有應用程式"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"已完成充電"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"充電中"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g>後完成充電"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 674b974..8a50cf9 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -161,8 +161,7 @@
     <skip />
     <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"關閉「<xliff:g id="APP">%s</xliff:g>」。"</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"「<xliff:g id="APP">%s</xliff:g>」已關閉。"</string>
-    <!-- no translation found for accessibility_recents_all_items_dismissed (4464697366179168836) -->
-    <skip />
+    <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"最近使用的使用程式已全部關閉。"</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"正在啟動「<xliff:g id="APP">%s</xliff:g>」。"</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"已關閉通知。"</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"通知欄。"</string>
@@ -284,8 +283,7 @@
     <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"螢幕固定"</string>
     <string name="recents_search_bar_label" msgid="8074997400187836677">"搜尋"</string>
     <string name="recents_launch_error_message" msgid="2969287838120550506">"無法啟動「<xliff:g id="APP">%s</xliff:g>」。"</string>
-    <!-- no translation found for recents_dismiss_all_message (8495275386693095768) -->
-    <skip />
+    <string name="recents_dismiss_all_message" msgid="8495275386693095768">"關閉所有應用程式"</string>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"已充飽"</string>
     <string name="expanded_header_battery_charging" msgid="205623198487189724">"充電中"</string>
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g>後充飽"</string>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 071b9a3..2659009 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -250,7 +250,7 @@
     <integer name="doze_pickup_vibration_threshold">2000</integer>
 
     <!-- Doze: can we assume the pickup sensor includes a proximity check? -->
-    <bool name="doze_pickup_performs_proximity_check">true</bool>
+    <bool name="doze_pickup_performs_proximity_check">false</bool>
 
     <!-- Doze: pulse parameter - how long does it take to fade in? -->
     <integer name="doze_pulse_duration_in">900</integer>
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
index ddb96a2..30f92b9 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -97,9 +97,7 @@
         state.icon = ResourceIcon.get(iconId);
         state.isOverlayIconWide = cb.isDataTypeIconWide;
         state.autoMirrorDrawable = !cb.noSim;
-        state.overlayIconId = cb.enabled && (cb.dataTypeIconId > 0) && !cb.wifiConnected
-                ? cb.dataTypeIconId
-                : 0;
+        state.overlayIconId = cb.enabled && (cb.dataTypeIconId > 0) ? cb.dataTypeIconId : 0;
         state.filter = iconId != R.drawable.ic_qs_no_sim;
         state.activityIn = cb.enabled && cb.activityIn;
         state.activityOut = cb.enabled && cb.activityOut;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index ac5602c..e8023bb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -57,7 +57,6 @@
     // Since some pieces of the phone state are interdependent we store it locally,
     // this could potentially become part of MobileState for simplification/complication
     // of code.
-    private IccCardConstants.State mSimState = IccCardConstants.State.READY;
     private int mDataNetType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
     private int mDataState = TelephonyManager.DATA_DISCONNECTED;
     private ServiceState mServiceState;
@@ -146,11 +145,6 @@
         return getIcons().mDataContentDescription;
     }
 
-    @VisibleForTesting
-    protected IccCardConstants.State getSimState() {
-        return mSimState;
-    }
-
     public void setAirplaneMode(boolean airplaneMode) {
         mCurrentState.airplaneMode = airplaneMode;
         notifyListenersIfNecessary();
@@ -239,10 +233,13 @@
 
         String contentDescription = getStringIfExists(getContentDescription());
         String dataContentDescription = getStringIfExists(icons.mDataContentDescription);
+
+        boolean showDataIcon = mCurrentState.dataConnected && mCurrentState.inetForNetwork != 0
+                || mCurrentState.iconGroup == TelephonyIcons.ROAMING;
+
         // Only send data sim callbacks to QS.
         if (mCurrentState.dataSim) {
-            int qsTypeIcon = mCurrentState.dataConnected ?
-                    icons.mQsDataType[mCurrentState.inetForNetwork] : 0;
+            int qsTypeIcon = showDataIcon ? icons.mQsDataType[mCurrentState.inetForNetwork] : 0;
             int length = mSignalsChangedCallbacks.size();
             for (int i = 0; i < length; i++) {
                 mSignalsChangedCallbacks.get(i).onMobileDataSignalChanged(mCurrentState.enabled
@@ -257,8 +254,6 @@
                         icons.mIsWide && qsTypeIcon != 0);
             }
         }
-        boolean showDataIcon = mCurrentState.dataConnected && mCurrentState.inetForNetwork != 0
-                || mCurrentState.iconGroup == TelephonyIcons.ROAMING;
         int typeIcon = showDataIcon ? icons.mDataType : 0;
         int signalClustersLength = mSignalClusters.size();
         for (int i = 0; i < signalClustersLength; i++) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
index 9b95d5c..260dea0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
@@ -69,6 +69,8 @@
     protected TelephonyManager mMockTm;
     protected Config mConfig;
 
+    protected int mSubId;
+
     private NetworkCapabilities mNetCapabilities;
 
     @Override
@@ -100,13 +102,13 @@
 
     protected void setupNetworkController() {
         // For now just pretend to be the data sim, so we can test that too.
-        final int subId = SubscriptionManager.getDefaultDataSubId();
+        mSubId = SubscriptionManager.getDefaultDataSubId();
         SubscriptionInfo subscription = mock(SubscriptionInfo.class);
         List<SubscriptionInfo> subs = new ArrayList<SubscriptionInfo>();
-        when(subscription.getSubscriptionId()).thenReturn(subId);
+        when(subscription.getSubscriptionId()).thenReturn(mSubId);
         subs.add(subscription);
         mNetworkController.setCurrentSubscriptions(subs);
-        mMobileSignalController = mNetworkController.mMobileSignalControllers.get(subId);
+        mMobileSignalController = mNetworkController.mMobileSignalControllers.get(mSubId);
         mPhoneStateListener = mMobileSignalController.mPhoneStateListener;
         mSignalCluster = mock(SignalCluster.class);
         mNetworkSignalChangedCallback = mock(NetworkSignalChangedCallback.class);
@@ -291,10 +293,6 @@
         assertEquals("Visibility in status bar", visible, (boolean) visibleArg.getValue());
     }
 
-   protected void assertSimStateEquals(IccCardConstants.State expected) {
-       assertEquals("Sim state", expected, mMobileSignalController.getSimState());
-   }
-
    protected void assertNetworkNameEquals(String expected) {
        assertEquals("Network name", expected, mNetworkController.getMobileNetworkName());
    }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
index 65b0971..7fa3f68 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
@@ -25,6 +25,7 @@
 import android.telephony.TelephonyManager;
 
 import com.android.internal.telephony.IccCardConstants;
+import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.systemui.R;
 
@@ -254,16 +255,6 @@
         setCdmaRoaming(false);
     }
 
-    public void testOnReceive_updateSimState_noSim() {
-        Intent intent = new Intent();
-        intent.setAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
-        intent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE, IccCardConstants.INTENT_VALUE_ICC_ABSENT);
-
-        mNetworkController.onReceive(mContext, intent);
-
-        assertSimStateEquals(IccCardConstants.State.ABSENT);
-    }
-
     public void testOnReceive_stringsUpdatedAction_spn() {
         String expectedMNetworkName = "Test";
         Intent intent = createStringsUpdatedIntent(true /* showSpn */,
@@ -344,6 +335,7 @@
 
         intent.putExtra(TelephonyIntents.EXTRA_SHOW_PLMN, showPlmn);
         intent.putExtra(TelephonyIntents.EXTRA_PLMN, plmn);
+        intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, mSubId);
 
         return intent;
     }
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 153b67b..1aa7366 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -3165,7 +3165,7 @@
 
             // If the user is chording a menu shortcut, release the chord since
             // this window lost focus
-            if (!hasWindowFocus && mPanelChordingKey != 0) {
+            if (hasFeature(FEATURE_OPTIONS_PANEL) && !hasWindowFocus && mPanelChordingKey != 0) {
                 closePanel(FEATURE_OPTIONS_PANEL);
             }
 
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 7124e5b..d4032cc 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -1723,7 +1723,6 @@
             case TYPE_STATUS_BAR_PANEL:
             case TYPE_STATUS_BAR_SUB_PANEL:
             case TYPE_SYSTEM_DIALOG:
-            case TYPE_UNIVERSE_BACKGROUND:
             case TYPE_VOLUME_OVERLAY:
             case TYPE_PRIVATE_PRESENTATION:
                 break;
@@ -1822,8 +1821,6 @@
             return 2;
         }
         switch (type) {
-        case TYPE_UNIVERSE_BACKGROUND:
-            return 1;
         case TYPE_PRIVATE_PRESENTATION:
             return 2;
         case TYPE_WALLPAPER:
@@ -1935,11 +1932,6 @@
     }
 
     @Override
-    public int getAboveUniverseLayer() {
-        return windowTypeToLayerLw(TYPE_SYSTEM_ERROR);
-    }
-
-    @Override
     public int getNonDecorDisplayWidth(int fullWidth, int fullHeight, int rotation) {
         if (mHasNavigationBar) {
             // For a basic navigation bar, when we are in landscape mode we place
@@ -1997,7 +1989,6 @@
             case TYPE_NAVIGATION_BAR:
             case TYPE_WALLPAPER:
             case TYPE_DREAM:
-            case TYPE_UNIVERSE_BACKGROUND:
             case TYPE_KEYGUARD_SCRIM:
                 return false;
             default:
@@ -3769,8 +3760,7 @@
                             + mOverscanScreenWidth;
                     pf.bottom = df.bottom = of.bottom = cf.bottom = mOverscanScreenTop
                             + mOverscanScreenHeight;
-                } else if (attrs.type == TYPE_BOOT_PROGRESS
-                        || attrs.type == TYPE_UNIVERSE_BACKGROUND) {
+                } else if (attrs.type == TYPE_BOOT_PROGRESS) {
                     // Boot progress screen always covers entire display.
                     pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
                     pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
diff --git a/rs/jni/android_renderscript_RenderScript.cpp b/rs/jni/android_renderscript_RenderScript.cpp
index dced99a..06f4def 100644
--- a/rs/jni/android_renderscript_RenderScript.cpp
+++ b/rs/jni/android_renderscript_RenderScript.cpp
@@ -1382,6 +1382,14 @@
         sc.zStart     = limit_ptr[4];
         sc.zEnd       = limit_ptr[5];
         sc.strategy   = RS_FOR_EACH_STRATEGY_DONT_CARE;
+        sc.arrayStart = 0;
+        sc.arrayEnd = 0;
+        sc.array2Start = 0;
+        sc.array2End = 0;
+        sc.array3Start = 0;
+        sc.array3End = 0;
+        sc.array4Start = 0;
+        sc.array4End = 0;
 
         sca = &sc;
     }
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 289152b..c1e4994 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -382,6 +382,7 @@
                     // we're now good to go, so start the backup alarms
                     if (MORE_DEBUG) Slog.d(TAG, "Now provisioned, so starting backups");
                     startBackupAlarmsLocked(FIRST_BACKUP_INTERVAL);
+                    scheduleNextFullBackupJob();
                 }
             }
         }
@@ -3853,6 +3854,16 @@
             PackageInfo currentPackage;
 
             try {
+                if (!mEnabled || !mProvisioned) {
+                    // Backups are globally disabled, so don't proceed.
+                    if (DEBUG) {
+                        Slog.i(TAG, "full backup requested but e=" + mEnabled
+                                + " p=" + mProvisioned + "; ignoring");
+                    }
+                    mUpdateSchedule = false;
+                    return;
+                }
+
                 IBackupTransport transport = getTransport(mCurrentTransport);
                 if (transport == null) {
                     Slog.w(TAG, "Transport not present; full data backup not performed");
@@ -4150,6 +4161,17 @@
         long now = System.currentTimeMillis();
         FullBackupEntry entry = null;
 
+        if (!mEnabled || !mProvisioned) {
+            // Backups are globally disabled, so don't proceed.  We also don't reschedule
+            // the job driving automatic backups; that job will be scheduled again when
+            // the user enables backup.
+            if (MORE_DEBUG) {
+                Slog.i(TAG, "beginFullBackup but e=" + mEnabled
+                        + " p=" + mProvisioned + "; ignoring");
+            }
+            return false;
+        }
+
         if (DEBUG_SCHEDULING) {
             Slog.i(TAG, "Beginning scheduled full backup operation");
         }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index b5d2720..69198a2 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -87,6 +87,7 @@
 import com.android.server.statusbar.StatusBarManagerInternal;
 import com.android.server.wm.AppTransition;
 import com.android.server.wm.WindowManagerService;
+
 import com.google.android.collect.Lists;
 import com.google.android.collect.Maps;
 
@@ -5617,7 +5618,10 @@
 
     @Override
     public void showBootMessage(final CharSequence msg, final boolean always) {
-        enforceNotIsolatedCaller("showBootMessage");
+        if (Binder.getCallingUid() != Process.myUid()) {
+            // These days only the core system can call this, so apps can't get in
+            // the way of what we show about running them.
+        }
         mWindowManager.showBootMessage(msg, always);
     }
 
@@ -7053,7 +7057,6 @@
                 return;
             }
 
-            final IPackageManager pm = AppGlobals.getPackageManager();
             final String authority = uri.getAuthority();
             final ProviderInfo pi = getProviderInfoLocked(authority, userId);
             if (pi == null) {
@@ -8164,7 +8167,7 @@
     @Override
     public void resizeStack(int stackId, Rect bounds) {
         enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
-                "resizeStackBox()");
+                "resizeStack()");
         long ident = Binder.clearCallingIdentity();
         try {
             synchronized (this) {
@@ -10036,7 +10039,7 @@
                 }
                 final boolean translucentChanged = r.changeWindowTranslucency(true);
                 if (translucentChanged) {
-                    r.task.stack.releaseBackgroundResources();
+                    r.task.stack.releaseBackgroundResources(r);
                     mStackSupervisor.ensureActivitiesVisibleLocked(null, 0);
                 }
                 mWindowManager.setAppFullscreen(token, true);
@@ -10063,7 +10066,7 @@
                 }
                 final boolean translucentChanged = r.changeWindowTranslucency(false);
                 if (translucentChanged) {
-                    r.task.stack.convertToTranslucent(r);
+                    r.task.stack.convertActivityToTranslucent(r);
                 }
                 mStackSupervisor.ensureActivitiesVisibleLocked(null, 0);
                 mWindowManager.setAppFullscreen(token, false);
@@ -10580,9 +10583,68 @@
         }
     }
 
+    final class PreBootContinuation extends IIntentReceiver.Stub {
+        final Intent intent;
+        final Runnable onFinishCallback;
+        final ArrayList<ComponentName> doneReceivers;
+        final List<ResolveInfo> ris;
+        final int[] users;
+        int lastRi = -1;
+        int curRi = 0;
+        int curUser = 0;
+
+        PreBootContinuation(Intent _intent, Runnable _onFinishCallback,
+                ArrayList<ComponentName> _doneReceivers, List<ResolveInfo> _ris, int[] _users) {
+            intent = _intent;
+            onFinishCallback = _onFinishCallback;
+            doneReceivers = _doneReceivers;
+            ris = _ris;
+            users = _users;
+        }
+
+        void go() {
+            if (lastRi != curRi) {
+                ActivityInfo ai = ris.get(curRi).activityInfo;
+                ComponentName comp = new ComponentName(ai.packageName, ai.name);
+                intent.setComponent(comp);
+                doneReceivers.add(comp);
+                lastRi = curRi;
+                CharSequence label = ai.loadLabel(mContext.getPackageManager());
+                showBootMessage(mContext.getString(R.string.android_preparing_apk, label), false);
+            }
+            Slog.i(TAG, "Pre-boot of " + intent.getComponent().toShortString()
+                    + " for user " + users[curUser]);
+            EventLogTags.writeAmPreBoot(users[curUser], intent.getComponent().getPackageName());
+            broadcastIntentLocked(null, null, intent, null, this,
+                    0, null, null, null, AppOpsManager.OP_NONE,
+                    true, false, MY_PID, Process.SYSTEM_UID,
+                    users[curUser]);
+        }
+
+        public void performReceive(Intent intent, int resultCode,
+                String data, Bundle extras, boolean ordered,
+                boolean sticky, int sendingUser) {
+            curUser++;
+            if (curUser >= users.length) {
+                curUser = 0;
+                curRi++;
+                if (curRi >= ris.size()) {
+                    // All done sending broadcasts!
+                    if (onFinishCallback != null) {
+                        // The raw IIntentReceiver interface is called
+                        // with the AM lock held, so redispatch to
+                        // execute our code without the lock.
+                        mHandler.post(onFinishCallback);
+                    }
+                    return;
+                }
+            }
+            go();
+        }
+    }
+
     private boolean deliverPreBootCompleted(final Runnable onFinishCallback,
             ArrayList<ComponentName> doneReceivers, int userId) {
-        boolean waitingUpdate = false;
         Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
         List<ResolveInfo> ris = null;
         try {
@@ -10590,71 +10652,51 @@
                     intent, null, 0, userId);
         } catch (RemoteException e) {
         }
-        if (ris != null) {
-            for (int i=ris.size()-1; i>=0; i--) {
-                if ((ris.get(i).activityInfo.applicationInfo.flags
-                        &ApplicationInfo.FLAG_SYSTEM) == 0) {
-                    ris.remove(i);
-                }
+        if (ris == null) {
+            return false;
+        }
+        for (int i=ris.size()-1; i>=0; i--) {
+            if ((ris.get(i).activityInfo.applicationInfo.flags
+                    &ApplicationInfo.FLAG_SYSTEM) == 0) {
+                ris.remove(i);
             }
-            intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
+        }
+        intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
 
-            // For User 0, load the version number. When delivering to a new user, deliver
-            // to all receivers.
-            if (userId == UserHandle.USER_OWNER) {
-                ArrayList<ComponentName> lastDoneReceivers = readLastDonePreBootReceivers();
-                for (int i=0; i<ris.size(); i++) {
-                    ActivityInfo ai = ris.get(i).activityInfo;
-                    ComponentName comp = new ComponentName(ai.packageName, ai.name);
-                    if (lastDoneReceivers.contains(comp)) {
-                        // We already did the pre boot receiver for this app with the current
-                        // platform version, so don't do it again...
-                        ris.remove(i);
-                        i--;
-                        // ...however, do keep it as one that has been done, so we don't
-                        // forget about it when rewriting the file of last done receivers.
-                        doneReceivers.add(comp);
-                    }
-                }
-            }
-
-            // If primary user, send broadcast to all available users, else just to userId
-            final int[] users = userId == UserHandle.USER_OWNER ? getUsersLocked()
-                    : new int[] { userId };
-            for (int i = 0; i < ris.size(); i++) {
+        // For User 0, load the version number. When delivering to a new user, deliver
+        // to all receivers.
+        if (userId == UserHandle.USER_OWNER) {
+            ArrayList<ComponentName> lastDoneReceivers = readLastDonePreBootReceivers();
+            for (int i=0; i<ris.size(); i++) {
                 ActivityInfo ai = ris.get(i).activityInfo;
                 ComponentName comp = new ComponentName(ai.packageName, ai.name);
-                doneReceivers.add(comp);
-                intent.setComponent(comp);
-                for (int j=0; j<users.length; j++) {
-                    IIntentReceiver finisher = null;
-                    // On last receiver and user, set up a completion callback
-                    if (i == ris.size() - 1 && j == users.length - 1 && onFinishCallback != null) {
-                        finisher = new IIntentReceiver.Stub() {
-                            public void performReceive(Intent intent, int resultCode,
-                                    String data, Bundle extras, boolean ordered,
-                                    boolean sticky, int sendingUser) {
-                                // The raw IIntentReceiver interface is called
-                                // with the AM lock held, so redispatch to
-                                // execute our code without the lock.
-                                mHandler.post(onFinishCallback);
-                            }
-                        };
-                    }
-                    Slog.i(TAG, "Sending system update to " + intent.getComponent()
-                            + " for user " + users[j]);
-                    broadcastIntentLocked(null, null, intent, null, finisher,
-                            0, null, null, null, AppOpsManager.OP_NONE,
-                            true, false, MY_PID, Process.SYSTEM_UID,
-                            users[j]);
-                    if (finisher != null) {
-                        waitingUpdate = true;
-                    }
+                if (false && lastDoneReceivers.contains(comp)) {
+                    // We already did the pre boot receiver for this app with the current
+                    // platform version, so don't do it again...
+                    ris.remove(i);
+                    i--;
+                    // ...however, do keep it as one that has been done, so we don't
+                    // forget about it when rewriting the file of last done receivers.
+                    doneReceivers.add(comp);
                 }
             }
         }
 
-        return waitingUpdate;
+        if (ris.size() <= 0) {
+            return false;
+        }
+
+        // If primary user, send broadcast to all available users, else just to userId
+        final int[] users = userId == UserHandle.USER_OWNER ? getUsersLocked()
+                : new int[] { userId };
+        if (users.length <= 0) {
+            return false;
+        }
+
+        PreBootContinuation cont = new PreBootContinuation(intent, onFinishCallback, doneReceivers,
+                ris, users);
+        cont.go();
+        return true;
     }
 
     public void systemReady(final Runnable goingCallback) {
@@ -10689,10 +10731,10 @@
                         synchronized (ActivityManagerService.this) {
                             mDidUpdate = true;
                         }
-                        writeLastDonePreBootReceivers(doneReceivers);
                         showBootMessage(mContext.getText(
                                 R.string.android_upgrading_complete),
                                 false);
+                        writeLastDonePreBootReceivers(doneReceivers);
                         systemReady(goingCallback);
                     }
                 }, doneReceivers, UserHandle.USER_OWNER);
@@ -15741,14 +15783,14 @@
                     callerPackage, callingPid, callingUid, resolvedType,
                     requiredPermission, appOp, receivers, resultTo, resultCode,
                     resultData, map, ordered, sticky, false, userId);
+
             if (DEBUG_BROADCAST) Slog.v(
                     TAG, "Enqueueing ordered broadcast " + r
                     + ": prev had " + queue.mOrderedBroadcasts.size());
-            if (DEBUG_BROADCAST) {
-                int seq = r.intent.getIntExtra("seq", -1);
-                Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
-            }
-            boolean replaced = replacePending && queue.replaceOrderedBroadcastLocked(r); 
+            if (DEBUG_BROADCAST) Slog.i(
+                    TAG, "Enqueueing broadcast " + r.intent.getAction());
+
+            boolean replaced = replacePending && queue.replaceOrderedBroadcastLocked(r);
             if (!replaced) {
                 queue.enqueueOrderedBroadcastLocked(r);
                 queue.scheduleBroadcastsLocked();
@@ -18309,8 +18351,8 @@
         }
     }
 
-    private Set getProfileIdsLocked(int userId) {
-        Set userIds = new HashSet<Integer>();
+    private Set<Integer> getProfileIdsLocked(int userId) {
+        Set<Integer> userIds = new HashSet<Integer>();
         final List<UserInfo> profiles = getUserManagerLocked().getProfiles(
                 userId, false /* enabledOnly */);
         for (UserInfo user : profiles) {
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index dbd787b..91013ef 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -220,6 +220,9 @@
      */
     boolean mConfigWillChange;
 
+    // Whether or not this stack covers the entire screen; by default stacks are full screen
+    boolean mFullscreen = true;
+
     long mLaunchStartTime = 0;
     long mFullyDrawnStartTime = 0;
 
@@ -1125,7 +1128,8 @@
 
         final int numStacks = mStacks.size();
         while (stackNdx < numStacks) {
-            tasks = mStacks.get(stackNdx).mTaskHistory;
+            ActivityStack historyStack = mStacks.get(stackNdx);
+            tasks = historyStack.mTaskHistory;
             final int numTasks = tasks.size();
             while (taskNdx < numTasks) {
                 activities = tasks.get(taskNdx).mActivities;
@@ -1133,7 +1137,7 @@
                 while (activityNdx < numActivities) {
                     final ActivityRecord activity = activities.get(activityNdx);
                     if (!activity.finishing) {
-                        return activity.fullscreen ? null : activity;
+                        return historyStack.mFullscreen && activity.fullscreen ? null : activity;
                     }
                     ++activityNdx;
                 }
@@ -1149,7 +1153,7 @@
 
     // Checks if any of the stacks above this one has a fullscreen activity behind it.
     // If so, this stack is hidden, otherwise it is visible.
-    private boolean isStackVisible() {
+    private boolean isStackVisibleLocked() {
         if (!isAttached()) {
             return false;
         }
@@ -1164,11 +1168,18 @@
          * wallpaper to be shown behind it.
          */
         for (int i = mStacks.indexOf(this) + 1; i < mStacks.size(); i++) {
-            final ArrayList<TaskRecord> tasks = mStacks.get(i).getAllTasks();
-            for (int taskNdx = 0; taskNdx < tasks.size(); taskNdx++) {
+            ActivityStack stack = mStacks.get(i);
+            // stack above isn't full screen, so, we assume we're still visible. at some point
+            // we should look at the stack bounds to see if we're occluded even if the stack
+            // isn't fullscreen
+            if (!stack.mFullscreen) {
+                continue;
+            }
+            final ArrayList<TaskRecord> tasks = stack.getAllTasks();
+            for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
                 final TaskRecord task = tasks.get(taskNdx);
                 final ArrayList<ActivityRecord> activities = task.mActivities;
-                for (int activityNdx = 0; activityNdx < activities.size(); activityNdx++) {
+                for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
                     final ActivityRecord r = activities.get(activityNdx);
 
                     // Conditions for an activity to obscure the stack we're
@@ -1214,7 +1225,7 @@
         // If the top activity is not fullscreen, then we need to
         // make sure any activities under it are now visible.
         boolean aboveTop = true;
-        boolean behindFullscreen = !isStackVisible();
+        boolean behindFullscreen = !isStackVisibleLocked();
 
         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
             final TaskRecord task = mTaskHistory.get(taskNdx);
@@ -1337,7 +1348,7 @@
                                     // This case created for transitioning activities from
                                     // translucent to opaque {@link Activity#convertToOpaque}.
                                     if (getVisibleBehindActivity() == r) {
-                                        releaseBackgroundResources();
+                                        releaseBackgroundResources(r);
                                     } else {
                                         if (!mStackSupervisor.mStoppingActivities.contains(r)) {
                                             mStackSupervisor.mStoppingActivities.add(r);
@@ -1369,7 +1380,7 @@
         }
     }
 
-    void convertToTranslucent(ActivityRecord r) {
+    void convertActivityToTranslucent(ActivityRecord r) {
         mTranslucentActivityWaiting = r;
         mUndrawnActivitiesBelowTopTranslucent.clear();
         mHandler.sendEmptyMessageDelayed(TRANSLUCENT_TIMEOUT_MSG, TRANSLUCENT_CONVERSION_TIMEOUT);
@@ -3282,10 +3293,9 @@
         }
     }
 
-    void releaseBackgroundResources() {
+    void releaseBackgroundResources(ActivityRecord r) {
         if (hasVisibleBehindActivity() &&
                 !mHandler.hasMessages(RELEASE_BACKGROUND_RESOURCES_TIMEOUT_MSG)) {
-            final ActivityRecord r = getVisibleBehindActivity();
             if (r == topRunningActivityLocked(null)) {
                 // Don't release the top activity if it has requested to run behind the next
                 // activity.
@@ -4143,6 +4153,10 @@
     boolean updateOverrideConfiguration(Configuration newConfig) {
         Configuration oldConfig = mOverrideConfig;
         mOverrideConfig = (newConfig == null) ? Configuration.EMPTY : newConfig;
+        // we override the configuration only when the stack's dimensions are different from
+        // the display. in this manner, we know that if the override configuration is empty,
+        // the stack is necessarily full screen
+        mFullscreen = Configuration.EMPTY.equals(mOverrideConfig);
         return !mOverrideConfig.equals(oldConfig);
     }
 }
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index 9b7d0b2..7ab3794 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -513,11 +513,7 @@
                 }
             }
             try {
-                if (DEBUG_BROADCAST_LIGHT) {
-                    int seq = r.intent.getIntExtra("seq", -1);
-                    Slog.i(TAG, "Delivering to " + filter
-                            + " (seq=" + seq + "): " + r);
-                }
+                if (DEBUG_BROADCAST_LIGHT) Slog.i(TAG, "Delivering to " + filter + " : " + r);
                 performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
                     new Intent(r.intent), r.resultCode, r.resultData,
                     r.resultExtras, r.ordered, r.initialSticky, r.userId);
@@ -662,12 +658,9 @@
                     // result if requested...
                     if (r.resultTo != null) {
                         try {
-                            if (DEBUG_BROADCAST) {
-                                int seq = r.intent.getIntExtra("seq", -1);
-                                Slog.i(TAG, "Finishing broadcast ["
-                                        + mQueueName + "] " + r.intent.getAction()
-                                        + " seq=" + seq + " app=" + r.callerApp);
-                            }
+                            if (DEBUG_BROADCAST) Slog.i(TAG,
+                                    "Finishing broadcast [" + mQueueName + "] "
+                                    + r.intent.getAction() + " app=" + r.callerApp);
                             performReceiveLocked(r.callerApp, r.resultTo,
                                 new Intent(r.intent), r.resultCode,
                                 r.resultData, r.resultExtras, false, false, r.userId);
diff --git a/services/core/java/com/android/server/am/EventLogTags.logtags b/services/core/java/com/android/server/am/EventLogTags.logtags
index c376744..e43e717 100644
--- a/services/core/java/com/android/server/am/EventLogTags.logtags
+++ b/services/core/java/com/android/server/am/EventLogTags.logtags
@@ -95,3 +95,6 @@
 
 # Home Stack brought to front or rear
 30044 am_home_stack_moved (User|1|5),(To Front|1|5),(Top Stack Id|1|5),(Focused Stack Id|1|5),(Reason|3)
+
+# Running pre boot receiver
+30045 am_pre_boot (User|1|5),(Package|3)
diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
index af5ed83..f900d0d 100644
--- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
@@ -163,6 +163,7 @@
     /**
      * Force evaluation even if it has succeeded in the past.
      * arg1 = UID responsible for requesting this reeval.  Will be billed for data.
+     * arg2 = Number of evaluation attempts to make. (If 0, make INITIAL_ATTEMPTS attempts.)
      */
     public static final int CMD_FORCE_REEVALUATION = BASE + 8;
 
@@ -212,11 +213,14 @@
 
     // Negative values disable reevaluation.
     private static final String REEVALUATE_DELAY_PROPERTY = "persist.netmon.reeval_delay";
-    // Default to 5s reevaluation delay.
+    // When connecting, attempt to validate 3 times, pausing 5s between them.
     private static final int DEFAULT_REEVALUATE_DELAY_MS = 5000;
-    private static final int MAX_RETRIES = 10;
-    // Between groups of MAX_RETRIES evaluation attempts, pause 10 mins in hopes ISP outage passes.
+    private static final int INITIAL_ATTEMPTS = 3;
+    // If a network is not validated, make one attempt every 10 mins to see if it starts working.
     private static final int REEVALUATE_PAUSE_MS = 10*60*1000;
+    private static final int PERIODIC_ATTEMPTS = 1;
+    // When an application calls reportBadNetwork, only make one attempt.
+    private static final int REEVALUATE_ATTEMPTS = 1;
     private final int mReevaluateDelayMs;
     private int mReevaluateToken = 0;
     private static final int INVALID_UID = -1;
@@ -236,6 +240,14 @@
     // Set if the user explicitly selected "Do not use this network" in captive portal sign-in app.
     private boolean mUserDoesNotWant = false;
 
+    // How many times we should attempt validation. Only checked in EvaluatingState; must be set
+    // before entering EvaluatingState. Note that whatever code causes us to transition to
+    // EvaluatingState last decides how many attempts will be made, so if one codepath were to
+    // enter EvaluatingState with a specific number of attempts, and then another were to enter it
+    // with a different number of attempts, the second number would be used. This is not currently
+    // a problem because EvaluatingState is not reentrant.
+    private int mMaxAttempts;
+
     public boolean systemReady = false;
 
     private final State mDefaultState = new DefaultState();
@@ -305,6 +317,7 @@
                     return HANDLED;
                 case CMD_NETWORK_CONNECTED:
                     if (DBG) log("Connected");
+                    mMaxAttempts = INITIAL_ATTEMPTS;
                     transitionTo(mEvaluatingState);
                     return HANDLED;
                 case CMD_NETWORK_DISCONNECTED:
@@ -318,6 +331,7 @@
                 case CMD_FORCE_REEVALUATION:
                     if (DBG) log("Forcing reevaluation");
                     mUidResponsibleForReeval = message.arg1;
+                    mMaxAttempts = message.arg2 != 0 ? message.arg2 : REEVALUATE_ATTEMPTS;
                     transitionTo(mEvaluatingState);
                     return HANDLED;
                 case CMD_CAPTIVE_PORTAL_APP_FINISHED:
@@ -347,7 +361,10 @@
         public void enter() {
             mConnectivityServiceHandler.sendMessage(obtainMessage(EVENT_NETWORK_TESTED,
                     NETWORK_TEST_RESULT_INVALID, 0, mNetworkAgentInfo));
-            if (!mUserDoesNotWant) sendMessageDelayed(CMD_FORCE_REEVALUATION, REEVALUATE_PAUSE_MS);
+            if (!mUserDoesNotWant) {
+                sendMessageDelayed(CMD_FORCE_REEVALUATION, 0 /* no UID */,
+                        PERIODIC_ATTEMPTS, REEVALUATE_PAUSE_MS);
+            }
         }
 
         @Override
@@ -413,11 +430,11 @@
     // Being in the EvaluatingState State indicates the Network is being evaluated for internet
     // connectivity.
     private class EvaluatingState extends State {
-        private int mRetries;
+        private int mAttempt;
 
         @Override
         public void enter() {
-            mRetries = 0;
+            mAttempt = 1;
             sendMessage(CMD_REEVALUATE, ++mReevaluateToken, 0);
             if (mUidResponsibleForReeval != INVALID_UID) {
                 TrafficStats.setThreadStatsUid(mUidResponsibleForReeval);
@@ -454,18 +471,18 @@
                         transitionTo(mValidatedState);
                         return HANDLED;
                     }
-                    // Note: This call to isCaptivePortal() could take minutes.  Resolving the
-                    // server's IP addresses could hit the DNS timeout and attempting connections
-                    // to each of the server's several (e.g. 11) IP addresses could each take
-                    // SOCKET_TIMEOUT_MS.  During this time this StateMachine will be unresponsive.
-                    // isCaptivePortal() could be executed on another Thread if this is found to
-                    // cause problems.
+                    // Note: This call to isCaptivePortal() could take up to a minute. Resolving the
+                    // server's IP addresses could hit the DNS timeout, and attempting connections
+                    // to each of the server's several IP addresses (currently one IPv4 and one
+                    // IPv6) could each take SOCKET_TIMEOUT_MS.  During this time this StateMachine
+                    // will be unresponsive. isCaptivePortal() could be executed on another Thread
+                    // if this is found to cause problems.
                     int httpResponseCode = isCaptivePortal();
                     if (httpResponseCode == 204) {
                         transitionTo(mValidatedState);
                     } else if (httpResponseCode >= 200 && httpResponseCode <= 399) {
                         transitionTo(mCaptivePortalState);
-                    } else if (++mRetries > MAX_RETRIES) {
+                    } else if (++mAttempt > mMaxAttempts) {
                         transitionTo(mOfflineState);
                     } else if (mReevaluateDelayMs >= 0) {
                         Message msg = obtainMessage(CMD_REEVALUATE, ++mReevaluateToken, 0);
diff --git a/services/core/java/com/android/server/hdmi/ActiveSourceHandler.java b/services/core/java/com/android/server/hdmi/ActiveSourceHandler.java
index 59d5605..7f48768 100644
--- a/services/core/java/com/android/server/hdmi/ActiveSourceHandler.java
+++ b/services/core/java/com/android/server/hdmi/ActiveSourceHandler.java
@@ -62,11 +62,6 @@
     void process(ActiveSource newActive, int deviceType) {
         // Seq #17
         HdmiCecLocalDeviceTv tv = mSource;
-        ActiveSource activeSource = tv.getActiveSource();
-        if (activeSource.equals(newActive)) {
-            invokeCallback(HdmiControlManager.RESULT_SUCCESS);
-            return;
-        }
         HdmiDeviceInfo device = mService.getDeviceInfo(newActive.logicalAddress);
         if (device == null) {
             tv.startNewDeviceAction(newActive, deviceType);
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index 43ef457..8241cdc 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -34,6 +34,7 @@
 import android.content.Context;
 import android.hardware.hdmi.HdmiControlManager;
 import android.hardware.hdmi.HdmiDeviceInfo;
+import android.hardware.hdmi.HdmiPortInfo;
 import android.hardware.hdmi.HdmiRecordSources;
 import android.hardware.hdmi.HdmiTimerRecordSources;
 import android.hardware.hdmi.IHdmiControlCallback;
@@ -431,11 +432,15 @@
             return;
         }
         List<SendKeyAction> action = getActions(SendKeyAction.class);
+        int logicalAddress = findKeyReceiverAddress();
+        if (logicalAddress == mAddress) {
+            Slog.w(TAG, "Discard key event to itself :" + keyCode + " pressed:" + isPressed);
+            return;
+        }
         if (!action.isEmpty()) {
             action.get(0).processKeyEvent(keyCode, isPressed);
         } else {
             if (isPressed) {
-                int logicalAddress = findKeyReceiverAddress();
                 if (logicalAddress != Constants.ADDR_INVALID) {
                     addAndStartAction(new SendKeyAction(this, logicalAddress, keyCode));
                     return;
@@ -580,6 +585,12 @@
         if (!isInDeviceList(address, path)) {
             handleNewDeviceAtTheTailOfActivePath(path);
         }
+
+        // Add the device ahead with default information to handle <Active Source>
+        // promptly, rather than waiting till the new device action is finished.
+        HdmiDeviceInfo deviceInfo = new HdmiDeviceInfo(address, path, getPortId(path), type,
+                Constants.UNKNOWN_VENDOR_ID, HdmiUtils.getDefaultDeviceName(address));
+        addCecDevice(deviceInfo);
         startNewDeviceAction(ActiveSource.of(address, path), type);
         return true;
     }
@@ -878,6 +889,17 @@
         return oldStatus;
     }
 
+    @ServiceThreadOnly
+    private void updateArcFeatureStatus(int portId, boolean isConnected) {
+        assertRunOnServiceThread();
+        // HEAC 2.4, HEACT 5-15
+        // Should not activate ARC if +5V status is false.
+        HdmiPortInfo portInfo = mService.getPortInfo(portId);
+        if (portInfo.isArcSupported()) {
+            changeArcFeatureEnabled(isConnected);
+        }
+    }
+
     private void notifyArcStatusToAudioService(boolean enabled) {
         // Note that we don't set any name to ARC.
         mService.getAudioManager().setWiredDeviceConnectionState(
@@ -1456,6 +1478,25 @@
     }
 
     /**
+     * Returns the {@link HdmiDeviceInfo} instance whose physical address matches
+     * the given routing path. This is the version accessible safely from threads
+     * other than service thread.
+     *
+     * @param path routing path or physical address
+     * @return {@link HdmiDeviceInfo} if the matched info is found; otherwise null
+     */
+    HdmiDeviceInfo getSafeDeviceInfoByPath(int path) {
+        synchronized (mLock) {
+            for (HdmiDeviceInfo info : mSafeAllDeviceInfos) {
+                if (info.getPhysicalAddress() == path) {
+                    return info;
+                }
+            }
+            return null;
+        }
+    }
+
+    /**
      * Whether a device of the specified physical address and logical address exists
      * in a device info list. However, both are minimal condition and it could
      * be different device from the original one.
@@ -1465,7 +1506,7 @@
      * @return true if exist; otherwise false
      */
     @ServiceThreadOnly
-    private boolean isInDeviceList(int logicalAddress, int physicalAddress) {
+    boolean isInDeviceList(int logicalAddress, int physicalAddress) {
         assertRunOnServiceThread();
         HdmiDeviceInfo device = getCecDeviceInfo(logicalAddress);
         if (device == null) {
@@ -1490,6 +1531,7 @@
             // It covers seq #40, #43.
             hotplugActions.get(0).pollAllDevicesNow();
         }
+        updateArcFeatureStatus(portId, connected);
     }
 
     private void removeCecSwitches(int portId) {
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 9f78c61..49a96d8 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -1196,7 +1196,7 @@
             }
             int activePath = tv.getActivePath();
             if (activePath != HdmiDeviceInfo.PATH_INVALID) {
-                HdmiDeviceInfo info = tv.getDeviceInfoByPath(activePath);
+                HdmiDeviceInfo info = tv.getSafeDeviceInfoByPath(activePath);
                 return (info != null) ? info : new HdmiDeviceInfo(activePath, tv.getActivePortId());
             }
             return null;
diff --git a/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java b/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java
index 722be71..1bbd038 100644
--- a/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java
+++ b/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java
@@ -38,6 +38,7 @@
 
     private static final int POLLING_INTERVAL_MS = 5000;
     private static final int TIMEOUT_COUNT = 3;
+    private static final int AVR_COUNT_MAX = 3;
 
     // State in which waits for next polling
     private static final int STATE_WAIT_FOR_NEXT_POLLING = 1;
@@ -48,6 +49,12 @@
 
     private int mTimeoutCount = 0;
 
+    // Counter used to ensure the connection to AVR is stable. Occasional failure to get
+    // polling response from AVR despite its presence leads to unstable status flipping.
+    // This is a workaround to deal with it, by removing the device only if the removal
+    // is detected {@code AVR_COUNT_MAX} times in a row.
+    private int mAvrStatusCount = 0;
+
     /**
      * Constructor
      *
@@ -148,10 +155,22 @@
         BitSet removed = complement(currentInfos, polledResult);
         int index = -1;
         while ((index = removed.nextSetBit(index + 1)) != -1) {
+            if (index == Constants.ADDR_AUDIO_SYSTEM) {
+                ++mAvrStatusCount;
+                Slog.w(TAG, "Ack not returned from AVR. count: " + mAvrStatusCount);
+                if (mAvrStatusCount < AVR_COUNT_MAX) {
+                    continue;
+                }
+            }
             Slog.v(TAG, "Remove device by hot-plug detection:" + index);
             removeDevice(index);
         }
 
+        // Reset the counter if the ack is returned from AVR.
+        if (!removed.get(Constants.ADDR_AUDIO_SYSTEM)) {
+            mAvrStatusCount = 0;
+        }
+
         // Next, check added devices.
         BitSet added = complement(polledResult, currentInfos);
         index = -1;
diff --git a/services/core/java/com/android/server/hdmi/NewDeviceAction.java b/services/core/java/com/android/server/hdmi/NewDeviceAction.java
index 3d64cc5..6753368 100644
--- a/services/core/java/com/android/server/hdmi/NewDeviceAction.java
+++ b/services/core/java/com/android/server/hdmi/NewDeviceAction.java
@@ -163,6 +163,12 @@
     }
 
     private void addDeviceInfo() {
+        // The device should be in the device list with default information.
+        if (!tv().isInDeviceList(mDeviceLogicalAddress, mDevicePhysicalAddress)) {
+            Slog.w(TAG, String.format("Device not found (%02x, %04x)",
+                    mDeviceLogicalAddress, mDevicePhysicalAddress));
+            return;
+        }
         if (mDisplayName == null) {
             mDisplayName = HdmiUtils.getDefaultDeviceName(mDeviceLogicalAddress);
         }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 13b2b0f..359359e 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -3281,7 +3281,7 @@
                             // If the result set is different from when this
                             // was created, we need to clear it and re-ask the
                             // user their preference, if we're looking for an "always" type entry.
-                            if (always && !pa.mPref.sameSet(query, priority)) {
+                            if (always && !pa.mPref.sameSet(query)) {
                                 Slog.i(TAG, "Result set changed, dropping preferred activity for "
                                         + intent + " type " + resolvedType);
                                 if (DEBUG_PREFERRED) {
@@ -3381,7 +3381,7 @@
                 if (resolveInfo != null) {
                     List<ResolveInfo> result = new ArrayList<ResolveInfo>(1);
                     result.add(resolveInfo);
-                    return result;
+                    return filterIfNotPrimaryUser(result, userId);
                 }
                 // Check for cross profile results.
                 resolveInfo = queryCrossProfileIntents(
@@ -3394,17 +3394,38 @@
                     result.add(resolveInfo);
                     Collections.sort(result, mResolvePrioritySorter);
                 }
-                return result;
+                return filterIfNotPrimaryUser(result, userId);
             }
             final PackageParser.Package pkg = mPackages.get(pkgName);
             if (pkg != null) {
-                return mActivities.queryIntentForPackage(intent, resolvedType, flags,
-                        pkg.activities, userId);
+                return filterIfNotPrimaryUser(
+                        mActivities.queryIntentForPackage(
+                                intent, resolvedType, flags, pkg.activities, userId),
+                        userId);
             }
             return new ArrayList<ResolveInfo>();
         }
     }
 
+    /**
+     * Filter out activities with primaryUserOnly flag set, when current user is not the owner.
+     *
+     * @return filtered list
+     */
+    private List<ResolveInfo> filterIfNotPrimaryUser(List<ResolveInfo> resolveInfos, int userId) {
+        if (userId == UserHandle.USER_OWNER) {
+            return resolveInfos;
+        }
+        for (int i = resolveInfos.size() - 1; i >= 0; i--) {
+            ResolveInfo info = resolveInfos.get(i);
+            if ((info.activityInfo.flags & ActivityInfo.FLAG_PRIMARY_USER_ONLY) != 0) {
+                resolveInfos.remove(i);
+            }
+        }
+        return resolveInfos;
+    }
+
+
     private ResolveInfo querySkipCurrentProfileIntents(
             List<CrossProfileIntentFilter> matchingFilters, Intent intent, String resolvedType,
             int flags, int sourceUserId) {
diff --git a/services/core/java/com/android/server/pm/PreferredComponent.java b/services/core/java/com/android/server/pm/PreferredComponent.java
index 69c1909..8e2e0cd 100644
--- a/services/core/java/com/android/server/pm/PreferredComponent.java
+++ b/services/core/java/com/android/server/pm/PreferredComponent.java
@@ -192,7 +192,7 @@
         }
     }
 
-    public boolean sameSet(List<ResolveInfo> query, int priority) {
+    public boolean sameSet(List<ResolveInfo> query) {
         if (mSetPackages == null) {
             return query == null;
         }
@@ -201,10 +201,10 @@
         }
         final int NQ = query.size();
         final int NS = mSetPackages.length;
+
         int numMatch = 0;
         for (int i=0; i<NQ; i++) {
             ResolveInfo ri = query.get(i);
-            if (ri.priority != priority) continue;
             ActivityInfo ai = ri.activityInfo;
             boolean good = false;
             for (int j=0; j<NS; j++) {
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index 08754f9..f8b40d1 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -606,9 +606,8 @@
                 final int windowCount = windowList.size();
                 for (int i = 0; i < windowCount; i++) {
                     WindowState windowState = windowList.get(i);
-                    if ((windowState.isOnScreen() || windowState.mAttrs.type == WindowManager
-                            .LayoutParams.TYPE_UNIVERSE_BACKGROUND)
-                            && !windowState.mWinAnimator.mEnterAnimationPending) {
+                    if (windowState.isOnScreen() &&
+                            !windowState.mWinAnimator.mEnterAnimationPending) {
                         outWindows.put(windowState.mLayer, windowState);
                     }
                 }
@@ -1237,7 +1236,6 @@
                     && windowType != WindowManager.LayoutParams.TYPE_DRAG
                     && windowType != WindowManager.LayoutParams.TYPE_HIDDEN_NAV_CONSUMER
                     && windowType != WindowManager.LayoutParams.TYPE_POINTER
-                    && windowType != WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND
                     && windowType != WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY
                     && windowType != WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY
                     && windowType != WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index 27ac32a..55dd911 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -239,9 +239,6 @@
         // As an optimization, we could try to prune the list of windows but this turns
         // out to be difficult because only the native code knows for sure which window
         // currently has touch focus.
-        final WindowStateAnimator universeBackground = mService.mAnimator.mUniverseBackground;
-        final int aboveUniverseLayer = mService.mAnimator.mAboveUniverseLayer;
-        boolean addedUniverse = false;
         boolean disableWallpaperTouchEvents = false;
 
         // If there's a drag in flight, provide a pseudowindow to catch drag input
@@ -299,20 +296,8 @@
                     mService.mDragState.sendDragStartedIfNeededLw(child);
                 }
 
-                if (universeBackground != null && !addedUniverse
-                        && child.mBaseLayer < aboveUniverseLayer && onDefaultDisplay) {
-                    final WindowState u = universeBackground.mWin;
-                    if (u.mInputChannel != null && u.mInputWindowHandle != null) {
-                        addInputWindowHandleLw(u.mInputWindowHandle, u, u.mAttrs.flags,
-                                u.mAttrs.type, true, u == mInputFocus, false);
-                    }
-                    addedUniverse = true;
-                }
-
-                if (child.mWinAnimator != universeBackground) {
-                    addInputWindowHandleLw(inputWindowHandle, child, flags, type, isVisible,
-                            hasFocus, hasWallpaper);
-                }
+                addInputWindowHandleLw(inputWindowHandle, child, flags, type, isVisible, hasFocus,
+                        hasWallpaper);
             }
         }
 
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index a4dfd8a4..d68c056 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -446,20 +446,6 @@
         mService.wallpaperCommandComplete(window, result);
     }
 
-    public void setUniverseTransform(IBinder window, float alpha, float offx, float offy,
-            float dsdx, float dtdx, float dsdy, float dtdy) {
-        synchronized(mService.mWindowMap) {
-            long ident = Binder.clearCallingIdentity();
-            try {
-                mService.setUniverseTransformLocked(
-                        mService.windowForClientLocked(this, window, true),
-                        alpha, offx, offy, dsdx, dtdx, dsdy, dtdy);
-            } finally {
-                Binder.restoreCallingIdentity(ident);
-            }
-        }
-    }
-
     public void onRectangleOnScreenRequested(IBinder token, Rect rectangle) {
         synchronized(mService.mWindowMap) {
             final long identity = Binder.clearCallingIdentity();
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 5d73149..6660843 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -26,6 +26,7 @@
 import android.util.EventLog;
 import android.util.Slog;
 import android.util.TypedValue;
+
 import com.android.server.EventLogTags;
 
 import java.io.PrintWriter;
@@ -126,6 +127,7 @@
         boolean oldFullscreen = mFullscreen;
         if (mDisplayContent != null) {
             mDisplayContent.getLogicalDisplayRect(mTmpRect);
+            bounds.intersect(mTmpRect); // ensure bounds are entirely within the display rect
             mFullscreen = mTmpRect.equals(bounds);
         }
 
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index 7e1f061..3987132 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -79,9 +79,6 @@
      * seen. If multiple windows satisfy this, use the lowest window. */
     WindowState mWindowDetachedWallpaper = null;
 
-    WindowStateAnimator mUniverseBackground = null;
-    int mAboveUniverseLayer = 0;
-
     int mBulkUpdateParams = 0;
     Object mLastWindowFreezeSource;
 
@@ -814,10 +811,6 @@
             pw.print(prefix); pw.print("mWindowDetachedWallpaper=");
                 pw.println(mWindowDetachedWallpaper);
         }
-        if (mUniverseBackground != null) {
-            pw.print(prefix); pw.print("mUniverseBackground="); pw.print(mUniverseBackground);
-                    pw.print(" mAboveUniverseLayer="); pw.println(mAboveUniverseLayer);
-        }
     }
 
     int getPendingLayoutChanges(final int displayId) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index a30dc91..66bef41 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -769,7 +769,7 @@
      * Whether the UI is currently running in touch mode (not showing
      * navigational focus because the user is directly pressing the screen).
      */
-    boolean mInTouchMode = true;
+    boolean mInTouchMode;
 
     private ViewServer mViewServer;
     private final ArrayList<WindowChangeListener> mWindowChangeListeners =
@@ -813,9 +813,6 @@
                 WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper());
 
                 mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this);
-                mAnimator.mAboveUniverseLayer = mPolicy.getAboveUniverseLayer()
-                        * TYPE_LAYER_MULTIPLIER
-                        + TYPE_LAYER_OFFSET;
             }
         }, 0);
     }
@@ -830,6 +827,8 @@
                 com.android.internal.R.bool.config_sf_limitedAlpha);
         mHasPermanentDpad = context.getResources().getBoolean(
                 com.android.internal.R.bool.config_hasPermanentDpad);
+        mInTouchMode = context.getResources().getBoolean(
+                com.android.internal.R.bool.config_defaultInTouchMode);
         mInputManager = inputManager; // Must be before createDisplayContentLocked.
         mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
         mDisplaySettings = new DisplaySettings();
@@ -2945,37 +2944,6 @@
         return null;
     }
 
-    public void setUniverseTransformLocked(WindowState window, float alpha,
-            float offx, float offy, float dsdx, float dtdx, float dsdy, float dtdy) {
-        Transformation transform = window.mWinAnimator.mUniverseTransform;
-        transform.setAlpha(alpha);
-        Matrix matrix = transform.getMatrix();
-        matrix.getValues(mTmpFloats);
-        mTmpFloats[Matrix.MTRANS_X] = offx;
-        mTmpFloats[Matrix.MTRANS_Y] = offy;
-        mTmpFloats[Matrix.MSCALE_X] = dsdx;
-        mTmpFloats[Matrix.MSKEW_Y] = dtdx;
-        mTmpFloats[Matrix.MSKEW_X] = dsdy;
-        mTmpFloats[Matrix.MSCALE_Y] = dtdy;
-        matrix.setValues(mTmpFloats);
-        final DisplayContent displayContent = window.getDisplayContent();
-        if (displayContent == null) {
-            return;
-        }
-
-        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
-        final RectF dispRect = new RectF(0, 0,
-                displayInfo.logicalWidth, displayInfo.logicalHeight);
-        matrix.mapRect(dispRect);
-        window.mGivenTouchableRegion.set(0, 0,
-                displayInfo.logicalWidth, displayInfo.logicalHeight);
-        window.mGivenTouchableRegion.op((int)dispRect.left, (int)dispRect.top,
-                (int)dispRect.right, (int)dispRect.bottom, Region.Op.DIFFERENCE);
-        window.mTouchableInsets = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION;
-        displayContent.layoutNeeded = true;
-        performLayoutAndPlaceSurfacesLocked();
-    }
-
     public void onRectangleOnScreenRequested(IBinder token, Rect rectangle) {
         synchronized (mWindowMap) {
             if (mAccessibilityController != null) {
@@ -7954,16 +7922,16 @@
                     break;
 
                 case TAP_OUTSIDE_STACK: {
-                    int stackId;
-                    synchronized (mWindowMap) {
-                        stackId = ((DisplayContent)msg.obj).stackIdFromPoint(msg.arg1, msg.arg2);
-                    }
-                    if (stackId >= 0) {
-                        try {
-                            mActivityManager.setFocusedStack(stackId);
-                        } catch (RemoteException e) {
-                        }
-                    }
+//                    int stackId;
+//                    synchronized (mWindowMap) {
+//                        stackId = ((DisplayContent)msg.obj).stackIdFromPoint(msg.arg1, msg.arg2);
+//                    }
+//                    if (stackId >= 0) {
+//                        try {
+//                            mActivityManager.setFocusedStack(stackId);
+//                        } catch (RemoteException e) {
+//                        }
+//                    }
                 }
                 break;
                 case NOTIFY_ACTIVITY_DRAWN:
@@ -8479,7 +8447,7 @@
                 numRemoved++;
                 continue;
             } else if (lastBelow == i-1) {
-                if (w.mAttrs.type == TYPE_WALLPAPER || w.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) {
+                if (w.mAttrs.type == TYPE_WALLPAPER) {
                     lastBelow = i;
                 }
             }
@@ -8734,8 +8702,6 @@
                     + displayContent.layoutNeeded + " dw=" + dw + " dh=" + dh);
         }
 
-        WindowStateAnimator universeBackground = null;
-
         mPolicy.beginLayoutLw(isDefaultDisplay, dw, dh, mRotation);
         if (isDefaultDisplay) {
             // Not needed on non-default displays.
@@ -8793,8 +8759,7 @@
                     || ((win.isConfigChanged() || win.setInsetsChanged()) &&
                             ((win.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 ||
                             (win.mHasSurface && win.mAppToken != null &&
-                            win.mAppToken.layoutConfigChanges)))
-                    || win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) {
+                            win.mAppToken.layoutConfigChanges)))) {
                 if (!win.mLayoutAttached) {
                     if (initial) {
                         //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
@@ -8818,16 +8783,6 @@
                     if (topAttached < 0) topAttached = i;
                 }
             }
-            if (win.mViewVisibility == View.VISIBLE
-                    && win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND
-                    && universeBackground == null) {
-                universeBackground = win.mWinAnimator;
-            }
-        }
-
-        if (mAnimator.mUniverseBackground  != universeBackground) {
-            mFocusMayChange = true;
-            mAnimator.mUniverseBackground = universeBackground;
         }
 
         boolean attachedBehindDream = false;
@@ -10370,11 +10325,6 @@
     }
 
     private WindowState computeFocusedWindowLocked() {
-        if (mAnimator.mUniverseBackground != null
-                && mAnimator.mUniverseBackground.mWin.canReceiveKeys()) {
-            return mAnimator.mUniverseBackground.mWin;
-        }
-
         final int displayCount = mDisplayContents.size();
         for (int i = 0; i < displayCount; i++) {
             final DisplayContent displayContent = mDisplayContents.valueAt(i);
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index c2d8004..8202880 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -85,10 +85,6 @@
     final Context mContext;
     final boolean mIsWallpaper;
 
-    // If this is a universe background window, this is the transformation
-    // it is applying to the rest of the universe.
-    final Transformation mUniverseTransform = new Transformation();
-
     // Currently running animation.
     boolean mAnimating;
     boolean mLocalAnimating;
@@ -1096,9 +1092,6 @@
             if (appTransformation != null) {
                 tmpMatrix.postConcat(appTransformation.getMatrix());
             }
-            if (mAnimator.mUniverseBackground != null) {
-                tmpMatrix.postConcat(mAnimator.mUniverseBackground.mUniverseTransform.getMatrix());
-            }
             if (screenAnimation) {
                 tmpMatrix.postConcat(screenRotationAnimation.getEnterTransformation().getMatrix());
             }
@@ -1164,9 +1157,6 @@
                         mHasClipRect = true;
                     }
                 }
-                if (mAnimator.mUniverseBackground != null) {
-                    mShownAlpha *= mAnimator.mUniverseBackground.mUniverseTransform.getAlpha();
-                }
                 if (screenAnimation) {
                     mShownAlpha *= screenRotationAnimation.getEnterTransformation().getAlpha();
                 }
@@ -1192,15 +1182,12 @@
                 TAG, "computeShownFrameLocked: " + this +
                 " not attached, mAlpha=" + mAlpha);
 
-        final boolean applyUniverseTransformation = (mAnimator.mUniverseBackground != null
-                && mWin.mAttrs.type != WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND
-                && mWin.mBaseLayer < mAnimator.mAboveUniverseLayer);
         MagnificationSpec spec = null;
         //TODO (multidisplay): Magnification is supported only for the default display.
         if (mService.mAccessibilityController != null && displayId == Display.DEFAULT_DISPLAY) {
             spec = mService.mAccessibilityController.getMagnificationSpecForWindowLocked(mWin);
         }
-        if (applyUniverseTransformation || spec != null) {
+        if (spec != null) {
             final Rect frame = mWin.mFrame;
             final float tmpFloats[] = mService.mTmpFloats;
             final Matrix tmpMatrix = mWin.mTmpMatrix;
@@ -1208,10 +1195,6 @@
             tmpMatrix.setScale(mWin.mGlobalScale, mWin.mGlobalScale);
             tmpMatrix.postTranslate(frame.left + mWin.mXOffset, frame.top + mWin.mYOffset);
 
-            if (applyUniverseTransformation) {
-                tmpMatrix.postConcat(mAnimator.mUniverseBackground.mUniverseTransform.getMatrix());
-            }
-
             if (spec != null && !spec.isNop()) {
                 tmpMatrix.postScale(spec.scale, spec.scale);
                 tmpMatrix.postTranslate(spec.offsetX, spec.offsetY);
@@ -1231,9 +1214,6 @@
             mWin.mShownFrame.set(x, y, x + w, y + h);
 
             mShownAlpha = mAlpha;
-            if (applyUniverseTransformation) {
-                mShownAlpha *= mAnimator.mUniverseBackground.mUniverseTransform.getAlpha();
-            }
         } else {
             mWin.mShownFrame.set(mWin.mFrame);
             if (mWin.mXOffset != 0 || mWin.mYOffset != 0) {
@@ -1301,17 +1281,9 @@
                     displayInfo.logicalHeight - w.mCompatFrame.top);
         } else if (w.mLayer >= mService.mSystemDecorLayer) {
             // Above the decor layer is easy, just use the entire window.
-            // Unless we have a universe background...  in which case all the
-            // windows need to be cropped by the screen, so they don't cover
-            // the universe background.
-            if (mAnimator.mUniverseBackground == null) {
-                w.mSystemDecorRect.set(0, 0, w.mCompatFrame.width(), w.mCompatFrame.height());
-            } else {
-                applyDecorRect(mService.mScreenRect);
-            }
-        } else if (w.mAttrs.type == WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND
-                || w.mDecorFrame.isEmpty()) {
-            // The universe background isn't cropped, nor windows without policy decor.
+            w.mSystemDecorRect.set(0, 0, w.mCompatFrame.width(), w.mCompatFrame.height());
+        } else if (w.mDecorFrame.isEmpty()) {
+            // Windows without policy decor aren't cropped.
             w.mSystemDecorRect.set(0, 0, w.mCompatFrame.width(), w.mCompatFrame.height());
         } else if (w.mAttrs.type == LayoutParams.TYPE_WALLPAPER && mAnimator.mAnimating) {
             // If we're animating, the wallpaper crop should only be updated at the end of the
@@ -1932,11 +1904,6 @@
             pw.print(prefix); pw.print("mSurfaceResized="); pw.print(mSurfaceResized);
                     pw.print(" mSurfaceDestroyDeferred="); pw.println(mSurfaceDestroyDeferred);
         }
-        if (mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND) {
-            pw.print(prefix); pw.print("mUniverseTransform=");
-                    mUniverseTransform.printShortString(pw);
-                    pw.println();
-        }
         if (mShownAlpha != 1 || mAlpha != 1 || mLastAlpha != 1) {
             pw.print(prefix); pw.print("mShownAlpha="); pw.print(mShownAlpha);
                     pw.print(" mAlpha="); pw.print(mAlpha);
diff --git a/services/usb/java/com/android/server/usb/UsbAlsaManager.java b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
index 01a044e..b508c89 100644
--- a/services/usb/java/com/android/server/usb/UsbAlsaManager.java
+++ b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
@@ -20,12 +20,15 @@
 import android.alsa.AlsaDevicesParser;
 import android.content.Context;
 import android.content.Intent;
+import android.content.res.Resources;
 import android.hardware.usb.UsbConstants;
 import android.hardware.usb.UsbDevice;
 import android.hardware.usb.UsbInterface;
 import android.media.AudioSystem;
 import android.media.IAudioService;
+import android.midi.MidiDeviceInfo;
 import android.os.FileObserver;
+import android.os.Bundle;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -73,6 +76,9 @@
 
     private UsbAudioDevice mSelectedAudioDevice = null;
 
+    // UsbMidiDevice for USB peripheral mode (gadget) device
+    private UsbMidiDevice mPeripheralMidiDevice = null;
+
     private final class AlsaDevice {
         public static final int TYPE_UNKNOWN = 0;
         public static final int TYPE_PLAYBACK = 1;
@@ -391,7 +397,17 @@
                 int device = mDevicesParser.getDefaultDeviceNum(addedCard);
                 AlsaDevice alsaDevice = waitForAlsaDevice(addedCard, device, AlsaDevice.TYPE_MIDI);
                 if (alsaDevice != null) {
-                    UsbMidiDevice usbMidiDevice = UsbMidiDevice.create(mContext, usbDevice,
+                    Bundle properties = new Bundle();
+                    properties.putString(MidiDeviceInfo.PROPERTY_MANUFACTURER,
+                            usbDevice.getManufacturerName());
+                    properties.putString(MidiDeviceInfo.PROPERTY_MODEL, usbDevice.getProductName());
+                    properties.putString(MidiDeviceInfo.PROPERTY_SERIAL_NUMBER,
+                            usbDevice.getSerialNumber());
+                    properties.putInt(MidiDeviceInfo.PROPERTY_ALSA_CARD, alsaDevice.mCard);
+                    properties.putInt(MidiDeviceInfo.PROPERTY_ALSA_DEVICE, alsaDevice.mDevice);
+                    properties.putParcelable(MidiDeviceInfo.PROPERTY_USB_DEVICE, usbDevice);
+
+                    UsbMidiDevice usbMidiDevice = UsbMidiDevice.create(mContext, properties,
                             alsaDevice.mCard, alsaDevice.mDevice);
                     if (usbMidiDevice != null) {
                         mMidiDevices.put(usbDevice, usbMidiDevice);
@@ -410,17 +426,16 @@
         if (audioDevice != null) {
             if (audioDevice.mHasPlayback || audioDevice.mHasPlayback) {
                 notifyDeviceState(audioDevice, false);
+                mSelectedAudioDevice = null;
+
+                // if there any external devices left, select one of them
+                selectDefaultDevice();
             }
         }
         UsbMidiDevice usbMidiDevice = mMidiDevices.remove(usbDevice);
         if (usbMidiDevice != null) {
             IoUtils.closeQuietly(usbMidiDevice);
         }
-
-        mSelectedAudioDevice = null;
-
-        // if there any external devices left, select one of them
-        selectDefaultDevice();
     }
 
    /* package */ void setAccessoryAudioState(boolean enabled, int card, int device) {
@@ -437,6 +452,23 @@
         }
     }
 
+   /* package */ void setPeripheralMidiState(boolean enabled, int card, int device) {
+        if (enabled) {
+            Bundle properties = new Bundle();
+            Resources r = mContext.getResources();
+            properties.putString(MidiDeviceInfo.PROPERTY_MANUFACTURER, r.getString(
+                    com.android.internal.R.string.usb_midi_peripheral_manufacturer_name));
+            properties.putString(MidiDeviceInfo.PROPERTY_MODEL, r.getString(
+                    com.android.internal.R.string.usb_midi_peripheral_model_name));
+            properties.putInt(MidiDeviceInfo.PROPERTY_ALSA_CARD, card);
+            properties.putInt(MidiDeviceInfo.PROPERTY_ALSA_DEVICE, device);
+            mPeripheralMidiDevice = UsbMidiDevice.create(mContext, properties, card, device);
+        } else if (mPeripheralMidiDevice != null) {
+            IoUtils.closeQuietly(mPeripheralMidiDevice);
+            mPeripheralMidiDevice = null;
+        }
+   }
+
     //
     // Devices List
     //
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 1426551..2fb6dbf 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -31,6 +31,7 @@
 import android.hardware.usb.UsbAccessory;
 import android.hardware.usb.UsbManager;
 import android.media.AudioManager;
+import android.midi.MidiDeviceInfo;
 import android.os.FileUtils;
 import android.os.Handler;
 import android.os.Looper;
@@ -85,6 +86,8 @@
             "/sys/class/android_usb/android0/f_rndis/ethaddr";
     private static final String AUDIO_SOURCE_PCM_PATH =
             "/sys/class/android_usb/android0/f_audio_source/pcm";
+    private static final String MIDI_ALSA_PATH =
+            "/sys/class/android_usb/android0/f_midi/alsa";
 
     private static final int MSG_UPDATE_STATE = 0;
     private static final int MSG_ENABLE_ADB = 1;
@@ -124,6 +127,7 @@
     private boolean mUseUsbNotification;
     private boolean mAdbEnabled;
     private boolean mAudioSourceEnabled;
+    private boolean mMidiEnabled;
     private Map<String, List<Pair<String, String>>> mOemModeMap;
     private String[] mAccessoryStrings;
     private UsbDebuggingManager mDebuggingManager;
@@ -618,6 +622,31 @@
             }
         }
 
+        private void updateMidiFunction() {
+            boolean enabled = containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_MIDI);
+            if (enabled != mMidiEnabled) {
+                int card = -1;
+                int device = -1;
+
+                if (enabled) {
+                    Scanner scanner = null;
+                    try {
+                        scanner = new Scanner(new File(MIDI_ALSA_PATH));
+                        card = scanner.nextInt();
+                        device = scanner.nextInt();
+                    } catch (FileNotFoundException e) {
+                        Slog.e(TAG, "could not open MIDI PCM file", e);
+                    } finally {
+                        if (scanner != null) {
+                            scanner.close();
+                        }
+                    }
+                }
+                mUsbAlsaManager.setPeripheralMidiState(enabled, card, device);
+                mMidiEnabled = enabled;
+            }
+        }
+
         @Override
         public void handleMessage(Message msg) {
             switch (msg.what) {
@@ -636,6 +665,7 @@
                     if (mBootCompleted) {
                         updateUsbState();
                         updateAudioSourceFunction();
+                        updateMidiFunction();
                     }
                     break;
                 case MSG_ENABLE_ADB:
@@ -651,6 +681,7 @@
                     updateAdbNotification();
                     updateUsbState();
                     updateAudioSourceFunction();
+                    updateMidiFunction();
                     break;
                 case MSG_BOOT_COMPLETED:
                     mBootCompleted = true;
diff --git a/services/usb/java/com/android/server/usb/UsbMidiDevice.java b/services/usb/java/com/android/server/usb/UsbMidiDevice.java
index 01b2df9..8d44905 100644
--- a/services/usb/java/com/android/server/usb/UsbMidiDevice.java
+++ b/services/usb/java/com/android/server/usb/UsbMidiDevice.java
@@ -17,13 +17,12 @@
 package com.android.server.usb;
 
 import android.content.Context;
-import android.hardware.usb.UsbDevice;
 import android.midi.MidiDeviceInfo;
 import android.midi.MidiDeviceServer;
 import android.midi.MidiManager;
+import android.midi.MidiPort;
 import android.midi.MidiReceiver;
 import android.midi.MidiSender;
-import android.midi.MidiUtils;
 import android.os.Bundle;
 import android.system.ErrnoException;
 import android.system.Os;
@@ -45,10 +44,12 @@
 
     // for polling multiple FileDescriptors for MIDI events
     private final StructPollfd[] mPollFDs;
+    // streams for reading from ALSA driver
     private final FileInputStream[] mInputStreams;
+    // streams for writing to ALSA driver
     private final FileOutputStream[] mOutputStreams;
 
-    public static UsbMidiDevice create(Context context, UsbDevice usbDevice, int card, int device) {
+    public static UsbMidiDevice create(Context context, Bundle properties, int card, int device) {
         MidiManager midiManager = (MidiManager)context.getSystemService(Context.MIDI_SERVICE);
         if (midiManager == null) {
             Log.e(TAG, "No MidiManager in UsbMidiDevice.create()");
@@ -69,13 +70,6 @@
             return null;
         }
 
-        Bundle properties = new Bundle();
-        properties.putString(MidiDeviceInfo.PROPERTY_MANUFACTURER, usbDevice.getManufacturerName());
-        properties.putString(MidiDeviceInfo.PROPERTY_MODEL, usbDevice.getProductName());
-        properties.putString(MidiDeviceInfo.PROPERTY_SERIAL_NUMBER, usbDevice.getSerialNumber());
-        properties.putInt(MidiDeviceInfo.PROPERTY_ALSA_CARD, card);
-        properties.putInt(MidiDeviceInfo.PROPERTY_ALSA_DEVICE, device);
-        properties.putParcelable(MidiDeviceInfo.PROPERTY_USB_DEVICE, usbDevice);
         MidiDeviceServer server = midiManager.createDeviceServer(subDevices, subDevices, properties,
                 false, MidiDeviceInfo.TYPE_USB);
         if (server == null) {
@@ -131,7 +125,7 @@
         new Thread() {
             @Override
             public void run() {
-                byte[] buffer = new byte[3];
+                byte[] buffer = new byte[MidiPort.MAX_PACKET_DATA_SIZE];
                 try {
                     boolean done = false;
                     while (!done) {
@@ -141,7 +135,8 @@
                             if ((pfd.revents & OsConstants.POLLIN) != 0) {
                                 // clear readable flag
                                 pfd.revents = 0;
-                                int count = readMessage(buffer, index);
+
+                                int count = mInputStreams[index].read(buffer);
                                 mOutputPortReceivers[index].onPost(buffer, 0, count,
                                         System.nanoTime());
                             } else if ((pfd.revents & (OsConstants.POLLERR
@@ -150,7 +145,7 @@
                             }
                         }
 
-                        // poll if none are readable
+                        // wait until we have a readable port
                         Os.poll(mPollFDs, -1 /* infinite timeout */);
                      }
                 } catch (IOException e) {
@@ -174,26 +169,6 @@
         }
     }
 
-    private int readMessage(byte[] buffer, int index) throws IOException {
-        FileInputStream inputStream = mInputStreams[index];
-
-        if (inputStream.read(buffer, 0, 1) != 1) {
-            Log.e(TAG, "could not read command byte");
-            return -1;
-        }
-        int dataSize = MidiUtils.getMessageDataSize(buffer[0]);
-        if (dataSize < 0) {
-            return -1;
-        }
-        if (dataSize > 0) {
-            if (inputStream.read(buffer, 1, dataSize) != dataSize) {
-                Log.e(TAG, "could not read command data");
-                return -1;
-            }
-        }
-        return dataSize + 1;
-    }
-
     private static native int nativeGetSubdeviceCount(int card, int device);
     private static native FileDescriptor[] nativeOpen(int card, int device, int subdeviceCount);
 }
diff --git a/telecomm/java/android/telecom/RemoteConnectionService.java b/telecomm/java/android/telecom/RemoteConnectionService.java
index 073dcd5f..43a92cb 100644
--- a/telecomm/java/android/telecom/RemoteConnectionService.java
+++ b/telecomm/java/android/telecom/RemoteConnectionService.java
@@ -235,8 +235,12 @@
 
         @Override
         public void setVideoProvider(String callId, IVideoProvider videoProvider) {
+            RemoteConnection.VideoProvider remoteVideoProvider = null;
+            if (videoProvider != null) {
+                remoteVideoProvider = new RemoteConnection.VideoProvider(videoProvider);
+            }
             findConnectionForAction(callId, "setVideoProvider")
-                    .setVideoProvider(new RemoteConnection.VideoProvider(videoProvider));
+                    .setVideoProvider(remoteVideoProvider);
         }
 
         @Override
diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java
index adbe1d8..ca3c636 100644
--- a/telephony/java/android/telephony/SubscriptionInfo.java
+++ b/telephony/java/android/telephony/SubscriptionInfo.java
@@ -335,7 +335,7 @@
     public String toString() {
         return "{id=" + mId + ", iccId=" + mIccId + " simSlotIndex=" + mSimSlotIndex
                 + " displayName=" + mDisplayName + " carrierName=" + mCarrierName
-                + " nameSource=" + mNameSource + " iconTint=" + mIconTint + " number=" + mNumber
+                + " nameSource=" + mNameSource + " iconTint=" + mIconTint
                 + " dataRoaming=" + mDataRoaming + " iconBitmap=" + mIconBitmap + " mcc " + mMcc
                 + " mnc " + mMnc + "}";
     }
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index ace945d..339fc6d 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -640,13 +640,9 @@
      */
     /** {@hide} */
     public String getDeviceId(int slotId) {
-        // FIXME methods taking slot id should not use subscription, instead us Uicc directly
-        int[] subId = SubscriptionManager.getSubId(slotId);
-        if (subId == null || subId.length == 0) {
-            return null;
-        }
+        // FIXME this assumes phoneId == slotId
         try {
-            return getSubscriberInfo().getDeviceIdForSubscriber(subId[0]);
+            return getSubscriberInfo().getDeviceIdForPhone(slotId);
         } catch (RemoteException ex) {
             return null;
         } catch (NullPointerException ex) {
@@ -703,7 +699,11 @@
     public String getNai(int slotId) {
         int[] subId = SubscriptionManager.getSubId(slotId);
         try {
-            return getSubscriberInfo().getNaiForSubscriber(subId[0]);
+            String nai = getSubscriberInfo().getNaiForSubscriber(subId[0]);
+            if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                Rlog.v(TAG, "Nai = " + nai);
+            }
+            return nai;
         } catch (RemoteException ex) {
             return null;
         } catch (NullPointerException ex) {
diff --git a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
index eec5333..c91a59c 100644
--- a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
+++ b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
@@ -33,10 +33,10 @@
     String getNaiForSubscriber(int subId);
 
     /**
-     * Retrieves the unique device ID of a subId for the device, e.g., IMEI
+     * Retrieves the unique device ID of a phone for the device, e.g., IMEI
      * for GSM phones.
      */
-    String getDeviceIdForSubscriber(int subId);
+    String getDeviceIdForPhone(int phoneId);
 
     /**
      * Retrieves the IMEI.
diff --git a/telephony/java/com/android/internal/telephony/ISms.aidl b/telephony/java/com/android/internal/telephony/ISms.aidl
index 6fdf121..70ac268 100644
--- a/telephony/java/com/android/internal/telephony/ISms.aidl
+++ b/telephony/java/com/android/internal/telephony/ISms.aidl
@@ -453,10 +453,6 @@
      */
     void setPremiumSmsPermission(String packageName, int permission);
 
-    /**
-     * Set the SMS send permission for the specified package.
-     * Requires system permission.
-     */
      /**
      * Set the SMS send permission for the specified package.
      * Requires system permission.
@@ -483,6 +479,14 @@
      */
     boolean isImsSmsSupportedForSubscriber(int subId);
 
+    /**
+     * User needs to pick SIM for SMS if multiple SIMs present and if current subId passed in is not
+     * active/valid.
+     * @param subId current subId for sending SMS
+     * @return true if SIM for SMS sending needs to be chosen
+     */
+    boolean isSmsSimPickActivityNeeded(int subId);
+
     /*
      * get user prefered SMS subId
      * @return subId id
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java
index 0f51d00..62a03e1 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java
@@ -191,12 +191,6 @@
     }
 
     @Override
-    public void setUniverseTransform(IBinder window, float alpha, float offx, float offy,
-            float dsdx, float dtdx, float dsdy, float dtdy) {
-        // pass for now.
-    }
-
-    @Override
     public IBinder asBinder() {
         // pass for now.
         return null;
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 5202cc3..52f2372 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -733,6 +733,31 @@
 
     /**
      * @hide
+     * Last time the system tried to roam and failed because of authentication failure or DHCP
+     * RENEW failure.
+     */
+    public long lastRoamingFailure;
+
+    /** @hide */
+    public static int ROAMING_FAILURE_IP_CONFIG = 1;
+    /** @hide */
+    public static int ROAMING_FAILURE_AUTH_FAILURE = 2;
+
+    /**
+     * @hide
+     * Initial amount of time this Wifi configuration gets blacklisted for network switching
+     * because of roaming failure
+     */
+    public long roamingFailureBlackListTimeMilli = 1000;
+
+    /**
+     * @hide
+     * Last roaming failure reason code
+     */
+    public int lastRoamingFailureReason;
+
+    /**
+     * @hide
      * Last time the system was disconnected to this configuration.
      */
     public long lastDisconnected;
@@ -1209,6 +1234,18 @@
                 sbuf.append( "sec");
             }
         }
+        if (this.lastRoamingFailure != 0) {
+            sbuf.append('\n');
+            long diff = now_ms - this.lastRoamingFailure;
+            if (diff <= 0) {
+                sbuf.append("lastRoamingFailure since <incorrect>");
+            } else {
+                sbuf.append("lastRoamingFailure: ").append(Long.toString(diff/1000));
+                sbuf.append( "sec");
+            }
+        }
+        sbuf.append("roamingFailureBlackListTimeMilli: ").
+                append(Long.toString(this.roamingFailureBlackListTimeMilli));
         sbuf.append('\n');
         if (this.linkedConfigurations != null) {
             for(String key : this.linkedConfigurations.keySet()) {
@@ -1595,6 +1632,9 @@
             lastConnected = source.lastConnected;
             lastDisconnected = source.lastDisconnected;
             lastConnectionFailure = source.lastConnectionFailure;
+            lastRoamingFailure = source.lastRoamingFailure;
+            lastRoamingFailureReason = source.lastRoamingFailureReason;
+            roamingFailureBlackListTimeMilli = source.roamingFailureBlackListTimeMilli;
             numConnectionFailures = source.numConnectionFailures;
             numIpConfigFailures = source.numIpConfigFailures;
             numAuthFailures = source.numAuthFailures;
@@ -1667,6 +1707,9 @@
         dest.writeString(lastUpdateName);
         dest.writeLong(blackListTimestamp);
         dest.writeLong(lastConnectionFailure);
+        dest.writeLong(lastRoamingFailure);
+        dest.writeInt(lastRoamingFailureReason);
+        dest.writeLong(roamingFailureBlackListTimeMilli);
         dest.writeInt(numConnectionFailures);
         dest.writeInt(numIpConfigFailures);
         dest.writeInt(numAuthFailures);
@@ -1732,6 +1775,9 @@
                 config.lastUpdateName = in.readString();
                 config.blackListTimestamp = in.readLong();
                 config.lastConnectionFailure = in.readLong();
+                config.lastRoamingFailure = in.readLong();
+                config.lastRoamingFailureReason = in.readInt();
+                config.roamingFailureBlackListTimeMilli = in.readLong();
                 config.numConnectionFailures = in.readInt();
                 config.numIpConfigFailures = in.readInt();
                 config.numAuthFailures = in.readInt();