Merge "UsbAlsaManager: Don't reselect current USB audio device on all USB disconnects"
diff --git a/api/current.txt b/api/current.txt
index e6d088d..9c26faa 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -482,7 +482,7 @@
     field public static final int dialogTitle = 16843250; // 0x10101f2
     field public static final int digits = 16843110; // 0x1010166
     field public static final int direction = 16843217; // 0x10101d1
-    field public static final int directionDescriptions = 16843681; // 0x10103a1
+    field public static final deprecated int directionDescriptions = 16843681; // 0x10103a1
     field public static final int directionPriority = 16843218; // 0x10101d2
     field public static final int disableDependentsState = 16843249; // 0x10101f1
     field public static final int disabledAlpha = 16842803; // 0x1010033
@@ -1200,7 +1200,7 @@
     field public static final int tag = 16842961; // 0x10100d1
     field public static final int targetActivity = 16843266; // 0x1010202
     field public static final int targetClass = 16842799; // 0x101002f
-    field public static final int targetDescriptions = 16843680; // 0x10103a0
+    field public static final deprecated int targetDescriptions = 16843680; // 0x10103a0
     field public static final int targetId = 16843740; // 0x10103dc
     field public static final int targetName = 16843853; // 0x101044d
     field public static final int targetPackage = 16842785; // 0x1010021
@@ -12616,6 +12616,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 {
@@ -12756,7 +12758,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 +12770,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
@@ -16205,6 +16217,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 +16247,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 +21789,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 {
@@ -24813,6 +24833,8 @@
     field public static final java.lang.String EMAIL = "email";
     field public static final java.lang.String EMAIL_ISPRIMARY = "email_isprimary";
     field public static final java.lang.String EMAIL_TYPE = "email_type";
+    field public static final java.lang.String EXTRA_ACCOUNT = "android.provider.extra.ACCOUNT";
+    field public static final java.lang.String EXTRA_DATA_SET = "android.provider.extra.DATA_SET";
     field public static final java.lang.String FULL_MODE = "full_mode";
     field public static final java.lang.String IM_HANDLE = "im_handle";
     field public static final java.lang.String IM_ISPRIMARY = "im_isprimary";
@@ -26139,6 +26161,8 @@
   }
 
   public static final class Telephony.Threads implements android.provider.Telephony.ThreadsColumns {
+    method public static long getOrCreateThreadId(android.content.Context, java.lang.String);
+    method public static long getOrCreateThreadId(android.content.Context, java.util.Set<java.lang.String>);
     field public static final int BROADCAST_THREAD = 1; // 0x1
     field public static final int COMMON_THREAD = 0; // 0x0
     field public static final android.net.Uri CONTENT_URI;
@@ -27344,6 +27368,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);
@@ -34080,6 +34105,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);
@@ -34347,6 +34373,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 e6ddb4f..62932fd 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -554,7 +554,7 @@
     field public static final int dialogTitle = 16843250; // 0x10101f2
     field public static final int digits = 16843110; // 0x1010166
     field public static final int direction = 16843217; // 0x10101d1
-    field public static final int directionDescriptions = 16843681; // 0x10103a1
+    field public static final deprecated int directionDescriptions = 16843681; // 0x10103a1
     field public static final int directionPriority = 16843218; // 0x10101d2
     field public static final int disableDependentsState = 16843249; // 0x10101f1
     field public static final int disabledAlpha = 16842803; // 0x1010033
@@ -1276,7 +1276,7 @@
     field public static final int tag = 16842961; // 0x10100d1
     field public static final int targetActivity = 16843266; // 0x1010202
     field public static final int targetClass = 16842799; // 0x101002f
-    field public static final int targetDescriptions = 16843680; // 0x10103a0
+    field public static final deprecated int targetDescriptions = 16843680; // 0x10103a0
     field public static final int targetId = 16843740; // 0x10103dc
     field public static final int targetName = 16843853; // 0x101044d
     field public static final int targetPackage = 16842785; // 0x1010021
@@ -12884,6 +12884,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 {
@@ -13024,7 +13026,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 +13038,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
@@ -17255,6 +17267,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 +17297,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 +23368,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 {
@@ -26402,6 +26422,8 @@
     field public static final java.lang.String EMAIL = "email";
     field public static final java.lang.String EMAIL_ISPRIMARY = "email_isprimary";
     field public static final java.lang.String EMAIL_TYPE = "email_type";
+    field public static final java.lang.String EXTRA_ACCOUNT = "android.provider.extra.ACCOUNT";
+    field public static final java.lang.String EXTRA_DATA_SET = "android.provider.extra.DATA_SET";
     field public static final java.lang.String FULL_MODE = "full_mode";
     field public static final java.lang.String IM_HANDLE = "im_handle";
     field public static final java.lang.String IM_ISPRIMARY = "im_isprimary";
@@ -27728,6 +27750,8 @@
   }
 
   public static final class Telephony.Threads implements android.provider.Telephony.ThreadsColumns {
+    method public static long getOrCreateThreadId(android.content.Context, java.lang.String);
+    method public static long getOrCreateThreadId(android.content.Context, java.util.Set<java.lang.String>);
     field public static final int BROADCAST_THREAD = 1; // 0x1
     field public static final int COMMON_THREAD = 0; // 0x0
     field public static final android.net.Uri CONTENT_URI;
@@ -28933,6 +28957,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);
@@ -30677,6 +30702,7 @@
     method public android.telecom.PhoneAccountHandle getConnectionManager();
     method public android.telecom.PhoneAccountHandle getDefaultOutgoingPhoneAccount(java.lang.String);
     method public android.content.ComponentName getDefaultPhoneApp();
+    method public java.lang.String getLine1Number(android.telecom.PhoneAccountHandle);
     method public android.telecom.PhoneAccount getPhoneAccount(android.telecom.PhoneAccountHandle);
     method public java.util.List<android.telecom.PhoneAccountHandle> getPhoneAccountsForPackage();
     method public java.util.List<android.telecom.PhoneAccountHandle> getPhoneAccountsSupportingScheme(java.lang.String);
@@ -36278,6 +36304,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);
@@ -36545,6 +36572,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/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 23b05c4..a09bca1 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -2373,8 +2373,10 @@
         if (mDefaultKeyMode == DEFAULT_KEYS_DISABLE) {
             return false;
         } else if (mDefaultKeyMode == DEFAULT_KEYS_SHORTCUT) {
-            if (getWindow().performPanelShortcut(Window.FEATURE_OPTIONS_PANEL,
-                    keyCode, event, Menu.FLAG_ALWAYS_PERFORM_CLOSE)) {
+            Window w = getWindow();
+            if (w.hasFeature(Window.FEATURE_OPTIONS_PANEL) &&
+                    w.performPanelShortcut(Window.FEATURE_OPTIONS_PANEL, keyCode, event,
+                            Menu.FLAG_ALWAYS_PERFORM_CLOSE)) {
                 return true;
             }
             return false;
@@ -2939,7 +2941,8 @@
      * time it needs to be displayed.
      */
     public void invalidateOptionsMenu() {
-        if (mActionBar == null || !mActionBar.invalidateOptionsMenu()) {
+        if (mWindow.hasFeature(Window.FEATURE_OPTIONS_PANEL) &&
+                (mActionBar == null || !mActionBar.invalidateOptionsMenu())) {
             mWindow.invalidatePanelMenu(Window.FEATURE_OPTIONS_PANEL);
         }
     }
@@ -3151,7 +3154,8 @@
      * open, this method does nothing.
      */
     public void openOptionsMenu() {
-        if (mActionBar == null || !mActionBar.openOptionsMenu()) {
+        if (mWindow.hasFeature(Window.FEATURE_OPTIONS_PANEL) &&
+                (mActionBar == null || !mActionBar.openOptionsMenu())) {
             mWindow.openPanel(Window.FEATURE_OPTIONS_PANEL, null);
         }
     }
@@ -3161,7 +3165,9 @@
      * closed, this method does nothing.
      */
     public void closeOptionsMenu() {
-        mWindow.closePanel(Window.FEATURE_OPTIONS_PANEL);
+        if (mWindow.hasFeature(Window.FEATURE_OPTIONS_PANEL)) {
+            mWindow.closePanel(Window.FEATURE_OPTIONS_PANEL);
+        }
     }
 
     /**
@@ -3220,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);
+        }
     }
 
     /**
@@ -4607,7 +4615,7 @@
         if (Looper.myLooper() != mMainThread.getLooper()) {
             throw new IllegalStateException("Must be called from main thread");
         }
-        mMainThread.requestRelaunchActivity(mToken, null, null, 0, false, null, false);
+        mMainThread.requestRelaunchActivity(mToken, null, null, 0, false, null, null, false);
     }
 
     /**
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index ea37b89..de3c95c 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -293,6 +293,7 @@
         boolean hideForNow;
         Configuration newConfig;
         Configuration createdConfig;
+        Configuration overrideConfig;
         ActivityClientRecord nextIdle;
 
         ProfilerInfo profilerInfo;
@@ -615,12 +616,13 @@
 
         // we use token to identify this activity without having to send the
         // activity itself back to the activity manager. (matters more with ipc)
+        @Override
         public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
-                ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
-                String referrer, IVoiceInteractor voiceInteractor, int procState, Bundle state,
-                PersistableBundle persistentState, List<ResultInfo> pendingResults,
-                List<ReferrerIntent> pendingNewIntents, boolean notResumed, boolean isForward,
-                ProfilerInfo profilerInfo) {
+                ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
+                CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
+                int procState, Bundle state, PersistableBundle persistentState,
+                List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
+                boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {
 
             updateProcessState(procState, false);
 
@@ -644,16 +646,19 @@
 
             r.profilerInfo = profilerInfo;
 
+            r.overrideConfig = overrideConfig;
             updatePendingConfiguration(curConfig);
 
             sendMessage(H.LAUNCH_ACTIVITY, r);
         }
 
+        @Override
         public final void scheduleRelaunchActivity(IBinder token,
                 List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
-                int configChanges, boolean notResumed, Configuration config) {
+                int configChanges, boolean notResumed, Configuration config,
+                Configuration overrideConfig) {
             requestRelaunchActivity(token, pendingResults, pendingNewIntents,
-                    configChanges, notResumed, config, true);
+                    configChanges, notResumed, config, overrideConfig, true);
         }
 
         public final void scheduleNewIntent(List<ReferrerIntent> intents, IBinder token) {
@@ -887,6 +892,7 @@
             sendMessage(H.LOW_MEMORY, null);
         }
 
+        @Override
         public void scheduleActivityConfigurationChanged(IBinder token) {
             sendMessage(H.ACTIVITY_CONFIGURATION_CHANGED, token);
         }
@@ -1668,7 +1674,7 @@
             String[] libDirs, int displayId, Configuration overrideConfiguration,
             LoadedApk pkgInfo) {
         return mResourcesManager.getTopLevelResources(resDir, splitResDirs, overlayDirs, libDirs,
-                displayId, overrideConfiguration, pkgInfo.getCompatibilityInfo(), null);
+                displayId, overrideConfiguration, pkgInfo.getCompatibilityInfo());
     }
 
     final Handler getHandler() {
@@ -2353,7 +2359,8 @@
 
     private Context createBaseContextForActivity(ActivityClientRecord r,
             final Activity activity) {
-        ContextImpl appContext = ContextImpl.createActivityContext(this, r.packageInfo, r.token);
+        ContextImpl appContext =
+                ContextImpl.createActivityContext(this, r.packageInfo, r.overrideConfig);
         appContext.setOuterContext(activity);
         Context baseContext = appContext;
 
@@ -3561,7 +3568,7 @@
 
             // request all activities to relaunch for the changes to take place
             for (Map.Entry<IBinder, ActivityClientRecord> entry : mActivities.entrySet()) {
-                requestRelaunchActivity(entry.getKey(), null, null, 0, false, null, false);
+                requestRelaunchActivity(entry.getKey(), null, null, 0, false, null, null, false);
             }
         }
     }
@@ -3805,7 +3812,7 @@
     public final void requestRelaunchActivity(IBinder token,
             List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
             int configChanges, boolean notResumed, Configuration config,
-            boolean fromServer) {
+            Configuration overrideConfig, boolean fromServer) {
         ActivityClientRecord target = null;
 
         synchronized (mResourcesManager) {
@@ -3854,6 +3861,9 @@
             if (config != null) {
                 target.createdConfig = config;
             }
+            if (overrideConfig != null) {
+                target.overrideConfig = overrideConfig;
+            }
             target.pendingConfigChanges |= configChanges;
         }
     }
@@ -3966,6 +3976,7 @@
             }
         }
         r.startsNotResumed = tmp.startsNotResumed;
+        r.overrideConfig = tmp.overrideConfig;
 
         handleLaunchActivity(r, currentIntent);
     }
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/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index eb3ddb2..349b66d 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -140,6 +140,10 @@
             int ident = data.readInt();
             ActivityInfo info = ActivityInfo.CREATOR.createFromParcel(data);
             Configuration curConfig = Configuration.CREATOR.createFromParcel(data);
+            Configuration overrideConfig = null;
+            if (data.readInt() != 0) {
+                overrideConfig = Configuration.CREATOR.createFromParcel(data);
+            }
             CompatibilityInfo compatInfo = CompatibilityInfo.CREATOR.createFromParcel(data);
             String referrer = data.readString();
             IVoiceInteractor voiceInteractor = IVoiceInteractor.Stub.asInterface(
@@ -153,8 +157,8 @@
             boolean isForward = data.readInt() != 0;
             ProfilerInfo profilerInfo = data.readInt() != 0
                     ? ProfilerInfo.CREATOR.createFromParcel(data) : null;
-            scheduleLaunchActivity(intent, b, ident, info, curConfig, compatInfo, referrer,
-                    voiceInteractor, procState, state, persistentState, ri, pi,
+            scheduleLaunchActivity(intent, b, ident, info, curConfig, overrideConfig, compatInfo,
+                    referrer, voiceInteractor, procState, state, persistentState, ri, pi,
                     notResumed, isForward, profilerInfo);
             return true;
         }
@@ -167,14 +171,15 @@
             List<ReferrerIntent> pi = data.createTypedArrayList(ReferrerIntent.CREATOR);
             int configChanges = data.readInt();
             boolean notResumed = data.readInt() != 0;
-            Configuration config = null;
+            Configuration config = Configuration.CREATOR.createFromParcel(data);
+            Configuration overrideConfig = null;
             if (data.readInt() != 0) {
-                config = Configuration.CREATOR.createFromParcel(data);
+                overrideConfig = Configuration.CREATOR.createFromParcel(data);
             }
-            scheduleRelaunchActivity(b, ri, pi, configChanges, notResumed, config);
+            scheduleRelaunchActivity(b, ri, pi, configChanges, notResumed, config, overrideConfig);
             return true;
         }
-        
+
         case SCHEDULE_NEW_INTENT_TRANSACTION:
         {
             data.enforceInterface(IApplicationThread.descriptor);
@@ -775,11 +780,11 @@
     }
 
     public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
-            ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
-            String referrer, IVoiceInteractor voiceInteractor, int procState, Bundle state,
-            PersistableBundle persistentState, List<ResultInfo> pendingResults,
-            List<ReferrerIntent> pendingNewIntents, boolean notResumed, boolean isForward,
-            ProfilerInfo profilerInfo) throws RemoteException {
+            ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
+            CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
+            int procState, Bundle state, PersistableBundle persistentState,
+            List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
+            boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) throws RemoteException {
         Parcel data = Parcel.obtain();
         data.writeInterfaceToken(IApplicationThread.descriptor);
         intent.writeToParcel(data, 0);
@@ -787,6 +792,12 @@
         data.writeInt(ident);
         info.writeToParcel(data, 0);
         curConfig.writeToParcel(data, 0);
+        if (overrideConfig != null) {
+            data.writeInt(1);
+            overrideConfig.writeToParcel(data, 0);
+        } else {
+            data.writeInt(0);
+        }
         compatInfo.writeToParcel(data, 0);
         data.writeString(referrer);
         data.writeStrongBinder(voiceInteractor != null ? voiceInteractor.asBinder() : null);
@@ -810,8 +821,8 @@
 
     public final void scheduleRelaunchActivity(IBinder token,
             List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
-            int configChanges, boolean notResumed, Configuration config)
-            throws RemoteException {
+            int configChanges, boolean notResumed, Configuration config,
+            Configuration overrideConfig) throws RemoteException {
         Parcel data = Parcel.obtain();
         data.writeInterfaceToken(IApplicationThread.descriptor);
         data.writeStrongBinder(token);
@@ -819,9 +830,10 @@
         data.writeTypedList(pendingNewIntents);
         data.writeInt(configChanges);
         data.writeInt(notResumed ? 1 : 0);
-        if (config != null) {
+        config.writeToParcel(data, 0);
+        if (overrideConfig != null) {
             data.writeInt(1);
-            config.writeToParcel(data, 0);
+            overrideConfig.writeToParcel(data, 0);
         } else {
             data.writeInt(0);
         }
@@ -1112,8 +1124,7 @@
         data.recycle();
     }
 
-    public final void scheduleActivityConfigurationChanged(
-            IBinder token) throws RemoteException {
+    public final void scheduleActivityConfigurationChanged(IBinder token) throws RemoteException {
         Parcel data = Parcel.obtain();
         data.writeInterfaceToken(IApplicationThread.descriptor);
         data.writeStrongBinder(token);
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index e9df8c6..39caf0b 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -2264,11 +2264,10 @@
     }
 
     static ContextImpl createActivityContext(ActivityThread mainThread,
-            LoadedApk packageInfo, IBinder activityToken) {
+            LoadedApk packageInfo, Configuration overrideConfiguration) {
         if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
-        if (activityToken == null) throw new IllegalArgumentException("activityInfo");
-        return new ContextImpl(null, mainThread,
-                packageInfo, activityToken, null, false, null, null);
+        return new ContextImpl(null, mainThread, packageInfo, null, null, false, null,
+                overrideConfiguration);
     }
 
     private ContextImpl(ContextImpl container, ActivityThread mainThread,
@@ -2303,15 +2302,14 @@
 
         Resources resources = packageInfo.getResources(mainThread);
         if (resources != null) {
-            if (activityToken != null
-                    || displayId != Display.DEFAULT_DISPLAY
+            if (displayId != Display.DEFAULT_DISPLAY
                     || overrideConfiguration != null
                     || (compatInfo != null && compatInfo.applicationScale
                             != resources.getCompatibilityInfo().applicationScale)) {
                 resources = mResourcesManager.getTopLevelResources(packageInfo.getResDir(),
                         packageInfo.getSplitResDirs(), packageInfo.getOverlayDirs(),
                         packageInfo.getApplicationInfo().sharedLibraryFiles, displayId,
-                        overrideConfiguration, compatInfo, activityToken);
+                        overrideConfiguration, compatInfo);
             }
         }
         mResources = resources;
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
index 12d4513..067073a 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -910,21 +910,27 @@
      * @see Activity#openOptionsMenu()
      */
     public void openOptionsMenu() {
-        mWindow.openPanel(Window.FEATURE_OPTIONS_PANEL, null);
+        if (mWindow.hasFeature(Window.FEATURE_OPTIONS_PANEL)) {
+            mWindow.openPanel(Window.FEATURE_OPTIONS_PANEL, null);
+        }
     }
-    
+
     /**
      * @see Activity#closeOptionsMenu()
      */
     public void closeOptionsMenu() {
-        mWindow.closePanel(Window.FEATURE_OPTIONS_PANEL);
+        if (mWindow.hasFeature(Window.FEATURE_OPTIONS_PANEL)) {
+            mWindow.closePanel(Window.FEATURE_OPTIONS_PANEL);
+        }
     }
 
     /**
      * @see Activity#invalidateOptionsMenu()
      */
     public void invalidateOptionsMenu() {
-        mWindow.invalidatePanelMenu(Window.FEATURE_OPTIONS_PANEL);
+        if (mWindow.hasFeature(Window.FEATURE_OPTIONS_PANEL)) {
+            mWindow.invalidatePanelMenu(Window.FEATURE_OPTIONS_PANEL);
+        }
     }
 
     /**
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/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index 8bf8cd7..f2c912e 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -33,7 +33,6 @@
 import android.os.RemoteException;
 import android.os.IBinder;
 import android.os.IInterface;
-import android.service.voice.IVoiceInteractionSession;
 import com.android.internal.app.IVoiceInteractor;
 import com.android.internal.content.ReferrerIntent;
 
@@ -59,14 +58,14 @@
             throws RemoteException;
     void scheduleSendResult(IBinder token, List<ResultInfo> results) throws RemoteException;
     void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
-            ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
-            String referrer, IVoiceInteractor voiceInteractor, int procState, Bundle state,
-            PersistableBundle persistentState, List<ResultInfo> pendingResults,
-            List<ReferrerIntent> pendingNewIntents, boolean notResumed, boolean isForward,
-            ProfilerInfo profilerInfo) throws RemoteException;
+            ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
+            CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
+            int procState, Bundle state, PersistableBundle persistentState,
+            List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
+            boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) throws RemoteException;
     void scheduleRelaunchActivity(IBinder token, List<ResultInfo> pendingResults,
-            List<ReferrerIntent> pendingNewIntents, int configChanges,
-            boolean notResumed, Configuration config) throws RemoteException;
+            List<ReferrerIntent> pendingNewIntents, int configChanges, boolean notResumed,
+            Configuration config, Configuration overrideConfig) throws RemoteException;
     void scheduleNewIntent(List<ReferrerIntent> intent, IBinder token) throws RemoteException;
     void scheduleDestroyActivity(IBinder token, boolean finished,
             int configChanges) throws RemoteException;
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index 1691d8e..fac40b2 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -25,7 +25,6 @@
 import android.content.res.Resources;
 import android.content.res.ResourcesKey;
 import android.hardware.display.DisplayManagerGlobal;
-import android.os.IBinder;
 import android.util.ArrayMap;
 import android.util.DisplayMetrics;
 import android.util.Slog;
@@ -38,8 +37,7 @@
 /** @hide */
 public class ResourcesManager {
     static final String TAG = "ResourcesManager";
-    static final boolean DEBUG_CACHE = false;
-    static final boolean DEBUG_STATS = true;
+    private static final boolean DEBUG = false;
 
     private static ResourcesManager sResourcesManager;
     final ArrayMap<ResourcesKey, WeakReference<Resources> > mActiveResources
@@ -51,7 +49,6 @@
     CompatibilityInfo mResCompatibilityInfo;
 
     Configuration mResConfiguration;
-    final Configuration mTmpConfig = new Configuration();
 
     public static ResourcesManager getInstance() {
         synchronized (ResourcesManager.class) {
@@ -144,30 +141,32 @@
      * Creates the top level Resources for applications with the given compatibility info.
      *
      * @param resDir the resource directory.
+     * @param splitResDirs split resource directories.
      * @param overlayDirs the resource overlay directories.
      * @param libDirs the shared library resource dirs this app references.
-     * @param compatInfo the compability info. Must not be null.
-     * @param token the application token for determining stack bounds.
+     * @param displayId display Id.
+     * @param overrideConfiguration override configurations.
+     * @param compatInfo the compatibility info. Must not be null.
      */
     public Resources getTopLevelResources(String resDir, String[] splitResDirs,
             String[] overlayDirs, String[] libDirs, int displayId,
-            Configuration overrideConfiguration, CompatibilityInfo compatInfo, IBinder token) {
+            Configuration overrideConfiguration, CompatibilityInfo compatInfo) {
         final float scale = compatInfo.applicationScale;
-        ResourcesKey key = new ResourcesKey(resDir, displayId, overrideConfiguration, scale, token);
+        Configuration overrideConfigCopy = (overrideConfiguration != null)
+                ? new Configuration(overrideConfiguration) : null;
+        ResourcesKey key = new ResourcesKey(resDir, displayId, overrideConfigCopy, scale);
         Resources r;
         synchronized (this) {
             // Resources is app scale dependent.
-            if (false) {
-                Slog.w(TAG, "getTopLevelResources: " + resDir + " / " + scale);
-            }
+            if (DEBUG) Slog.w(TAG, "getTopLevelResources: " + resDir + " / " + scale);
+
             WeakReference<Resources> wr = mActiveResources.get(key);
             r = wr != null ? wr.get() : null;
             //if (r != null) Slog.i(TAG, "isUpToDate " + resDir + ": " + r.getAssets().isUpToDate());
             if (r != null && r.getAssets().isUpToDate()) {
-                if (false) {
-                    Slog.w(TAG, "Returning cached resources " + r + " " + resDir
-                            + ": appScale=" + r.getCompatibilityInfo().applicationScale);
-                }
+                if (DEBUG) Slog.w(TAG, "Returning cached resources " + r + " " + resDir
+                        + ": appScale=" + r.getCompatibilityInfo().applicationScale
+                        + " key=" + key + " overrideConfig=" + overrideConfiguration);
                 return r;
             }
         }
@@ -213,7 +212,7 @@
         //Slog.i(TAG, "Resource: key=" + key + ", display metrics=" + metrics);
         DisplayMetrics dm = getDisplayMetricsLocked(displayId);
         Configuration config;
-        boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
+        final boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
         final boolean hasOverrideConfig = key.hasOverrideConfiguration();
         if (!isDefaultDisplay || hasOverrideConfig) {
             config = new Configuration(getConfiguration());
@@ -222,16 +221,14 @@
             }
             if (hasOverrideConfig) {
                 config.updateFrom(key.mOverrideConfiguration);
+                if (DEBUG) Slog.v(TAG, "Applied overrideConfig=" + key.mOverrideConfiguration);
             }
         } else {
             config = getConfiguration();
         }
-        r = new Resources(assets, dm, config, compatInfo, token);
-        if (false) {
-            Slog.i(TAG, "Created app resources " + resDir + " " + r + ": "
-                    + r.getConfiguration() + " appScale="
-                    + r.getCompatibilityInfo().applicationScale);
-        }
+        r = new Resources(assets, dm, config, compatInfo);
+        if (DEBUG) Slog.i(TAG, "Created app resources " + resDir + " " + r + ": "
+                + r.getConfiguration() + " appScale=" + r.getCompatibilityInfo().applicationScale);
 
         synchronized (this) {
             WeakReference<Resources> wr = mActiveResources.get(key);
@@ -244,7 +241,8 @@
             }
 
             // XXX need to remove entries when weak references go away
-            mActiveResources.put(key, new WeakReference<Resources>(r));
+            mActiveResources.put(key, new WeakReference<>(r));
+            if (DEBUG) Slog.v(TAG, "mActiveResources.size()=" + mActiveResources.size());
             return r;
         }
     }
@@ -255,7 +253,7 @@
             mResConfiguration = new Configuration();
         }
         if (!mResConfiguration.isOtherSeqNewer(config) && compat == null) {
-            if (DEBUG_CONFIGURATION) Slog.v(TAG, "Skipping new config: curSeq="
+            if (DEBUG || DEBUG_CONFIGURATION) Slog.v(TAG, "Skipping new config: curSeq="
                     + mResConfiguration.seq + ", newSeq=" + config.seq);
             return false;
         }
@@ -287,7 +285,7 @@
             ResourcesKey key = mActiveResources.keyAt(i);
             Resources r = mActiveResources.valueAt(i).get();
             if (r != null) {
-                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Changing resources "
+                if (DEBUG || DEBUG_CONFIGURATION) Slog.v(TAG, "Changing resources "
                         + r + " config to: " + config);
                 int displayId = key.mDisplayId;
                 boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
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/content/res/Resources.java b/core/java/android/content/res/Resources.java
index c931c01..6fb7299 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -141,9 +141,6 @@
 
     private CompatibilityInfo mCompatibilityInfo = CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
 
-    @SuppressWarnings("unused")
-    private WeakReference<IBinder> mToken;
-
     static {
         sPreloadedDrawables = new LongSparseArray[2];
         sPreloadedDrawables[0] = new LongSparseArray<ConstantState>();
@@ -224,46 +221,44 @@
     /**
      * Create a new Resources object on top of an existing set of assets in an
      * AssetManager.
-     * 
-     * @param assets Previously created AssetManager. 
-     * @param metrics Current display metrics to consider when 
+     *
+     * @param assets Previously created AssetManager.
+     * @param metrics Current display metrics to consider when
      *                selecting/computing resource values.
-     * @param config Desired device configuration to consider when 
+     * @param config Desired device configuration to consider when
      *               selecting/computing resource values (optional).
      */
     public Resources(AssetManager assets, DisplayMetrics metrics, Configuration config) {
-        this(assets, metrics, config, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
+        this(assets, metrics, config, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO);
     }
 
     /**
      * Creates a new Resources object with CompatibilityInfo.
-     * 
-     * @param assets Previously created AssetManager. 
-     * @param metrics Current display metrics to consider when 
+     *
+     * @param assets Previously created AssetManager.
+     * @param metrics Current display metrics to consider when
      *                selecting/computing resource values.
-     * @param config Desired device configuration to consider when 
+     * @param config Desired device configuration to consider when
      *               selecting/computing resource values (optional).
      * @param compatInfo this resource's compatibility info. Must not be null.
-     * @param token The Activity token for determining stack affiliation. Usually null.
      * @hide
      */
     public Resources(AssetManager assets, DisplayMetrics metrics, Configuration config,
-            CompatibilityInfo compatInfo, IBinder token) {
+            CompatibilityInfo compatInfo) {
         mAssets = assets;
         mMetrics.setToDefaults();
         if (compatInfo != null) {
             mCompatibilityInfo = compatInfo;
         }
-        mToken = new WeakReference<IBinder>(token);
         updateConfiguration(config, metrics);
         assets.ensureStringBlocks();
     }
 
     /**
      * Return a global shared Resources object that provides access to only
-     * system resources (no application resources), and is not configured for 
-     * the current screen (can not use dimension units, does not change based 
-     * on orientation, etc). 
+     * system resources (no application resources), and is not configured for
+     * the current screen (can not use dimension units, does not change based
+     * on orientation, etc).
      */
     public static Resources getSystem() {
         synchronized (sSync) {
diff --git a/core/java/android/content/res/ResourcesKey.java b/core/java/android/content/res/ResourcesKey.java
index 4ae3825..9548d49 100644
--- a/core/java/android/content/res/ResourcesKey.java
+++ b/core/java/android/content/res/ResourcesKey.java
@@ -16,27 +16,23 @@
 
 package android.content.res;
 
-import android.os.IBinder;
+import java.util.Objects;
 
 /** @hide */
 public final class ResourcesKey {
-    final String mResDir;
-    final float mScale;
+    private final String mResDir;
+    private final float mScale;
     private final int mHash;
-    private final IBinder mToken;
 
     public final int mDisplayId;
-    public final Configuration mOverrideConfiguration = new Configuration();
+    public final Configuration mOverrideConfiguration;
 
     public ResourcesKey(String resDir, int displayId, Configuration overrideConfiguration,
-            float scale, IBinder token) {
+            float scale) {
         mResDir = resDir;
         mDisplayId = displayId;
-        if (overrideConfiguration != null) {
-            mOverrideConfiguration.setTo(overrideConfiguration);
-        }
+        mOverrideConfiguration = overrideConfiguration;
         mScale = scale;
-        mToken = token;
 
         int hash = 17;
         hash = 31 * hash + (mResDir == null ? 0 : mResDir.hashCode());
@@ -48,7 +44,8 @@
     }
 
     public boolean hasOverrideConfiguration() {
-        return !Configuration.EMPTY.equals(mOverrideConfiguration);
+        return mOverrideConfiguration != null
+                && !Configuration.EMPTY.equals(mOverrideConfiguration);
     }
 
     @Override
@@ -63,17 +60,9 @@
         }
         ResourcesKey peer = (ResourcesKey) obj;
 
-        if ((mResDir == null) && (peer.mResDir != null)) {
+        if (!Objects.equals(mResDir, peer.mResDir)) {
             return false;
         }
-        if ((mResDir != null) && (peer.mResDir == null)) {
-            return false;
-        }
-        if ((mResDir != null) && (peer.mResDir != null)) {
-            if (!mResDir.equals(peer.mResDir)) {
-                return false;
-            }
-        }
         if (mDisplayId != peer.mDisplayId) {
             return false;
         }
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/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/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/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/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/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index d24e614..7dd559c 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -8709,10 +8709,8 @@
              * dialog to chose an account
              * <p>
              * Type: {@link Account}
-             *
-             * @hide
              */
-            public static final String ACCOUNT = "com.android.contacts.extra.ACCOUNT";
+            public static final String EXTRA_ACCOUNT = "android.provider.extra.ACCOUNT";
 
             /**
              * Used to specify the data set within the account in which to create the
@@ -8722,10 +8720,8 @@
              * created in the base account, with no data set.
              * <p>
              * Type: String
-             *
-             * @hide
              */
-            public static final String DATA_SET = "com.android.contacts.extra.DATA_SET";
+            public static final String EXTRA_DATA_SET = "android.provider.extra.DATA_SET";
         }
     }
 }
diff --git a/core/java/android/util/NtpTrustedTime.java b/core/java/android/util/NtpTrustedTime.java
index b18cc3b..ed2d3c6 100644
--- a/core/java/android/util/NtpTrustedTime.java
+++ b/core/java/android/util/NtpTrustedTime.java
@@ -19,6 +19,8 @@
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.res.Resources;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
 import android.net.SntpClient;
 import android.os.SystemClock;
 import android.provider.Settings;
@@ -35,10 +37,13 @@
     private static final boolean LOGD = false;
 
     private static NtpTrustedTime sSingleton;
+    private static Context sContext;
 
     private final String mServer;
     private final long mTimeout;
 
+    private ConnectivityManager mCM;
+
     private boolean mHasCache;
     private long mCachedNtpTime;
     private long mCachedNtpElapsedRealtime;
@@ -67,6 +72,7 @@
 
             final String server = secureServer != null ? secureServer : defaultServer;
             sSingleton = new NtpTrustedTime(server, timeout);
+            sContext = context;
         }
 
         return sSingleton;
@@ -79,6 +85,20 @@
             return false;
         }
 
+        // We can't do this at initialization time: ConnectivityService might not be running yet.
+        synchronized (this) {
+            if (mCM == null) {
+                mCM = (ConnectivityManager) sContext.getSystemService(Context.CONNECTIVITY_SERVICE);
+            }
+        }
+
+        final NetworkInfo ni = mCM == null ? null : mCM.getActiveNetworkInfo();
+        if (ni == null || !ni.isConnected()) {
+            if (LOGD) Log.d(TAG, "forceRefresh: no connectivity");
+            return false;
+        }
+
+
         if (LOGD) Log.d(TAG, "forceRefresh() from cache miss");
         final SntpClient client = new SntpClient();
         if (client.requestTime(mServer, (int) mTimeout)) {
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 7b20e72..743f6b7 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -81,7 +81,7 @@
     void addAppToken(int addPos, IApplicationToken token, int groupId, int stackId,
             int requestedOrientation, boolean fullscreen, boolean showWhenLocked, int userId,
             int configChanges, boolean voiceInteraction, boolean launchTaskBehind);
-    void setAppGroupId(IBinder token, int groupId);
+    void setAppTask(IBinder token, int taskId);
     void setAppOrientation(IApplicationToken token, int requestedOrientation);
     int getAppOrientation(IApplicationToken token);
     void setFocusedApp(IBinder token, boolean moveFocusNow);
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 1e6f6c9..259367e 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 {
         /**
@@ -16642,6 +16638,7 @@
 
         if (changed) {
             requestLayout();
+            invalidateOutline();
         }
     }
 
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 87d9a58..151ff83 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1326,6 +1326,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 094a8a1..12b310f 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/ListPopupWindow.java b/core/java/android/widget/ListPopupWindow.java
index fe8b08b..d85bbb9 100644
--- a/core/java/android/widget/ListPopupWindow.java
+++ b/core/java/android/widget/ListPopupWindow.java
@@ -1648,19 +1648,32 @@
         private void setPressedItem(View child, int position, float x, float y) {
             mDrawsInPressedState = true;
 
-            // Ordering is essential. First update the pressed state and layout
-            // the children. This will ensure the selector actually gets drawn.
-            setPressed(true);
-            layoutChildren();
+            // Ordering is essential. First, update the container's pressed state.
+            drawableHotspotChanged(x, y);
+            if (!isPressed()) {
+                setPressed(true);
+            }
+
+            // Next, run layout if we need to stabilize child positions.
+            if (mDataChanged) {
+                layoutChildren();
+            }
 
             // Manage the pressed view based on motion position. This allows us to
             // play nicely with actual touch and scroll events.
             final View motionView = getChildAt(mMotionPosition - mFirstPosition);
-            if (motionView != null) {
+            if (motionView != null && motionView != child && motionView.isPressed()) {
                 motionView.setPressed(false);
             }
             mMotionPosition = position;
-            child.setPressed(true);
+
+            // Offset for child coordinates.
+            final float childX = x - child.getLeft();
+            final float childY = y - child.getTop();
+            child.drawableHotspotChanged(childX, childY);
+            if (!child.isPressed()) {
+                child.setPressed(true);
+            }
 
             // Ensure that keyboard focus starts from the last touched position.
             setSelectedPositionInt(position);
diff --git a/core/java/android/widget/RadialTimePickerView.java b/core/java/android/widget/RadialTimePickerView.java
index 094a712..4b061d3 100644
--- a/core/java/android/widget/RadialTimePickerView.java
+++ b/core/java/android/widget/RadialTimePickerView.java
@@ -1271,11 +1271,19 @@
         @Override
         protected int getVirtualViewAt(float x, float y) {
             final int id;
+
+            // Calling getDegreesXY() has side-effects, so we need to cache the
+            // current inner circle value and restore after the call.
+            final boolean wasOnInnerCircle = mIsOnInnerCircle;
             final int degrees = getDegreesFromXY(x, y, true);
+            final boolean isOnInnerCircle = mIsOnInnerCircle;
+            mIsOnInnerCircle = wasOnInnerCircle;
+
             if (degrees != -1) {
                 final int snapDegrees = snapOnly30s(degrees, 0) % 360;
                 if (mShowHours) {
-                    final int hour = getHourForDegrees(snapDegrees, mIsOnInnerCircle);
+                    final int hour24 = getHourForDegrees(snapDegrees, isOnInnerCircle);
+                    final int hour = mIs24HourMode ? hour24 : hour24To12(hour24);
                     id = makeId(TYPE_HOUR, hour);
                 } else {
                     final int current = getCurrentMinute();
@@ -1404,6 +1412,16 @@
             return hour24;
         }
 
+        private int hour24To12(int hour24) {
+            if (hour24 == 0) {
+                return 12;
+            } else if (hour24 > 12) {
+                return hour24 - 12;
+            } else {
+                return hour24;
+            }
+        }
+
         private void getBoundsForVirtualView(int virtualViewId, Rect bounds) {
             final float radius;
             final int type = getTypeFromId(virtualViewId);
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/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/java/com/android/internal/widget/FaceUnlockView.java b/core/java/com/android/internal/widget/FaceUnlockView.java
deleted file mode 100644
index 121e601..0000000
--- a/core/java/com/android/internal/widget/FaceUnlockView.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.widget;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.widget.RelativeLayout;
-
-public class FaceUnlockView extends RelativeLayout {
-    private static final String TAG = "FaceUnlockView";
-
-    public FaceUnlockView(Context context) {
-        this(context, null);
-    }
-
-    public FaceUnlockView(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    private int resolveMeasured(int measureSpec, int desired)
-    {
-        int result = 0;
-        int specSize = MeasureSpec.getSize(measureSpec);
-        switch (MeasureSpec.getMode(measureSpec)) {
-            case MeasureSpec.UNSPECIFIED:
-                result = desired;
-                break;
-            case MeasureSpec.AT_MOST:
-                result = Math.max(specSize, desired);
-                break;
-            case MeasureSpec.EXACTLY:
-            default:
-                result = specSize;
-        }
-        return result;
-    }
-
-    @Override
-    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        final int minimumWidth = getSuggestedMinimumWidth();
-        final int minimumHeight = getSuggestedMinimumHeight();
-        int viewWidth = resolveMeasured(widthMeasureSpec, minimumWidth);
-        int viewHeight = resolveMeasured(heightMeasureSpec, minimumHeight);
-
-        final int chosenSize = Math.min(viewWidth, viewHeight);
-        final int newWidthMeasureSpec =
-                MeasureSpec.makeMeasureSpec(chosenSize, MeasureSpec.AT_MOST);
-        final int newHeightMeasureSpec =
-                MeasureSpec.makeMeasureSpec(chosenSize, MeasureSpec.AT_MOST);
-
-        super.onMeasure(newWidthMeasureSpec, newHeightMeasureSpec);
-    }
-}
diff --git a/core/java/com/android/internal/widget/SizeAdaptiveLayout.java b/core/java/com/android/internal/widget/SizeAdaptiveLayout.java
deleted file mode 100644
index 5f3c5f9..0000000
--- a/core/java/com/android/internal/widget/SizeAdaptiveLayout.java
+++ /dev/null
@@ -1,442 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.widget;
-
-import java.lang.Math;
-
-import com.android.internal.R;
-
-import android.animation.Animator;
-import android.animation.Animator.AnimatorListener;
-import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.Color;
-import android.graphics.drawable.ColorDrawable;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.StateListDrawable;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.util.StateSet;
-import android.view.View;
-import android.view.ViewDebug;
-import android.view.ViewGroup;
-import android.widget.RemoteViews.RemoteView;
-
-/**
- * A layout that switches between its children based on the requested layout height.
- * Each child specifies its minimum and maximum valid height.  Results are undefined
- * if children specify overlapping ranges.  A child may specify the maximum height
- * as 'unbounded' to indicate that it is willing to be displayed arbitrarily tall.
- *
- * <p>
- * See {@link SizeAdaptiveLayout.LayoutParams} for a full description of the
- * layout parameters used by SizeAdaptiveLayout.
- */
-@RemoteView
-public class SizeAdaptiveLayout extends ViewGroup {
-
-    private static final String TAG = "SizeAdaptiveLayout";
-    private static final boolean DEBUG = false;
-    private static final boolean REPORT_BAD_BOUNDS = true;
-    private static final long CROSSFADE_TIME = 250;
-
-    // TypedArray indices
-    private static final int MIN_VALID_HEIGHT =
-            R.styleable.SizeAdaptiveLayout_Layout_layout_minHeight;
-    private static final int MAX_VALID_HEIGHT =
-            R.styleable.SizeAdaptiveLayout_Layout_layout_maxHeight;
-
-    // view state
-    private View mActiveChild;
-    private View mLastActive;
-
-    // animation state
-    private AnimatorSet mTransitionAnimation;
-    private AnimatorListener mAnimatorListener;
-    private ObjectAnimator mFadePanel;
-    private ObjectAnimator mFadeView;
-    private int mCanceledAnimationCount;
-    private View mEnteringView;
-    private View mLeavingView;
-    // View used to hide larger views under smaller ones to create a uniform crossfade
-    private View mModestyPanel;
-    private int mModestyPanelTop;
-
-    public SizeAdaptiveLayout(Context context) {
-        this(context, null);
-    }
-
-    public SizeAdaptiveLayout(Context context, AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public SizeAdaptiveLayout(Context context, AttributeSet attrs, int defStyleAttr) {
-        this(context, attrs, defStyleAttr, 0);
-    }
-
-    public SizeAdaptiveLayout(
-            Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
-        super(context, attrs, defStyleAttr, defStyleRes);
-        initialize();
-    }
-
-    private void initialize() {
-        mModestyPanel = new View(getContext());
-        // If the SizeAdaptiveLayout has a solid background, use it as a transition hint.
-        Drawable background = getBackground();
-        if (background instanceof StateListDrawable) {
-            StateListDrawable sld = (StateListDrawable) background;
-            sld.setState(StateSet.WILD_CARD);
-            background = sld.getCurrent();
-        }
-        if (background instanceof ColorDrawable) {
-            mModestyPanel.setBackgroundDrawable(background);
-        }
-        SizeAdaptiveLayout.LayoutParams layout =
-                new SizeAdaptiveLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
-                                                    ViewGroup.LayoutParams.MATCH_PARENT);
-        mModestyPanel.setLayoutParams(layout);
-        addView(mModestyPanel);
-        mFadePanel = ObjectAnimator.ofFloat(mModestyPanel, "alpha", 0f);
-        mFadeView = ObjectAnimator.ofFloat(null, "alpha", 0f);
-        mAnimatorListener = new BringToFrontOnEnd();
-        mTransitionAnimation = new AnimatorSet();
-        mTransitionAnimation.play(mFadeView).with(mFadePanel);
-        mTransitionAnimation.setDuration(CROSSFADE_TIME);
-        mTransitionAnimation.addListener(mAnimatorListener);
-    }
-
-    /**
-     * Visible for testing
-     * @hide
-     */
-    public Animator getTransitionAnimation() {
-        return mTransitionAnimation;
-    }
-
-    /**
-     * Visible for testing
-     * @hide
-     */
-    public View getModestyPanel() {
-        return mModestyPanel;
-    }
-
-    @Override
-    public void onAttachedToWindow() {
-        mLastActive = null;
-        // make sure all views start off invisible.
-        for (int i = 0; i < getChildCount(); i++) {
-            getChildAt(i).setVisibility(View.GONE);
-        }
-    }
-
-    @Override
-    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        if (DEBUG) Log.d(TAG, this + " measure spec: " +
-                         MeasureSpec.toString(heightMeasureSpec));
-        View model = selectActiveChild(heightMeasureSpec);
-        if (model == null) {
-            setMeasuredDimension(0, 0);
-            return;
-        }
-        SizeAdaptiveLayout.LayoutParams lp =
-          (SizeAdaptiveLayout.LayoutParams) model.getLayoutParams();
-        if (DEBUG) Log.d(TAG, "active min: " + lp.minHeight + " max: " + lp.maxHeight);
-        measureChild(model, widthMeasureSpec, heightMeasureSpec);
-        int childHeight = model.getMeasuredHeight();
-        int childWidth = model.getMeasuredHeight();
-        int childState = combineMeasuredStates(0, model.getMeasuredState());
-        if (DEBUG) Log.d(TAG, "measured child at: " + childHeight);
-        int resolvedWidth = resolveSizeAndState(childWidth, widthMeasureSpec, childState);
-        int resolvedHeight = resolveSizeAndState(childHeight, heightMeasureSpec, childState);
-        if (DEBUG) Log.d(TAG, "resolved to: " + resolvedHeight);
-        int boundedHeight = clampSizeToBounds(resolvedHeight, model);
-        if (DEBUG) Log.d(TAG, "bounded to: " + boundedHeight);
-        setMeasuredDimension(resolvedWidth, boundedHeight);
-    }
-
-    private int clampSizeToBounds(int measuredHeight, View child) {
-        SizeAdaptiveLayout.LayoutParams lp =
-                (SizeAdaptiveLayout.LayoutParams) child.getLayoutParams();
-        int heightIn = View.MEASURED_SIZE_MASK & measuredHeight;
-        int height = Math.max(heightIn, lp.minHeight);
-        if (lp.maxHeight != SizeAdaptiveLayout.LayoutParams.UNBOUNDED) {
-            height = Math.min(height, lp.maxHeight);
-        }
-
-        if (REPORT_BAD_BOUNDS && heightIn != height) {
-            Log.d(TAG, this + "child view " + child + " " +
-                  "measured out of bounds at " + heightIn +"px " +
-                  "clamped to " + height + "px");
-        }
-
-        return height;
-    }
-
-    //TODO extend to width and height
-    private View selectActiveChild(int heightMeasureSpec) {
-        final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
-        final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
-
-        View unboundedView = null;
-        View tallestView = null;
-        int tallestViewSize = 0;
-        View smallestView = null;
-        int smallestViewSize = Integer.MAX_VALUE;
-        for (int i = 0; i < getChildCount(); i++) {
-            View child = getChildAt(i);
-            if (child != mModestyPanel) {
-                SizeAdaptiveLayout.LayoutParams lp =
-                    (SizeAdaptiveLayout.LayoutParams) child.getLayoutParams();
-                if (DEBUG) Log.d(TAG, "looking at " + i +
-                                 " with min: " + lp.minHeight +
-                                 " max: " +  lp.maxHeight);
-                if (lp.maxHeight == SizeAdaptiveLayout.LayoutParams.UNBOUNDED &&
-                    unboundedView == null) {
-                    unboundedView = child;
-                }
-                if (lp.maxHeight > tallestViewSize) {
-                    tallestViewSize = lp.maxHeight;
-                    tallestView = child;
-                }
-                if (lp.minHeight < smallestViewSize) {
-                    smallestViewSize = lp.minHeight;
-                    smallestView = child;
-                }
-                if (heightMode != MeasureSpec.UNSPECIFIED &&
-                    heightSize >= lp.minHeight && heightSize <= lp.maxHeight) {
-                    if (DEBUG) Log.d(TAG, "  found exact match, finishing early");
-                    return child;
-                }
-            }
-        }
-        if (unboundedView != null) {
-            tallestView = unboundedView;
-        }
-        if (heightMode == MeasureSpec.UNSPECIFIED || heightSize > tallestViewSize) {
-            return tallestView;
-        } else {
-            return smallestView;
-        }
-    }
-
-    @Override
-    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
-        if (DEBUG) Log.d(TAG, this + " onlayout height: " + (bottom - top));
-        mLastActive = mActiveChild;
-        int measureSpec = View.MeasureSpec.makeMeasureSpec(bottom - top,
-                                                           View.MeasureSpec.EXACTLY);
-        mActiveChild = selectActiveChild(measureSpec);
-        if (mActiveChild == null) return;
-
-        mActiveChild.setVisibility(View.VISIBLE);
-
-        if (mLastActive != mActiveChild && mLastActive != null) {
-            if (DEBUG) Log.d(TAG, this + " changed children from: " + mLastActive +
-                    " to: " + mActiveChild);
-
-            mEnteringView = mActiveChild;
-            mLeavingView = mLastActive;
-
-            mEnteringView.setAlpha(1f);
-
-            mModestyPanel.setAlpha(1f);
-            mModestyPanel.bringToFront();
-            mModestyPanelTop = mLeavingView.getHeight();
-            mModestyPanel.setVisibility(View.VISIBLE);
-            // TODO: mModestyPanel background should be compatible with mLeavingView
-
-            mLeavingView.bringToFront();
-
-            if (mTransitionAnimation.isRunning()) {
-                mTransitionAnimation.cancel();
-            }
-            mFadeView.setTarget(mLeavingView);
-            mFadeView.setFloatValues(0f);
-            mFadePanel.setFloatValues(0f);
-            mTransitionAnimation.setupStartValues();
-            mTransitionAnimation.start();
-        }
-        final int childWidth = mActiveChild.getMeasuredWidth();
-        final int childHeight = mActiveChild.getMeasuredHeight();
-        // TODO investigate setting LAYER_TYPE_HARDWARE on mLastActive
-        mActiveChild.layout(0, 0, childWidth, childHeight);
-
-        if (DEBUG) Log.d(TAG, "got modesty offset of " + mModestyPanelTop);
-        mModestyPanel.layout(0, mModestyPanelTop, childWidth, mModestyPanelTop + childHeight);
-    }
-
-    @Override
-    public LayoutParams generateLayoutParams(AttributeSet attrs) {
-        if (DEBUG) Log.d(TAG, "generate layout from attrs");
-        return new SizeAdaptiveLayout.LayoutParams(getContext(), attrs);
-    }
-
-    @Override
-    protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
-        if (DEBUG) Log.d(TAG, "generate default layout from viewgroup");
-        return new SizeAdaptiveLayout.LayoutParams(p);
-    }
-
-    @Override
-    protected LayoutParams generateDefaultLayoutParams() {
-        if (DEBUG) Log.d(TAG, "generate default layout from null");
-        return new SizeAdaptiveLayout.LayoutParams();
-    }
-
-    @Override
-    protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
-        return p instanceof SizeAdaptiveLayout.LayoutParams;
-    }
-
-    /**
-     * Per-child layout information associated with ViewSizeAdaptiveLayout.
-     *
-     * TODO extend to width and height
-     *
-     * @attr ref android.R.styleable#SizeAdaptiveLayout_Layout_layout_minHeight
-     * @attr ref android.R.styleable#SizeAdaptiveLayout_Layout_layout_maxHeight
-     */
-    public static class LayoutParams extends ViewGroup.LayoutParams {
-
-        /**
-         * Indicates the minimum valid height for the child.
-         */
-        @ViewDebug.ExportedProperty(category = "layout")
-        public int minHeight;
-
-        /**
-         * Indicates the maximum valid height for the child.
-         */
-        @ViewDebug.ExportedProperty(category = "layout")
-        public int maxHeight;
-
-        /**
-         * Constant value for maxHeight that indicates there is not maximum height.
-         */
-        public static final int UNBOUNDED = -1;
-
-        /**
-         * {@inheritDoc}
-         */
-        public LayoutParams(Context c, AttributeSet attrs) {
-            super(c, attrs);
-            if (DEBUG) {
-                Log.d(TAG, "construct layout from attrs");
-                for (int i = 0; i < attrs.getAttributeCount(); i++) {
-                    Log.d(TAG, " " + attrs.getAttributeName(i) + " = " +
-                          attrs.getAttributeValue(i));
-                }
-            }
-            TypedArray a =
-                    c.obtainStyledAttributes(attrs,
-                            R.styleable.SizeAdaptiveLayout_Layout);
-
-            minHeight = a.getDimensionPixelSize(MIN_VALID_HEIGHT, 0);
-            if (DEBUG) Log.d(TAG, "got minHeight of: " + minHeight);
-
-            try {
-                maxHeight = a.getLayoutDimension(MAX_VALID_HEIGHT, UNBOUNDED);
-                if (DEBUG) Log.d(TAG, "got maxHeight of: " + maxHeight);
-            } catch (Exception e) {
-                if (DEBUG) Log.d(TAG, "caught exception looking for maxValidHeight " + e);
-            }
-
-            a.recycle();
-        }
-
-        /**
-         * Creates a new set of layout parameters with the specified width, height
-         * and valid height bounds.
-         *
-         * @param width the width, either {@link #MATCH_PARENT},
-         *        {@link #WRAP_CONTENT} or a fixed size in pixels
-         * @param height the height, either {@link #MATCH_PARENT},
-         *        {@link #WRAP_CONTENT} or a fixed size in pixels
-         * @param minHeight the minimum height of this child
-         * @param maxHeight the maximum height of this child
-         *        or {@link #UNBOUNDED} if the child can grow forever
-         */
-        public LayoutParams(int width, int height, int minHeight, int maxHeight) {
-            super(width, height);
-            this.minHeight = minHeight;
-            this.maxHeight = maxHeight;
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public LayoutParams(int width, int height) {
-            this(width, height, UNBOUNDED, UNBOUNDED);
-        }
-
-        /**
-         * Constructs a new LayoutParams with default values as defined in {@link LayoutParams}.
-         */
-        public LayoutParams() {
-            this(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public LayoutParams(ViewGroup.LayoutParams p) {
-            super(p);
-            minHeight = UNBOUNDED;
-            maxHeight = UNBOUNDED;
-        }
-
-        public String debug(String output) {
-            return output + "SizeAdaptiveLayout.LayoutParams={" +
-                    ", max=" + maxHeight +
-                    ", max=" + minHeight + "}";
-        }
-    }
-
-    class BringToFrontOnEnd implements AnimatorListener {
-        @Override
-            public void onAnimationEnd(Animator animation) {
-            if (mCanceledAnimationCount == 0) {
-                mLeavingView.setVisibility(View.GONE);
-                mModestyPanel.setVisibility(View.GONE);
-                mEnteringView.bringToFront();
-                mEnteringView = null;
-                mLeavingView = null;
-            } else {
-                mCanceledAnimationCount--;
-            }
-        }
-
-        @Override
-            public void onAnimationCancel(Animator animation) {
-            mCanceledAnimationCount++;
-        }
-
-        @Override
-            public void onAnimationRepeat(Animator animation) {
-            if (DEBUG) Log.d(TAG, "fade animation repeated: should never happen.");
-            assert(false);
-        }
-
-        @Override
-            public void onAnimationStart(Animator animation) {
-        }
-    }
-}
diff --git a/core/java/com/android/internal/widget/WaveView.java b/core/java/com/android/internal/widget/WaveView.java
deleted file mode 100644
index 9e7a649..0000000
--- a/core/java/com/android/internal/widget/WaveView.java
+++ /dev/null
@@ -1,663 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.widget;
-
-import java.util.ArrayList;
-
-import android.animation.ValueAnimator;
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Canvas;
-import android.graphics.drawable.BitmapDrawable;
-import android.media.AudioAttributes;
-import android.os.UserHandle;
-import android.os.Vibrator;
-import android.provider.Settings;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.accessibility.AccessibilityEvent;
-import android.view.accessibility.AccessibilityManager;
-
-import com.android.internal.R;
-
-/**
- * A special widget containing a center and outer ring. Moving the center ring to the outer ring
- * causes an event that can be caught by implementing OnTriggerListener.
- */
-public class WaveView extends View implements ValueAnimator.AnimatorUpdateListener {
-    private static final String TAG = "WaveView";
-    private static final boolean DBG = false;
-    private static final int WAVE_COUNT = 20; // default wave count
-    private static final long VIBRATE_SHORT = 20;  // msec
-    private static final long VIBRATE_LONG = 20;  // msec
-
-    // Lock state machine states
-    private static final int STATE_RESET_LOCK = 0;
-    private static final int STATE_READY = 1;
-    private static final int STATE_START_ATTEMPT = 2;
-    private static final int STATE_ATTEMPTING = 3;
-    private static final int STATE_UNLOCK_ATTEMPT = 4;
-    private static final int STATE_UNLOCK_SUCCESS = 5;
-
-    // Animation properties.
-    private static final long DURATION = 300; // duration of transitional animations
-    private static final long FINAL_DURATION = 200; // duration of final animations when unlocking
-    private static final long RING_DELAY = 1300; // when to start fading animated rings
-    private static final long FINAL_DELAY = 200; // delay for unlock success animation
-    private static final long SHORT_DELAY = 100; // for starting one animation after another.
-    private static final long WAVE_DURATION = 2000; // amount of time for way to expand/decay
-    private static final long RESET_TIMEOUT = 3000; // elapsed time of inactivity before we reset
-    private static final long DELAY_INCREMENT = 15; // increment per wave while tracking motion
-    private static final long DELAY_INCREMENT2 = 12; // increment per wave while not tracking
-    private static final long WAVE_DELAY = WAVE_DURATION / WAVE_COUNT; // initial propagation delay
-
-    /**
-     * The scale by which to multiply the unlock handle width to compute the radius
-     * in which it can be grabbed when accessibility is disabled.
-     */
-    private static final float GRAB_HANDLE_RADIUS_SCALE_ACCESSIBILITY_DISABLED = 0.5f;
-
-    /**
-     * The scale by which to multiply the unlock handle width to compute the radius
-     * in which it can be grabbed when accessibility is enabled (more generous).
-     */
-    private static final float GRAB_HANDLE_RADIUS_SCALE_ACCESSIBILITY_ENABLED = 1.0f;
-
-    private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder()
-            .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
-            .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
-            .build();
-
-    private Vibrator mVibrator;
-    private OnTriggerListener mOnTriggerListener;
-    private ArrayList<DrawableHolder> mDrawables = new ArrayList<DrawableHolder>(3);
-    private ArrayList<DrawableHolder> mLightWaves = new ArrayList<DrawableHolder>(WAVE_COUNT);
-    private boolean mFingerDown = false;
-    private float mRingRadius = 182.0f; // Radius of bitmap ring. Used to snap halo to it
-    private int mSnapRadius = 136; // minimum threshold for drag unlock
-    private int mWaveCount = WAVE_COUNT;  // number of waves
-    private long mWaveTimerDelay = WAVE_DELAY;
-    private int mCurrentWave = 0;
-    private float mLockCenterX; // center of widget as dictated by widget size
-    private float mLockCenterY;
-    private float mMouseX; // current mouse position as of last touch event
-    private float mMouseY;
-    private DrawableHolder mUnlockRing;
-    private DrawableHolder mUnlockDefault;
-    private DrawableHolder mUnlockHalo;
-    private int mLockState = STATE_RESET_LOCK;
-    private int mGrabbedState = OnTriggerListener.NO_HANDLE;
-    private boolean mWavesRunning;
-    private boolean mFinishWaves;
-
-    public WaveView(Context context) {
-        this(context, null);
-    }
-
-    public WaveView(Context context, AttributeSet attrs) {
-        super(context, attrs);
-
-        // TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.WaveView);
-        // mOrientation = a.getInt(R.styleable.WaveView_orientation, HORIZONTAL);
-        // a.recycle();
-
-        initDrawables();
-    }
-
-    @Override
-    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
-        mLockCenterX = 0.5f * w;
-        mLockCenterY = 0.5f * h;
-        super.onSizeChanged(w, h, oldw, oldh);
-    }
-
-    @Override
-    protected int getSuggestedMinimumWidth() {
-        // View should be large enough to contain the unlock ring + halo
-        return mUnlockRing.getWidth() + mUnlockHalo.getWidth();
-    }
-
-    @Override
-    protected int getSuggestedMinimumHeight() {
-        // View should be large enough to contain the unlock ring + halo
-        return mUnlockRing.getHeight() + mUnlockHalo.getHeight();
-    }
-
-    @Override
-    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
-        int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
-        int widthSpecSize =  MeasureSpec.getSize(widthMeasureSpec);
-        int heightSpecSize =  MeasureSpec.getSize(heightMeasureSpec);
-        int width;
-        int height;
-
-        if (widthSpecMode == MeasureSpec.AT_MOST) {
-            width = Math.min(widthSpecSize, getSuggestedMinimumWidth());
-        } else if (widthSpecMode == MeasureSpec.EXACTLY) {
-            width = widthSpecSize;
-        } else {
-            width = getSuggestedMinimumWidth();
-        }
-
-        if (heightSpecMode == MeasureSpec.AT_MOST) {
-            height = Math.min(heightSpecSize, getSuggestedMinimumWidth());
-        } else if (heightSpecMode == MeasureSpec.EXACTLY) {
-            height = heightSpecSize;
-        } else {
-            height = getSuggestedMinimumHeight();
-        }
-
-        setMeasuredDimension(width, height);
-    }
-
-    private void initDrawables() {
-        mUnlockRing = new DrawableHolder(createDrawable(R.drawable.unlock_ring));
-        mUnlockRing.setX(mLockCenterX);
-        mUnlockRing.setY(mLockCenterY);
-        mUnlockRing.setScaleX(0.1f);
-        mUnlockRing.setScaleY(0.1f);
-        mUnlockRing.setAlpha(0.0f);
-        mDrawables.add(mUnlockRing);
-
-        mUnlockDefault = new DrawableHolder(createDrawable(R.drawable.unlock_default));
-        mUnlockDefault.setX(mLockCenterX);
-        mUnlockDefault.setY(mLockCenterY);
-        mUnlockDefault.setScaleX(0.1f);
-        mUnlockDefault.setScaleY(0.1f);
-        mUnlockDefault.setAlpha(0.0f);
-        mDrawables.add(mUnlockDefault);
-
-        mUnlockHalo = new DrawableHolder(createDrawable(R.drawable.unlock_halo));
-        mUnlockHalo.setX(mLockCenterX);
-        mUnlockHalo.setY(mLockCenterY);
-        mUnlockHalo.setScaleX(0.1f);
-        mUnlockHalo.setScaleY(0.1f);
-        mUnlockHalo.setAlpha(0.0f);
-        mDrawables.add(mUnlockHalo);
-
-        BitmapDrawable wave = createDrawable(R.drawable.unlock_wave);
-        for (int i = 0; i < mWaveCount; i++) {
-            DrawableHolder holder = new DrawableHolder(wave);
-            mLightWaves.add(holder);
-            holder.setAlpha(0.0f);
-        }
-    }
-
-    private void waveUpdateFrame(float mouseX, float mouseY, boolean fingerDown) {
-        double distX = mouseX - mLockCenterX;
-        double distY = mouseY - mLockCenterY;
-        int dragDistance = (int) Math.ceil(Math.hypot(distX, distY));
-        double touchA = Math.atan2(distX, distY);
-        float ringX = (float) (mLockCenterX + mRingRadius * Math.sin(touchA));
-        float ringY = (float) (mLockCenterY + mRingRadius * Math.cos(touchA));
-
-        switch (mLockState) {
-            case STATE_RESET_LOCK:
-                if (DBG) Log.v(TAG, "State RESET_LOCK");
-                mWaveTimerDelay = WAVE_DELAY;
-                for (int i = 0; i < mLightWaves.size(); i++) {
-                    DrawableHolder holder = mLightWaves.get(i);
-                    holder.addAnimTo(300, 0, "alpha", 0.0f, false);
-                }
-                for (int i = 0; i < mLightWaves.size(); i++) {
-                    mLightWaves.get(i).startAnimations(this);
-                }
-
-                mUnlockRing.addAnimTo(DURATION, 0, "x", mLockCenterX, true);
-                mUnlockRing.addAnimTo(DURATION, 0, "y", mLockCenterY, true);
-                mUnlockRing.addAnimTo(DURATION, 0, "scaleX", 0.1f, true);
-                mUnlockRing.addAnimTo(DURATION, 0, "scaleY", 0.1f, true);
-                mUnlockRing.addAnimTo(DURATION, 0, "alpha", 0.0f, true);
-
-                mUnlockDefault.removeAnimationFor("x");
-                mUnlockDefault.removeAnimationFor("y");
-                mUnlockDefault.removeAnimationFor("scaleX");
-                mUnlockDefault.removeAnimationFor("scaleY");
-                mUnlockDefault.removeAnimationFor("alpha");
-                mUnlockDefault.setX(mLockCenterX);
-                mUnlockDefault.setY(mLockCenterY);
-                mUnlockDefault.setScaleX(0.1f);
-                mUnlockDefault.setScaleY(0.1f);
-                mUnlockDefault.setAlpha(0.0f);
-                mUnlockDefault.addAnimTo(DURATION, SHORT_DELAY, "scaleX", 1.0f, true);
-                mUnlockDefault.addAnimTo(DURATION, SHORT_DELAY, "scaleY", 1.0f, true);
-                mUnlockDefault.addAnimTo(DURATION, SHORT_DELAY, "alpha", 1.0f, true);
-
-                mUnlockHalo.removeAnimationFor("x");
-                mUnlockHalo.removeAnimationFor("y");
-                mUnlockHalo.removeAnimationFor("scaleX");
-                mUnlockHalo.removeAnimationFor("scaleY");
-                mUnlockHalo.removeAnimationFor("alpha");
-                mUnlockHalo.setX(mLockCenterX);
-                mUnlockHalo.setY(mLockCenterY);
-                mUnlockHalo.setScaleX(0.1f);
-                mUnlockHalo.setScaleY(0.1f);
-                mUnlockHalo.setAlpha(0.0f);
-                mUnlockHalo.addAnimTo(DURATION, SHORT_DELAY, "x", mLockCenterX, true);
-                mUnlockHalo.addAnimTo(DURATION, SHORT_DELAY, "y", mLockCenterY, true);
-                mUnlockHalo.addAnimTo(DURATION, SHORT_DELAY, "scaleX", 1.0f, true);
-                mUnlockHalo.addAnimTo(DURATION, SHORT_DELAY, "scaleY", 1.0f, true);
-                mUnlockHalo.addAnimTo(DURATION, SHORT_DELAY, "alpha", 1.0f, true);
-
-                removeCallbacks(mLockTimerActions);
-
-                mLockState = STATE_READY;
-                break;
-
-            case STATE_READY:
-                if (DBG) Log.v(TAG, "State READY");
-                mWaveTimerDelay = WAVE_DELAY;
-                break;
-
-            case STATE_START_ATTEMPT:
-                if (DBG) Log.v(TAG, "State START_ATTEMPT");
-                mUnlockDefault.removeAnimationFor("x");
-                mUnlockDefault.removeAnimationFor("y");
-                mUnlockDefault.removeAnimationFor("scaleX");
-                mUnlockDefault.removeAnimationFor("scaleY");
-                mUnlockDefault.removeAnimationFor("alpha");
-                mUnlockDefault.setX(mLockCenterX + 182);
-                mUnlockDefault.setY(mLockCenterY);
-                mUnlockDefault.setScaleX(0.1f);
-                mUnlockDefault.setScaleY(0.1f);
-                mUnlockDefault.setAlpha(0.0f);
-
-                mUnlockDefault.addAnimTo(DURATION, SHORT_DELAY, "scaleX", 1.0f, false);
-                mUnlockDefault.addAnimTo(DURATION, SHORT_DELAY, "scaleY", 1.0f, false);
-                mUnlockDefault.addAnimTo(DURATION, SHORT_DELAY, "alpha", 1.0f, false);
-
-                mUnlockRing.addAnimTo(DURATION, 0, "scaleX", 1.0f, true);
-                mUnlockRing.addAnimTo(DURATION, 0, "scaleY", 1.0f, true);
-                mUnlockRing.addAnimTo(DURATION, 0, "alpha", 1.0f, true);
-
-                mLockState = STATE_ATTEMPTING;
-                break;
-
-            case STATE_ATTEMPTING:
-                if (DBG) Log.v(TAG, "State ATTEMPTING (fingerDown = " + fingerDown + ")");
-                if (dragDistance > mSnapRadius) {
-                    mFinishWaves = true; // don't start any more waves.
-                    if (fingerDown) {
-                        mUnlockHalo.addAnimTo(0, 0, "x", ringX, true);
-                        mUnlockHalo.addAnimTo(0, 0, "y", ringY, true);
-                        mUnlockHalo.addAnimTo(0, 0, "scaleX", 1.0f, true);
-                        mUnlockHalo.addAnimTo(0, 0, "scaleY", 1.0f, true);
-                        mUnlockHalo.addAnimTo(0, 0, "alpha", 1.0f, true);
-                    }  else {
-                        if (DBG) Log.v(TAG, "up detected, moving to STATE_UNLOCK_ATTEMPT");
-                        mLockState = STATE_UNLOCK_ATTEMPT;
-                    }
-                } else {
-                    // If waves have stopped, we need to kick them off again...
-                    if (!mWavesRunning) {
-                        mWavesRunning = true;
-                        mFinishWaves = false;
-                        // mWaveTimerDelay = WAVE_DELAY;
-                        postDelayed(mAddWaveAction, mWaveTimerDelay);
-                    }
-                    mUnlockHalo.addAnimTo(0, 0, "x", mouseX, true);
-                    mUnlockHalo.addAnimTo(0, 0, "y", mouseY, true);
-                    mUnlockHalo.addAnimTo(0, 0, "scaleX", 1.0f, true);
-                    mUnlockHalo.addAnimTo(0, 0, "scaleY", 1.0f, true);
-                    mUnlockHalo.addAnimTo(0, 0, "alpha", 1.0f, true);
-                }
-                break;
-
-            case STATE_UNLOCK_ATTEMPT:
-                if (DBG) Log.v(TAG, "State UNLOCK_ATTEMPT");
-                if (dragDistance > mSnapRadius) {
-                    for (int n = 0; n < mLightWaves.size(); n++) {
-                        DrawableHolder wave = mLightWaves.get(n);
-                        long delay = 1000L*(6 + n - mCurrentWave)/10L;
-                        wave.addAnimTo(FINAL_DURATION, delay, "x", ringX, true);
-                        wave.addAnimTo(FINAL_DURATION, delay, "y", ringY, true);
-                        wave.addAnimTo(FINAL_DURATION, delay, "scaleX", 0.1f, true);
-                        wave.addAnimTo(FINAL_DURATION, delay, "scaleY", 0.1f, true);
-                        wave.addAnimTo(FINAL_DURATION, delay, "alpha", 0.0f, true);
-                    }
-                    for (int i = 0; i < mLightWaves.size(); i++) {
-                        mLightWaves.get(i).startAnimations(this);
-                    }
-
-                    mUnlockRing.addAnimTo(FINAL_DURATION, 0, "x", ringX, false);
-                    mUnlockRing.addAnimTo(FINAL_DURATION, 0, "y", ringY, false);
-                    mUnlockRing.addAnimTo(FINAL_DURATION, 0, "scaleX", 0.1f, false);
-                    mUnlockRing.addAnimTo(FINAL_DURATION, 0, "scaleY", 0.1f, false);
-                    mUnlockRing.addAnimTo(FINAL_DURATION, 0, "alpha", 0.0f, false);
-
-                    mUnlockRing.addAnimTo(FINAL_DURATION, FINAL_DELAY, "alpha", 0.0f, false);
-
-                    mUnlockDefault.removeAnimationFor("x");
-                    mUnlockDefault.removeAnimationFor("y");
-                    mUnlockDefault.removeAnimationFor("scaleX");
-                    mUnlockDefault.removeAnimationFor("scaleY");
-                    mUnlockDefault.removeAnimationFor("alpha");
-                    mUnlockDefault.setX(ringX);
-                    mUnlockDefault.setY(ringY);
-                    mUnlockDefault.setScaleX(0.1f);
-                    mUnlockDefault.setScaleY(0.1f);
-                    mUnlockDefault.setAlpha(0.0f);
-
-                    mUnlockDefault.addAnimTo(FINAL_DURATION, 0, "x", ringX, true);
-                    mUnlockDefault.addAnimTo(FINAL_DURATION, 0, "y", ringY, true);
-                    mUnlockDefault.addAnimTo(FINAL_DURATION, 0, "scaleX", 1.0f, true);
-                    mUnlockDefault.addAnimTo(FINAL_DURATION, 0, "scaleY", 1.0f, true);
-                    mUnlockDefault.addAnimTo(FINAL_DURATION, 0, "alpha", 1.0f, true);
-
-                    mUnlockDefault.addAnimTo(FINAL_DURATION, FINAL_DELAY, "scaleX", 3.0f, false);
-                    mUnlockDefault.addAnimTo(FINAL_DURATION, FINAL_DELAY, "scaleY", 3.0f, false);
-                    mUnlockDefault.addAnimTo(FINAL_DURATION, FINAL_DELAY, "alpha", 0.0f, false);
-
-                    mUnlockHalo.addAnimTo(FINAL_DURATION, 0, "x", ringX, false);
-                    mUnlockHalo.addAnimTo(FINAL_DURATION, 0, "y", ringY, false);
-
-                    mUnlockHalo.addAnimTo(FINAL_DURATION, FINAL_DELAY, "scaleX", 3.0f, false);
-                    mUnlockHalo.addAnimTo(FINAL_DURATION, FINAL_DELAY, "scaleY", 3.0f, false);
-                    mUnlockHalo.addAnimTo(FINAL_DURATION, FINAL_DELAY, "alpha", 0.0f, false);
-
-                    removeCallbacks(mLockTimerActions);
-
-                    postDelayed(mLockTimerActions, RESET_TIMEOUT);
-
-                    dispatchTriggerEvent(OnTriggerListener.CENTER_HANDLE);
-                    mLockState = STATE_UNLOCK_SUCCESS;
-                } else {
-                    mLockState = STATE_RESET_LOCK;
-                }
-                break;
-
-            case STATE_UNLOCK_SUCCESS:
-                if (DBG) Log.v(TAG, "State UNLOCK_SUCCESS");
-                removeCallbacks(mAddWaveAction);
-                break;
-
-            default:
-                if (DBG) Log.v(TAG, "Unknown state " + mLockState);
-                break;
-        }
-        mUnlockDefault.startAnimations(this);
-        mUnlockHalo.startAnimations(this);
-        mUnlockRing.startAnimations(this);
-    }
-
-    BitmapDrawable createDrawable(int resId) {
-        Resources res = getResources();
-        Bitmap bitmap = BitmapFactory.decodeResource(res, resId);
-        return new BitmapDrawable(res, bitmap);
-    }
-
-    @Override
-    protected void onDraw(Canvas canvas) {
-        waveUpdateFrame(mMouseX, mMouseY, mFingerDown);
-        for (int i = 0; i < mDrawables.size(); ++i) {
-            mDrawables.get(i).draw(canvas);
-        }
-        for (int i = 0; i < mLightWaves.size(); ++i) {
-            mLightWaves.get(i).draw(canvas);
-        }
-    }
-
-    private final Runnable mLockTimerActions = new Runnable() {
-        public void run() {
-            if (DBG) Log.v(TAG, "LockTimerActions");
-            // reset lock after inactivity
-            if (mLockState == STATE_ATTEMPTING) {
-                if (DBG) Log.v(TAG, "Timer resets to STATE_RESET_LOCK");
-                mLockState = STATE_RESET_LOCK;
-            }
-            // for prototype, reset after successful unlock
-            if (mLockState == STATE_UNLOCK_SUCCESS) {
-                if (DBG) Log.v(TAG, "Timer resets to STATE_RESET_LOCK after success");
-                mLockState = STATE_RESET_LOCK;
-            }
-            invalidate();
-        }
-    };
-
-    private final Runnable mAddWaveAction = new Runnable() {
-        public void run() {
-            double distX = mMouseX - mLockCenterX;
-            double distY = mMouseY - mLockCenterY;
-            int dragDistance = (int) Math.ceil(Math.hypot(distX, distY));
-            if (mLockState == STATE_ATTEMPTING && dragDistance < mSnapRadius
-                    && mWaveTimerDelay >= WAVE_DELAY) {
-                mWaveTimerDelay = Math.min(WAVE_DURATION, mWaveTimerDelay + DELAY_INCREMENT);
-
-                DrawableHolder wave = mLightWaves.get(mCurrentWave);
-                wave.setAlpha(0.0f);
-                wave.setScaleX(0.2f);
-                wave.setScaleY(0.2f);
-                wave.setX(mMouseX);
-                wave.setY(mMouseY);
-
-                wave.addAnimTo(WAVE_DURATION, 0, "x", mLockCenterX, true);
-                wave.addAnimTo(WAVE_DURATION, 0, "y", mLockCenterY, true);
-                wave.addAnimTo(WAVE_DURATION*2/3, 0, "alpha", 1.0f, true);
-                wave.addAnimTo(WAVE_DURATION, 0, "scaleX", 1.0f, true);
-                wave.addAnimTo(WAVE_DURATION, 0, "scaleY", 1.0f, true);
-
-                wave.addAnimTo(1000, RING_DELAY, "alpha", 0.0f, false);
-                wave.startAnimations(WaveView.this);
-
-                mCurrentWave = (mCurrentWave+1) % mWaveCount;
-                if (DBG) Log.v(TAG, "WaveTimerDelay: start new wave in " + mWaveTimerDelay);
-            } else {
-                mWaveTimerDelay += DELAY_INCREMENT2;
-            }
-            if (mFinishWaves) {
-                // sentinel used to restart the waves after they've stopped
-                mWavesRunning = false;
-            } else {
-                postDelayed(mAddWaveAction, mWaveTimerDelay);
-            }
-        }
-    };
-
-    @Override
-    public boolean onHoverEvent(MotionEvent event) {
-        if (AccessibilityManager.getInstance(mContext).isTouchExplorationEnabled()) {
-            final int action = event.getAction();
-            switch (action) {
-                case MotionEvent.ACTION_HOVER_ENTER:
-                    event.setAction(MotionEvent.ACTION_DOWN);
-                    break;
-                case MotionEvent.ACTION_HOVER_MOVE:
-                    event.setAction(MotionEvent.ACTION_MOVE);
-                    break;
-                case MotionEvent.ACTION_HOVER_EXIT:
-                    event.setAction(MotionEvent.ACTION_UP);
-                    break;
-            }
-            onTouchEvent(event);
-            event.setAction(action);
-        }
-        return super.onHoverEvent(event);
-    }
-
-    @Override
-    public boolean onTouchEvent(MotionEvent event) {
-        final int action = event.getAction();
-        mMouseX = event.getX();
-        mMouseY = event.getY();
-        boolean handled = false;
-        switch (action) {
-            case MotionEvent.ACTION_DOWN:
-                removeCallbacks(mLockTimerActions);
-                mFingerDown = true;
-                tryTransitionToStartAttemptState(event);
-                handled = true;
-                break;
-
-            case MotionEvent.ACTION_MOVE:
-                tryTransitionToStartAttemptState(event);
-                handled = true;
-                break;
-
-            case MotionEvent.ACTION_UP:
-                if (DBG) Log.v(TAG, "ACTION_UP");
-                mFingerDown = false;
-                postDelayed(mLockTimerActions, RESET_TIMEOUT);
-                setGrabbedState(OnTriggerListener.NO_HANDLE);
-                // Normally the state machine is driven by user interaction causing redraws.
-                // However, when there's no more user interaction and no running animations,
-                // the state machine stops advancing because onDraw() never gets called.
-                // The following ensures we advance to the next state in this case,
-                // either STATE_UNLOCK_ATTEMPT or STATE_RESET_LOCK.
-                waveUpdateFrame(mMouseX, mMouseY, mFingerDown);
-                handled = true;
-                break;
-
-            case MotionEvent.ACTION_CANCEL:
-                mFingerDown = false;
-                handled = true;
-                break;
-        }
-        invalidate();
-        return handled ? true : super.onTouchEvent(event);
-    }
-
-    /**
-     * Tries to transition to start attempt state.
-     *
-     * @param event A motion event.
-     */
-    private void tryTransitionToStartAttemptState(MotionEvent event) {
-        final float dx = event.getX() - mUnlockHalo.getX();
-        final float dy = event.getY() - mUnlockHalo.getY();
-        float dist = (float) Math.hypot(dx, dy);
-        if (dist <= getScaledGrabHandleRadius()) {
-            setGrabbedState(OnTriggerListener.CENTER_HANDLE);
-            if (mLockState == STATE_READY) {
-                mLockState = STATE_START_ATTEMPT;
-                if (AccessibilityManager.getInstance(mContext).isEnabled()) {
-                    announceUnlockHandle();
-                }
-            }
-        }
-    }
-
-    /**
-     * @return The radius in which the handle is grabbed scaled based on
-     *     whether accessibility is enabled.
-     */
-    private float getScaledGrabHandleRadius() {
-        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
-            return GRAB_HANDLE_RADIUS_SCALE_ACCESSIBILITY_ENABLED * mUnlockHalo.getWidth();
-        } else {
-            return GRAB_HANDLE_RADIUS_SCALE_ACCESSIBILITY_DISABLED * mUnlockHalo.getWidth();
-        }
-    }
-
-    /**
-     * Announces the unlock handle if accessibility is enabled.
-     */
-    private void announceUnlockHandle() {
-        setContentDescription(mContext.getString(R.string.description_target_unlock_tablet));
-        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
-        setContentDescription(null);
-    }
-
-    /**
-     * Triggers haptic feedback.
-     */
-    private synchronized void vibrate(long duration) {
-        final boolean hapticEnabled = Settings.System.getIntForUser(
-                mContext.getContentResolver(), Settings.System.HAPTIC_FEEDBACK_ENABLED, 1,
-                UserHandle.USER_CURRENT) != 0;
-        if (hapticEnabled) {
-            if (mVibrator == null) {
-                mVibrator = (android.os.Vibrator) getContext()
-                        .getSystemService(Context.VIBRATOR_SERVICE);
-            }
-            mVibrator.vibrate(duration, VIBRATION_ATTRIBUTES);
-        }
-    }
-
-    /**
-     * Registers a callback to be invoked when the user triggers an event.
-     *
-     * @param listener the OnDialTriggerListener to attach to this view
-     */
-    public void setOnTriggerListener(OnTriggerListener listener) {
-        mOnTriggerListener = listener;
-    }
-
-    /**
-     * Dispatches a trigger event to listener. Ignored if a listener is not set.
-     * @param whichHandle the handle that triggered the event.
-     */
-    private void dispatchTriggerEvent(int whichHandle) {
-        vibrate(VIBRATE_LONG);
-        if (mOnTriggerListener != null) {
-            mOnTriggerListener.onTrigger(this, whichHandle);
-        }
-    }
-
-    /**
-     * Sets the current grabbed state, and dispatches a grabbed state change
-     * event to our listener.
-     */
-    private void setGrabbedState(int newState) {
-        if (newState != mGrabbedState) {
-            mGrabbedState = newState;
-            if (mOnTriggerListener != null) {
-                mOnTriggerListener.onGrabbedStateChange(this, mGrabbedState);
-            }
-        }
-    }
-
-    public interface OnTriggerListener {
-        /**
-         * Sent when the user releases the handle.
-         */
-        public static final int NO_HANDLE = 0;
-
-        /**
-         * Sent when the user grabs the center handle
-         */
-        public static final int CENTER_HANDLE = 10;
-
-        /**
-         * Called when the user drags the center ring beyond a threshold.
-         */
-        void onTrigger(View v, int whichHandle);
-
-        /**
-         * Called when the "grabbed state" changes (i.e. when the user either grabs or releases
-         * one of the handles.)
-         *
-         * @param v the view that was triggered
-         * @param grabbedState the new state: {@link #NO_HANDLE}, {@link #CENTER_HANDLE},
-         */
-        void onGrabbedStateChange(View v, int grabbedState);
-    }
-
-    public void onAnimationUpdate(ValueAnimator animation) {
-        invalidate();
-    }
-
-    public void reset() {
-        if (DBG) Log.v(TAG, "reset() : resets state to STATE_RESET_LOCK");
-        mLockState = STATE_RESET_LOCK;
-        invalidate();
-    }
-}
diff --git a/core/java/com/android/internal/widget/multiwaveview/Ease.java b/core/java/com/android/internal/widget/multiwaveview/Ease.java
deleted file mode 100644
index 7f90c44..0000000
--- a/core/java/com/android/internal/widget/multiwaveview/Ease.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.widget.multiwaveview;
-
-import android.animation.TimeInterpolator;
-
-class Ease {
-    private static final float DOMAIN = 1.0f;
-    private static final float DURATION = 1.0f;
-    private static final float START = 0.0f;
-
-    static class Linear {
-        public static final TimeInterpolator easeNone = new TimeInterpolator() {
-            public float getInterpolation(float input) {
-                return input;
-            }
-        };
-    }
-
-    static class Cubic {
-        public static final TimeInterpolator easeIn = new TimeInterpolator() {
-            public float getInterpolation(float input) {
-                return DOMAIN*(input/=DURATION)*input*input + START;
-            }
-        };
-        public static final TimeInterpolator easeOut = new TimeInterpolator() {
-            public float getInterpolation(float input) {
-                return DOMAIN*((input=input/DURATION-1)*input*input + 1) + START;
-            }
-        };
-        public static final TimeInterpolator easeInOut = new TimeInterpolator() {
-            public float getInterpolation(float input) {
-                return ((input/=DURATION/2) < 1.0f) ?
-                        (DOMAIN/2*input*input*input + START)
-                            : (DOMAIN/2*((input-=2)*input*input + 2) + START);
-            }
-        };
-    }
-
-    static class Quad {
-        public static final TimeInterpolator easeIn = new TimeInterpolator() {
-            public float getInterpolation (float input) {
-                return DOMAIN*(input/=DURATION)*input + START;
-            }
-        };
-        public static final TimeInterpolator easeOut = new TimeInterpolator() {
-            public float getInterpolation(float input) {
-                return -DOMAIN *(input/=DURATION)*(input-2) + START;
-            }
-        };
-        public static final TimeInterpolator easeInOut = new TimeInterpolator() {
-            public float getInterpolation(float input) {
-                return ((input/=DURATION/2) < 1) ?
-                        (DOMAIN/2*input*input + START)
-                            : (-DOMAIN/2 * ((--input)*(input-2) - 1) + START);
-            }
-        };
-    }
-
-    static class Quart {
-        public static final TimeInterpolator easeIn = new TimeInterpolator() {
-            public float getInterpolation(float input) {
-                return DOMAIN*(input/=DURATION)*input*input*input + START;
-            }
-        };
-        public static final TimeInterpolator easeOut = new TimeInterpolator() {
-            public float getInterpolation(float input) {
-                return -DOMAIN * ((input=input/DURATION-1)*input*input*input - 1) + START;
-            }
-        };
-        public static final TimeInterpolator easeInOut = new TimeInterpolator() {
-            public float getInterpolation(float input) {
-                return ((input/=DURATION/2) < 1) ?
-                        (DOMAIN/2*input*input*input*input + START)
-                            : (-DOMAIN/2 * ((input-=2)*input*input*input - 2) + START);
-            }
-        };
-    }
-
-    static class Quint {
-        public static final TimeInterpolator easeIn = new TimeInterpolator() {
-            public float getInterpolation(float input) {
-                return DOMAIN*(input/=DURATION)*input*input*input*input + START;
-            }
-        };
-        public static final TimeInterpolator easeOut = new TimeInterpolator() {
-            public float getInterpolation(float input) {
-                return DOMAIN*((input=input/DURATION-1)*input*input*input*input + 1) + START;
-            }
-        };
-        public static final TimeInterpolator easeInOut = new TimeInterpolator() {
-            public float getInterpolation(float input) {
-                return ((input/=DURATION/2) < 1) ?
-                        (DOMAIN/2*input*input*input*input*input + START)
-                            : (DOMAIN/2*((input-=2)*input*input*input*input + 2) + START);
-            }
-        };
-    }
-
-    static class Sine {
-        public static final TimeInterpolator easeIn = new TimeInterpolator() {
-            public float getInterpolation(float input) {
-                return -DOMAIN * (float) Math.cos(input/DURATION * (Math.PI/2)) + DOMAIN + START;
-            }
-        };
-        public static final TimeInterpolator easeOut = new TimeInterpolator() {
-            public float getInterpolation(float input) {
-                return DOMAIN * (float) Math.sin(input/DURATION * (Math.PI/2)) + START;
-            }
-        };
-        public static final TimeInterpolator easeInOut = new TimeInterpolator() {
-            public float getInterpolation(float input) {
-                return -DOMAIN/2 * ((float)Math.cos(Math.PI*input/DURATION) - 1.0f) + START;
-            }
-        };
-    }
-
-}
diff --git a/core/java/com/android/internal/widget/multiwaveview/GlowPadView.java b/core/java/com/android/internal/widget/multiwaveview/GlowPadView.java
deleted file mode 100644
index 11ac19e..0000000
--- a/core/java/com/android/internal/widget/multiwaveview/GlowPadView.java
+++ /dev/null
@@ -1,1383 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.widget.multiwaveview;
-
-import android.animation.Animator;
-import android.animation.Animator.AnimatorListener;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.TimeInterpolator;
-import android.animation.ValueAnimator;
-import android.animation.ValueAnimator.AnimatorUpdateListener;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.graphics.Canvas;
-import android.graphics.drawable.Drawable;
-import android.media.AudioAttributes;
-import android.os.Bundle;
-import android.os.UserHandle;
-import android.os.Vibrator;
-import android.provider.Settings;
-import android.text.TextUtils;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.util.TypedValue;
-import android.view.Gravity;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.accessibility.AccessibilityManager;
-
-import com.android.internal.R;
-
-import java.util.ArrayList;
-
-/**
- * A re-usable widget containing a center, outer ring and wave animation.
- */
-public class GlowPadView extends View {
-    private static final String TAG = "GlowPadView";
-    private static final boolean DEBUG = false;
-
-    // Wave state machine
-    private static final int STATE_IDLE = 0;
-    private static final int STATE_START = 1;
-    private static final int STATE_FIRST_TOUCH = 2;
-    private static final int STATE_TRACKING = 3;
-    private static final int STATE_SNAP = 4;
-    private static final int STATE_FINISH = 5;
-
-    // Animation properties.
-    private static final float SNAP_MARGIN_DEFAULT = 20.0f; // distance to ring before we snap to it
-
-    public interface OnTriggerListener {
-        int NO_HANDLE = 0;
-        int CENTER_HANDLE = 1;
-        public void onGrabbed(View v, int handle);
-        public void onReleased(View v, int handle);
-        public void onTrigger(View v, int target);
-        public void onGrabbedStateChange(View v, int handle);
-        public void onFinishFinalAnimation();
-    }
-
-    // Tuneable parameters for animation
-    private static final int WAVE_ANIMATION_DURATION = 1000;
-    private static final int RETURN_TO_HOME_DELAY = 1200;
-    private static final int RETURN_TO_HOME_DURATION = 200;
-    private static final int HIDE_ANIMATION_DELAY = 200;
-    private static final int HIDE_ANIMATION_DURATION = 200;
-    private static final int SHOW_ANIMATION_DURATION = 200;
-    private static final int SHOW_ANIMATION_DELAY = 50;
-    private static final int INITIAL_SHOW_HANDLE_DURATION = 200;
-    private static final int REVEAL_GLOW_DELAY = 0;
-    private static final int REVEAL_GLOW_DURATION = 0;
-
-    private static final float TAP_RADIUS_SCALE_ACCESSIBILITY_ENABLED = 1.3f;
-    private static final float TARGET_SCALE_EXPANDED = 1.0f;
-    private static final float TARGET_SCALE_COLLAPSED = 0.8f;
-    private static final float RING_SCALE_EXPANDED = 1.0f;
-    private static final float RING_SCALE_COLLAPSED = 0.5f;
-
-    private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder()
-            .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
-            .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
-            .build();
-
-    private ArrayList<TargetDrawable> mTargetDrawables = new ArrayList<TargetDrawable>();
-    private AnimationBundle mWaveAnimations = new AnimationBundle();
-    private AnimationBundle mTargetAnimations = new AnimationBundle();
-    private AnimationBundle mGlowAnimations = new AnimationBundle();
-    private ArrayList<String> mTargetDescriptions;
-    private ArrayList<String> mDirectionDescriptions;
-    private OnTriggerListener mOnTriggerListener;
-    private TargetDrawable mHandleDrawable;
-    private TargetDrawable mOuterRing;
-    private Vibrator mVibrator;
-
-    private int mFeedbackCount = 3;
-    private int mVibrationDuration = 0;
-    private int mGrabbedState;
-    private int mActiveTarget = -1;
-    private float mGlowRadius;
-    private float mWaveCenterX;
-    private float mWaveCenterY;
-    private int mMaxTargetHeight;
-    private int mMaxTargetWidth;
-    private float mRingScaleFactor = 1f;
-    private boolean mAllowScaling;
-
-    private float mOuterRadius = 0.0f;
-    private float mSnapMargin = 0.0f;
-    private float mFirstItemOffset = 0.0f;
-    private boolean mMagneticTargets = false;
-    private boolean mDragging;
-    private int mNewTargetResources;
-
-    private class AnimationBundle extends ArrayList<Tweener> {
-        private static final long serialVersionUID = 0xA84D78726F127468L;
-        private boolean mSuspended;
-
-        public void start() {
-            if (mSuspended) return; // ignore attempts to start animations
-            final int count = size();
-            for (int i = 0; i < count; i++) {
-                Tweener anim = get(i);
-                anim.animator.start();
-            }
-        }
-
-        public void cancel() {
-            final int count = size();
-            for (int i = 0; i < count; i++) {
-                Tweener anim = get(i);
-                anim.animator.cancel();
-            }
-            clear();
-        }
-
-        public void stop() {
-            final int count = size();
-            for (int i = 0; i < count; i++) {
-                Tweener anim = get(i);
-                anim.animator.end();
-            }
-            clear();
-        }
-
-        public void setSuspended(boolean suspend) {
-            mSuspended = suspend;
-        }
-    };
-
-    private AnimatorListener mResetListener = new AnimatorListenerAdapter() {
-        public void onAnimationEnd(Animator animator) {
-            switchToState(STATE_IDLE, mWaveCenterX, mWaveCenterY);
-            dispatchOnFinishFinalAnimation();
-        }
-    };
-
-    private AnimatorListener mResetListenerWithPing = new AnimatorListenerAdapter() {
-        public void onAnimationEnd(Animator animator) {
-            ping();
-            switchToState(STATE_IDLE, mWaveCenterX, mWaveCenterY);
-            dispatchOnFinishFinalAnimation();
-        }
-    };
-
-    private AnimatorUpdateListener mUpdateListener = new AnimatorUpdateListener() {
-        public void onAnimationUpdate(ValueAnimator animation) {
-            invalidate();
-        }
-    };
-
-    private boolean mAnimatingTargets;
-    private AnimatorListener mTargetUpdateListener = new AnimatorListenerAdapter() {
-        public void onAnimationEnd(Animator animator) {
-            if (mNewTargetResources != 0) {
-                internalSetTargetResources(mNewTargetResources);
-                mNewTargetResources = 0;
-                hideTargets(false, false);
-            }
-            mAnimatingTargets = false;
-        }
-    };
-    private int mTargetResourceId;
-    private int mTargetDescriptionsResourceId;
-    private int mDirectionDescriptionsResourceId;
-    private boolean mAlwaysTrackFinger;
-    private int mHorizontalInset;
-    private int mVerticalInset;
-    private int mGravity = Gravity.TOP;
-    private boolean mInitialLayout = true;
-    private Tweener mBackgroundAnimator;
-    private PointCloud mPointCloud;
-    private float mInnerRadius;
-    private int mPointerId;
-
-    public GlowPadView(Context context) {
-        this(context, null);
-    }
-
-    public GlowPadView(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        Resources res = context.getResources();
-
-        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.GlowPadView);
-        mInnerRadius = a.getDimension(R.styleable.GlowPadView_innerRadius, mInnerRadius);
-        mOuterRadius = a.getDimension(R.styleable.GlowPadView_outerRadius, mOuterRadius);
-        mSnapMargin = a.getDimension(R.styleable.GlowPadView_snapMargin, mSnapMargin);
-        mFirstItemOffset = (float) Math.toRadians(
-                a.getFloat(R.styleable.GlowPadView_firstItemOffset,
-                        (float) Math.toDegrees(mFirstItemOffset)));
-        mVibrationDuration = a.getInt(R.styleable.GlowPadView_vibrationDuration,
-                mVibrationDuration);
-        mFeedbackCount = a.getInt(R.styleable.GlowPadView_feedbackCount,
-                mFeedbackCount);
-        mAllowScaling = a.getBoolean(R.styleable.GlowPadView_allowScaling, false);
-        TypedValue handle = a.peekValue(R.styleable.GlowPadView_handleDrawable);
-        mHandleDrawable = new TargetDrawable(res, handle != null ? handle.resourceId : 0);
-        mHandleDrawable.setState(TargetDrawable.STATE_INACTIVE);
-        mOuterRing = new TargetDrawable(res,
-                getResourceId(a, R.styleable.GlowPadView_outerRingDrawable));
-
-        mAlwaysTrackFinger = a.getBoolean(R.styleable.GlowPadView_alwaysTrackFinger, false);
-        mMagneticTargets = a.getBoolean(R.styleable.GlowPadView_magneticTargets, mMagneticTargets);
-
-        int pointId = getResourceId(a, R.styleable.GlowPadView_pointDrawable);
-        Drawable pointDrawable = pointId != 0 ? context.getDrawable(pointId) : null;
-        mGlowRadius = a.getDimension(R.styleable.GlowPadView_glowRadius, 0.0f);
-
-        mPointCloud = new PointCloud(pointDrawable);
-        mPointCloud.makePointCloud(mInnerRadius, mOuterRadius);
-        mPointCloud.glowManager.setRadius(mGlowRadius);
-
-        TypedValue outValue = new TypedValue();
-
-        // Read array of target drawables
-        if (a.getValue(R.styleable.GlowPadView_targetDrawables, outValue)) {
-            internalSetTargetResources(outValue.resourceId);
-        }
-        if (mTargetDrawables == null || mTargetDrawables.size() == 0) {
-            throw new IllegalStateException("Must specify at least one target drawable");
-        }
-
-        // Read array of target descriptions
-        if (a.getValue(R.styleable.GlowPadView_targetDescriptions, outValue)) {
-            final int resourceId = outValue.resourceId;
-            if (resourceId == 0) {
-                throw new IllegalStateException("Must specify target descriptions");
-            }
-            setTargetDescriptionsResourceId(resourceId);
-        }
-
-        // Read array of direction descriptions
-        if (a.getValue(R.styleable.GlowPadView_directionDescriptions, outValue)) {
-            final int resourceId = outValue.resourceId;
-            if (resourceId == 0) {
-                throw new IllegalStateException("Must specify direction descriptions");
-            }
-            setDirectionDescriptionsResourceId(resourceId);
-        }
-
-        mGravity = a.getInt(R.styleable.GlowPadView_gravity, Gravity.TOP);
-
-        a.recycle();
-
-        setVibrateEnabled(mVibrationDuration > 0);
-
-        assignDefaultsIfNeeded();
-    }
-
-    private int getResourceId(TypedArray a, int id) {
-        TypedValue tv = a.peekValue(id);
-        return tv == null ? 0 : tv.resourceId;
-    }
-
-    private void dump() {
-        Log.v(TAG, "Outer Radius = " + mOuterRadius);
-        Log.v(TAG, "SnapMargin = " + mSnapMargin);
-        Log.v(TAG, "FeedbackCount = " + mFeedbackCount);
-        Log.v(TAG, "VibrationDuration = " + mVibrationDuration);
-        Log.v(TAG, "GlowRadius = " + mGlowRadius);
-        Log.v(TAG, "WaveCenterX = " + mWaveCenterX);
-        Log.v(TAG, "WaveCenterY = " + mWaveCenterY);
-    }
-
-    public void suspendAnimations() {
-        mWaveAnimations.setSuspended(true);
-        mTargetAnimations.setSuspended(true);
-        mGlowAnimations.setSuspended(true);
-    }
-
-    public void resumeAnimations() {
-        mWaveAnimations.setSuspended(false);
-        mTargetAnimations.setSuspended(false);
-        mGlowAnimations.setSuspended(false);
-        mWaveAnimations.start();
-        mTargetAnimations.start();
-        mGlowAnimations.start();
-    }
-
-    @Override
-    protected int getSuggestedMinimumWidth() {
-        // View should be large enough to contain the background + handle and
-        // target drawable on either edge.
-        return (int) (Math.max(mOuterRing.getWidth(), 2 * mOuterRadius) + mMaxTargetWidth);
-    }
-
-    @Override
-    protected int getSuggestedMinimumHeight() {
-        // View should be large enough to contain the unlock ring + target and
-        // target drawable on either edge
-        return (int) (Math.max(mOuterRing.getHeight(), 2 * mOuterRadius) + mMaxTargetHeight);
-    }
-
-    /**
-     * This gets the suggested width accounting for the ring's scale factor.
-     */
-    protected int getScaledSuggestedMinimumWidth() {
-        return (int) (mRingScaleFactor * Math.max(mOuterRing.getWidth(), 2 * mOuterRadius)
-                + mMaxTargetWidth);
-    }
-
-    /**
-     * This gets the suggested height accounting for the ring's scale factor.
-     */
-    protected int getScaledSuggestedMinimumHeight() {
-        return (int) (mRingScaleFactor * Math.max(mOuterRing.getHeight(), 2 * mOuterRadius)
-                + mMaxTargetHeight);
-    }
-
-    private int resolveMeasured(int measureSpec, int desired)
-    {
-        int result = 0;
-        int specSize = MeasureSpec.getSize(measureSpec);
-        switch (MeasureSpec.getMode(measureSpec)) {
-            case MeasureSpec.UNSPECIFIED:
-                result = desired;
-                break;
-            case MeasureSpec.AT_MOST:
-                result = Math.min(specSize, desired);
-                break;
-            case MeasureSpec.EXACTLY:
-            default:
-                result = specSize;
-        }
-        return result;
-    }
-
-    private void switchToState(int state, float x, float y) {
-        switch (state) {
-            case STATE_IDLE:
-                deactivateTargets();
-                hideGlow(0, 0, 0.0f, null);
-                startBackgroundAnimation(0, 0.0f);
-                mHandleDrawable.setState(TargetDrawable.STATE_INACTIVE);
-                mHandleDrawable.setAlpha(1.0f);
-                break;
-
-            case STATE_START:
-                startBackgroundAnimation(0, 0.0f);
-                break;
-
-            case STATE_FIRST_TOUCH:
-                mHandleDrawable.setAlpha(0.0f);
-                deactivateTargets();
-                showTargets(true);
-                startBackgroundAnimation(INITIAL_SHOW_HANDLE_DURATION, 1.0f);
-                setGrabbedState(OnTriggerListener.CENTER_HANDLE);
-                if (AccessibilityManager.getInstance(mContext).isEnabled()) {
-                    announceTargets();
-                }
-                break;
-
-            case STATE_TRACKING:
-                mHandleDrawable.setAlpha(0.0f);
-                showGlow(REVEAL_GLOW_DURATION , REVEAL_GLOW_DELAY, 1.0f, null);
-                break;
-
-            case STATE_SNAP:
-                // TODO: Add transition states (see list_selector_background_transition.xml)
-                mHandleDrawable.setAlpha(0.0f);
-                showGlow(REVEAL_GLOW_DURATION , REVEAL_GLOW_DELAY, 0.0f, null);
-                break;
-
-            case STATE_FINISH:
-                doFinish();
-                break;
-        }
-    }
-
-    private void showGlow(int duration, int delay, float finalAlpha,
-            AnimatorListener finishListener) {
-        mGlowAnimations.cancel();
-        mGlowAnimations.add(Tweener.to(mPointCloud.glowManager, duration,
-                "ease", Ease.Cubic.easeIn,
-                "delay", delay,
-                "alpha", finalAlpha,
-                "onUpdate", mUpdateListener,
-                "onComplete", finishListener));
-        mGlowAnimations.start();
-    }
-
-    private void hideGlow(int duration, int delay, float finalAlpha,
-            AnimatorListener finishListener) {
-        mGlowAnimations.cancel();
-        mGlowAnimations.add(Tweener.to(mPointCloud.glowManager, duration,
-                "ease", Ease.Quart.easeOut,
-                "delay", delay,
-                "alpha", finalAlpha,
-                "x", 0.0f,
-                "y", 0.0f,
-                "onUpdate", mUpdateListener,
-                "onComplete", finishListener));
-        mGlowAnimations.start();
-    }
-
-    private void deactivateTargets() {
-        final int count = mTargetDrawables.size();
-        for (int i = 0; i < count; i++) {
-            TargetDrawable target = mTargetDrawables.get(i);
-            target.setState(TargetDrawable.STATE_INACTIVE);
-        }
-        mActiveTarget = -1;
-    }
-
-    /**
-     * Dispatches a trigger event to listener. Ignored if a listener is not set.
-     * @param whichTarget the target that was triggered.
-     */
-    private void dispatchTriggerEvent(int whichTarget) {
-        vibrate();
-        if (mOnTriggerListener != null) {
-            mOnTriggerListener.onTrigger(this, whichTarget);
-        }
-    }
-
-    private void dispatchOnFinishFinalAnimation() {
-        if (mOnTriggerListener != null) {
-            mOnTriggerListener.onFinishFinalAnimation();
-        }
-    }
-
-    private void doFinish() {
-        final int activeTarget = mActiveTarget;
-        final boolean targetHit =  activeTarget != -1;
-
-        if (targetHit) {
-            if (DEBUG) Log.v(TAG, "Finish with target hit = " + targetHit);
-
-            highlightSelected(activeTarget);
-
-            // Inform listener of any active targets.  Typically only one will be active.
-            hideGlow(RETURN_TO_HOME_DURATION, RETURN_TO_HOME_DELAY, 0.0f, mResetListener);
-            dispatchTriggerEvent(activeTarget);
-            if (!mAlwaysTrackFinger) {
-                // Force ring and targets to finish animation to final expanded state
-                mTargetAnimations.stop();
-            }
-        } else {
-            // Animate handle back to the center based on current state.
-            hideGlow(HIDE_ANIMATION_DURATION, 0, 0.0f, mResetListenerWithPing);
-            hideTargets(true, false);
-        }
-
-        setGrabbedState(OnTriggerListener.NO_HANDLE);
-    }
-
-    private void highlightSelected(int activeTarget) {
-        // Highlight the given target and fade others
-        mTargetDrawables.get(activeTarget).setState(TargetDrawable.STATE_ACTIVE);
-        hideUnselected(activeTarget);
-    }
-
-    private void hideUnselected(int active) {
-        for (int i = 0; i < mTargetDrawables.size(); i++) {
-            if (i != active) {
-                mTargetDrawables.get(i).setAlpha(0.0f);
-            }
-        }
-    }
-
-    private void hideTargets(boolean animate, boolean expanded) {
-        mTargetAnimations.cancel();
-        // Note: these animations should complete at the same time so that we can swap out
-        // the target assets asynchronously from the setTargetResources() call.
-        mAnimatingTargets = animate;
-        final int duration = animate ? HIDE_ANIMATION_DURATION : 0;
-        final int delay = animate ? HIDE_ANIMATION_DELAY : 0;
-
-        final float targetScale = expanded ?
-                TARGET_SCALE_EXPANDED : TARGET_SCALE_COLLAPSED;
-        final int length = mTargetDrawables.size();
-        final TimeInterpolator interpolator = Ease.Cubic.easeOut;
-        for (int i = 0; i < length; i++) {
-            TargetDrawable target = mTargetDrawables.get(i);
-            target.setState(TargetDrawable.STATE_INACTIVE);
-            mTargetAnimations.add(Tweener.to(target, duration,
-                    "ease", interpolator,
-                    "alpha", 0.0f,
-                    "scaleX", targetScale,
-                    "scaleY", targetScale,
-                    "delay", delay,
-                    "onUpdate", mUpdateListener));
-        }
-
-        float ringScaleTarget = expanded ?
-                RING_SCALE_EXPANDED : RING_SCALE_COLLAPSED;
-        ringScaleTarget *= mRingScaleFactor;
-        mTargetAnimations.add(Tweener.to(mOuterRing, duration,
-                "ease", interpolator,
-                "alpha", 0.0f,
-                "scaleX", ringScaleTarget,
-                "scaleY", ringScaleTarget,
-                "delay", delay,
-                "onUpdate", mUpdateListener,
-                "onComplete", mTargetUpdateListener));
-
-        mTargetAnimations.start();
-    }
-
-    private void showTargets(boolean animate) {
-        mTargetAnimations.stop();
-        mAnimatingTargets = animate;
-        final int delay = animate ? SHOW_ANIMATION_DELAY : 0;
-        final int duration = animate ? SHOW_ANIMATION_DURATION : 0;
-        final int length = mTargetDrawables.size();
-        for (int i = 0; i < length; i++) {
-            TargetDrawable target = mTargetDrawables.get(i);
-            target.setState(TargetDrawable.STATE_INACTIVE);
-            mTargetAnimations.add(Tweener.to(target, duration,
-                    "ease", Ease.Cubic.easeOut,
-                    "alpha", 1.0f,
-                    "scaleX", 1.0f,
-                    "scaleY", 1.0f,
-                    "delay", delay,
-                    "onUpdate", mUpdateListener));
-        }
-
-        float ringScale = mRingScaleFactor * RING_SCALE_EXPANDED;
-        mTargetAnimations.add(Tweener.to(mOuterRing, duration,
-                "ease", Ease.Cubic.easeOut,
-                "alpha", 1.0f,
-                "scaleX", ringScale,
-                "scaleY", ringScale,
-                "delay", delay,
-                "onUpdate", mUpdateListener,
-                "onComplete", mTargetUpdateListener));
-
-        mTargetAnimations.start();
-    }
-
-    private void vibrate() {
-        final boolean hapticEnabled = Settings.System.getIntForUser(
-                mContext.getContentResolver(), Settings.System.HAPTIC_FEEDBACK_ENABLED, 1,
-                UserHandle.USER_CURRENT) != 0;
-        if (mVibrator != null && hapticEnabled) {
-            mVibrator.vibrate(mVibrationDuration, VIBRATION_ATTRIBUTES);
-        }
-    }
-
-    private ArrayList<TargetDrawable> loadDrawableArray(int resourceId) {
-        Resources res = getContext().getResources();
-        TypedArray array = res.obtainTypedArray(resourceId);
-        final int count = array.length();
-        ArrayList<TargetDrawable> drawables = new ArrayList<TargetDrawable>(count);
-        for (int i = 0; i < count; i++) {
-            TypedValue value = array.peekValue(i);
-            TargetDrawable target = new TargetDrawable(res, value != null ? value.resourceId : 0);
-            drawables.add(target);
-        }
-        array.recycle();
-        return drawables;
-    }
-
-    private void internalSetTargetResources(int resourceId) {
-        final ArrayList<TargetDrawable> targets = loadDrawableArray(resourceId);
-        mTargetDrawables = targets;
-        mTargetResourceId = resourceId;
-
-        int maxWidth = mHandleDrawable.getWidth();
-        int maxHeight = mHandleDrawable.getHeight();
-        final int count = targets.size();
-        for (int i = 0; i < count; i++) {
-            TargetDrawable target = targets.get(i);
-            maxWidth = Math.max(maxWidth, target.getWidth());
-            maxHeight = Math.max(maxHeight, target.getHeight());
-        }
-        if (mMaxTargetWidth != maxWidth || mMaxTargetHeight != maxHeight) {
-            mMaxTargetWidth = maxWidth;
-            mMaxTargetHeight = maxHeight;
-            requestLayout(); // required to resize layout and call updateTargetPositions()
-        } else {
-            updateTargetPositions(mWaveCenterX, mWaveCenterY);
-            updatePointCloudPosition(mWaveCenterX, mWaveCenterY);
-        }
-    }
-
-    /**
-     * Loads an array of drawables from the given resourceId.
-     *
-     * @param resourceId
-     */
-    public void setTargetResources(int resourceId) {
-        if (mAnimatingTargets) {
-            // postpone this change until we return to the initial state
-            mNewTargetResources = resourceId;
-        } else {
-            internalSetTargetResources(resourceId);
-        }
-    }
-
-    public int getTargetResourceId() {
-        return mTargetResourceId;
-    }
-
-    /**
-     * Sets the resource id specifying the target descriptions for accessibility.
-     *
-     * @param resourceId The resource id.
-     */
-    public void setTargetDescriptionsResourceId(int resourceId) {
-        mTargetDescriptionsResourceId = resourceId;
-        if (mTargetDescriptions != null) {
-            mTargetDescriptions.clear();
-        }
-    }
-
-    /**
-     * Gets the resource id specifying the target descriptions for accessibility.
-     *
-     * @return The resource id.
-     */
-    public int getTargetDescriptionsResourceId() {
-        return mTargetDescriptionsResourceId;
-    }
-
-    /**
-     * Sets the resource id specifying the target direction descriptions for accessibility.
-     *
-     * @param resourceId The resource id.
-     */
-    public void setDirectionDescriptionsResourceId(int resourceId) {
-        mDirectionDescriptionsResourceId = resourceId;
-        if (mDirectionDescriptions != null) {
-            mDirectionDescriptions.clear();
-        }
-    }
-
-    /**
-     * Gets the resource id specifying the target direction descriptions.
-     *
-     * @return The resource id.
-     */
-    public int getDirectionDescriptionsResourceId() {
-        return mDirectionDescriptionsResourceId;
-    }
-
-    /**
-     * Enable or disable vibrate on touch.
-     *
-     * @param enabled
-     */
-    public void setVibrateEnabled(boolean enabled) {
-        if (enabled && mVibrator == null) {
-            mVibrator = (Vibrator) getContext().getSystemService(Context.VIBRATOR_SERVICE);
-        } else {
-            mVibrator = null;
-        }
-    }
-
-    /**
-     * Starts wave animation.
-     *
-     */
-    public void ping() {
-        if (mFeedbackCount > 0) {
-            boolean doWaveAnimation = true;
-            final AnimationBundle waveAnimations = mWaveAnimations;
-
-            // Don't do a wave if there's already one in progress
-            if (waveAnimations.size() > 0 && waveAnimations.get(0).animator.isRunning()) {
-                long t = waveAnimations.get(0).animator.getCurrentPlayTime();
-                if (t < WAVE_ANIMATION_DURATION/2) {
-                    doWaveAnimation = false;
-                }
-            }
-
-            if (doWaveAnimation) {
-                startWaveAnimation();
-            }
-        }
-    }
-
-    private void stopAndHideWaveAnimation() {
-        mWaveAnimations.cancel();
-        mPointCloud.waveManager.setAlpha(0.0f);
-    }
-
-    private void startWaveAnimation() {
-        mWaveAnimations.cancel();
-        mPointCloud.waveManager.setAlpha(1.0f);
-        mPointCloud.waveManager.setRadius(mHandleDrawable.getWidth()/2.0f);
-        mWaveAnimations.add(Tweener.to(mPointCloud.waveManager, WAVE_ANIMATION_DURATION,
-                "ease", Ease.Quad.easeOut,
-                "delay", 0,
-                "radius", 2.0f * mOuterRadius,
-                "onUpdate", mUpdateListener,
-                "onComplete",
-                new AnimatorListenerAdapter() {
-                    public void onAnimationEnd(Animator animator) {
-                        mPointCloud.waveManager.setRadius(0.0f);
-                        mPointCloud.waveManager.setAlpha(0.0f);
-                    }
-                }));
-        mWaveAnimations.start();
-    }
-
-    /**
-     * Resets the widget to default state and cancels all animation. If animate is 'true', will
-     * animate objects into place. Otherwise, objects will snap back to place.
-     *
-     * @param animate
-     */
-    public void reset(boolean animate) {
-        mGlowAnimations.stop();
-        mTargetAnimations.stop();
-        startBackgroundAnimation(0, 0.0f);
-        stopAndHideWaveAnimation();
-        hideTargets(animate, false);
-        hideGlow(0, 0, 0.0f, null);
-        Tweener.reset();
-    }
-
-    private void startBackgroundAnimation(int duration, float alpha) {
-        final Drawable background = getBackground();
-        if (mAlwaysTrackFinger && background != null) {
-            if (mBackgroundAnimator != null) {
-                mBackgroundAnimator.animator.cancel();
-            }
-            mBackgroundAnimator = Tweener.to(background, duration,
-                    "ease", Ease.Cubic.easeIn,
-                    "alpha", (int)(255.0f * alpha),
-                    "delay", SHOW_ANIMATION_DELAY);
-            mBackgroundAnimator.animator.start();
-        }
-    }
-
-    @Override
-    public boolean onTouchEvent(MotionEvent event) {
-        final int action = event.getActionMasked();
-        boolean handled = false;
-        switch (action) {
-            case MotionEvent.ACTION_POINTER_DOWN:
-            case MotionEvent.ACTION_DOWN:
-                if (DEBUG) Log.v(TAG, "*** DOWN ***");
-                handleDown(event);
-                handleMove(event);
-                handled = true;
-                break;
-
-            case MotionEvent.ACTION_MOVE:
-                if (DEBUG) Log.v(TAG, "*** MOVE ***");
-                handleMove(event);
-                handled = true;
-                break;
-
-            case MotionEvent.ACTION_POINTER_UP:
-            case MotionEvent.ACTION_UP:
-                if (DEBUG) Log.v(TAG, "*** UP ***");
-                handleMove(event);
-                handleUp(event);
-                handled = true;
-                break;
-
-            case MotionEvent.ACTION_CANCEL:
-                if (DEBUG) Log.v(TAG, "*** CANCEL ***");
-                handleMove(event);
-                handleCancel(event);
-                handled = true;
-                break;
-
-        }
-        invalidate();
-        return handled ? true : super.onTouchEvent(event);
-    }
-
-    private void updateGlowPosition(float x, float y) {
-        float dx = x - mOuterRing.getX();
-        float dy = y - mOuterRing.getY();
-        dx *= 1f / mRingScaleFactor;
-        dy *= 1f / mRingScaleFactor;
-        mPointCloud.glowManager.setX(mOuterRing.getX() + dx);
-        mPointCloud.glowManager.setY(mOuterRing.getY() + dy);
-    }
-
-    private void handleDown(MotionEvent event) {
-        int actionIndex = event.getActionIndex();
-        float eventX = event.getX(actionIndex);
-        float eventY = event.getY(actionIndex);
-        switchToState(STATE_START, eventX, eventY);
-        if (!trySwitchToFirstTouchState(eventX, eventY)) {
-            mDragging = false;
-        } else {
-            mPointerId = event.getPointerId(actionIndex);
-            updateGlowPosition(eventX, eventY);
-        }
-    }
-
-    private void handleUp(MotionEvent event) {
-        if (DEBUG && mDragging) Log.v(TAG, "** Handle RELEASE");
-        int actionIndex = event.getActionIndex();
-        if (event.getPointerId(actionIndex) == mPointerId) {
-            switchToState(STATE_FINISH, event.getX(actionIndex), event.getY(actionIndex));
-        }
-    }
-
-    private void handleCancel(MotionEvent event) {
-        if (DEBUG && mDragging) Log.v(TAG, "** Handle CANCEL");
-
-        // Drop the active target if canceled.
-        mActiveTarget = -1; 
-
-        int actionIndex = event.findPointerIndex(mPointerId);
-        actionIndex = actionIndex == -1 ? 0 : actionIndex;
-        switchToState(STATE_FINISH, event.getX(actionIndex), event.getY(actionIndex));
-    }
-
-    private void handleMove(MotionEvent event) {
-        int activeTarget = -1;
-        final int historySize = event.getHistorySize();
-        ArrayList<TargetDrawable> targets = mTargetDrawables;
-        int ntargets = targets.size();
-        float x = 0.0f;
-        float y = 0.0f;
-        float activeAngle = 0.0f;
-        int actionIndex = event.findPointerIndex(mPointerId);
-
-        if (actionIndex == -1) {
-            return;  // no data for this pointer
-        }
-
-        for (int k = 0; k < historySize + 1; k++) {
-            float eventX = k < historySize ? event.getHistoricalX(actionIndex, k)
-                    : event.getX(actionIndex);
-            float eventY = k < historySize ? event.getHistoricalY(actionIndex, k)
-                    : event.getY(actionIndex);
-            // tx and ty are relative to wave center
-            float tx = eventX - mWaveCenterX;
-            float ty = eventY - mWaveCenterY;
-            float touchRadius = (float) Math.hypot(tx, ty);
-            final float scale = touchRadius > mOuterRadius ? mOuterRadius / touchRadius : 1.0f;
-            float limitX = tx * scale;
-            float limitY = ty * scale;
-            double angleRad = Math.atan2(-ty, tx);
-
-            if (!mDragging) {
-                trySwitchToFirstTouchState(eventX, eventY);
-            }
-
-            if (mDragging) {
-                // For multiple targets, snap to the one that matches
-                final float snapRadius = mRingScaleFactor * mOuterRadius - mSnapMargin;
-                final float snapDistance2 = snapRadius * snapRadius;
-                // Find first target in range
-                for (int i = 0; i < ntargets; i++) {
-                    TargetDrawable target = targets.get(i);
-
-                    double targetMinRad = mFirstItemOffset + (i - 0.5) * 2 * Math.PI / ntargets;
-                    double targetMaxRad = mFirstItemOffset + (i + 0.5) * 2 * Math.PI / ntargets;
-                    if (target.isEnabled()) {
-                        boolean angleMatches =
-                            (angleRad > targetMinRad && angleRad <= targetMaxRad) ||
-                            (angleRad + 2 * Math.PI > targetMinRad &&
-                             angleRad + 2 * Math.PI <= targetMaxRad) ||
-                            (angleRad - 2 * Math.PI > targetMinRad &&
-                             angleRad - 2 * Math.PI <= targetMaxRad);
-                        if (angleMatches && (dist2(tx, ty) > snapDistance2)) {
-                            activeTarget = i;
-                            activeAngle = (float) -angleRad;
-                        }
-                    }
-                }
-            }
-            x = limitX;
-            y = limitY;
-        }
-
-        if (!mDragging) {
-            return;
-        }
-
-        if (activeTarget != -1) {
-            switchToState(STATE_SNAP, x,y);
-            updateGlowPosition(x, y);
-        } else {
-            switchToState(STATE_TRACKING, x, y);
-            updateGlowPosition(x, y);
-        }
-
-        if (mActiveTarget != activeTarget) {
-            // Defocus the old target
-            if (mActiveTarget != -1) {
-                TargetDrawable target = targets.get(mActiveTarget);
-                if (target.hasState(TargetDrawable.STATE_FOCUSED)) {
-                    target.setState(TargetDrawable.STATE_INACTIVE);
-                }
-                if (mMagneticTargets) {
-                    updateTargetPosition(mActiveTarget, mWaveCenterX, mWaveCenterY);
-                }
-            }
-            // Focus the new target
-            if (activeTarget != -1) {
-                TargetDrawable target = targets.get(activeTarget);
-                if (target.hasState(TargetDrawable.STATE_FOCUSED)) {
-                    target.setState(TargetDrawable.STATE_FOCUSED);
-                }
-                if (mMagneticTargets) {
-                    updateTargetPosition(activeTarget, mWaveCenterX, mWaveCenterY, activeAngle);
-                }
-                if (AccessibilityManager.getInstance(mContext).isEnabled()) {
-                    String targetContentDescription = getTargetDescription(activeTarget);
-                    announceForAccessibility(targetContentDescription);
-                }
-            }
-        }
-        mActiveTarget = activeTarget;
-    }
-
-    @Override
-    public boolean onHoverEvent(MotionEvent event) {
-        if (AccessibilityManager.getInstance(mContext).isTouchExplorationEnabled()) {
-            final int action = event.getAction();
-            switch (action) {
-                case MotionEvent.ACTION_HOVER_ENTER:
-                    event.setAction(MotionEvent.ACTION_DOWN);
-                    break;
-                case MotionEvent.ACTION_HOVER_MOVE:
-                    event.setAction(MotionEvent.ACTION_MOVE);
-                    break;
-                case MotionEvent.ACTION_HOVER_EXIT:
-                    event.setAction(MotionEvent.ACTION_UP);
-                    break;
-            }
-            onTouchEvent(event);
-            event.setAction(action);
-        }
-        super.onHoverEvent(event);
-        return true;
-    }
-
-    /**
-     * Sets the current grabbed state, and dispatches a grabbed state change
-     * event to our listener.
-     */
-    private void setGrabbedState(int newState) {
-        if (newState != mGrabbedState) {
-            if (newState != OnTriggerListener.NO_HANDLE) {
-                vibrate();
-            }
-            mGrabbedState = newState;
-            if (mOnTriggerListener != null) {
-                if (newState == OnTriggerListener.NO_HANDLE) {
-                    mOnTriggerListener.onReleased(this, OnTriggerListener.CENTER_HANDLE);
-                } else {
-                    mOnTriggerListener.onGrabbed(this, OnTriggerListener.CENTER_HANDLE);
-                }
-                mOnTriggerListener.onGrabbedStateChange(this, newState);
-            }
-        }
-    }
-
-    private boolean trySwitchToFirstTouchState(float x, float y) {
-        final float tx = x - mWaveCenterX;
-        final float ty = y - mWaveCenterY;
-        if (mAlwaysTrackFinger || dist2(tx,ty) <= getScaledGlowRadiusSquared()) {
-            if (DEBUG) Log.v(TAG, "** Handle HIT");
-            switchToState(STATE_FIRST_TOUCH, x, y);
-            updateGlowPosition(tx, ty);
-            mDragging = true;
-            return true;
-        }
-        return false;
-    }
-
-    private void assignDefaultsIfNeeded() {
-        if (mOuterRadius == 0.0f) {
-            mOuterRadius = Math.max(mOuterRing.getWidth(), mOuterRing.getHeight())/2.0f;
-        }
-        if (mSnapMargin == 0.0f) {
-            mSnapMargin = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
-                    SNAP_MARGIN_DEFAULT, getContext().getResources().getDisplayMetrics());
-        }
-        if (mInnerRadius == 0.0f) {
-            mInnerRadius = mHandleDrawable.getWidth() / 10.0f;
-        }
-    }
-
-    private void computeInsets(int dx, int dy) {
-        final int layoutDirection = getLayoutDirection();
-        final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection);
-
-        switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
-            case Gravity.LEFT:
-                mHorizontalInset = 0;
-                break;
-            case Gravity.RIGHT:
-                mHorizontalInset = dx;
-                break;
-            case Gravity.CENTER_HORIZONTAL:
-            default:
-                mHorizontalInset = dx / 2;
-                break;
-        }
-        switch (absoluteGravity & Gravity.VERTICAL_GRAVITY_MASK) {
-            case Gravity.TOP:
-                mVerticalInset = 0;
-                break;
-            case Gravity.BOTTOM:
-                mVerticalInset = dy;
-                break;
-            case Gravity.CENTER_VERTICAL:
-            default:
-                mVerticalInset = dy / 2;
-                break;
-        }
-    }
-
-    /**
-     * Given the desired width and height of the ring and the allocated width and height, compute
-     * how much we need to scale the ring.
-     */
-    private float computeScaleFactor(int desiredWidth, int desiredHeight,
-            int actualWidth, int actualHeight) {
-
-        // Return unity if scaling is not allowed.
-        if (!mAllowScaling) return 1f;
-
-        final int layoutDirection = getLayoutDirection();
-        final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection);
-
-        float scaleX = 1f;
-        float scaleY = 1f;
-
-        // We use the gravity as a cue for whether we want to scale on a particular axis.
-        // We only scale to fit horizontally if we're not pinned to the left or right. Likewise,
-        // we only scale to fit vertically if we're not pinned to the top or bottom. In these
-        // cases, we want the ring to hang off the side or top/bottom, respectively.
-        switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
-            case Gravity.LEFT:
-            case Gravity.RIGHT:
-                break;
-            case Gravity.CENTER_HORIZONTAL:
-            default:
-                if (desiredWidth > actualWidth) {
-                    scaleX = (1f * actualWidth - mMaxTargetWidth) /
-                            (desiredWidth - mMaxTargetWidth);
-                }
-                break;
-        }
-        switch (absoluteGravity & Gravity.VERTICAL_GRAVITY_MASK) {
-            case Gravity.TOP:
-            case Gravity.BOTTOM:
-                break;
-            case Gravity.CENTER_VERTICAL:
-            default:
-                if (desiredHeight > actualHeight) {
-                    scaleY = (1f * actualHeight - mMaxTargetHeight) /
-                            (desiredHeight - mMaxTargetHeight);
-                }
-                break;
-        }
-        return Math.min(scaleX, scaleY);
-    }
-
-    @Override
-    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        final int minimumWidth = getSuggestedMinimumWidth();
-        final int minimumHeight = getSuggestedMinimumHeight();
-        int computedWidth = resolveMeasured(widthMeasureSpec, minimumWidth);
-        int computedHeight = resolveMeasured(heightMeasureSpec, minimumHeight);
-
-        mRingScaleFactor = computeScaleFactor(minimumWidth, minimumHeight,
-                computedWidth, computedHeight);
-
-        int scaledWidth = getScaledSuggestedMinimumWidth();
-        int scaledHeight = getScaledSuggestedMinimumHeight();
-
-        computeInsets(computedWidth - scaledWidth, computedHeight - scaledHeight);
-        setMeasuredDimension(computedWidth, computedHeight);
-    }
-
-    private float getRingWidth() {
-        return mRingScaleFactor * Math.max(mOuterRing.getWidth(), 2 * mOuterRadius);
-    }
-
-    private float getRingHeight() {
-        return mRingScaleFactor * Math.max(mOuterRing.getHeight(), 2 * mOuterRadius);
-    }
-
-    @Override
-    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
-        super.onLayout(changed, left, top, right, bottom);
-        final int width = right - left;
-        final int height = bottom - top;
-
-        // Target placement width/height. This puts the targets on the greater of the ring
-        // width or the specified outer radius.
-        final float placementWidth = getRingWidth();
-        final float placementHeight = getRingHeight();
-        float newWaveCenterX = mHorizontalInset
-                + Math.max(width, mMaxTargetWidth + placementWidth) / 2;
-        float newWaveCenterY = mVerticalInset
-                + Math.max(height, + mMaxTargetHeight + placementHeight) / 2;
-
-        if (mInitialLayout) {
-            stopAndHideWaveAnimation();
-            hideTargets(false, false);
-            mInitialLayout = false;
-        }
-
-        mOuterRing.setPositionX(newWaveCenterX);
-        mOuterRing.setPositionY(newWaveCenterY);
-
-        mPointCloud.setScale(mRingScaleFactor);
-
-        mHandleDrawable.setPositionX(newWaveCenterX);
-        mHandleDrawable.setPositionY(newWaveCenterY);
-
-        updateTargetPositions(newWaveCenterX, newWaveCenterY);
-        updatePointCloudPosition(newWaveCenterX, newWaveCenterY);
-        updateGlowPosition(newWaveCenterX, newWaveCenterY);
-
-        mWaveCenterX = newWaveCenterX;
-        mWaveCenterY = newWaveCenterY;
-
-        if (DEBUG) dump();
-    }
-
-    private void updateTargetPosition(int i, float centerX, float centerY) {
-        final float angle = getAngle(getSliceAngle(), i);
-        updateTargetPosition(i, centerX, centerY, angle);
-    }
-
-    private void updateTargetPosition(int i, float centerX, float centerY, float angle) {
-        final float placementRadiusX = getRingWidth() / 2;
-        final float placementRadiusY = getRingHeight() / 2;
-        if (i >= 0) {
-            ArrayList<TargetDrawable> targets = mTargetDrawables;
-            final TargetDrawable targetIcon = targets.get(i);
-            targetIcon.setPositionX(centerX);
-            targetIcon.setPositionY(centerY);
-            targetIcon.setX(placementRadiusX * (float) Math.cos(angle));
-            targetIcon.setY(placementRadiusY * (float) Math.sin(angle));
-        }
-    }
-
-    private void updateTargetPositions(float centerX, float centerY) {
-        updateTargetPositions(centerX, centerY, false);
-    }
-
-    private void updateTargetPositions(float centerX, float centerY, boolean skipActive) {
-        final int size = mTargetDrawables.size();
-        final float alpha = getSliceAngle();
-        // Reposition the target drawables if the view changed.
-        for (int i = 0; i < size; i++) {
-            if (!skipActive || i != mActiveTarget) {
-                updateTargetPosition(i, centerX, centerY, getAngle(alpha, i));
-            }
-        }
-    }
-
-    private float getAngle(float alpha, int i) {
-        return mFirstItemOffset + alpha * i;
-    }
-
-    private float getSliceAngle() {
-        return (float) (-2.0f * Math.PI / mTargetDrawables.size());
-    }
-
-    private void updatePointCloudPosition(float centerX, float centerY) {
-        mPointCloud.setCenter(centerX, centerY);
-    }
-
-    @Override
-    protected void onDraw(Canvas canvas) {
-        mPointCloud.draw(canvas);
-        mOuterRing.draw(canvas);
-        final int ntargets = mTargetDrawables.size();
-        for (int i = 0; i < ntargets; i++) {
-            TargetDrawable target = mTargetDrawables.get(i);
-            if (target != null) {
-                target.draw(canvas);
-            }
-        }
-        mHandleDrawable.draw(canvas);
-    }
-
-    public void setOnTriggerListener(OnTriggerListener listener) {
-        mOnTriggerListener = listener;
-    }
-
-    private float square(float d) {
-        return d * d;
-    }
-
-    private float dist2(float dx, float dy) {
-        return dx*dx + dy*dy;
-    }
-
-    private float getScaledGlowRadiusSquared() {
-        final float scaledTapRadius;
-        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
-            scaledTapRadius = TAP_RADIUS_SCALE_ACCESSIBILITY_ENABLED * mGlowRadius;
-        } else {
-            scaledTapRadius = mGlowRadius;
-        }
-        return square(scaledTapRadius);
-    }
-
-    private void announceTargets() {
-        StringBuilder utterance = new StringBuilder();
-        final int targetCount = mTargetDrawables.size();
-        for (int i = 0; i < targetCount; i++) {
-            String targetDescription = getTargetDescription(i);
-            String directionDescription = getDirectionDescription(i);
-            if (!TextUtils.isEmpty(targetDescription)
-                    && !TextUtils.isEmpty(directionDescription)) {
-                String text = String.format(directionDescription, targetDescription);
-                utterance.append(text);
-            }
-        }
-        if (utterance.length() > 0) {
-            announceForAccessibility(utterance.toString());
-        }
-    }
-
-    private String getTargetDescription(int index) {
-        if (mTargetDescriptions == null || mTargetDescriptions.isEmpty()) {
-            mTargetDescriptions = loadDescriptions(mTargetDescriptionsResourceId);
-            if (mTargetDrawables.size() != mTargetDescriptions.size()) {
-                Log.w(TAG, "The number of target drawables must be"
-                        + " equal to the number of target descriptions.");
-                return null;
-            }
-        }
-        return mTargetDescriptions.get(index);
-    }
-
-    private String getDirectionDescription(int index) {
-        if (mDirectionDescriptions == null || mDirectionDescriptions.isEmpty()) {
-            mDirectionDescriptions = loadDescriptions(mDirectionDescriptionsResourceId);
-            if (mTargetDrawables.size() != mDirectionDescriptions.size()) {
-                Log.w(TAG, "The number of target drawables must be"
-                        + " equal to the number of direction descriptions.");
-                return null;
-            }
-        }
-        return mDirectionDescriptions.get(index);
-    }
-
-    private ArrayList<String> loadDescriptions(int resourceId) {
-        TypedArray array = getContext().getResources().obtainTypedArray(resourceId);
-        final int count = array.length();
-        ArrayList<String> targetContentDescriptions = new ArrayList<String>(count);
-        for (int i = 0; i < count; i++) {
-            String contentDescription = array.getString(i);
-            targetContentDescriptions.add(contentDescription);
-        }
-        array.recycle();
-        return targetContentDescriptions;
-    }
-
-    public int getResourceIdForTarget(int index) {
-        final TargetDrawable drawable = mTargetDrawables.get(index);
-        return drawable == null ? 0 : drawable.getResourceId();
-    }
-
-    public void setEnableTarget(int resourceId, boolean enabled) {
-        for (int i = 0; i < mTargetDrawables.size(); i++) {
-            final TargetDrawable target = mTargetDrawables.get(i);
-            if (target.getResourceId() == resourceId) {
-                target.setEnabled(enabled);
-                break; // should never be more than one match
-            }
-        }
-    }
-
-    /**
-     * Gets the position of a target in the array that matches the given resource.
-     * @param resourceId
-     * @return the index or -1 if not found
-     */
-    public int getTargetPosition(int resourceId) {
-        for (int i = 0; i < mTargetDrawables.size(); i++) {
-            final TargetDrawable target = mTargetDrawables.get(i);
-            if (target.getResourceId() == resourceId) {
-                return i; // should never be more than one match
-            }
-        }
-        return -1;
-    }
-
-    private boolean replaceTargetDrawables(Resources res, int existingResourceId,
-            int newResourceId) {
-        if (existingResourceId == 0 || newResourceId == 0) {
-            return false;
-        }
-
-        boolean result = false;
-        final ArrayList<TargetDrawable> drawables = mTargetDrawables;
-        final int size = drawables.size();
-        for (int i = 0; i < size; i++) {
-            final TargetDrawable target = drawables.get(i);
-            if (target != null && target.getResourceId() == existingResourceId) {
-                target.setDrawable(res, newResourceId);
-                result = true;
-            }
-        }
-
-        if (result) {
-            requestLayout(); // in case any given drawable's size changes
-        }
-
-        return result;
-    }
-
-    /**
-     * Searches the given package for a resource to use to replace the Drawable on the
-     * target with the given resource id
-     * @param component of the .apk that contains the resource
-     * @param name of the metadata in the .apk
-     * @param existingResId the resource id of the target to search for
-     * @return true if found in the given package and replaced at least one target Drawables
-     */
-    public boolean replaceTargetDrawablesIfPresent(ComponentName component, String name,
-                int existingResId) {
-        if (existingResId == 0) return false;
-
-        boolean replaced = false;
-        if (component != null) {
-            try {
-                PackageManager packageManager = mContext.getPackageManager();
-                // Look for the search icon specified in the activity meta-data
-                Bundle metaData = packageManager.getActivityInfo(
-                        component, PackageManager.GET_META_DATA).metaData;
-                if (metaData != null) {
-                    int iconResId = metaData.getInt(name);
-                    if (iconResId != 0) {
-                        Resources res = packageManager.getResourcesForActivity(component);
-                        replaced = replaceTargetDrawables(res, existingResId, iconResId);
-                    }
-                }
-            } catch (NameNotFoundException e) {
-                Log.w(TAG, "Failed to swap drawable; "
-                        + component.flattenToShortString() + " not found", e);
-            } catch (Resources.NotFoundException nfe) {
-                Log.w(TAG, "Failed to swap drawable from "
-                        + component.flattenToShortString(), nfe);
-            }
-        }
-        if (!replaced) {
-            // Restore the original drawable
-            replaceTargetDrawables(mContext.getResources(), existingResId, existingResId);
-        }
-        return replaced;
-    }
-}
diff --git a/core/java/com/android/internal/widget/multiwaveview/PointCloud.java b/core/java/com/android/internal/widget/multiwaveview/PointCloud.java
deleted file mode 100644
index 6f26b99..0000000
--- a/core/java/com/android/internal/widget/multiwaveview/PointCloud.java
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.widget.multiwaveview;
-
-import java.util.ArrayList;
-
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.drawable.Drawable;
-import android.util.Log;
-
-public class PointCloud {
-    private static final float MIN_POINT_SIZE = 2.0f;
-    private static final float MAX_POINT_SIZE = 4.0f;
-    private static final int INNER_POINTS = 8;
-    private static final String TAG = "PointCloud";
-    private ArrayList<Point> mPointCloud = new ArrayList<Point>();
-    private Drawable mDrawable;
-    private float mCenterX;
-    private float mCenterY;
-    private Paint mPaint;
-    private float mScale = 1.0f;
-    private static final float PI = (float) Math.PI;
-
-    // These allow us to have multiple concurrent animations.
-    WaveManager waveManager = new WaveManager();
-    GlowManager glowManager = new GlowManager();
-    private float mOuterRadius;
-
-    public class WaveManager {
-        private float radius = 50;
-        private float alpha = 0.0f;
-
-        public void setRadius(float r) {
-            radius = r;
-        }
-
-        public float getRadius() {
-            return radius;
-        }
-
-        public void setAlpha(float a) {
-            alpha = a;
-        }
-
-        public float getAlpha() {
-            return alpha;
-        }
-    };
-
-    public class GlowManager {
-        private float x;
-        private float y;
-        private float radius = 0.0f;
-        private float alpha = 0.0f;
-
-        public void setX(float x1) {
-            x = x1;
-        }
-
-        public float getX() {
-            return x;
-        }
-
-        public void setY(float y1) {
-            y = y1;
-        }
-
-        public float getY() {
-            return y;
-        }
-
-        public void setAlpha(float a) {
-            alpha = a;
-        }
-
-        public float getAlpha() {
-            return alpha;
-        }
-
-        public void setRadius(float r) {
-            radius = r;
-        }
-
-        public float getRadius() {
-            return radius;
-        }
-    }
-
-    class Point {
-        float x;
-        float y;
-        float radius;
-
-        public Point(float x2, float y2, float r) {
-            x = (float) x2;
-            y = (float) y2;
-            radius = r;
-        }
-    }
-
-    public PointCloud(Drawable drawable) {
-        mPaint = new Paint();
-        mPaint.setFilterBitmap(true);
-        mPaint.setColor(Color.rgb(255, 255, 255)); // TODO: make configurable
-        mPaint.setAntiAlias(true);
-        mPaint.setDither(true);
-
-        mDrawable = drawable;
-        if (mDrawable != null) {
-            drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
-        }
-    }
-
-    public void setCenter(float x, float y) {
-        mCenterX = x;
-        mCenterY = y;
-    }
-
-    public void makePointCloud(float innerRadius, float outerRadius) {
-        if (innerRadius == 0) {
-            Log.w(TAG, "Must specify an inner radius");
-            return;
-        }
-        mOuterRadius = outerRadius;
-        mPointCloud.clear();
-        final float pointAreaRadius =  (outerRadius - innerRadius);
-        final float ds = (2.0f * PI * innerRadius / INNER_POINTS);
-        final int bands = (int) Math.round(pointAreaRadius / ds);
-        final float dr = pointAreaRadius / bands;
-        float r = innerRadius;
-        for (int b = 0; b <= bands; b++, r += dr) {
-            float circumference = 2.0f * PI * r;
-            final int pointsInBand = (int) (circumference / ds);
-            float eta = PI/2.0f;
-            float dEta = 2.0f * PI / pointsInBand;
-            for (int i = 0; i < pointsInBand; i++) {
-                float x = r * (float) Math.cos(eta);
-                float y = r * (float) Math.sin(eta);
-                eta += dEta;
-                mPointCloud.add(new Point(x, y, r));
-            }
-        }
-    }
-
-    public void setScale(float scale) {
-        mScale  = scale;
-    }
-
-    public float getScale() {
-        return mScale;
-    }
-
-    public int getAlphaForPoint(Point point) {
-        // Contribution from positional glow
-        float glowDistance = (float) Math.hypot(glowManager.x - point.x, glowManager.y - point.y);
-        float glowAlpha = 0.0f;
-        if (glowDistance < glowManager.radius) {
-            float cosf = (float) Math.cos(PI * 0.25f * glowDistance / glowManager.radius);
-            glowAlpha = glowManager.alpha * Math.max(0.0f, (float) Math.pow(cosf, 10.0f));
-        }
-
-        // Compute contribution from Wave
-        float radius = (float) Math.hypot(point.x, point.y);
-        float waveAlpha = 0.0f;
-        if (radius < waveManager.radius * 2) {
-            float distanceToWaveRing = (radius - waveManager.radius);
-            float cosf = (float) Math.cos(PI * 0.5f * distanceToWaveRing / waveManager.radius);
-            waveAlpha = waveManager.alpha * Math.max(0.0f, (float) Math.pow(cosf, 6.0f));
-        }
-        return (int) (Math.max(glowAlpha, waveAlpha) * 255);
-    }
-
-    private float interp(float min, float max, float f) {
-        return min + (max - min) * f;
-    }
-
-    public void draw(Canvas canvas) {
-        ArrayList<Point> points = mPointCloud;
-        canvas.save(Canvas.MATRIX_SAVE_FLAG);
-        canvas.scale(mScale, mScale, mCenterX, mCenterY);
-        for (int i = 0; i < points.size(); i++) {
-            Point point = points.get(i);
-            final float pointSize = interp(MAX_POINT_SIZE, MIN_POINT_SIZE,
-                    point.radius / mOuterRadius);
-            final float px = point.x + mCenterX;
-            final float py = point.y + mCenterY;
-            int alpha = getAlphaForPoint(point);
-
-            if (alpha == 0) continue;
-
-            if (mDrawable != null) {
-                canvas.save(Canvas.MATRIX_SAVE_FLAG);
-                final float cx = mDrawable.getIntrinsicWidth() * 0.5f;
-                final float cy = mDrawable.getIntrinsicHeight() * 0.5f;
-                final float s = pointSize / MAX_POINT_SIZE;
-                canvas.scale(s, s, px, py);
-                canvas.translate(px - cx, py - cy);
-                mDrawable.setAlpha(alpha);
-                mDrawable.draw(canvas);
-                canvas.restore();
-            } else {
-                mPaint.setAlpha(alpha);
-                canvas.drawCircle(px, py, pointSize, mPaint);
-            }
-        }
-        canvas.restore();
-    }
-
-}
diff --git a/core/java/com/android/internal/widget/multiwaveview/TargetDrawable.java b/core/java/com/android/internal/widget/multiwaveview/TargetDrawable.java
deleted file mode 100644
index 5a4c441..0000000
--- a/core/java/com/android/internal/widget/multiwaveview/TargetDrawable.java
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.widget.multiwaveview;
-
-import android.content.res.Resources;
-import android.graphics.Canvas;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.StateListDrawable;
-import android.util.Log;
-
-public class TargetDrawable {
-    private static final String TAG = "TargetDrawable";
-    private static final boolean DEBUG = false;
-
-    public static final int[] STATE_ACTIVE =
-            { android.R.attr.state_enabled, android.R.attr.state_active };
-    public static final int[] STATE_INACTIVE =
-            { android.R.attr.state_enabled, -android.R.attr.state_active };
-    public static final int[] STATE_FOCUSED =
-            { android.R.attr.state_enabled, -android.R.attr.state_active,
-                android.R.attr.state_focused };
-
-    private float mTranslationX = 0.0f;
-    private float mTranslationY = 0.0f;
-    private float mPositionX = 0.0f;
-    private float mPositionY = 0.0f;
-    private float mScaleX = 1.0f;
-    private float mScaleY = 1.0f;
-    private float mAlpha = 1.0f;
-    private Drawable mDrawable;
-    private boolean mEnabled = true;
-    private final int mResourceId;
-
-    public TargetDrawable(Resources res, int resId) {
-        mResourceId = resId;
-        setDrawable(res, resId);
-    }
-
-    public void setDrawable(Resources res, int resId) {
-        // Note we explicitly don't set mResourceId to resId since we allow the drawable to be
-        // swapped at runtime and want to re-use the existing resource id for identification.
-        Drawable drawable = resId == 0 ? null : res.getDrawable(resId);
-        // Mutate the drawable so we can animate shared drawable properties.
-        mDrawable = drawable != null ? drawable.mutate() : null;
-        resizeDrawables();
-        setState(STATE_INACTIVE);
-    }
-
-    public TargetDrawable(TargetDrawable other) {
-        mResourceId = other.mResourceId;
-        // Mutate the drawable so we can animate shared drawable properties.
-        mDrawable = other.mDrawable != null ? other.mDrawable.mutate() : null;
-        resizeDrawables();
-        setState(STATE_INACTIVE);
-    }
-
-    public void setState(int [] state) {
-        if (mDrawable instanceof StateListDrawable) {
-            StateListDrawable d = (StateListDrawable) mDrawable;
-            d.setState(state);
-        }
-    }
-
-    public boolean hasState(int [] state) {
-        if (mDrawable instanceof StateListDrawable) {
-            StateListDrawable d = (StateListDrawable) mDrawable;
-            // TODO: this doesn't seem to work
-            return d.getStateDrawableIndex(state) != -1;
-        }
-        return false;
-    }
-
-    /**
-     * Returns true if the drawable is a StateListDrawable and is in the focused state.
-     *
-     * @return
-     */
-    public boolean isActive() {
-        if (mDrawable instanceof StateListDrawable) {
-            StateListDrawable d = (StateListDrawable) mDrawable;
-            int[] states = d.getState();
-            for (int i = 0; i < states.length; i++) {
-                if (states[i] == android.R.attr.state_focused) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Returns true if this target is enabled. Typically an enabled target contains a valid
-     * drawable in a valid state. Currently all targets with valid drawables are valid.
-     *
-     * @return
-     */
-    public boolean isEnabled() {
-        return mDrawable != null && mEnabled;
-    }
-
-    /**
-     * Makes drawables in a StateListDrawable all the same dimensions.
-     * If not a StateListDrawable, then justs sets the bounds to the intrinsic size of the
-     * drawable.
-     */
-    private void resizeDrawables() {
-        if (mDrawable instanceof StateListDrawable) {
-            StateListDrawable d = (StateListDrawable) mDrawable;
-            int maxWidth = 0;
-            int maxHeight = 0;
-            for (int i = 0; i < d.getStateCount(); i++) {
-                Drawable childDrawable = d.getStateDrawable(i);
-                maxWidth = Math.max(maxWidth, childDrawable.getIntrinsicWidth());
-                maxHeight = Math.max(maxHeight, childDrawable.getIntrinsicHeight());
-            }
-            if (DEBUG) Log.v(TAG, "union of childDrawable rects " + d + " to: "
-                        + maxWidth + "x" + maxHeight);
-            d.setBounds(0, 0, maxWidth, maxHeight);
-            for (int i = 0; i < d.getStateCount(); i++) {
-                Drawable childDrawable = d.getStateDrawable(i);
-                if (DEBUG) Log.v(TAG, "sizing drawable " + childDrawable + " to: "
-                            + maxWidth + "x" + maxHeight);
-                childDrawable.setBounds(0, 0, maxWidth, maxHeight);
-            }
-        } else if (mDrawable != null) {
-            mDrawable.setBounds(0, 0,
-                    mDrawable.getIntrinsicWidth(), mDrawable.getIntrinsicHeight());
-        }
-    }
-
-    public void setX(float x) {
-        mTranslationX = x;
-    }
-
-    public void setY(float y) {
-        mTranslationY = y;
-    }
-
-    public void setScaleX(float x) {
-        mScaleX = x;
-    }
-
-    public void setScaleY(float y) {
-        mScaleY = y;
-    }
-
-    public void setAlpha(float alpha) {
-        mAlpha = alpha;
-    }
-
-    public float getX() {
-        return mTranslationX;
-    }
-
-    public float getY() {
-        return mTranslationY;
-    }
-
-    public float getScaleX() {
-        return mScaleX;
-    }
-
-    public float getScaleY() {
-        return mScaleY;
-    }
-
-    public float getAlpha() {
-        return mAlpha;
-    }
-
-    public void setPositionX(float x) {
-        mPositionX = x;
-    }
-
-    public void setPositionY(float y) {
-        mPositionY = y;
-    }
-
-    public float getPositionX() {
-        return mPositionX;
-    }
-
-    public float getPositionY() {
-        return mPositionY;
-    }
-
-    public int getWidth() {
-        return mDrawable != null ? mDrawable.getIntrinsicWidth() : 0;
-    }
-
-    public int getHeight() {
-        return mDrawable != null ? mDrawable.getIntrinsicHeight() : 0;
-    }
-
-    public void draw(Canvas canvas) {
-        if (mDrawable == null || !mEnabled) {
-            return;
-        }
-        canvas.save(Canvas.MATRIX_SAVE_FLAG);
-        canvas.scale(mScaleX, mScaleY, mPositionX, mPositionY);
-        canvas.translate(mTranslationX + mPositionX, mTranslationY + mPositionY);
-        canvas.translate(-0.5f * getWidth(), -0.5f * getHeight());
-        mDrawable.setAlpha((int) Math.round(mAlpha * 255f));
-        mDrawable.draw(canvas);
-        canvas.restore();
-    }
-
-    public void setEnabled(boolean enabled) {
-        mEnabled  = enabled;
-    }
-
-    public int getResourceId() {
-        return mResourceId;
-    }
-}
diff --git a/core/java/com/android/internal/widget/multiwaveview/Tweener.java b/core/java/com/android/internal/widget/multiwaveview/Tweener.java
deleted file mode 100644
index d559d9d..0000000
--- a/core/java/com/android/internal/widget/multiwaveview/Tweener.java
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.widget.multiwaveview;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map.Entry;
-
-import android.animation.Animator.AnimatorListener;
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ObjectAnimator;
-import android.animation.PropertyValuesHolder;
-import android.animation.TimeInterpolator;
-import android.animation.ValueAnimator.AnimatorUpdateListener;
-import android.util.Log;
-
-class Tweener {
-    private static final String TAG = "Tweener";
-    private static final boolean DEBUG = false;
-
-    ObjectAnimator animator;
-    private static HashMap<Object, Tweener> sTweens = new HashMap<Object, Tweener>();
-
-    public Tweener(ObjectAnimator anim) {
-        animator = anim;
-    }
-
-    private static void remove(Animator animator) {
-        Iterator<Entry<Object, Tweener>> iter = sTweens.entrySet().iterator();
-        while (iter.hasNext()) {
-            Entry<Object, Tweener> entry = iter.next();
-            if (entry.getValue().animator == animator) {
-                if (DEBUG) Log.v(TAG, "Removing tweener " + sTweens.get(entry.getKey())
-                        + " sTweens.size() = " + sTweens.size());
-                iter.remove();
-                break; // an animator can only be attached to one object
-            }
-        }
-    }
-
-    public static Tweener to(Object object, long duration, Object... vars) {
-        long delay = 0;
-        AnimatorUpdateListener updateListener = null;
-        AnimatorListener listener = null;
-        TimeInterpolator interpolator = null;
-
-        // Iterate through arguments and discover properties to animate
-        ArrayList<PropertyValuesHolder> props = new ArrayList<PropertyValuesHolder>(vars.length/2);
-        for (int i = 0; i < vars.length; i+=2) {
-            if (!(vars[i] instanceof String)) {
-                throw new IllegalArgumentException("Key must be a string: " + vars[i]);
-            }
-            String key = (String) vars[i];
-            Object value = vars[i+1];
-            if ("simultaneousTween".equals(key)) {
-                // TODO
-            } else if ("ease".equals(key)) {
-                interpolator = (TimeInterpolator) value; // TODO: multiple interpolators?
-            } else if ("onUpdate".equals(key) || "onUpdateListener".equals(key)) {
-                updateListener = (AnimatorUpdateListener) value;
-            } else if ("onComplete".equals(key) || "onCompleteListener".equals(key)) {
-                listener = (AnimatorListener) value;
-            } else if ("delay".equals(key)) {
-                delay = ((Number) value).longValue();
-            } else if ("syncWith".equals(key)) {
-                // TODO
-            } else if (value instanceof float[]) {
-                props.add(PropertyValuesHolder.ofFloat(key,
-                        ((float[])value)[0], ((float[])value)[1]));
-            } else if (value instanceof int[]) {
-                props.add(PropertyValuesHolder.ofInt(key,
-                        ((int[])value)[0], ((int[])value)[1]));
-            } else if (value instanceof Number) {
-                float floatValue = ((Number)value).floatValue();
-                props.add(PropertyValuesHolder.ofFloat(key, floatValue));
-            } else {
-                throw new IllegalArgumentException(
-                        "Bad argument for key \"" + key + "\" with value " + value.getClass());
-            }
-        }
-
-        // Re-use existing tween, if present
-        Tweener tween = sTweens.get(object);
-        ObjectAnimator anim = null;
-        if (tween == null) {
-            anim = ObjectAnimator.ofPropertyValuesHolder(object,
-                    props.toArray(new PropertyValuesHolder[props.size()]));
-            tween = new Tweener(anim);
-            sTweens.put(object, tween);
-            if (DEBUG) Log.v(TAG, "Added new Tweener " + tween);
-        } else {
-            anim = sTweens.get(object).animator;
-            replace(props, object); // Cancel all animators for given object
-        }
-
-        if (interpolator != null) {
-            anim.setInterpolator(interpolator);
-        }
-
-        // Update animation with properties discovered in loop above
-        anim.setStartDelay(delay);
-        anim.setDuration(duration);
-        if (updateListener != null) {
-            anim.removeAllUpdateListeners(); // There should be only one
-            anim.addUpdateListener(updateListener);
-        }
-        if (listener != null) {
-            anim.removeAllListeners(); // There should be only one.
-            anim.addListener(listener);
-        }
-        anim.addListener(mCleanupListener);
-
-        return tween;
-    }
-
-    Tweener from(Object object, long duration, Object... vars) {
-        // TODO:  for v of vars
-        //            toVars[v] = object[v]
-        //            object[v] = vars[v]
-        return Tweener.to(object, duration, vars);
-    }
-
-    // Listener to watch for completed animations and remove them.
-    private static AnimatorListener mCleanupListener = new AnimatorListenerAdapter() {
-
-        @Override
-        public void onAnimationEnd(Animator animation) {
-            remove(animation);
-        }
-
-        @Override
-        public void onAnimationCancel(Animator animation) {
-            remove(animation);
-        }
-    };
-
-    public static void reset() {
-        if (DEBUG) {
-            Log.v(TAG, "Reset()");
-            if (sTweens.size() > 0) {
-                Log.v(TAG, "Cleaning up " + sTweens.size() + " animations");
-            }
-        }
-        sTweens.clear();
-    }
-
-    private static void replace(ArrayList<PropertyValuesHolder> props, Object... args) {
-        for (final Object killobject : args) {
-            Tweener tween = sTweens.get(killobject);
-            if (tween != null) {
-                tween.animator.cancel();
-                if (props != null) {
-                    tween.animator.setValues(
-                            props.toArray(new PropertyValuesHolder[props.size()]));
-                } else {
-                    sTweens.remove(tween);
-                }
-            }
-        }
-    }
-}
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index 9996ce1..9ea63aa 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -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/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/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/notification_template_material_base.xml b/core/res/res/layout/notification_template_material_base.xml
index 3fdcaf7..ea22b15 100644
--- a/core/res/res/layout/notification_template_material_base.xml
+++ b/core/res/res/layout/notification_template_material_base.xml
@@ -16,12 +16,9 @@
   -->
 
 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:internal="http://schemas.android.com/apk/prv/res/android"
     android:id="@+id/status_bar_latest_event_content"
     android:layout_width="match_parent"
     android:layout_height="64dp"
-    internal:layout_minHeight="64dp"
-    internal:layout_maxHeight="64dp"
     >
     <include layout="@layout/notification_template_icon_group"
         android:layout_width="@dimen/notification_large_icon_width"
diff --git a/core/res/res/layout/notification_template_material_big_base.xml b/core/res/res/layout/notification_template_material_big_base.xml
index 935424a..2a3ee90 100644
--- a/core/res/res/layout/notification_template_material_big_base.xml
+++ b/core/res/res/layout/notification_template_material_big_base.xml
@@ -16,12 +16,9 @@
   -->
 
 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:internal="http://schemas.android.com/apk/prv/res/android"
     android:id="@+id/status_bar_latest_event_content"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    internal:layout_minHeight="65dp"
-    internal:layout_maxHeight="unbounded"
     >
     <include layout="@layout/notification_template_icon_group"
         android:layout_width="@dimen/notification_large_icon_width"
diff --git a/core/res/res/layout/notification_template_material_big_picture.xml b/core/res/res/layout/notification_template_material_big_picture.xml
index 302e651..f1a9549 100644
--- a/core/res/res/layout/notification_template_material_big_picture.xml
+++ b/core/res/res/layout/notification_template_material_big_picture.xml
@@ -16,12 +16,9 @@
   -->
 
 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:internal="http://schemas.android.com/apk/prv/res/android"
     android:id="@+id/status_bar_latest_event_content"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    internal:layout_minHeight="65dp"
-    internal:layout_maxHeight="unbounded"
     >
     <ImageView
         android:id="@+id/big_picture"
diff --git a/core/res/res/layout/notification_template_material_big_text.xml b/core/res/res/layout/notification_template_material_big_text.xml
index d0c10b2..f657f04 100644
--- a/core/res/res/layout/notification_template_material_big_text.xml
+++ b/core/res/res/layout/notification_template_material_big_text.xml
@@ -16,12 +16,9 @@
   -->
 
 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:internal="http://schemas.android.com/apk/prv/res/android"
     android:id="@+id/status_bar_latest_event_content"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    internal:layout_minHeight="65dp"
-    internal:layout_maxHeight="unbounded"
     >
     <include layout="@layout/notification_template_icon_group"
         android:layout_width="@dimen/notification_large_icon_width"
diff --git a/core/res/res/layout/notification_template_material_inbox.xml b/core/res/res/layout/notification_template_material_inbox.xml
index ac448ee..d292d4e 100644
--- a/core/res/res/layout/notification_template_material_inbox.xml
+++ b/core/res/res/layout/notification_template_material_inbox.xml
@@ -16,12 +16,9 @@
   -->
 
 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:internal="http://schemas.android.com/apk/prv/res/android"
     android:id="@+id/status_bar_latest_event_content"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    internal:layout_minHeight="65dp"
-    internal:layout_maxHeight="unbounded"
     >
     <include layout="@layout/notification_template_icon_group"
         android:layout_width="@dimen/notification_large_icon_width"
diff --git a/core/res/res/layout/notification_template_material_media.xml b/core/res/res/layout/notification_template_material_media.xml
index 69020a4..0292d28 100644
--- a/core/res/res/layout/notification_template_material_media.xml
+++ b/core/res/res/layout/notification_template_material_media.xml
@@ -16,14 +16,11 @@
   -->
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:internal="http://schemas.android.com/apk/prv/res/android"
     android:id="@+id/status_bar_latest_event_content"
     android:layout_width="match_parent"
     android:layout_height="64dp"
     android:orientation="horizontal"
     android:background="#00000000"
-    internal:layout_minHeight="64dp"
-    internal:layout_maxHeight="64dp"
     >
     <include layout="@layout/notification_template_icon_group"
         android:layout_width="@dimen/notification_large_icon_width"
diff --git a/core/res/res/values-television/config.xml b/core/res/res/values-television/config.xml
new file mode 100644
index 0000000..3435474
--- /dev/null
+++ b/core/res/res/values-television/config.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+     for TV products.  Do not translate. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+    <!-- Flags enabling default window features. See Window.java -->
+    <bool name="config_defaultWindowFeatureOptionsPanel">false</bool>
+</resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 551c044..39c42ee 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -7034,75 +7034,16 @@
     <!-- =============================== -->
     <eat-comment />
     <declare-styleable name="GlowPadView">
-        <!-- Reference to an array resource that be shown as targets around a circle. -->
-        <attr name="targetDrawables" format="reference" />
-
-        <!-- Reference to an array resource that be used as description for the targets around the circle. -->
+        <!-- Reference to an array resource that be used as description for the targets around the circle.
+             {@deprecated Removed.} -->
         <attr name="targetDescriptions" format="reference" />
 
-        <!-- Reference to an array resource that be used to announce the directions with targets around the circle. -->
+        <!-- Reference to an array resource that be used to announce the directions with targets around the circle.
+             {@deprecated Removed.}-->
         <attr name="directionDescriptions" format="reference" />
-
-        <!-- Sets a drawable as the center. -->
-        <attr name="handleDrawable" format="reference" />
-
-        <!-- Drawable to use for wave ripple animation. -->
-        <attr name="outerRingDrawable" format="reference"/>
-
-        <!-- Drawble used for drawing points -->
-        <attr name="pointDrawable" format="reference" />
-
-        <!-- Inner radius of glow area. -->
-        <attr name="innerRadius"/>
-
-        <!-- Outer radius of glow area. Target icons will be drawn on this circle. -->
-        <attr name="outerRadius" format="dimension" />
-
-        <!-- Radius of glow under finger. -->
-        <attr name="glowRadius" format="dimension" />
-
-        <!-- Tactile feedback duration for actions. Set to '0' for no vibration. -->
-        <attr name="vibrationDuration" format="integer" />
-
-        <!-- How close we need to be before snapping to a target. -->
-        <attr name="snapMargin" format="dimension" />
-
-        <!-- Number of waves/chevrons to show in animation. -->
-        <attr name="feedbackCount" format="integer" />
-
-        <!-- Used when the handle shouldn't wait to be hit before following the finger -->
-        <attr name="alwaysTrackFinger" format="boolean" />
-
-        <!-- Location along the circle of the first item, in degrees.-->
-        <attr name="firstItemOffset" format="float" />
-
-        <!-- Causes targets to snap to the finger location on activation. -->
-        <attr name="magneticTargets" format="boolean" />
-
-        <attr name="gravity" />
-
-        <!-- Determine whether the glow pad is allowed to scale to fit the bounds indicated
-            by its parent. If this is set to false, no scaling will occur. If this is set to true
-            scaling will occur to fit for any axis in which gravity is set to center. -->
-        <attr name="allowScaling" format="boolean" />
     </declare-styleable>
 
     <!-- =============================== -->
-    <!-- SizeAdaptiveLayout class attributes -->
-    <!-- =============================== -->
-    <eat-comment />
-    <declare-styleable name="SizeAdaptiveLayout_Layout">
-      <!-- The maximum valid height for this item. -->
-      <attr name="layout_maxHeight" format="dimension">
-        <!-- Indicates that the view may be resized arbitrarily large. -->
-        <enum name="unbounded" value="-1" />
-      </attr>
-      <!-- The minimum valid height for this item. -->
-      <attr name="layout_minHeight" format="dimension" />
-    </declare-styleable>
-    <declare-styleable name="SizeAdaptiveLayout" />
-
-    <!-- =============================== -->
     <!-- Location package class attributes -->
     <!-- =============================== -->
     <eat-comment />
@@ -7509,11 +7450,6 @@
         <enum name="pageDeleteDropTarget" value="7" />
     </attr>
 
-    <declare-styleable name="SlidingChallengeLayout_Layout">
-        <attr name="layout_childType" />
-        <attr name="layout_maxHeight" />
-    </declare-styleable>
-
     <!-- Attributes that can be used with <code>&lt;FragmentBreadCrumbs&gt;</code>
     tags. -->
     <declare-styleable name="FragmentBreadCrumbs">
@@ -7522,27 +7458,6 @@
         <attr name="itemColor" format="color|reference" />
     </declare-styleable>
 
-    <declare-styleable name="MultiPaneChallengeLayout">
-        <!-- Influences how layout_centerWithinArea behaves -->
-        <attr name="orientation" />
-    </declare-styleable>
-
-    <declare-styleable name="MultiPaneChallengeLayout_Layout">
-        <!-- Percentage of the screen this child should consume or center within.
-             If 0/default, the view will be measured by standard rules
-             as if this were a FrameLayout. -->
-        <attr name="layout_centerWithinArea" format="float" />
-        <attr name="layout_childType" />
-        <attr name="layout_gravity" />
-        <attr name="layout_maxWidth" format="dimension" />
-        <attr name="layout_maxHeight" />
-    </declare-styleable>
-
-    <declare-styleable name="KeyguardSecurityViewFlipper_Layout">
-        <attr name="layout_maxWidth" />
-        <attr name="layout_maxHeight" />
-    </declare-styleable>
-
     <declare-styleable name="Toolbar">
         <attr name="titleTextAppearance" format="reference" />
         <attr name="subtitleTextAppearance" format="reference" />
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/public.xml b/core/res/res/values/public.xml
index 9f49b08..9945c63 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1759,7 +1759,9 @@
   <public type="attr" name="actionModeSplitBackground" id="0x0101039d" />
   <public type="attr" name="textAppearanceListItem" id="0x0101039e" />
   <public type="attr" name="textAppearanceListItemSmall" id="0x0101039f" />
+  <!-- @deprecated Removed. -->
   <public type="attr" name="targetDescriptions" id="0x010103a0" />
+  <!-- @deprecated Removed. -->
   <public type="attr" name="directionDescriptions" id="0x010103a1" />
   <public type="attr" name="overridesImplicitlyEnabledSubtype" id="0x010103a2" />
   <public type="attr" name="listPreferredItemPaddingLeft" id="0x010103a3" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index f51e82c9..efdc3c8 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -5188,4 +5188,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..607744f 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" />
 
@@ -2154,4 +2155,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/core/tests/coretests/res/layout/size_adaptive.xml b/core/tests/coretests/res/layout/size_adaptive.xml
deleted file mode 100644
index 03d0574..0000000
--- a/core/tests/coretests/res/layout/size_adaptive.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 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.
--->
-<com.android.internal.widget.SizeAdaptiveLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:internal="http://schemas.android.com/apk/prv/res/android"
-    android:id="@+id/multi1"
-    android:layout_width="match_parent"
-    android:layout_height="64dp" >
-
-    <include
-        android:id="@+id/one_u"
-        layout="@layout/size_adaptive_one_u"
-        android:layout_width="fill_parent"
-        android:layout_height="64dp"
-        internal:layout_minHeight="64dp"
-        internal:layout_maxHeight="64dp"
-        />
-
-    <include
-        android:id="@+id/four_u"
-        layout="@layout/size_adaptive_four_u"
-        android:layout_width="fill_parent"
-        android:layout_height="wrap_content"
-        internal:layout_minHeight="65dp"
-        internal:layout_maxHeight="unbounded"/>
-
-</com.android.internal.widget.SizeAdaptiveLayout>
diff --git a/core/tests/coretests/res/layout/size_adaptive_color.xml b/core/tests/coretests/res/layout/size_adaptive_color.xml
deleted file mode 100644
index cdb7a59..0000000
--- a/core/tests/coretests/res/layout/size_adaptive_color.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 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.
--->
-<com.android.internal.widget.SizeAdaptiveLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:internal="http://schemas.android.com/apk/prv/res/android"
-    android:background="#ffffff"
-    android:id="@+id/multi1"
-    android:layout_width="match_parent"
-    android:layout_height="64dp" >
-
-    <include
-        android:id="@+id/one_u"
-        layout="@layout/size_adaptive_one_u"
-        android:layout_width="fill_parent"
-        android:layout_height="64dp"
-        internal:layout_minHeight="64dp"
-        internal:layout_maxHeight="64dp"
-        />
-
-    <include
-        android:id="@+id/four_u"
-        layout="@layout/size_adaptive_four_u"
-        android:layout_width="fill_parent"
-        android:layout_height="wrap_content"
-        internal:layout_minHeight="65dp"
-        internal:layout_maxHeight="unbounded"/>
-
-</com.android.internal.widget.SizeAdaptiveLayout>
diff --git a/core/tests/coretests/res/layout/size_adaptive_color_statelist.xml b/core/tests/coretests/res/layout/size_adaptive_color_statelist.xml
deleted file mode 100644
index d24df5b..0000000
--- a/core/tests/coretests/res/layout/size_adaptive_color_statelist.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 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.
--->
-<com.android.internal.widget.SizeAdaptiveLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:internal="http://schemas.android.com/apk/prv/res/android"
-    android:background="@drawable/size_adaptive_statelist"
-    android:id="@+id/multi1"
-    android:layout_width="match_parent"
-    android:layout_height="64dp" >
-
-    <include
-        android:id="@+id/one_u"
-        layout="@layout/size_adaptive_one_u"
-        android:layout_width="fill_parent"
-        android:layout_height="64dp"
-        internal:layout_minHeight="64dp"
-        internal:layout_maxHeight="64dp"
-        />
-
-    <include
-        android:id="@+id/four_u"
-        layout="@layout/size_adaptive_four_u"
-        android:layout_width="fill_parent"
-        android:layout_height="wrap_content"
-        internal:layout_minHeight="65dp"
-        internal:layout_maxHeight="unbounded"/>
-
-</com.android.internal.widget.SizeAdaptiveLayout>
diff --git a/core/tests/coretests/res/layout/size_adaptive_four_u.xml b/core/tests/coretests/res/layout/size_adaptive_four_u.xml
deleted file mode 100644
index 232b921..0000000
--- a/core/tests/coretests/res/layout/size_adaptive_four_u.xml
+++ /dev/null
@@ -1,68 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 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.
--->
-<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/gridLayout4"
-    android:layout_width="match_parent"
-    android:layout_height="256dp"
-    android:background="#000000"
-    android:columnCount="2"
-    android:padding="1dp" >
-
-    <ImageView
-        android:id="@+id/actor"
-        android:layout_width="62dp"
-        android:layout_height="62dp"
-        android:layout_row="0"
-        android:layout_column="0"
-        android:layout_rowSpan="2"
-        android:contentDescription="@string/actor"
-        android:src="@drawable/abe" />
-
-    <TextView
-        android:layout_width="0dp"
-        android:id="@+id/name"
-        android:layout_row="0"
-        android:layout_column="1"
-        android:layout_gravity="fill_horizontal"
-        android:padding="3dp"
-        android:text="@string/actor"
-        android:textColor="#ffffff"
-        android:textStyle="bold" />
-
-    <ImageView
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        android:layout_row="1"
-        android:layout_column="1"
-        android:layout_gravity="fill_horizontal"
-        android:padding="5dp"
-        android:adjustViewBounds="true"
-        android:background="#555555"
-        android:scaleType="centerCrop"
-        android:src="@drawable/gettysburg"
-        android:contentDescription="@string/caption" />
-
-    <TextView
-        android:layout_width="0dp"
-        android:id="@+id/note"
-        android:layout_row="2"
-        android:layout_column="1"
-        android:layout_gravity="fill_horizontal"
-        android:padding="3dp"
-        android:singleLine="true"
-        android:text="@string/first"
-        android:textColor="#ffffff" />
-</GridLayout>
diff --git a/core/tests/coretests/res/layout/size_adaptive_four_u_text.xml b/core/tests/coretests/res/layout/size_adaptive_four_u_text.xml
deleted file mode 100644
index 93a10de..0000000
--- a/core/tests/coretests/res/layout/size_adaptive_four_u_text.xml
+++ /dev/null
@@ -1,59 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 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.
--->
-<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/gridLayout4"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:background="#000000"
-    android:columnCount="2"
-    android:padding="1dp"
-    android:orientation="horizontal" >
-
-    <ImageView
-        android:id="@+id/actor"
-        android:layout_width="62dp"
-        android:layout_height="62dp"
-        android:layout_row="0"
-        android:layout_column="0"
-        android:layout_rowSpan="2"
-        android:contentDescription="@string/actor"
-        android:src="@drawable/abe" />
-
-    <TextView
-        android:layout_width="0dp"
-        android:id="@+id/name"
-        android:layout_row="0"
-        android:layout_column="1"
-        android:layout_gravity="fill_horizontal"
-        android:padding="3dp"
-        android:text="@string/actor"
-        android:textColor="#ffffff"
-        android:textStyle="bold" />
-
-    <TextView
-        android:id="@+id/note"
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        android:layout_column="1"
-        android:layout_gravity="fill_horizontal"
-        android:layout_marginTop="5dp"
-        android:layout_row="1"
-        android:padding="3dp"
-        android:singleLine="false"
-        android:text="@string/first"
-        android:textColor="#ffffff" />
-
-    </GridLayout>
diff --git a/core/tests/coretests/res/layout/size_adaptive_gappy.xml b/core/tests/coretests/res/layout/size_adaptive_gappy.xml
deleted file mode 100644
index d5e3b41..0000000
--- a/core/tests/coretests/res/layout/size_adaptive_gappy.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 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.
--->
-<com.android.internal.widget.SizeAdaptiveLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:internal="http://schemas.android.com/apk/prv/res/android"
-    android:id="@+id/multi_with_gap"
-    android:layout_width="match_parent"
-    android:layout_height="64dp" >
-
-    <include
-        android:id="@+id/one_u"
-        layout="@layout/size_adaptive_one_u"
-        android:layout_width="fill_parent"
-        android:layout_height="64dp"
-        internal:layout_minHeight="64dp"
-        internal:layout_maxHeight="64dp"
-        />
-
-    <include
-        android:id="@+id/four_u"
-        layout="@layout/size_adaptive_four_u"
-        android:layout_width="fill_parent"
-        android:layout_height="256dp"
-        internal:layout_minHeight="128dp"
-        internal:layout_maxHeight="unbounded"/>
-
-</com.android.internal.widget.SizeAdaptiveLayout>
diff --git a/core/tests/coretests/res/layout/size_adaptive_large_only.xml b/core/tests/coretests/res/layout/size_adaptive_large_only.xml
deleted file mode 100644
index cf58265..0000000
--- a/core/tests/coretests/res/layout/size_adaptive_large_only.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 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.
--->
-<com.android.internal.widget.SizeAdaptiveLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:internal="http://schemas.android.com/apk/prv/res/android"
-    android:id="@+id/large_only_multi"
-    android:layout_width="match_parent"
-    android:layout_height="64dp" >
-
-    <include
-        android:id="@+id/four_u"
-        layout="@layout/size_adaptive_four_u"
-        android:layout_width="fill_parent"
-        android:layout_height="256dp"
-        internal:layout_minHeight="65dp"
-        internal:layout_maxHeight="unbounded"/>
-
-</com.android.internal.widget.SizeAdaptiveLayout>
diff --git a/core/tests/coretests/res/layout/size_adaptive_lies.xml b/core/tests/coretests/res/layout/size_adaptive_lies.xml
deleted file mode 100644
index 7de892e..0000000
--- a/core/tests/coretests/res/layout/size_adaptive_lies.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 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.
--->
-<com.android.internal.widget.SizeAdaptiveLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:internal="http://schemas.android.com/apk/prv/res/android"
-    android:id="@+id/multi1"
-    android:layout_width="match_parent"
-    android:layout_height="64dp" >
-
-    <include
-        android:id="@+id/one_u"
-        layout="@layout/size_adaptive_one_u"
-        android:layout_width="fill_parent"
-        android:layout_height="64dp"
-        internal:layout_minHeight="64dp"
-        internal:layout_maxHeight="64dp"
-        />
-
-    <include
-        android:id="@+id/four_u"
-        layout="@layout/size_adaptive_one_u"
-        android:layout_width="fill_parent"
-        android:layout_height="wrap_content"
-        internal:layout_minHeight="65dp"
-        internal:layout_maxHeight="unbounded"/>
-
-</com.android.internal.widget.SizeAdaptiveLayout>
diff --git a/core/tests/coretests/res/layout/size_adaptive_one_u.xml b/core/tests/coretests/res/layout/size_adaptive_one_u.xml
deleted file mode 100644
index b6fe4a0..0000000
--- a/core/tests/coretests/res/layout/size_adaptive_one_u.xml
+++ /dev/null
@@ -1,66 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 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.
--->
-<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/gridLayout1"
-    android:layout_width="match_parent"
-    android:layout_height="64dp"
-    android:background="#000000"
-    android:columnCount="3"
-    android:padding="1dp"
-    android:rowCount="2" >
-
-    <ImageView
-        android:id="@+id/actor"
-        android:layout_width="62dp"
-        android:layout_height="62dp"
-        android:layout_column="0"
-        android:layout_row="0"
-        android:layout_rowSpan="2"
-        android:contentDescription="@string/actor"
-        android:src="@drawable/abe" />
-
-    <TextView
-        android:id="@+id/name"
-        android:layout_gravity="fill"
-        android:padding="3dp"
-        android:text="@string/actor"
-        android:textColor="#ffffff"
-        android:textStyle="bold" />
-
-    <ImageView
-        android:layout_width="62dp"
-        android:layout_height="62dp"
-        android:layout_gravity="fill_vertical"
-        android:layout_rowSpan="2"
-        android:adjustViewBounds="true"
-        android:background="#555555"
-        android:padding="2dp"
-        android:scaleType="fitXY"
-        android:src="@drawable/gettysburg"
-        android:contentDescription="@string/caption" />
-
-    <TextView
-        android:id="@+id/note"
-        android:layout_width="0dp"
-        android:layout_height="0dp"
-        android:layout_gravity="fill"
-        android:layout_marginTop="5dp"
-        android:padding="3dp"
-        android:singleLine="true"
-        android:text="@string/first"
-        android:textColor="#ffffff" />
-
-</GridLayout>
diff --git a/core/tests/coretests/res/layout/size_adaptive_one_u_text.xml b/core/tests/coretests/res/layout/size_adaptive_one_u_text.xml
deleted file mode 100644
index df54eb6..0000000
--- a/core/tests/coretests/res/layout/size_adaptive_one_u_text.xml
+++ /dev/null
@@ -1,54 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 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.
--->
-<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/gridLayout1"
-    android:layout_width="match_parent"
-    android:layout_height="64dp"
-    android:background="#000000"
-    android:columnCount="2"
-    android:padding="1dp"
-    android:rowCount="2" >
-
-    <ImageView
-        android:id="@+id/actor"
-        android:layout_width="62dp"
-        android:layout_height="62dp"
-        android:layout_column="0"
-        android:layout_row="0"
-        android:layout_rowSpan="2"
-        android:contentDescription="@string/actor"
-        android:src="@drawable/abe" />
-
-    <TextView
-        android:id="@+id/name"
-        android:layout_gravity="fill"
-        android:padding="3dp"
-        android:text="@string/actor"
-        android:textColor="#ffffff"
-        android:textStyle="bold" />
-
-    <TextView
-        android:id="@+id/note"
-        android:layout_width="0dp"
-        android:layout_height="0dp"
-        android:layout_gravity="fill"
-        android:layout_marginTop="5dp"
-        android:padding="3dp"
-        android:singleLine="true"
-        android:text="@string/first"
-        android:textColor="#ffffff" />
-
-</GridLayout>
diff --git a/core/tests/coretests/res/layout/size_adaptive_overlapping.xml b/core/tests/coretests/res/layout/size_adaptive_overlapping.xml
deleted file mode 100644
index 4abe8b0..0000000
--- a/core/tests/coretests/res/layout/size_adaptive_overlapping.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 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.
--->
-<com.android.internal.widget.SizeAdaptiveLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:internal="http://schemas.android.com/apk/prv/res/android"
-    android:id="@+id/multi_with_overlap"
-    android:layout_width="match_parent"
-    android:layout_height="64dp" >
-
-    <include
-        android:id="@+id/one_u"
-        layout="@layout/size_adaptive_one_u"
-        android:layout_width="fill_parent"
-        android:layout_height="64dp"
-        internal:layout_minHeight="64dp"
-        internal:layout_maxHeight="64dp"
-        />
-
-    <include
-        android:id="@+id/four_u"
-        layout="@layout/size_adaptive_four_u"
-        android:layout_width="fill_parent"
-        android:layout_height="256dp"
-        internal:layout_minHeight="64dp"
-        internal:layout_maxHeight="256dp"/>
-
-</com.android.internal.widget.SizeAdaptiveLayout>
diff --git a/core/tests/coretests/res/layout/size_adaptive_singleton.xml b/core/tests/coretests/res/layout/size_adaptive_singleton.xml
deleted file mode 100644
index eba387f..0000000
--- a/core/tests/coretests/res/layout/size_adaptive_singleton.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 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.
--->
-<com.android.internal.widget.SizeAdaptiveLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:internal="http://schemas.android.com/apk/prv/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="64dp" >
-
-    <include
-        android:id="@+id/one_u"
-        layout="@layout/size_adaptive_one_u_text"
-        android:layout_width="fill_parent"
-        android:layout_height="64dp"
-        internal:layout_minHeight="64dp"
-        internal:layout_maxHeight="64dp"
-        />
-
-</com.android.internal.widget.SizeAdaptiveLayout>
diff --git a/core/tests/coretests/res/layout/size_adaptive_text.xml b/core/tests/coretests/res/layout/size_adaptive_text.xml
deleted file mode 100644
index a9f0ba9..0000000
--- a/core/tests/coretests/res/layout/size_adaptive_text.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 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.
--->
-<com.android.internal.widget.SizeAdaptiveLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:internal="http://schemas.android.com/apk/prv/res/android"
-    android:id="@+id/multi1"
-    android:layout_width="match_parent"
-    android:layout_height="64dp" >
-
-    <include
-        android:id="@+id/one_u"
-        layout="@layout/size_adaptive_one_u_text"
-        android:layout_width="fill_parent"
-        android:layout_height="64dp"
-        internal:layout_minHeight="64dp"
-        internal:layout_maxHeight="64dp"
-        />
-
-    <include
-        android:id="@+id/four_u"
-        layout="@layout/size_adaptive_four_u_text"
-        android:layout_width="fill_parent"
-        android:layout_height="wrap_content"
-        internal:layout_minHeight="65dp"
-        internal:layout_maxHeight="unbounded"/>
-
-</com.android.internal.widget.SizeAdaptiveLayout>
diff --git a/core/tests/coretests/res/layout/size_adaptive_three_way.xml b/core/tests/coretests/res/layout/size_adaptive_three_way.xml
deleted file mode 100644
index 1eb5396..0000000
--- a/core/tests/coretests/res/layout/size_adaptive_three_way.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 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.
--->
-<com.android.internal.widget.SizeAdaptiveLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:internal="http://schemas.android.com/apk/prv/res/android"
-    android:id="@+id/three_way_multi"
-    android:layout_width="match_parent"
-    android:layout_height="64dp" >
-
-    <include
-        android:id="@+id/one_u"
-        layout="@layout/size_adaptive_one_u"
-        android:layout_width="fill_parent"
-        android:layout_height="64dp"
-        internal:layout_minHeight="64dp"
-        internal:layout_maxHeight="64dp"
-        />
-
-    <include
-        android:id="@+id/two_u"
-        layout="@layout/size_adaptive_four_u"
-        android:layout_width="fill_parent"
-        android:layout_height="128dp"
-        internal:layout_minHeight="65dp"
-        internal:layout_maxHeight="128dp"/>
-
-    <include
-        android:id="@+id/four_u"
-        layout="@layout/size_adaptive_four_u"
-        android:layout_width="fill_parent"
-        android:layout_height="256dp"
-        internal:layout_minHeight="129dp"
-        internal:layout_maxHeight="unbounded"/>
-
-</com.android.internal.widget.SizeAdaptiveLayout>
diff --git a/core/tests/coretests/src/com/android/internal/widget/SizeAdaptiveLayoutTest.java b/core/tests/coretests/src/com/android/internal/widget/SizeAdaptiveLayoutTest.java
deleted file mode 100644
index 18411b0..0000000
--- a/core/tests/coretests/src/com/android/internal/widget/SizeAdaptiveLayoutTest.java
+++ /dev/null
@@ -1,479 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.widget;
-
-import com.android.frameworks.coretests.R;
-
-import android.content.Context;
-import android.graphics.Color;
-import android.graphics.drawable.ColorDrawable;
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.view.LayoutInflater;
-import android.view.View;
-
-import com.android.internal.widget.SizeAdaptiveLayout;
-
-
-public class SizeAdaptiveLayoutTest extends AndroidTestCase {
-
-    private LayoutInflater mInflater;
-    private int mOneU;
-    private int mFourU;
-    private SizeAdaptiveLayout mSizeAdaptiveLayout;
-    private View mSmallView;
-    private View mMediumView;
-    private View mLargeView;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-
-        // inflate the layout
-        final Context context = getContext();
-        mInflater = LayoutInflater.from(context);
-        mOneU = 64;
-        mFourU = 4 * mOneU;
-    }
-
-    private void inflate(int resource){
-        mSizeAdaptiveLayout = (SizeAdaptiveLayout) mInflater.inflate(resource, null);
-        mSizeAdaptiveLayout.onAttachedToWindow();
-
-        mSmallView = mSizeAdaptiveLayout.findViewById(R.id.one_u);
-        mMediumView = mSizeAdaptiveLayout.findViewById(R.id.two_u);
-        mLargeView = mSizeAdaptiveLayout.findViewById(R.id.four_u);
-    }
-
-    /**
-     * The name 'test preconditions' is a convention to signal that if this
-     * test doesn't pass, the test case was not set up properly and it might
-     * explain any and all failures in other tests.  This is not guaranteed
-     * to run before other tests, as junit uses reflection to find the tests.
-     */
-    @SmallTest
-    public void testPreconditions() {
-        assertNotNull(mInflater);
-
-        inflate(R.layout.size_adaptive);
-        assertNotNull(mSizeAdaptiveLayout);
-        assertNotNull(mSmallView);
-        assertNotNull(mLargeView);
-    }
-
-    @SmallTest
-    public void testOpenLarge() {
-        inflate(R.layout.size_adaptive);
-        SizeAdaptiveLayout.LayoutParams lp =
-          (SizeAdaptiveLayout.LayoutParams) mLargeView.getLayoutParams();
-        int height = (int) lp.minHeight + 10;
-
-        measureAndLayout(height);
-
-        assertEquals("4U should be visible",
-                View.VISIBLE,
-                mLargeView.getVisibility());
-        assertEquals("1U should be gone",
-                View.GONE,
-                mSmallView.getVisibility());
-    }
-
-    @SmallTest
-    public void testOpenSmall() {
-        inflate(R.layout.size_adaptive);
-        SizeAdaptiveLayout.LayoutParams lp =
-          (SizeAdaptiveLayout.LayoutParams) mSmallView.getLayoutParams();
-        int height = (int) lp.minHeight;
-
-        measureAndLayout(height);
-
-        assertEquals("1U should be visible",
-                View.VISIBLE,
-                mSmallView.getVisibility());
-        assertEquals("4U should be gone",
-                View.GONE,
-                mLargeView.getVisibility());
-    }
-
-    @SmallTest
-    public void testOpenTooSmall() {
-        inflate(R.layout.size_adaptive);
-        SizeAdaptiveLayout.LayoutParams lp =
-          (SizeAdaptiveLayout.LayoutParams) mSmallView.getLayoutParams();
-        int height = (int) lp.minHeight - 10;
-
-        measureAndLayout(height);
-
-        assertEquals("1U should be visible",
-                View.VISIBLE,
-                mSmallView.getVisibility());
-        assertEquals("4U should be gone",
-                View.GONE,
-                mLargeView.getVisibility());
-    }
-
-    @SmallTest
-    public void testOpenTooBig() {
-        inflate(R.layout.size_adaptive);
-        SizeAdaptiveLayout.LayoutParams lp =
-          (SizeAdaptiveLayout.LayoutParams) mLargeView.getLayoutParams();
-        lp.maxHeight = 500;
-        mLargeView.setLayoutParams(lp);
-        int height = (int) (lp.minHeight + 10);
-
-        measureAndLayout(height);
-
-        assertEquals("4U should be visible",
-                View.VISIBLE,
-                mLargeView.getVisibility());
-        assertEquals("1U should be gone",
-                View.GONE,
-                mSmallView.getVisibility());
-    }
-
-    @SmallTest
-    public void testOpenWrapContent() {
-        inflate(R.layout.size_adaptive_text);
-        SizeAdaptiveLayout.LayoutParams lp =
-          (SizeAdaptiveLayout.LayoutParams) mLargeView.getLayoutParams();
-        int height = (int) lp.minHeight + 10;
-
-        // manually measure it, and lay it out
-        int measureSpec = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.AT_MOST);
-        mSizeAdaptiveLayout.measure(500, measureSpec);
-        assertTrue("should not be forced to 4U",
-                mSizeAdaptiveLayout.getMeasuredHeight() < mFourU);
-    }
-
-    @SmallTest
-    public void testOpenOneUOnlySmall() {
-        inflate(R.layout.size_adaptive_singleton);
-        assertNull("largeView should be NULL in the singleton layout", mLargeView);
-
-        SizeAdaptiveLayout.LayoutParams lp =
-          (SizeAdaptiveLayout.LayoutParams) mSmallView.getLayoutParams();
-        int height = (int) lp.minHeight - 10;
-
-        measureAndLayout(height);
-
-        assertEquals("1U should be visible",
-                View.VISIBLE,
-                mSmallView.getVisibility());
-    }
-
-    @SmallTest
-    public void testOpenOneUOnlyLarge() {
-        inflate(R.layout.size_adaptive_singleton);
-        assertNull("largeView should be NULL in the singleton layout", mLargeView);
-
-        SizeAdaptiveLayout.LayoutParams lp =
-          (SizeAdaptiveLayout.LayoutParams) mSmallView.getLayoutParams();
-        int height = (int) lp.maxHeight + 10;
-
-        measureAndLayout(height);
-
-        assertEquals("1U should be visible",
-                View.VISIBLE,
-                mSmallView.getVisibility());
-    }
-
-    @SmallTest
-    public void testOpenOneUOnlyJustRight() {
-        inflate(R.layout.size_adaptive_singleton);
-        assertNull("largeView should be NULL in the singleton layout", mLargeView);
-
-        SizeAdaptiveLayout.LayoutParams lp =
-          (SizeAdaptiveLayout.LayoutParams) mSmallView.getLayoutParams();
-        int height = (int) lp.minHeight;
-
-        measureAndLayout(height);
-
-        assertEquals("1U should be visible",
-                View.VISIBLE,
-                mSmallView.getVisibility());
-    }
-
-    @SmallTest
-    public void testOpenFourUOnlySmall() {
-        inflate(R.layout.size_adaptive_large_only);
-        assertNull("smallView should be NULL in the singleton layout", mSmallView);
-
-        SizeAdaptiveLayout.LayoutParams lp =
-          (SizeAdaptiveLayout.LayoutParams) mLargeView.getLayoutParams();
-        int height = (int) lp.minHeight - 10;
-
-        measureAndLayout(height);
-
-        assertEquals("4U should be visible",
-                View.VISIBLE,
-                mLargeView.getVisibility());
-    }
-
-    @SmallTest
-    public void testOpenFourUOnlyLarge() {
-        inflate(R.layout.size_adaptive_large_only);
-        assertNull("smallView should be NULL in the singleton layout", mSmallView);
-
-        SizeAdaptiveLayout.LayoutParams lp =
-          (SizeAdaptiveLayout.LayoutParams) mLargeView.getLayoutParams();
-        int height = (int) lp.maxHeight + 10;
-
-        measureAndLayout(height);
-
-        assertEquals("4U should be visible",
-                View.VISIBLE,
-                mLargeView.getVisibility());
-    }
-
-    @SmallTest
-    public void testOpenFourUOnlyJustRight() {
-        inflate(R.layout.size_adaptive_large_only);
-        assertNull("smallView should be NULL in the singleton layout", mSmallView);
-
-        SizeAdaptiveLayout.LayoutParams lp =
-          (SizeAdaptiveLayout.LayoutParams) mLargeView.getLayoutParams();
-        int height = (int) lp.minHeight;
-
-        measureAndLayout(height);
-
-        assertEquals("4U should be visible",
-                View.VISIBLE,
-                mLargeView.getVisibility());
-    }
-
-    @SmallTest
-    public void testOpenIntoAGap() {
-        inflate(R.layout.size_adaptive_gappy);
-
-        SizeAdaptiveLayout.LayoutParams smallParams =
-          (SizeAdaptiveLayout.LayoutParams) mSmallView.getLayoutParams();
-        SizeAdaptiveLayout.LayoutParams largeParams =
-          (SizeAdaptiveLayout.LayoutParams) mLargeView.getLayoutParams();
-        assertTrue("gappy layout should have a gap",
-                smallParams.maxHeight + 10 < largeParams.minHeight);
-        int height = (int) smallParams.maxHeight + 10;
-
-        measureAndLayout(height);
-
-        assertTrue("one and only one view should be visible",
-                mLargeView.getVisibility() != mSmallView.getVisibility());
-        // behavior is undefined in this case.
-    }
-
-    @SmallTest
-    public void testOpenIntoAnOverlap() {
-        inflate(R.layout.size_adaptive_overlapping);
-
-        SizeAdaptiveLayout.LayoutParams smallParams =
-          (SizeAdaptiveLayout.LayoutParams) mSmallView.getLayoutParams();
-        SizeAdaptiveLayout.LayoutParams largeParams =
-          (SizeAdaptiveLayout.LayoutParams) mLargeView.getLayoutParams();
-        assertEquals("overlapping layout should overlap",
-                smallParams.minHeight,
-                largeParams.minHeight);
-        int height = (int) smallParams.maxHeight;
-
-        measureAndLayout(height);
-
-        assertTrue("one and only one view should be visible",
-                mLargeView.getVisibility() != mSmallView.getVisibility());
-        assertEquals("1U should get priority in an overlap because it is first",
-                View.VISIBLE,
-                mSmallView.getVisibility());
-    }
-
-    @SmallTest
-    public void testOpenThreeWayViewSmall() {
-        inflate(R.layout.size_adaptive_three_way);
-        assertNotNull("mMediumView should not be NULL in the three view layout", mMediumView);
-
-        SizeAdaptiveLayout.LayoutParams lp =
-          (SizeAdaptiveLayout.LayoutParams) mSmallView.getLayoutParams();
-        int height = (int) lp.minHeight;
-
-        measureAndLayout(height);
-
-        assertEquals("1U should be visible",
-                View.VISIBLE,
-                mSmallView.getVisibility());
-        assertEquals("2U should be gone",
-                View.GONE,
-                mMediumView.getVisibility());
-        assertEquals("4U should be gone",
-                View.GONE,
-                mLargeView.getVisibility());
-    }
-
-    @SmallTest
-    public void testOpenThreeWayViewMedium() {
-        inflate(R.layout.size_adaptive_three_way);
-        assertNotNull("mMediumView should not be NULL in the three view layout", mMediumView);
-
-        SizeAdaptiveLayout.LayoutParams lp =
-          (SizeAdaptiveLayout.LayoutParams) mMediumView.getLayoutParams();
-        int height = (int) lp.minHeight;
-
-        measureAndLayout(height);
-
-        assertEquals("1U should be gone",
-                View.GONE,
-                mSmallView.getVisibility());
-        assertEquals("2U should be visible",
-                View.VISIBLE,
-                mMediumView.getVisibility());
-        assertEquals("4U should be gone",
-                View.GONE,
-                mLargeView.getVisibility());
-    }
-
-    @SmallTest
-    public void testOpenThreeWayViewLarge() {
-        inflate(R.layout.size_adaptive_three_way);
-        assertNotNull("mMediumView should not be NULL in the three view layout", mMediumView);
-
-        SizeAdaptiveLayout.LayoutParams lp =
-          (SizeAdaptiveLayout.LayoutParams) mLargeView.getLayoutParams();
-        int height = (int) lp.minHeight;
-
-        measureAndLayout(height);
-
-        assertEquals("1U should be gone",
-                View.GONE,
-                mSmallView.getVisibility());
-        assertEquals("2U should be gone",
-                View.GONE,
-                mMediumView.getVisibility());
-        assertEquals("4U should be visible",
-                View.VISIBLE,
-                mLargeView.getVisibility());
-    }
-
-    @SmallTest
-    public void testResizeWithoutAnimation() {
-        inflate(R.layout.size_adaptive);
-
-        SizeAdaptiveLayout.LayoutParams largeParams =
-          (SizeAdaptiveLayout.LayoutParams) mLargeView.getLayoutParams();
-        int startHeight = (int) largeParams.minHeight + 10;
-        int endHeight = (int) largeParams.minHeight + 10;
-
-        measureAndLayout(startHeight);
-
-        assertEquals("4U should be visible",
-                View.VISIBLE,
-                mLargeView.getVisibility());
-        assertFalse("There should be no animation on initial rendering.",
-                    mSizeAdaptiveLayout.getTransitionAnimation().isRunning());
-
-        measureAndLayout(endHeight);
-
-        assertEquals("4U should still be visible",
-                View.VISIBLE,
-                mLargeView.getVisibility());
-        assertFalse("There should be no animation on scale within a view.",
-                    mSizeAdaptiveLayout.getTransitionAnimation().isRunning());
-    }
-
-    @SmallTest
-    public void testResizeWithAnimation() {
-        inflate(R.layout.size_adaptive);
-
-        SizeAdaptiveLayout.LayoutParams smallParams =
-          (SizeAdaptiveLayout.LayoutParams) mSmallView.getLayoutParams();
-        SizeAdaptiveLayout.LayoutParams largeParams =
-          (SizeAdaptiveLayout.LayoutParams) mLargeView.getLayoutParams();
-        int startHeight = (int) largeParams.minHeight + 10;
-        int endHeight = (int) smallParams.maxHeight;
-
-        measureAndLayout(startHeight);
-
-        assertEquals("4U should be visible",
-                View.VISIBLE,
-                mLargeView.getVisibility());
-        assertFalse("There should be no animation on initial rendering.",
-                    mSizeAdaptiveLayout.getTransitionAnimation().isRunning());
-
-        measureAndLayout(endHeight);
-
-        assertEquals("1U should now be visible",
-                View.VISIBLE,
-                mSmallView.getVisibility());
-        assertTrue("There should be an animation on scale between views.",
-                   mSizeAdaptiveLayout.getTransitionAnimation().isRunning());
-    }
-
-    @SmallTest
-    public void testModestyPanelChangesColorWhite() {
-        inflate(R.layout.size_adaptive_color);
-        View panel = mSizeAdaptiveLayout.getModestyPanel();
-        assertTrue("ModestyPanel should have a ColorDrawable background",
-                   panel.getBackground() instanceof ColorDrawable);
-        ColorDrawable panelColor = (ColorDrawable) panel.getBackground();
-        ColorDrawable salColor = (ColorDrawable) mSizeAdaptiveLayout.getBackground();
-        assertEquals("ModestyPanel color should match the SizeAdaptiveLayout",
-                     panelColor.getColor(), salColor.getColor());
-    }
-
-    @SmallTest
-    public void testModestyPanelTracksStateListColor() {
-        inflate(R.layout.size_adaptive_color_statelist);
-        View panel = mSizeAdaptiveLayout.getModestyPanel();
-        assertEquals("ModestyPanel should have a ColorDrawable background" ,
-                     panel.getBackground().getClass(), ColorDrawable.class);
-        ColorDrawable panelColor = (ColorDrawable) panel.getBackground();
-        assertEquals("ModestyPanel color should match the SizeAdaptiveLayout",
-                     panelColor.getColor(), Color.RED);
-    }
-    @SmallTest
-    public void testOpenSmallEvenWhenLargeIsActuallySmall() {
-        inflate(R.layout.size_adaptive_lies);
-        SizeAdaptiveLayout.LayoutParams lp =
-          (SizeAdaptiveLayout.LayoutParams) mSmallView.getLayoutParams();
-        int height = (int) lp.minHeight;
-
-        measureAndLayout(height);
-
-        assertEquals("1U should be visible",
-                View.VISIBLE,
-                mSmallView.getVisibility());
-        assertTrue("1U should also have been measured",
-                   mSmallView.getMeasuredHeight() > 0);
-    }
-
-    @SmallTest
-    public void testOpenLargeEvenWhenLargeIsActuallySmall() {
-        inflate(R.layout.size_adaptive_lies);
-        SizeAdaptiveLayout.LayoutParams lp =
-          (SizeAdaptiveLayout.LayoutParams) mLargeView.getLayoutParams();
-        int height = (int) lp.minHeight;
-
-        measureAndLayout(height);
-
-        assertEquals("4U should be visible",
-                View.VISIBLE,
-                mLargeView.getVisibility());
-        assertTrue("4U should also have been measured",
-                   mLargeView.getMeasuredHeight() > 0);
-    }
-
-    private void measureAndLayout(int height) {
-        // manually measure it, and lay it out
-        int measureSpec = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.AT_MOST);
-        mSizeAdaptiveLayout.measure(500, measureSpec);
-        mSizeAdaptiveLayout.layout(0, 0, 500, mSizeAdaptiveLayout.getMeasuredHeight());
-    }
-}
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/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/location/display-address.jd b/docs/html/training/location/display-address.jd
index 621b082..516f14f 100644
--- a/docs/html/training/location/display-address.jd
+++ b/docs/html/training/location/display-address.jd
@@ -1,280 +1,468 @@
 page.title=Displaying a Location Address
-
 trainingnavtop=true
-
 @jd:body
 
-
-
 <div id="tb-wrapper">
-<div id="tb">
+  <div id="tb">
 
-<h2>This lesson teaches you to</h2>
-<ol>
-  <li><a href="#DefineTask">Define the Address Lookup Task</a></li>
-  <li><a href="#DisplayResults">Define a Method to Display the Results</a></li>
-  <li><a href="#RunTask">Run the Lookup Task</a></li>
-</ol>
+    <h2>This lesson teaches you how to</h2>
+    <ol>
+      <li><a href="#connect">Get a Geographic Location</a></li>
+      <li><a href="#fetch-address">Define an Intent Service to Fetch the
+        Address</a></li>
+      <li><a href="#start-intent">Start the Intent Service</a></li>
+      <li><a href="#result-receiver">Receive the Geocoding Results</a></li>
+    </ol>
 
-<h2>You should also read</h2>
-<ul>
-    <li>
-        <a href="{@docRoot}google/play-services/setup.html">Setup Google Play Services SDK</a>
-    </li>
-    <li>
-        <a href="retrieve-current.html">Retrieving the Current Location</a>
-    </li>
-    <li>
-        <a href="receive-location-updates.html">Receiving Location Updates</a>
-    </li>
-</ul>
-<h2>Try it out</h2>
+    <h2>You should also read</h2>
+      <ul>
+        <li>
+          <a href="{@docRoot}google/play-services/setup.html">Setting up Google
+          Play Services</a>
+        </li>
+        <li>
+          <a href="retrieve-current.html">Getting the Last Known Location</a>
+        </li>
+        <li>
+          <a href="receive-location-updates.html">Receiving Location Updates</a>
+        </li>
+      </ul>
+    <h2>Try it out</h2>
 
-<div class="download-box">
-<a href="http://developer.android.com/shareables/training/LocationUpdates.zip" class="button">Download
-  the sample app</a>
-<p class="filename">LocationUpdates.zip</p>
+    <ul>
+      <li>
+        <a href="https://github.com/googlesamples/android-play-location/tree/master/LocationAddress" class="external-link">LocationAddress</a>
+      </li>
+    </ul>
+  </div>
 </div>
 
-</div>
-</div>
+<p>The lessons <a href="retrieve-current.html">Getting the Last Known
+  Location</a> and <a href="receive-location-updates.html">Receiving Location
+  Updates</a> describe how to get the user's location in the form of a
+  {@link android.location.Location} object that contains latitude and longitude
+  coordinates. Although latitude and longitude are useful for calculating
+  distance or displaying a map position, in many cases the address of the
+  location is more useful. For example, if you want to let your users know where
+  they are or what is close by, a street address is more meaningful than the
+  geographic coordinates (latitude/longitude) of the location.</p>
 
-<p>
-    The lessons <a href="retrieve-current.html">Retrieving the Current Location</a> and
-    <a href="receive-location-updates.html">Receiving Location Updates</a> describe how to get the
-    user's current location in the form of a {@link android.location.Location} object that
-    contains latitude and longitude coordinates. Although latitude and longitude are useful for
-    calculating distance or displaying a map position, in many cases the address of the location is
-    more useful.
-</p>
-<p>
-    The Android platform API provides a feature that returns an estimated street addresses for
-    latitude and longitude values. This lesson shows you how to use this address lookup feature.
-</p>
-<p class="note">
-    <strong>Note:</strong> Address lookup requires a backend service that is not included in the
-    core Android framework. If this backend service is not available,
-    {@link android.location.Geocoder#getFromLocation Geocoder.getFromLocation()} returns an empty
-    list. The helper method {@link android.location.Geocoder#isPresent isPresent()}, available
-    in API level 9 and later, checks to see if the backend service is available.
-</p>
-<p>
-    The snippets in the following sections assume that your app has already retrieved the
-    current location and stored it as a {@link android.location.Location} object in the global
-    variable {@code mLocation}.
-</p>
-<!--
-    Define the address lookup task
--->
-<h2 id="DefineTask">Define the Address Lookup Task</h2>
-<p>
-To get an address for a given latitude and longitude, call
-{@link android.location.Geocoder#getFromLocation Geocoder.getFromLocation()}, which returns a
-list of addresses. The method is synchronous, and may take a long time to do its work, so you
-should call the method from the {@link android.os.AsyncTask#doInBackground
-doInBackground()} method of an {@link android.os.AsyncTask}.
-</p>
-<p>
-While your app is getting the address, display an indeterminate activity
-indicator to show that your app is working in the background. Set the indicator's initial state
-to {@code android:visibility="gone"}, to make it invisible and remove it from the layout
-hierarchy. When you start the address lookup, you set its visibility to "visible".
-</p>
-<p>
-The following snippet shows how to add an indeterminate {@link android.widget.ProgressBar} to
-your layout file:
-</p>
+<p>Using the {@link android.location.Geocoder} class in the Android framework
+  location APIs, you can convert an address to the corresponding geographic
+  coordinates. This process is called <em>geocoding</em>. Alternatively, you can
+  convert a geographic location to an address. The address lookup feature is
+  also known as <em>reverse geocoding</em>.</p>
+
+<p>This lesson shows you how to use the
+  {@link android.location.Geocoder#getFromLocation getFromLocation()} method to
+  convert a geographic location to an address. The method returns an estimated
+  street address corresponding to a given latitude and longitude.</p>
+
+<h2 id="connect">Get a Geographic Location</h2>
+
+<p>The last known location of the device is a useful starting point for the
+  address lookup feature. The lesson on
+  <a href="retrieve-current.html">Getting the Last Known Location</a> shows you
+  how to use the
+  <a href="{@docRoot}reference/com/google/android/gms/location/FusedLocationProviderApi.html#getLastLocation(com.google.android.gms.common.api.GoogleApiClient)">{@code getLastLocation()}</a>
+  method provided by the
+  <a href="{@docRoot}reference/com/google/android/gms/location/FusedLocationProviderApi.html">fused
+  location provider</a> to find the latest location of the device.</p>
+
+<p>To access the fused location provider, you need to create an instance of the
+  Google Play services API client. To learn how to connect your client, see
+  <a href="{@docRoot}training/location/retrieve-current.html#play-services">Connect
+  to Google Play Services</a>.</p>
+
+<p>In order for the fused location provider to retrieve a precise street
+  address, set the location permission in your app manifest to
+  {@code ACCESS_FINE_LOCATION}, as shown in the following example:</p>
+
 <pre>
-&lt;ProgressBar
-android:id="&#64;+id/address_progress"
-android:layout_width="wrap_content"
-android:layout_height="wrap_content"
-android:layout_centerHorizontal="true"
-android:indeterminate="true"
-android:visibility="gone" /&gt;
+&lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.google.android.gms.location.sample.locationupdates" &gt;
+
+  &lt;uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/&gt;
+&lt;/manifest&gt;
 </pre>
-<p>
-To create the background task, define a subclass of {@link android.os.AsyncTask} that calls
-{@link android.location.Geocoder#getFromLocation getFromLocation()} and returns an address.
-Define a {@link android.widget.TextView} object {@code mAddress} to contain the returned
-address, and a {@link android.widget.ProgressBar} object that allows you to control the
-indeterminate activity indicator. For example:
-</p>
+
+<h2 id="fetch-address">Define an Intent Service to Fetch the Address</h2>
+
+<p>The {@link android.location.Geocoder#getFromLocation getFromLocation()}
+  method provided by the {@link android.location.Geocoder} class accepts a
+  latitude and longitude, and returns a list of addresses. The method is
+  synchronous, and may take a long time to do its work, so you should not call
+  it from the main, user interface (UI) thread of your app.</p>
+
+<p>The {@link android.app.IntentService IntentService} class provides a
+  structure for running a task on a background thread. Using this class, you can
+  handle a long-running operation without affecting your UI's responsiveness.
+  Note that the {@link android.os.AsyncTask AsyncTask} class also allows you to
+  perform background operations, but it's designed for short operations. An
+  {@link android.os.AsyncTask AsyncTask} shouldn't keep a reference to the UI if
+  the activity is recreated, for example when the device is rotated. In
+  contrast, an {@link android.app.IntentService IntentService} doesn't need to
+  be cancelled when the activity is rebuilt.</p>
+
+<p>Define a {@code FetchAddressIntentService} class that extends
+  {@link android.app.IntentService}. This class is your address lookup service.
+  The intent service handles an intent asynchronously on a worker thread, and
+  stops itself when it runs out of work. The intent extras provide the data
+  needed by the service, including a {@link android.location.Location} object
+  for conversion to an address, and a {@link android.os.ResultReceiver} object
+  to handle the results of the address lookup. The service uses a {@link
+  android.location.Geocoder} to fetch the address for the location, and sends
+  the results to the {@link android.os.ResultReceiver}.</p>
+
+<h3>Define the Intent Service in your App Manifest</h3>
+
+<p>Add an entry to your app manifest defining the intent service:</p>
+
 <pre>
-public class MainActivity extends FragmentActivity {
+&lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.google.android.gms.location.sample.locationaddress" &gt;
+    &lt;application
+        ...
+        &lt;service
+            android:name=".FetchAddressIntentService"
+            android:exported="false"/&gt;
+    &lt;/application&gt;
     ...
-    private TextView mAddress;
-    private ProgressBar mActivityIndicator;
+&lt;/manifest&gt;
+</pre>
+
+<p class="note"><strong>Note:</strong> The {@code &lt;service&gt;} element in
+  the manifest doesn't need to include an intent filter, because your main
+  activity creates an explicit intent by specifying the name of the class to use
+  for the intent.</p>
+
+<h3>Create a Geocoder</h3>
+
+<p>The process of converting a geographic location to an address is called
+  <em>reverse geocoding</em>. To perform the main work of the intent service,
+  that is, your reverse geocoding request, implement
+  {@link android.app.IntentService#onHandleIntent onHandleIntent()} within the
+  {@code FetchAddressIntentService} class. Create a
+  {@link android.location.Geocoder} object to handle the reverse geocoding.</p>
+
+<p>A locale represents a specific geographical or linguistic region. Locale
+  objects are used to adjust the presentation of information, such as numbers or
+  dates, to suit the conventions in the region represented by the locale. Pass a
+  <a href="{@docRoot}reference/java/util/Locale.html">{@code Locale}</a> object
+  to the {@link android.location.Geocoder} object, to ensure that the resulting
+  address is localized to the user's geographic region.</p>
+
+<pre>
+&#64;Override
+protected void onHandleIntent(Intent intent) {
+    Geocoder geocoder = new Geocoder(this, Locale.getDefault());
+    ...
+}
+</pre>
+
+<h3 id="retrieve-street-address">Retrieve the street address data</h3>
+
+<p>The next step is to retrieve the street address from the geocoder, handle
+  any errors that may occur, and send the results back to the activity that
+  requested the address. To report the results of the geocoding
+  process, you need two numeric constants that indicate success or failure.
+  Define a {@code Constants} class to contain the values, as shown in this code
+  snippet:</p>
+
+<pre>
+public final class Constants {
+    public static final int SUCCESS_RESULT = 0;
+    public static final int FAILURE_RESULT = 1;
+    public static final String PACKAGE_NAME =
+        "com.google.android.gms.location.sample.locationaddress";
+    public static final String RECEIVER = PACKAGE_NAME + ".RECEIVER";
+    public static final String RESULT_DATA_KEY = PACKAGE_NAME +
+        ".RESULT_DATA_KEY";
+    public static final String LOCATION_DATA_EXTRA = PACKAGE_NAME +
+        ".LOCATION_DATA_EXTRA";
+}
+</pre>
+
+<p>To get a street address corresponding to a geographical location, call
+  {@link android.location.Geocoder#getFromLocation getFromLocation()},
+  passing it the latitude and longitude from the location object, and the
+  maximum number of addresses you want returned. In this case, you want just one
+  address. The geocoder returns an array of addresses. If no addresses were
+  found to match the given location, it returns an empty list. If there is no
+  backend geocoding service available, the geocoder returns null.</p>
+
+<p>Check for the following errors as shown in the code sample below. If an error
+  occurs, place the corresponding error message in the {@code errorMessage}
+  variable, so you can send it back to the requesting activity:</p>
+
+<ul>
+  <li><strong>No location data provided</strong> - The intent extras do not
+    include the {@link android.location.Location} object required for reverse
+    geocoding.</li>
+  <li><strong>Invalid latitude or longitude used</strong> - The latitude
+    and/or longitude values provided in the {@link android.location.Location}
+    object are invalid.</li>
+  <li><strong>No geocoder available</strong> - The background geocoding service
+    is not available, due to a network error or IO exception.</li>
+  <li><strong>Sorry, no address found</strong> - The geocoder could not find an
+    address for the given latitude/longitude.</li>
+</ul>
+
+<p>To get the individual lines of an address object, use the
+  {@link android.location.Address#getAddressLine getAddressLine()}
+  method provided by the {@link android.location.Address} class. Then join the
+  lines into a list of address fragments ready to return to the activity that
+  requested the address.</p>
+
+<p>To send the results back to the requesting activity, call the
+  {@code deliverResultToReceiver()} method (defined in
+  <a href="#return-address">Return the address to the requestor</a>). The
+  results consist of the previously-mentioned numeric success/failure code and
+  a string. In the case of a successful reverse geocoding, the string contains
+  the address. In the case of a failure, the string contains the error message,
+  as shown in the code sample below:</p>
+
+<pre>
+&#64;Override
+protected void onHandleIntent(Intent intent) {
+    String errorMessage = "";
+
+    // Get the location passed to this service through an extra.
+    Location location = intent.getParcelableExtra(
+            Constants.LOCATION_DATA_EXTRA);
+
+    ...
+
+    List&lt;Address&gt; addresses = null;
+
+    try {
+        addresses = geocoder.getFromLocation(
+                location.getLatitude(),
+                location.getLongitude(),
+                // In this sample, get just a single address.
+                1);
+    } catch (IOException ioException) {
+        // Catch network or other I/O problems.
+        errorMessage = getString(R.string.service_not_available);
+        Log.e(TAG, errorMessage, ioException);
+    } catch (IllegalArgumentException illegalArgumentException) {
+        // Catch invalid latitude or longitude values.
+        errorMessage = getString(R.string.invalid_lat_long_used);
+        Log.e(TAG, errorMessage + ". " +
+                "Latitude = " + location.getLatitude() +
+                ", Longitude = " +
+                location.getLongitude(), illegalArgumentException);
+    }
+
+    // Handle case where no address was found.
+    if (addresses == null || addresses.size()  == 0) {
+        if (errorMessage.isEmpty()) {
+            errorMessage = getString(R.string.no_address_found);
+            Log.e(TAG, errorMessage);
+        }
+        deliverResultToReceiver(Constants.FAILURE_RESULT, errorMessage);
+    } else {
+        Address address = addresses.get(0);
+        ArrayList&lt;String&gt; addressFragments = new ArrayList&lt;String&gt;();
+
+        // Fetch the address lines using {@code getAddressLine},
+        // join them, and send them to the thread.
+        for(int i = 0; i < address.getMaxAddressLineIndex(); i++) {
+            addressFragments.add(address.getAddressLine(i));
+        }
+        Log.i(TAG, getString(R.string.address_found));
+        deliverResultToReceiver(Constants.SUCCESS_RESULT,
+                TextUtils.join(System.getProperty("line.separator"),
+                        addressFragments));
+    }
+}
+</pre>
+
+<h3 id="return-address">Return the address to the requestor</h3>
+
+<p>The final thing the intent service must do is send the address back to a
+  {@link android.os.ResultReceiver} in the activity that started the service.
+  The {@link android.os.ResultReceiver} class allows you to send a
+  numeric result code as well as a message containing the result data. The
+  numeric code is useful for reporting the success or failure of the geocoding
+  request. In the case of a successful reverse geocoding, the message contains
+  the address. In the case of a failure, the message contains some text
+  describing the reason for failure.</p>
+
+<p>You have already retrieved the address from the geocoder, trapped any errors
+  that may occur, and called the {@code deliverResultToReceiver()} method. Now
+  you need to define the {@code deliverResultToReceiver()} method that sends
+  a result code and message bundle to the result receiver.</p>
+
+<p>For the result code, use the value that you've passed to the
+  {@code deliverResultToReceiver()} method in the {@code resultCode} parameter.
+  To construct the message bundle, concatenate the {@code RESULT_DATA_KEY}
+  constant from your {@code Constants} class (defined in
+  <a href="#retrieve-street-address">Retrieve the street address data</a>) and
+  the value in the {@code message} parameter passed to the
+  {@code deliverResultToReceiver()} method, as shown in the following sample:
+</p>
+
+<pre>
+public class FetchAddressIntentService extends IntentService {
+    protected ResultReceiver mReceiver;
+    ...
+    private void deliverResultToReceiver(int resultCode, String message) {
+        Bundle bundle = new Bundle();
+        bundle.putString(Constants.RESULT_DATA_KEY, message);
+        mReceiver.send(resultCode, bundle);
+    }
+}
+</pre>
+
+<h2 id="start-intent">Start the Intent Service</h2>
+
+<p>The intent service, as defined in the previous section, runs in the
+  background and is responsible for fetching the address corresponding to a
+  given geographic location. When you start the service, the Android framework
+  instantiates and starts the service if it isn't already running, and creates a
+  process if needed. If the service is already running then it remains running.
+  Because the service extends {@link android.app.IntentService IntentService},
+  it shuts down automatically when all intents have been processed.</p>
+  
+<p>Start the service from your app's main activity,
+  and create an {@link android.content.Intent} to pass data to the service. You
+  need an <em>explicit</em> intent, because you want only your service
+  to respond to the intent. For more information, see
+  <a href="{@docRoot}guide/components/intents-filters.html#Types">Intent
+  Types</a>.</p>
+
+<p>To create an explicit intent, specify the name of the
+  class to use for the service: {@code FetchAddressIntentService.class}.
+  Pass two pieces of information in the intent extras:</p>
+
+<ul>
+  <li>A {@link android.os.ResultReceiver} to handle the results of the address
+    lookup.</li>
+  <li>A {@link android.location.Location} object containing the latitude and
+    longitude that you want to convert to an address.</li>
+</ul>
+
+<p>The following code sample shows you how to start the intent service:</p>
+
+<pre>
+public class MainActivity extends ActionBarActivity implements
+        ConnectionCallbacks, OnConnectionFailedListener {
+
+    protected Location mLastLocation;
+    private AddressResultReceiver mResultReceiver;
+    ...
+
+    protected void startIntentService() {
+        Intent intent = new Intent(this, FetchAddressIntentService.class);
+        intent.putExtra(Constants.RECEIVER, mResultReceiver);
+        intent.putExtra(Constants.LOCATION_DATA_EXTRA, mLastLocation);
+        startService(intent);
+    }
+}
+</pre>
+
+<p>Call the above {@code startIntentService()} method when the
+  user takes an action that requires a geocoding address lookup. For example,
+  the user may press a <em>Fetch address</em> button on your app's UI. Before
+  starting the intent service, you need to check that the connection to Google
+  Play services is present. The following code snippet shows the call to the
+  {@code startIntentService()} method in the button handler:</p>
+
+<pre>
+public void fetchAddressButtonHandler(View view) {
+    // Only start the service to fetch the address if GoogleApiClient is
+    // connected.
+    if (mGoogleApiClient.isConnected() && mLastLocation != null) {
+        startIntentService();
+    }
+    // If GoogleApiClient isn't connected, process the user's request by
+    // setting mAddressRequested to true. Later, when GoogleApiClient connects,
+    // launch the service to fetch the address. As far as the user is
+    // concerned, pressing the Fetch Address button
+    // immediately kicks off the process of getting the address.
+    mAddressRequested = true;
+    updateUIWidgets();
+}
+</pre>
+
+<p>You must also start the intent service when the connection to Google Play
+  services is established, if the user has already clicked the button on your
+  app's UI. The following code snippet shows the call to the
+  {@code startIntentService()} method in the
+  <a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.ConnectionCallbacks.html#onConnected(android.os.Bundle)">{@code onConnected()}</a>
+  callback provided by the Google API Client:</p>
+
+<pre>
+public class MainActivity extends ActionBarActivity implements
+        ConnectionCallbacks, OnConnectionFailedListener {
     ...
     &#64;Override
-    protected void onCreate(Bundle savedInstanceState) {
-    super.onCreate(savedInstanceState);
-    ...
-    mAddress = (TextView) findViewById(R.id.address);
-    mActivityIndicator =
-            (ProgressBar) findViewById(R.id.address_progress);
-    }
-    ...
-    /**
-    * A subclass of AsyncTask that calls getFromLocation() in the
-    * background. The class definition has these generic types:
-    * Location - A {@link android.location.Location} object containing
-    * the current location.
-    * Void     - indicates that progress units are not used
-    * String   - An address passed to onPostExecute()
-    */
-    private class GetAddressTask extends
-            AsyncTask&lt;Location, Void, String&gt; {
-        Context mContext;
-        public GetAddressTask(Context context) {
-            super();
-            mContext = context;
-        }
-        ...
-        /**
-         * Get a Geocoder instance, get the latitude and longitude
-         * look up the address, and return it
-         *
-         * &#64;params params One or more Location objects
-         * &#64;return A string containing the address of the current
-         * location, or an empty string if no address can be found,
-         * or an error message
-         */
-        &#64;Override
-        protected String doInBackground(Location... params) {
-            Geocoder geocoder =
-                    new Geocoder(mContext, Locale.getDefault());
-            // Get the current location from the input parameter list
-            Location loc = params[0];
-            // Create a list to contain the result address
-            List&lt;Address&gt; addresses = null;
-            try {
-                /*
-                 * Return 1 address.
-                 */
-                addresses = geocoder.getFromLocation(loc.getLatitude(),
-                        loc.getLongitude(), 1);
-            } catch (IOException e1) {
-            Log.e("LocationSampleActivity",
-                    "IO Exception in getFromLocation()");
-            e1.printStackTrace();
-            return ("IO Exception trying to get address");
-            } catch (IllegalArgumentException e2) {
-            // Error message to post in the log
-            String errorString = "Illegal arguments " +
-                    Double.toString(loc.getLatitude()) +
-                    " , " +
-                    Double.toString(loc.getLongitude()) +
-                    " passed to address service";
-            Log.e("LocationSampleActivity", errorString);
-            e2.printStackTrace();
-            return errorString;
+    public void onConnected(Bundle connectionHint) {
+        // Gets the best and most recent location currently available,
+        // which may be null in rare cases when a location is not available.
+        mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
+                mGoogleApiClient);
+
+        if (mLastLocation != null) {
+            // Determine whether a Geocoder is available.
+            if (!Geocoder.isPresent()) {
+                Toast.makeText(this, R.string.no_geocoder_available,
+                        Toast.LENGTH_LONG).show();
+                return;
             }
-            // If the reverse geocode returned an address
-            if (addresses != null &amp;&amp; addresses.size() &gt; 0) {
-                // Get the first address
-                Address address = addresses.get(0);
-                /*
-                 * Format the first line of address (if available),
-                 * city, and country name.
-                 */
-                String addressText = String.format(
-                        "&#037;s, &#037;s, &#037;s",
-                        // If there's a street address, add it
-                        address.getMaxAddressLineIndex() &gt; 0 ?
-                                address.getAddressLine(0) : "",
-                        // Locality is usually a city
-                        address.getLocality(),
-                        // The country of the address
-                        address.getCountryName());
-                // Return the text
-                return addressText;
-            } else {
-                return "No address found";
+
+            if (mAddressRequested) {
+                startIntentService();
             }
         }
-        ...
     }
-    ...
 }
 </pre>
-<p>
-The next section shows you how to display the address in the user interface.
-</p>
-<!-- Define a method to display the address -->
-<h2 id="DisplayResults">Define a Method to Display the Results</h2>
-<p>
-    {@link android.os.AsyncTask#doInBackground doInBackground()} returns the result of the address
-    lookup as a {@link java.lang.String}. This value is passed to
-    {@link android.os.AsyncTask#onPostExecute onPostExecute()}, where you do further processing
-    on the results. Since {@link android.os.AsyncTask#onPostExecute onPostExecute()}
-    runs on the UI thread, it can update the user interface; for example, it can turn off the
-    activity indicator and display the results to the user:
-</p>
+
+<h2 id="result-receiver">Receive the Geocoding Results</h2>
+
+<p>The intent service has handled the geocoding request, and uses a
+  {@link android.os.ResultReceiver} to return the results to the activity that
+  made the request. In the activity that makes the request, define an
+  {@code AddressResultReceiver} that extends {@link android.os.ResultReceiver}
+  to handle the response from {@code FetchAddressIntentService}.</p>
+
+<p>The result includes a numeric result code (<code>resultCode</code>) as well
+  as a message containing the result data (<code>resultData</code>). If the
+  reverse geocoding process was successful, the <code>resultData</code> contains
+  the address. In the case of a failure, the <code>resultData</code> contains
+  text describing the reason for failure. For details of the possible errors,
+  see <a href="#return-address">Return the address to the requestor</a>.</p>
+
+<p>Override the
+  {@link android.os.ResultReceiver#onReceiveResult onReceiveResult()} method
+  to handle the results delivered to the result receiver, as shown in the
+  following code sample:</p>
+
 <pre>
-    private class GetAddressTask extends
-            AsyncTask&lt;Location, Void, String&gt; {
-        ...
-        /**
-         * A method that's called once doInBackground() completes. Turn
-         * off the indeterminate activity indicator and set
-         * the text of the UI element that shows the address. If the
-         * lookup failed, display the error message.
-         */
+public class MainActivity extends ActionBarActivity implements
+        ConnectionCallbacks, OnConnectionFailedListener {
+    ...
+    class AddressResultReceiver extends ResultReceiver {
+        public AddressResultReceiver(Handler handler) {
+            super(handler);
+        }
+
         &#64;Override
-        protected void onPostExecute(String address) {
-            // Set activity indicator visibility to "gone"
-            mActivityIndicator.setVisibility(View.GONE);
-            // Display the results of the lookup.
-            mAddress.setText(address);
+        protected void onReceiveResult(int resultCode, Bundle resultData) {
+
+            // Display the address string
+            // or an error message sent from the intent service.
+            mAddressOutput = resultData.getString(Constants.RESULT_DATA_KEY);
+            displayAddressOutput();
+
+            // Show a toast message if an address was found.
+            if (resultCode == Constants.SUCCESS_RESULT) {
+                showToast(getString(R.string.address_found));
+            }
+
         }
-        ...
     }
-</pre>
-<p>
-    The final step is to run the address lookup.
-</p>
-<!-- Get and display the address -->
-<h2 id="RunTask">Run the Lookup Task</h2>
-<p>
-    To get the address, call {@link android.os.AsyncTask#execute execute()}. For example, the
-    following snippet starts the address lookup when the user clicks the "Get Address" button:
-</p>
-<pre>
-public class MainActivity extends FragmentActivity {
-    ...
-    /**
-     * The "Get Address" button in the UI is defined with
-     * android:onClick="getAddress". The method is invoked whenever the
-     * user clicks the button.
-     *
-     * &#64;param v The view object associated with this method,
-     * in this case a Button.
-     */
-    public void getAddress(View v) {
-        // Ensure that a Geocoder services is available
-        if (Build.VERSION.SDK_INT &gt;=
-                Build.VERSION_CODES.GINGERBREAD
-                            &amp;&amp;
-                Geocoder.isPresent()) {
-            // Show the activity indicator
-            mActivityIndicator.setVisibility(View.VISIBLE);
-            /*
-             * Reverse geocoding is long-running and synchronous.
-             * Run it on a background thread.
-             * Pass the current location to the background task.
-             * When the task finishes,
-             * onPostExecute() displays the address.
-             */
-            (new GetAddressTask(this)).execute(mLocation);
-        }
-        ...
-    }
-    ...
 }
 </pre>
-<p>
-    The next lesson, <a href="geofencing.html">Creating and Monitoring Geofences</a>, demonstrates
-    how to define locations of interest called <b>geofences</b> and how to use geofence monitoring
-    to detect the user's proximity to a location of interest.
-</p>
diff --git a/docs/html/training/training_toc.cs b/docs/html/training/training_toc.cs
index 0fcfb9c..f5999a5 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=
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/wearables/data-layer/data-items.jd b/docs/html/training/wearables/data-layer/data-items.jd
index 12babbf..49a8d32 100644
--- a/docs/html/training/wearables/data-layer/data-items.jd
+++ b/docs/html/training/wearables/data-layer/data-items.jd
@@ -46,7 +46,7 @@
 </ol>
 
 <p>
-However, instead of working with raw bytes using <a href="{@docRoot}reference/com/google/android/gms/wearable/PutDataRequest.html#setData(byte[])">setData()</a>,
+However, instead of working with raw bytes using <a href="{@docRoot}reference/com/google/android/gms/wearable/PutDataRequest.html#setData(byte[])"><code>setData()</code></a>,
 we recommend you <a href="#SyncData">use a data map</a>, which exposes
 a data item in an easy-to-use {@link android.os.Bundle}-like interface.
 </p>
@@ -88,39 +88,121 @@
   </li>
 </ol>
 
-<p>The following example shows how to create a data map and put data on it:</p>
+<p>The <code>increaseCounter()</code> method in the following example shows how to create a
+data map and put data in it:</p>
 
 <pre>
-PutDataMapRequest dataMap = PutDataMapRequest.create("/count");
-dataMap.getDataMap().putInt(COUNT_KEY, count++);
-PutDataRequest request = dataMap.asPutDataRequest();
-PendingResult&lt;DataApi.DataItemResult&gt; pendingResult = Wearable.DataApi
-        .putDataItem(mGoogleApiClient, request);
-</pre>
+public class MainActivity extends Activity implements
+        DataApi.DataListener,
+        GoogleApiClient.ConnectionCallbacks,
+        GoogleApiClient.OnConnectionFailedListener {
 
-<h2 id="ListenEvents">Listen for Data Item Events</h2>
-If one side of the data layer connection changes a data item, you probably want
-to be notified of any changes on the other side of the connection.
-You can do this by implementing a listener for data item events.
+    private static final String COUNT_KEY = "com.example.key.count";
 
-<p>For example, here's what a typical callback looks like to carry out certain actions
-when data changes:</p>
+    private GoogleApiClient mGoogleApiClient;
+    private int count = 0;
 
-<pre>
-&#64;Override
-public void onDataChanged(DataEventBuffer dataEvents) {
-    for (DataEvent event : dataEvents) {
-        if (event.getType() == DataEvent.TYPE_DELETED) {
-            Log.d(TAG, "DataItem deleted: " + event.getDataItem().getUri());
-        } else if (event.getType() == DataEvent.TYPE_CHANGED) {
-             Log.d(TAG, "DataItem changed: " + event.getDataItem().getUri());
-        }
+    ...
+
+    // Create a data map and put data in it
+    private void <strong>increaseCounter</strong>() {
+        PutDataMapRequest putDataMapReq = PutDataMapRequest.create("/count");
+        putDataMapReq.getDataMap().putInt(COUNT_KEY, count++);
+        PutDataRequest putDataReq = putDataMapReq.asPutDataRequest();
+        PendingResult&lt;DataApi.DataItemResult> pendingResult =
+                Wearable.DataApi.putDataItem(mGoogleApiClient, putDataReq);
     }
+
+    ...
 }
 </pre>
-<p>
-This is just a snippet that requires more implementation details. Learn about
-how to implement a full listener service or activity in
+
+<p>For more information about handling the
+<a href="{@docRoot}reference/com/google/android/gms/common/api/PendingResult.html">
+<code>PendingResult</code></a> object, see
+<a href="{@docRoot}training/wearables/data-layer/events.html#Wait">Wait for the Status of Data
+Layer Calls</a>.</p>
+
+
+<h2 id="ListenEvents">Listen for Data Item Events</h2>
+
+<p>If one side of the data layer connection changes a data item, you probably want
+to be notified of any changes on the other side of the connection.
+You can do this by implementing a listener for data item events.</p>
+
+<p>The code snippet in the following example notifies your app when the value of the
+counter defined in the previous example changes:</p>
+
+<pre>
+public class MainActivity extends Activity implements
+        DataApi.DataListener,
+        GoogleApiClient.ConnectionCallbacks,
+        GoogleApiClient.OnConnectionFailedListener {
+
+    private static final String COUNT_KEY = "com.example.key.count";
+
+    private GoogleApiClient mGoogleApiClient;
+    private int count = 0;
+
+    &#64;Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_main);
+
+        mGoogleApiClient = new GoogleApiClient.Builder(this)
+                .addApi(Wearable.API)
+                .addConnectionCallbacks(this)
+                .addOnConnectionFailedListener(this)
+                .build();
+    }
+
+    &#64;Override
+    protected void onResume() {
+        super.onStart();
+        mGoogleApiClient.connect();
+    }
+
+    &#64;Override
+    public void onConnected(Bundle bundle) {
+        <strong>Wearable.DataApi.addListener</strong>(mGoogleApiClient, this);
+    }
+
+    &#64;Override
+    protected void onPause() {
+        super.onPause();
+        <strong>Wearable.DataApi.removeListener</strong>(mGoogleApiClient, this);
+        mGoogleApiClient.disconnect();
+    }
+
+    &#64;Override
+    public void <strong>onDataChanged</strong>(DataEventBuffer dataEvents) {
+        for (DataEvent event : dataEvents) {
+            if (event.getType() == DataEvent.TYPE_CHANGED) {
+                // DataItem changed
+                DataItem item = event.getDataItem();
+                if (item.getUri().getPath().compareTo("/count") == 0) {
+                    DataMap dataMap = DataMapItem.fromDataItem(item).getDataMap();
+                    updateCount(dataMap.getInt(COUNT_KEY));
+                }
+            } else if (event.getType() == DataEvent.TYPE_DELETED) {
+                // DataItem deleted
+            }
+        }
+    }
+
+    // Our method to update the count
+    private void updateCount(int c) { ... }
+
+    ...
+}
+</pre>
+
+<p>This activity implements the
+<a href="{@docRoot}reference/com/google/android/gms/wearable/DataApi.DataListener.html">
+<code>DataItem.DataListener</code></a> interface. This activity adds itself as a listener
+for data item events inside the <code>onConnected()</code> method and removes the listener
+in the <code>onPause()</code> method.</p>
+
+<p>You can also implement the listener as a service. For more information, see
 <a href="{@docRoot}training/wearables/data-layer/events.html#Listen">Listen for Data Layer
-Events</a>.
-</p>
\ No newline at end of file
+Events</a>.</p>
diff --git a/docs/html/training/wearables/data-layer/events.jd b/docs/html/training/wearables/data-layer/events.jd
index 6a3949a..c797f68 100644
--- a/docs/html/training/wearables/data-layer/events.jd
+++ b/docs/html/training/wearables/data-layer/events.jd
@@ -267,6 +267,8 @@
 public class MainActivity extends Activity implements
         DataApi.DataListener, ConnectionCallbacks, OnConnectionFailedListener {
 
+    private GoogleApiClient mGoogleApiClient;
+
     &#64;Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -314,4 +316,5 @@
             }
         }
     }
+}
 </pre>
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/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/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/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/mtp/MtpDatabase.java b/media/java/android/mtp/MtpDatabase.java
index 13cdc69..5d9355a 100755
--- a/media/java/android/mtp/MtpDatabase.java
+++ b/media/java/android/mtp/MtpDatabase.java
@@ -88,6 +88,10 @@
             Files.FileColumns._ID, // 0
             Files.FileColumns.DATA, // 1
     };
+    private static final String[] FORMAT_PROJECTION = new String[] {
+            Files.FileColumns._ID, // 0
+            Files.FileColumns.FORMAT, // 1
+    };
     private static final String[] PATH_FORMAT_PROJECTION = new String[] {
             Files.FileColumns._ID, // 0
             Files.FileColumns.DATA, // 1
@@ -597,6 +601,7 @@
             MtpConstants.PROPERTY_PARENT_OBJECT,
             MtpConstants.PROPERTY_PERSISTENT_UID,
             MtpConstants.PROPERTY_NAME,
+            MtpConstants.PROPERTY_DISPLAY_NAME,
             MtpConstants.PROPERTY_DATE_ADDED,
     };
 
@@ -669,43 +674,6 @@
             MtpConstants.PROPERTY_DESCRIPTION,
     };
 
-    static final int[] ALL_PROPERTIES = {
-            // NOTE must match FILE_PROPERTIES above
-            MtpConstants.PROPERTY_STORAGE_ID,
-            MtpConstants.PROPERTY_OBJECT_FORMAT,
-            MtpConstants.PROPERTY_PROTECTION_STATUS,
-            MtpConstants.PROPERTY_OBJECT_SIZE,
-            MtpConstants.PROPERTY_OBJECT_FILE_NAME,
-            MtpConstants.PROPERTY_DATE_MODIFIED,
-            MtpConstants.PROPERTY_PARENT_OBJECT,
-            MtpConstants.PROPERTY_PERSISTENT_UID,
-            MtpConstants.PROPERTY_NAME,
-            MtpConstants.PROPERTY_DISPLAY_NAME,
-            MtpConstants.PROPERTY_DATE_ADDED,
-
-            // image specific properties
-            MtpConstants.PROPERTY_DESCRIPTION,
-
-            // audio specific properties
-            MtpConstants.PROPERTY_ARTIST,
-            MtpConstants.PROPERTY_ALBUM_NAME,
-            MtpConstants.PROPERTY_ALBUM_ARTIST,
-            MtpConstants.PROPERTY_TRACK,
-            MtpConstants.PROPERTY_ORIGINAL_RELEASE_DATE,
-            MtpConstants.PROPERTY_DURATION,
-            MtpConstants.PROPERTY_GENRE,
-            MtpConstants.PROPERTY_COMPOSER,
-
-            // video specific properties
-            MtpConstants.PROPERTY_ARTIST,
-            MtpConstants.PROPERTY_ALBUM_NAME,
-            MtpConstants.PROPERTY_DURATION,
-            MtpConstants.PROPERTY_DESCRIPTION,
-
-            // image specific properties
-            MtpConstants.PROPERTY_DESCRIPTION,
-    };
-
     private int[] getSupportedObjectProperties(int format) {
         switch (format) {
             case MtpConstants.FORMAT_MP3:
@@ -723,8 +691,6 @@
             case MtpConstants.FORMAT_PNG:
             case MtpConstants.FORMAT_BMP:
                 return IMAGE_PROPERTIES;
-            case 0:
-                return ALL_PROPERTIES;
             default:
                 return FILE_PROPERTIES;
         }
@@ -749,6 +715,10 @@
 
         MtpPropertyGroup propertyGroup;
         if (property == 0xFFFFFFFFL) {
+            if (format == 0 && handle > 0) {
+                // return properties based on the object's format
+                format = getObjectFormat((int)handle);
+            }
              propertyGroup = mPropertyGroupsByFormat.get(format);
              if (propertyGroup == null) {
                 int[] propertyList = getSupportedObjectProperties(format);
@@ -988,6 +958,26 @@
         }
     }
 
+    private int getObjectFormat(int handle) {
+        Cursor c = null;
+        try {
+            c = mMediaProvider.query(mPackageName, mObjectsUri, FORMAT_PROJECTION,
+                            ID_WHERE, new String[] {  Integer.toString(handle) }, null, null);
+            if (c != null && c.moveToNext()) {
+                return c.getInt(1);
+            } else {
+                return -1;
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in getObjectFilePath", e);
+            return -1;
+        } finally {
+            if (c != null) {
+                c.close();
+            }
+        }
+    }
+
     private int deleteFile(int handle) {
         mDatabaseModified = true;
         String path = null;
diff --git a/media/java/android/mtp/MtpPropertyGroup.java b/media/java/android/mtp/MtpPropertyGroup.java
index 781988d..c80adfa 100644
--- a/media/java/android/mtp/MtpPropertyGroup.java
+++ b/media/java/android/mtp/MtpPropertyGroup.java
@@ -172,6 +172,17 @@
                 column = Images.ImageColumns.DESCRIPTION;
                 type = MtpConstants.TYPE_STR;
                 break;
+            case MtpConstants.PROPERTY_AUDIO_WAVE_CODEC:
+            case MtpConstants.PROPERTY_AUDIO_BITRATE:
+            case MtpConstants.PROPERTY_SAMPLE_RATE:
+                // these are special cased
+                type = MtpConstants.TYPE_UINT32;
+                break;
+            case MtpConstants.PROPERTY_BITRATE_TYPE:
+            case MtpConstants.PROPERTY_NUMBER_OF_CHANNELS:
+                // these are special cased
+                type = MtpConstants.TYPE_UINT16;
+                break;
             default:
                 type = MtpConstants.TYPE_UNDEFINED;
                 Log.e(TAG, "unsupported property " + code);
@@ -420,6 +431,17 @@
                                 result.setResult(MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE);
                             }
                             break;
+                        case MtpConstants.PROPERTY_AUDIO_WAVE_CODEC:
+                        case MtpConstants.PROPERTY_AUDIO_BITRATE:
+                        case MtpConstants.PROPERTY_SAMPLE_RATE:
+                            // we don't have these in our database, so return 0
+                            result.append(handle, propertyCode, MtpConstants.TYPE_UINT32, 0);
+                            break;
+                        case MtpConstants.PROPERTY_BITRATE_TYPE:
+                        case MtpConstants.PROPERTY_NUMBER_OF_CHANNELS:
+                            // we don't have these in our database, so return 0
+                            result.append(handle, propertyCode, MtpConstants.TYPE_UINT16, 0);
+                            break;
                         default:
                             if (property.type == MtpConstants.TYPE_STR) {
                                 result.append(handle, propertyCode, c.getString(column));
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/android_mtp_MtpDatabase.cpp b/media/jni/android_mtp_MtpDatabase.cpp
index 803ab05..713f28c 100644
--- a/media/jni/android_mtp_MtpDatabase.cpp
+++ b/media/jni/android_mtp_MtpDatabase.cpp
@@ -934,6 +934,11 @@
     {   MTP_PROPERTY_COMPOSER,          MTP_TYPE_STR        },
     {   MTP_PROPERTY_DURATION,          MTP_TYPE_UINT32     },
     {   MTP_PROPERTY_DESCRIPTION,       MTP_TYPE_STR        },
+    {   MTP_PROPERTY_AUDIO_WAVE_CODEC,  MTP_TYPE_UINT32     },
+    {   MTP_PROPERTY_BITRATE_TYPE,      MTP_TYPE_UINT16     },
+    {   MTP_PROPERTY_AUDIO_BITRATE,     MTP_TYPE_UINT32     },
+    {   MTP_PROPERTY_NUMBER_OF_CHANNELS,MTP_TYPE_UINT16     },
+    {   MTP_PROPERTY_SAMPLE_RATE,       MTP_TYPE_UINT32     },
 };
 
 static const PropertyTableEntry   kDevicePropertyTable[] = {
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/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/layout/notification_public_default.xml b/packages/SystemUI/res/layout/notification_public_default.xml
index efabc06..044ba09 100644
--- a/packages/SystemUI/res/layout/notification_public_default.xml
+++ b/packages/SystemUI/res/layout/notification_public_default.xml
@@ -16,12 +16,9 @@
   -->
 
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:internal="http://schemas.android.com/apk/prv/res/android"
     android:id="@+id/status_bar_latest_event_content"
     android:layout_width="match_parent"
     android:layout_height="64dp"
-    internal:layout_minHeight="64dp"
-    internal:layout_maxHeight="64dp"
     >
     <ImageView android:id="@+id/icon"
         android:layout_width="40dp"
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 ed43d8e..1aa7366 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -894,7 +894,10 @@
     }
 
     void doInvalidatePanelMenu(int featureId) {
-        PanelFeatureState st = getPanelState(featureId, true);
+        PanelFeatureState st = getPanelState(featureId, false);
+        if (st == null) {
+            return;
+        }
         Bundle savedActionViewStates = null;
         if (st.menu != null) {
             savedActionViewStates = new Bundle();
@@ -933,8 +936,8 @@
             // The panel key was pushed, so set the chording key
             mPanelChordingKey = keyCode;
 
-            PanelFeatureState st = getPanelState(featureId, true);
-            if (!st.isOpen) {
+            PanelFeatureState st = getPanelState(featureId, false);
+            if (st != null && !st.isOpen) {
                 return preparePanel(st, event);
             }
         }
@@ -952,12 +955,14 @@
         if (mPanelChordingKey != 0) {
             mPanelChordingKey = 0;
 
-            if (event.isCanceled() || (mDecor != null && mDecor.mActionMode != null)) {
+            final PanelFeatureState st = getPanelState(featureId, false);
+
+            if (event.isCanceled() || (mDecor != null && mDecor.mActionMode != null) ||
+                    (st == null)) {
                 return;
             }
 
             boolean playSoundEffect = false;
-            final PanelFeatureState st = getPanelState(featureId, true);
             if (featureId == FEATURE_OPTIONS_PANEL && mDecorContentParent != null &&
                     mDecorContentParent.canShowOverflowMenu() &&
                     !ViewConfiguration.get(getContext()).hasPermanentMenuKey()) {
@@ -1056,7 +1061,7 @@
 
     @Override
     public boolean performPanelShortcut(int featureId, int keyCode, KeyEvent event, int flags) {
-        return performPanelShortcut(getPanelState(featureId, true), keyCode, event, flags);
+        return performPanelShortcut(getPanelState(featureId, false), keyCode, event, flags);
     }
 
     private boolean performPanelShortcut(PanelFeatureState st, int keyCode, KeyEvent event,
@@ -1149,11 +1154,11 @@
                         mInvalidatePanelMenuRunnable.run();
                     }
 
-                    final PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, true);
+                    final PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false);
 
                     // If we don't have a menu or we're waiting for a full content refresh,
                     // forget it. This is a lingering event that no longer matters.
-                    if (st.menu != null && !st.refreshMenuContent &&
+                    if (st != null && st.menu != null && !st.refreshMenuContent &&
                             cb.onPreparePanel(FEATURE_OPTIONS_PANEL, st.createdPanelView, st.menu)) {
                         cb.onMenuOpened(FEATURE_ACTION_BAR, st.menu);
                         mDecorContentParent.showOverflowMenu();
@@ -1161,15 +1166,19 @@
                 }
             } else {
                 mDecorContentParent.hideOverflowMenu();
-                if (cb != null && !isDestroyed()) {
-                    final PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, true);
+                final PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false);
+                if (st != null && cb != null && !isDestroyed()) {
                     cb.onPanelClosed(FEATURE_ACTION_BAR, st.menu);
                 }
             }
             return;
         }
 
-        PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, true);
+        PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false);
+
+        if (st == null) {
+            return;
+        }
 
         // Save the future expanded mode state since closePanel will reset it
         boolean newExpandedMode = toggleMenuMode ? !st.isInExpandedMode : st.isInExpandedMode;
@@ -2302,8 +2311,8 @@
             // combination such as Control+C.  Temporarily prepare the panel then mark it
             // unprepared again when finished to ensure that the panel will again be prepared
             // the next time it is shown for real.
-            if (mPreparedPanel == null) {
-                PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, true);
+            PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false);
+            if (st != null && mPreparedPanel == null) {
                 preparePanel(st, ev);
                 handled = performPanelShortcut(st, ev.getKeyCode(), ev,
                         Menu.FLAG_PERFORM_NO_CLOSE);
@@ -3156,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);
             }
 
@@ -3906,8 +3915,8 @@
 
     @Override
     public boolean isShortcutKey(int keyCode, KeyEvent event) {
-        PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, true);
-        return st.menu != null && st.menu.isShortcutKey(keyCode, event);
+        PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false);
+        return st != null && st.menu != null && st.menu.isShortcutKey(keyCode, event);
     }
 
     private void updateDrawable(int featureId, DrawableFeatureState st, boolean fromResume) {
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/core/java/com/android/server/NetworkTimeUpdateService.java b/services/core/java/com/android/server/NetworkTimeUpdateService.java
index fddb54e..d6abce9 100644
--- a/services/core/java/com/android/server/NetworkTimeUpdateService.java
+++ b/services/core/java/com/android/server/NetworkTimeUpdateService.java
@@ -55,7 +55,7 @@
 
     private static final int EVENT_AUTO_TIME_CHANGED = 1;
     private static final int EVENT_POLL_NETWORK_TIME = 2;
-    private static final int EVENT_NETWORK_CONNECTED = 3;
+    private static final int EVENT_NETWORK_CHANGED = 3;
 
     private static final String ACTION_POLL =
             "com.android.server.NetworkTimeUpdateService.action.POLL";
@@ -248,18 +248,8 @@
         public void onReceive(Context context, Intent intent) {
             String action = intent.getAction();
             if (ConnectivityManager.CONNECTIVITY_ACTION.equals(action)) {
-                // There is connectivity
-                final ConnectivityManager connManager = (ConnectivityManager) context
-                        .getSystemService(Context.CONNECTIVITY_SERVICE);
-                final NetworkInfo netInfo = connManager.getActiveNetworkInfo();
-                if (netInfo != null) {
-                    // Verify that it's a WIFI connection
-                    if (netInfo.getState() == NetworkInfo.State.CONNECTED &&
-                            (netInfo.getType() == ConnectivityManager.TYPE_WIFI ||
-                                netInfo.getType() == ConnectivityManager.TYPE_ETHERNET) ) {
-                        mHandler.obtainMessage(EVENT_NETWORK_CONNECTED).sendToTarget();
-                    }
-                }
+                // Don't bother checking if we have connectivity, NtpTrustedTime does that for us.
+                mHandler.obtainMessage(EVENT_NETWORK_CHANGED).sendToTarget();
             }
         }
     };
@@ -276,7 +266,7 @@
             switch (msg.what) {
                 case EVENT_AUTO_TIME_CHANGED:
                 case EVENT_POLL_NETWORK_TIME:
-                case EVENT_NETWORK_CONNECTED:
+                case EVENT_NETWORK_CHANGED:
                     onPollNetworkTime(msg.what);
                     break;
             }
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 9f8d665..059dde1 100755
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -72,7 +72,7 @@
     static final boolean DEBUG_DELAYED_SERVICE = ActivityManagerService.DEBUG_SERVICE;
     static final boolean DEBUG_DELAYED_STARTS = DEBUG_DELAYED_SERVICE;
     static final boolean DEBUG_MU = ActivityManagerService.DEBUG_MU;
-    static final boolean LOG_SERVICE_START_STOP = true;
+    static final boolean LOG_SERVICE_START_STOP = false;
     static final String TAG = ActivityManagerService.TAG;
     static final String TAG_MU = ActivityManagerService.TAG_MU;
 
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 2935bc0..b5d2720 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -2363,7 +2363,7 @@
         return mAppBindArgs;
     }
 
-    final void setFocusedActivityLocked(ActivityRecord r) {
+    final void setFocusedActivityLocked(ActivityRecord r, String reason) {
         if (mFocusedActivity != r) {
             if (DEBUG_FOCUS) Slog.d(TAG, "setFocusedActivityLocked: r=" + r);
             mFocusedActivity = r;
@@ -2372,7 +2372,7 @@
             } else {
                 finishRunningVoiceLocked();
             }
-            mStackSupervisor.setFocusedStack(r);
+            mStackSupervisor.setFocusedStack(r, reason + " setFocusedActivity");
             if (r != null) {
                 mWindowManager.setFocusedApp(r.appToken, true);
             }
@@ -2396,7 +2396,7 @@
             if (stack != null) {
                 ActivityRecord r = stack.topRunningActivityLocked(null);
                 if (r != null) {
-                    setFocusedActivityLocked(r);
+                    setFocusedActivityLocked(r, "setFocusedStack");
                 }
             }
         }
@@ -2440,7 +2440,7 @@
         mHandler.sendMessage(msg);
     }
 
-    private final int updateLruProcessInternalLocked(ProcessRecord app, long now, int index,
+    private int updateLruProcessInternalLocked(ProcessRecord app, long now, int index,
             String what, Object obj, ProcessRecord srcApp) {
         app.lastActivityTime = now;
 
@@ -3114,7 +3114,7 @@
         return intent;
     }
 
-    boolean startHomeActivityLocked(int userId) {
+    boolean startHomeActivityLocked(int userId, String reason) {
         if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL
                 && mTopAction == null) {
             // We are running in factory test mode, but unable to find
@@ -3136,7 +3136,7 @@
                     aInfo.applicationInfo.uid, true);
             if (app == null || app.instrumentationClass == null) {
                 intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
-                mStackSupervisor.startHomeActivity(intent, aInfo);
+                mStackSupervisor.startHomeActivity(intent, aInfo, reason);
             }
         }
 
@@ -5697,7 +5697,7 @@
                     startProcessLocked(procs.get(ip), "on-hold", null);
                 }
             }
-            
+
             if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
                 // Start looking for apps that are abusing wake locks.
                 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
@@ -5837,7 +5837,7 @@
         synchronized (this) {
             ActivityStack stack = ActivityRecord.getStackLocked(token);
             if (stack != null) {
-                stack.activityDestroyedLocked(token);
+                stack.activityDestroyedLocked(token, "activityDestroyed");
             }
         }
     }
@@ -5948,7 +5948,7 @@
                 throw new IllegalArgumentException("File descriptors passed in options");
             }
         }
-        
+
         synchronized(this) {
             int callingUid = Binder.getCallingUid();
             int origUserId = userId;
@@ -5978,7 +5978,7 @@
 
                 return getIntentSenderLocked(type, packageName, callingUid, userId,
                         token, resultWho, requestCode, intents, resolvedTypes, flags, options);
-                
+
             } catch (RemoteException e) {
                 throw new SecurityException(e);
             }
@@ -8019,7 +8019,7 @@
             if (prev != null && prev.isRecentsActivity()) {
                 task.setTaskToReturnTo(ActivityRecord.RECENTS_ACTIVITY_TYPE);
             }
-            mStackSupervisor.findTaskToMoveToFrontLocked(task, flags, options);
+            mStackSupervisor.findTaskToMoveToFrontLocked(task, flags, options, "moveTaskToFront");
         } finally {
             Binder.restoreCallingIdentity(origId);
         }
@@ -8048,7 +8048,7 @@
                         mStackSupervisor.showLockTaskToast();
                         return false;
                     }
-                    return ActivityRecord.getStackLocked(token).moveTaskToBackLocked(taskId, null);
+                    return ActivityRecord.getStackLocked(token).moveTaskToBackLocked(taskId);
                 }
             } finally {
                 Binder.restoreCallingIdentity(origId);
@@ -8154,7 +8154,7 @@
             try {
                 if (DEBUG_STACK) Slog.d(TAG, "moveTaskToStack: moving task=" + taskId + " to stackId="
                         + stackId + " toTop=" + toTop);
-                mStackSupervisor.moveTaskToStack(taskId, stackId, toTop);
+                mStackSupervisor.moveTaskToStackLocked(taskId, stackId, toTop);
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
@@ -8162,12 +8162,14 @@
     }
 
     @Override
-    public void resizeStack(int stackBoxId, Rect bounds) {
+    public void resizeStack(int stackId, Rect bounds) {
         enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
                 "resizeStackBox()");
         long ident = Binder.clearCallingIdentity();
         try {
-            mWindowManager.resizeStack(stackBoxId, bounds);
+            synchronized (this) {
+                mStackSupervisor.resizeStackLocked(stackId, bounds);
+            }
         } finally {
             Binder.restoreCallingIdentity(ident);
         }
@@ -8260,7 +8262,8 @@
                                     || (task != mStackSupervisor.getFocusedStack().topTask()))) {
                         throw new IllegalArgumentException("Invalid task, not in foreground");
                     }
-                    mStackSupervisor.setLockTaskModeLocked(task, !isSystemInitiated);
+                    mStackSupervisor.setLockTaskModeLocked(task, !isSystemInitiated,
+                            "startLockTask");
                 }
             }
         } finally {
@@ -8345,7 +8348,7 @@
             Log.d(TAG, "stopLockTaskMode");
             // Stop lock task
             synchronized (this) {
-                mStackSupervisor.setLockTaskModeLocked(null, false);
+                mStackSupervisor.setLockTaskModeLocked(null, false, "stopLockTask");
             }
         } finally {
             Binder.restoreCallingIdentity(ident);
@@ -10811,7 +10814,7 @@
 
             // Start up initial activity.
             mBooting = true;
-            startHomeActivityLocked(mCurrentUserId);
+            startHomeActivityLocked(mCurrentUserId, "systemReady");
 
             try {
                 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
@@ -18366,7 +18369,7 @@
                     return true;
                 }
 
-                mStackSupervisor.setLockTaskModeLocked(null, false);
+                mStackSupervisor.setLockTaskModeLocked(null, false, "startUser");
 
                 final UserInfo userInfo = getUserManagerLocked().getUserInfo(userId);
                 if (userInfo == null) {
@@ -18623,7 +18626,7 @@
     void moveUserToForeground(UserStartedState uss, int oldUserId, int newUserId) {
         boolean homeInFront = mStackSupervisor.switchUserLocked(newUserId, uss);
         if (homeInFront) {
-            startHomeActivityLocked(newUserId);
+            startHomeActivityLocked(newUserId, "moveUserToFroreground");
         } else {
             mStackSupervisor.resumeTopActivitiesLocked();
         }
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index af6a314..a3676f9 100755
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -127,6 +127,10 @@
     long pauseTime;         // last time we started pausing the activity
     long launchTickTime;    // base time for launch tick messages
     Configuration configuration; // configuration activity was last running in
+    // Overridden configuration by the activity stack
+    // WARNING: Reference points to {@link ActivityStack#mOverrideConfig}, so its internal state
+    // should never be altered directly.
+    Configuration stackConfigOverride;
     CompatibilityInfo compat;// last used compatibility mode
     ActivityRecord resultTo; // who started this entry, so will get our reply
     final String resultWho; // additional identifier for use by resultTo.
@@ -204,6 +208,7 @@
                 pw.print(" icon=0x"); pw.print(Integer.toHexString(icon));
                 pw.print(" theme=0x"); pw.println(Integer.toHexString(theme));
         pw.print(prefix); pw.print("config="); pw.println(configuration);
+        pw.print(prefix); pw.print("stackConfigOverride="); pw.println(stackConfigOverride);
         if (resultTo != null || resultWho != null) {
             pw.print(prefix); pw.print("resultTo="); pw.print(resultTo);
                     pw.print(" resultWho="); pw.print(resultWho);
@@ -394,6 +399,8 @@
         resolvedType = _resolvedType;
         componentSpecified = _componentSpecified;
         configuration = _configuration;
+        stackConfigOverride = (container != null)
+                ? container.mStack.mOverrideConfig : Configuration.EMPTY;
         resultTo = _resultTo;
         resultWho = _resultWho;
         requestCode = _reqCode;
@@ -515,7 +522,7 @@
     void setTask(TaskRecord newTask, TaskRecord taskToAffiliateWith) {
         if (task != null && task.removeActivity(this)) {
             if (task != newTask) {
-                task.stack.removeTask(task);
+                task.stack.removeTask(task, "setTask");
             } else {
                 Slog.d(TAG, "!!! REMOVE THIS LOG !!! setTask: nearly removed stack=" +
                         (newTask == null ? null : newTask.stack));
@@ -1066,10 +1073,7 @@
 
     static ActivityRecord isInStackLocked(IBinder token) {
         final ActivityRecord r = ActivityRecord.forToken(token);
-        if (r != null) {
-            return r.task.stack.isInStackLocked(token);
-        }
-        return null;
+        return (r != null) ? r.task.stack.isInStackLocked(r) : null;
     }
 
     static ActivityStack getStackLocked(IBinder token) {
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 5d21de7..dbd787b 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -235,6 +235,8 @@
     /** Run all ActivityStacks through this */
     final ActivityStackSupervisor mStackSupervisor;
 
+    Configuration mOverrideConfig;
+
     static final int PAUSE_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 1;
     static final int DESTROY_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 2;
     static final int LAUNCH_TICK_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 3;
@@ -292,7 +294,7 @@
                     // so we need to be conservative and assume it isn't.
                     Slog.w(TAG, "Activity destroy timeout for " + r);
                     synchronized (mService) {
-                        activityDestroyedLocked(r != null ? r.appToken : null);
+                        activityDestroyedLocked(r != null ? r.appToken : null, "destroyTimeout");
                     }
                 } break;
                 case STOP_TIMEOUT_MSG: {
@@ -348,6 +350,7 @@
         mStackId = activityContainer.mStackId;
         mCurrentUser = mService.mCurrentUserId;
         mRecentTasks = recentTasks;
+        mOverrideConfig = Configuration.EMPTY;
     }
 
     /**
@@ -450,13 +453,18 @@
 
     ActivityRecord isInStackLocked(IBinder token) {
         final ActivityRecord r = ActivityRecord.forToken(token);
-        if (r != null) {
-            final TaskRecord task = r.task;
-            if (task != null && task.mActivities.contains(r) && mTaskHistory.contains(task)) {
-                if (task.stack != this) Slog.w(TAG,
+        return isInStackLocked(r);
+    }
+
+    ActivityRecord isInStackLocked(ActivityRecord r) {
+        if (r == null) {
+            return null;
+        }
+        final TaskRecord task = r.task;
+        if (task != null && task.mActivities.contains(r) && mTaskHistory.contains(task)) {
+            if (task.stack != this) Slog.w(TAG,
                     "Illegal state! task does not point to stack it is in.");
-                return r;
-            }
+            return r;
         }
         return null;
     }
@@ -476,10 +484,10 @@
                 mActivityContainer.mActivityDisplay.mDisplayId == Display.DEFAULT_DISPLAY;
     }
 
-    final void moveToFront() {
+    final void moveToFront(String reason) {
         if (isAttached()) {
             if (isOnHomeDisplay()) {
-                mStackSupervisor.moveHomeStack(isHomeStack());
+                mStackSupervisor.moveHomeStack(isHomeStack(), reason);
             }
             mStacks.remove(this);
             mStacks.add(this);
@@ -1497,7 +1505,7 @@
             final int returnTaskType = prevTask == null || !prevTask.isOverHomeStack() ?
                     HOME_ACTIVITY_TYPE : prevTask.getTaskToReturnTo();
             return isOnHomeDisplay() &&
-                    mStackSupervisor.resumeHomeStackTask(returnTaskType, prev);
+                    mStackSupervisor.resumeHomeStackTask(returnTaskType, prev, "noMoreActivities");
         }
 
         next.delayedResume = false;
@@ -1533,7 +1541,7 @@
                         "resumeTopActivityLocked: Launching home next");
                 final int returnTaskType = prevTask == null || !prevTask.isOverHomeStack() ?
                         HOME_ACTIVITY_TYPE : prevTask.getTaskToReturnTo();
-                return mStackSupervisor.resumeHomeStackTask(returnTaskType, prev);
+                return mStackSupervisor.resumeHomeStackTask(returnTaskType, prev, "prevFinished");
             }
         }
 
@@ -1819,11 +1827,8 @@
                     next.app.thread.scheduleNewIntent(next.newIntents, next.appToken);
                 }
 
-                EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY,
-                        next.userId, System.identityHashCode(next),
-                        next.task.taskId, next.shortComponentName + " top="
-                                + mStacks.get(mStacks.size() - 1).mStackId + " Callers="
-                                + Debug.getCallers(6));
+                EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY, next.userId,
+                        System.identityHashCode(next), next.task.taskId, next.shortComponentName);
 
                 next.sleeping = false;
                 mService.showAskCompatModeDialogLocked(next);
@@ -2198,7 +2203,7 @@
                 }
 
                 final int targetTaskId = targetTask.taskId;
-                mWindowManager.setAppGroupId(target.appToken, targetTaskId);
+                mWindowManager.setAppTask(target.appToken, targetTaskId);
 
                 boolean noOptions = canMoveOptions;
                 final int start = replyChainEnd < 0 ? i : replyChainEnd;
@@ -2223,7 +2228,7 @@
                     p.setTask(targetTask, null);
                     targetTask.addActivityAtBottom(p);
 
-                    mWindowManager.setAppGroupId(p.appToken, targetTaskId);
+                    mWindowManager.setAppTask(p.appToken, targetTaskId);
                 }
 
                 mWindowManager.moveTaskToBottom(targetTaskId);
@@ -2363,7 +2368,7 @@
                                 new RuntimeException("here").fillInStackTrace());
                         if (DEBUG_TASKS) Slog.v(TAG, "Pulling activity " + p + " from " + srcPos
                                 + " in to resetting task " + task);
-                        mWindowManager.setAppGroupId(p.appToken, taskId);
+                        mWindowManager.setAppTask(p.appToken, taskId);
                     }
                     mWindowManager.moveTaskToTop(taskId);
                     if (VALIDATE_TOKENS) {
@@ -2472,18 +2477,19 @@
         r.addResultLocked(null, resultWho, requestCode, resultCode, data);
     }
 
-    private void adjustFocusedActivityLocked(ActivityRecord r) {
+    private void adjustFocusedActivityLocked(ActivityRecord r, String reason) {
         if (mStackSupervisor.isFrontStack(this) && mService.mFocusedActivity == r) {
             ActivityRecord next = topRunningActivityLocked(null);
             if (next != r) {
                 final TaskRecord task = r.task;
                 if (r.frontOfTask && task == topTask() && task.isOverHomeStack()) {
-                    mStackSupervisor.moveHomeStackTaskToTop(task.getTaskToReturnTo());
+                    mStackSupervisor.moveHomeStackTaskToTop(task.getTaskToReturnTo(),
+                            reason + " adjustFocus");
                 }
             }
             ActivityRecord top = mStackSupervisor.topRunningActivityLocked();
             if (top != null) {
-                mService.setFocusedActivityLocked(top);
+                mService.setFocusedActivityLocked(top, reason + " adjustTopFocus");
             }
         }
     }
@@ -2507,7 +2513,7 @@
         }
 
         if (r.app != null && r.app.thread != null) {
-            adjustFocusedActivityLocked(r);
+            adjustFocusedActivityLocked(r, "stopActivity");
             r.resumeKeyDispatchingLocked();
             try {
                 r.stopped = false;
@@ -2711,7 +2717,7 @@
 
         r.pauseKeyDispatchingLocked();
 
-        adjustFocusedActivityLocked(r);
+        adjustFocusedActivityLocked(r, "finishActivity");
 
         finishActivityResultsLocked(r, resultCode, resultData);
 
@@ -3014,7 +3020,7 @@
         r.finishLaunchTickingLocked();
     }
 
-    private void removeActivityFromHistoryLocked(ActivityRecord r) {
+    private void removeActivityFromHistoryLocked(ActivityRecord r, String reason) {
         mStackSupervisor.removeChildActivityContainers(r);
         finishActivityResultsLocked(r, Activity.RESULT_CANCELED, null);
         r.makeFinishing();
@@ -3039,9 +3045,9 @@
                     "removeActivityFromHistoryLocked: last activity removed from " + this);
             if (mStackSupervisor.isFrontStack(this) && task == topTask() &&
                     task.isOverHomeStack()) {
-                mStackSupervisor.moveHomeStackTaskToTop(task.getTaskToReturnTo());
+                mStackSupervisor.moveHomeStackTaskToTop(task.getTaskToReturnTo(), reason);
             }
-            removeTask(task);
+            removeTask(task, reason);
         }
         cleanUpActivityServicesLocked(r);
         r.removeUriPermissionsLocked();
@@ -3206,7 +3212,7 @@
                 // up.
                 //Slog.w(TAG, "Exception thrown during finish", e);
                 if (r.finishing) {
-                    removeActivityFromHistoryLocked(r);
+                    removeActivityFromHistoryLocked(r, reason + " exceptionInScheduleDestroy");
                     removedFromHistory = true;
                     skipDestroy = true;
                 }
@@ -3236,7 +3242,7 @@
         } else {
             // remove this record from the history.
             if (r.finishing) {
-                removeActivityFromHistoryLocked(r);
+                removeActivityFromHistoryLocked(r, reason + " hadNoApp");
                 removedFromHistory = true;
             } else {
                 if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r + " (no app)");
@@ -3255,7 +3261,7 @@
         return removedFromHistory;
     }
 
-    final void activityDestroyedLocked(IBinder token) {
+    final void activityDestroyedLocked(IBinder token, String reason) {
         final long origId = Binder.clearCallingIdentity();
         try {
             ActivityRecord r = ActivityRecord.forToken(token);
@@ -3264,10 +3270,10 @@
             }
             if (DEBUG_CONTAINERS) Slog.d(TAG, "activityDestroyedLocked: r=" + r);
 
-            if (isInStackLocked(token) != null) {
+            if (isInStackLocked(r) != null) {
                 if (r.state == ActivityState.DESTROYING) {
                     cleanUpActivityLocked(r, true, false);
-                    removeActivityFromHistoryLocked(r);
+                    removeActivityFromHistoryLocked(r, reason);
                 }
             }
             mStackSupervisor.resumeTopActivitiesLocked();
@@ -3403,7 +3409,7 @@
                                 mService.updateUsageStats(r, false);
                             }
                         }
-                        removeActivityFromHistoryLocked(r);
+                        removeActivityFromHistoryLocked(r, "appDied");
 
                     } else {
                         // We have the current state for this activity, so
@@ -3472,15 +3478,15 @@
         }
     }
 
-    final void moveTaskToFrontLocked(TaskRecord tr, ActivityRecord reason, Bundle options) {
+    final void moveTaskToFrontLocked(TaskRecord tr, boolean noAnimation, Bundle options,
+            String reason) {
         if (DEBUG_SWITCH) Slog.v(TAG, "moveTaskToFront: " + tr);
 
         final int numTasks = mTaskHistory.size();
         final int index = mTaskHistory.indexOf(tr);
         if (numTasks == 0 || index < 0)  {
             // nothing to do!
-            if (reason != null &&
-                    (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
+            if (noAnimation) {
                 ActivityOptions.abort(options);
             } else {
                 updateTransitLocked(AppTransition.TRANSIT_TASK_TO_FRONT, options);
@@ -3491,11 +3497,10 @@
         // Shift all activities with this task up to the top
         // of the stack, keeping them in the same internal order.
         insertTaskAtTop(tr);
-        moveToFront();
+        moveToFront(reason);
 
         if (DEBUG_TRANSITION) Slog.v(TAG, "Prepare to front transition: task=" + tr);
-        if (reason != null &&
-                (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
+        if (noAnimation) {
             mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);
             ActivityRecord r = topRunningActivityLocked(null);
             if (r != null) {
@@ -3525,7 +3530,7 @@
      * @param taskId The taskId to collect and move to the bottom.
      * @return Returns true if the move completed, false if not.
      */
-    final boolean moveTaskToBackLocked(int taskId, ActivityRecord reason) {
+    final boolean moveTaskToBackLocked(int taskId) {
         final TaskRecord tr = taskForIdLocked(taskId);
         if (tr == null) {
             Slog.i(TAG, "moveTaskToBack: bad taskId=" + taskId);
@@ -3580,16 +3585,7 @@
             }
         }
 
-        if (reason != null &&
-                (reason.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
-            mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);
-            ActivityRecord r = topRunningActivityLocked(null);
-            if (r != null) {
-                mNoAnimActivities.add(r);
-            }
-        } else {
-            mWindowManager.prepareAppTransition(AppTransition.TRANSIT_TASK_TO_BACK, false);
-        }
+        mWindowManager.prepareAppTransition(AppTransition.TRANSIT_TASK_TO_BACK, false);
         mWindowManager.moveTaskToBottom(taskId);
 
         if (VALIDATE_TOKENS) {
@@ -3604,7 +3600,7 @@
             }
             final int taskToReturnTo = tr.getTaskToReturnTo();
             tr.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
-            return mStackSupervisor.resumeHomeStackTask(taskToReturnTo, null);
+            return mStackSupervisor.resumeHomeStackTask(taskToReturnTo, null, "moveTaskToBack");
         }
 
         mStackSupervisor.resumeTopActivitiesLocked();
@@ -3643,7 +3639,9 @@
         // Short circuit: if the two configurations are the exact same
         // object (the common case), then there is nothing to do.
         Configuration newConfig = mService.mConfiguration;
-        if (r.configuration == newConfig && !r.forceNewConfig) {
+        if (r.configuration == newConfig
+                && r.stackConfigOverride == mOverrideConfig
+                && !r.forceNewConfig) {
             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
                     "Configuration unchanged in " + r);
             return true;
@@ -3659,14 +3657,22 @@
 
         // Okay we now are going to make this activity have the new config.
         // But then we need to figure out how it needs to deal with that.
-        Configuration oldConfig = r.configuration;
+        final Configuration oldConfig = r.configuration;
+        final Configuration oldStackOverride = r.stackConfigOverride;
         r.configuration = newConfig;
+        r.stackConfigOverride = mOverrideConfig;
 
         // Determine what has changed.  May be nothing, if this is a config
         // that has come back from the app after going idle.  In that case
         // we just want to leave the official config object now in the
         // activity and do nothing else.
-        final int changes = oldConfig.diff(newConfig);
+        int stackChanges = oldStackOverride.diff(mOverrideConfig);
+        if (stackChanges == 0 && !oldStackOverride.equals(mOverrideConfig)) {
+            // Assume size change if diff didn't report any changes,
+            // but configurations are not equal.
+            stackChanges = ActivityInfo.CONFIG_SCREEN_SIZE;
+        }
+        final int changes = oldConfig.diff(newConfig) | stackChanges;
         if (changes == 0 && !r.forceNewConfig) {
             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
                     "Configuration no differences in " + r);
@@ -3770,8 +3776,9 @@
                     (andResume ? "Relaunching to RESUMED " : "Relaunching to PAUSED ")
                     + r);
             r.forceNewConfig = false;
-            r.app.thread.scheduleRelaunchActivity(r.appToken, results, newIntents,
-                    changes, !andResume, new Configuration(mService.mConfiguration));
+            r.app.thread.scheduleRelaunchActivity(r.appToken, results, newIntents, changes,
+                    !andResume, new Configuration(mService.mConfiguration),
+                    new Configuration(mOverrideConfig));
             // Note: don't need to call pauseIfSleepingLocked() here, because
             // the caller will only pass in 'andResume' if this activity is
             // currently resumed, which implies we aren't sleeping.
@@ -4046,7 +4053,7 @@
         return starting;
     }
 
-    void removeTask(TaskRecord task) {
+    void removeTask(TaskRecord task, String reason) {
         mStackSupervisor.endLockTaskModeIfTaskEnding(task);
         mWindowManager.removeTask(task.taskId);
         final ActivityRecord r = mResumedActivity;
@@ -4084,7 +4091,7 @@
         if (mTaskHistory.isEmpty()) {
             if (DEBUG_STACK) Slog.i(TAG, "removeTask: moving to back stack=" + this);
             if (isOnHomeDisplay()) {
-                mStackSupervisor.moveHomeStack(!isHomeStack());
+                mStackSupervisor.moveHomeStack(!isHomeStack(), reason + " leftTaskHistoryEmpty");
             }
             if (mStacks != null) {
                 mStacks.remove(this);
@@ -4132,4 +4139,10 @@
         return "ActivityStack{" + Integer.toHexString(System.identityHashCode(this))
                 + " stackId=" + mStackId + ", " + mTaskHistory.size() + " tasks}";
     }
+
+    boolean updateOverrideConfiguration(Configuration newConfig) {
+        Configuration oldConfig = mOverrideConfig;
+        mOverrideConfig = (newConfig == null) ? Configuration.EMPTY : newConfig;
+        return !mOverrideConfig.equals(oldConfig);
+    }
 }
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 4cf8f00..4674cc2 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -63,6 +63,7 @@
 import android.content.pm.ResolveInfo;
 import android.content.res.Configuration;
 import android.graphics.Point;
+import android.graphics.Rect;
 import android.hardware.display.DisplayManager;
 import android.hardware.display.DisplayManager.DisplayListener;
 import android.hardware.display.DisplayManagerGlobal;
@@ -399,7 +400,7 @@
         return false;
     }
 
-    void moveHomeStack(boolean toFront) {
+    void moveHomeStack(boolean toFront, String reason) {
         ArrayList<ActivityStack> stacks = mHomeStack.mStacks;
         final int topNdx = stacks.size() - 1;
         if (topNdx <= 0) {
@@ -417,7 +418,7 @@
         }
         EventLog.writeEvent(EventLogTags.AM_HOME_STACK_MOVED,
                 mCurrentUser, toFront ? 1 : 0, stacks.get(topNdx).getStackId(),
-                mFocusedStack == null ? -1 : mFocusedStack.getStackId());
+                mFocusedStack == null ? -1 : mFocusedStack.getStackId(), reason);
 
         if (mService.mBooting || !mService.mBooted) {
             final ActivityRecord r = topRunningActivityLocked();
@@ -427,16 +428,16 @@
         }
     }
 
-    void moveHomeStackTaskToTop(int homeStackTaskType) {
+    void moveHomeStackTaskToTop(int homeStackTaskType, String reason) {
         if (homeStackTaskType == RECENTS_ACTIVITY_TYPE) {
             mWindowManager.showRecentApps();
             return;
         }
-        moveHomeStack(true);
+        moveHomeStack(true, reason);
         mHomeStack.moveHomeStackTaskToTop(homeStackTaskType);
     }
 
-    boolean resumeHomeStackTask(int homeStackTaskType, ActivityRecord prev) {
+    boolean resumeHomeStackTask(int homeStackTaskType, ActivityRecord prev, String reason) {
         if (!mService.mBooting && !mService.mBooted) {
             // Not ready yet!
             return false;
@@ -446,7 +447,7 @@
             mWindowManager.showRecentApps();
             return false;
         }
-        moveHomeStackTaskToTop(homeStackTaskType);
+        moveHomeStackTaskToTop(homeStackTaskType, reason);
         if (prev != null) {
             prev.task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
         }
@@ -454,10 +455,10 @@
         ActivityRecord r = mHomeStack.topRunningActivityLocked(null);
         // if (r != null && (r.isHomeActivity() || r.isRecentsActivity())) {
         if (r != null && r.isHomeActivity()) {
-            mService.setFocusedActivityLocked(r);
+            mService.setFocusedActivityLocked(r, reason);
             return resumeTopActivitiesLocked(mHomeStack, prev, null);
         }
-        return mService.startHomeActivityLocked(mCurrentUser);
+        return mService.startHomeActivityLocked(mCurrentUser, reason);
     }
 
     TaskRecord anyTaskForIdLocked(int id) {
@@ -829,8 +830,8 @@
         return aInfo;
     }
 
-    void startHomeActivity(Intent intent, ActivityInfo aInfo) {
-        moveHomeStackTaskToTop(HOME_ACTIVITY_TYPE);
+    void startHomeActivity(Intent intent, ActivityInfo aInfo, String reason) {
+        moveHomeStackTaskToTop(HOME_ACTIVITY_TYPE, reason);
         startActivityLocked(null, intent, null, aInfo, null, null, null, null, 0, 0, 0, null,
                 0, 0, 0, null, false, null, null, null);
     }
@@ -874,8 +875,7 @@
             } else {
                 stack = container.mStack;
             }
-            stack.mConfigWillChange = config != null
-                    && mService.mConfiguration.diff(config) != 0;
+            stack.mConfigWillChange = config != null && mService.mConfiguration.diff(config) != 0;
             if (DEBUG_CONFIGURATION) Slog.v(TAG,
                     "Starting activity when config will change = " + stack.mConfigWillChange);
 
@@ -1181,9 +1181,9 @@
             app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_TOP);
             app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                     System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
-                    r.compat, r.launchedFromPackage, r.task.voiceInteractor, app.repProcState,
-                    r.icicle, r.persistentState, results, newIntents, !andResume,
-                    mService.isNextTransitionForward(), profilerInfo);
+                    new Configuration(stack.mOverrideConfig), r.compat, r.launchedFromPackage,
+                    r.task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
+                    newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);
 
             if ((app.info.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
                 // This may be a heavy-weight process!  Note that the package
@@ -1581,7 +1581,7 @@
         return mHomeStack;
     }
 
-    void setFocusedStack(ActivityRecord r) {
+    void setFocusedStack(ActivityRecord r, String reason) {
         if (r != null) {
             final TaskRecord task = r.task;
             boolean isHomeActivity = !r.isApplicationActivity();
@@ -1592,11 +1592,11 @@
                 final ActivityRecord parent = task.stack.mActivityContainer.mParentActivity;
                 isHomeActivity = parent != null && parent.isHomeActivity();
             }
-            moveHomeStack(isHomeActivity);
+            moveHomeStack(isHomeActivity, reason);
         }
     }
 
-    final int startActivityUncheckedLocked(ActivityRecord r, ActivityRecord sourceRecord,
+    final int startActivityUncheckedLocked(final ActivityRecord r, ActivityRecord sourceRecord,
             IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags,
             boolean doResume, Bundle options, TaskRecord inTask) {
         final Intent intent = r.intent;
@@ -1807,6 +1807,7 @@
         ActivityStack targetStack;
 
         intent.setFlags(launchFlags);
+        final boolean noAnimation = (launchFlags & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0;
 
         // We may want to try to place the new activity in to an existing task.  We always
         // do this if the target activity is singleTask or singleInstance; we will also do
@@ -1840,7 +1841,7 @@
                     targetStack.mLastPausedActivity = null;
                     if (DEBUG_TASKS) Slog.d(TAG, "Bring to front target: " + targetStack
                             + " from " + intentActivity);
-                    targetStack.moveToFront();
+                    targetStack.moveToFront("intentActivityFound");
                     if (intentActivity.task.intent == null) {
                         // This task was started because of movement of
                         // the activity based on affinity...  now that we
@@ -1869,7 +1870,8 @@
                                 intentActivity.setTaskToAffiliateWith(sourceRecord.task);
                             }
                             movedHome = true;
-                            targetStack.moveTaskToFrontLocked(intentActivity.task, r, options);
+                            targetStack.moveTaskToFrontLocked(intentActivity.task, noAnimation,
+                                    options, "bringingFoundTaskToFront");
                             if ((launchFlags &
                                     (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
                                     == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
@@ -2067,7 +2069,7 @@
             newTask = true;
             targetStack = adjustStackFocus(r, newTask);
             if (!launchTaskBehind) {
-                targetStack.moveToFront();
+                targetStack.moveToFront("startingNewTask");
             }
             if (reuseTask == null) {
                 r.setTask(targetStack.createTaskRecord(getNextTaskId(),
@@ -2096,10 +2098,11 @@
                 return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
             }
             targetStack = sourceTask.stack;
-            targetStack.moveToFront();
+            targetStack.moveToFront("sourceStackToFront");
             final TaskRecord topTask = targetStack.topTask();
             if (topTask != sourceTask) {
-                targetStack.moveTaskToFrontLocked(sourceTask, r, options);
+                targetStack.moveTaskToFrontLocked(sourceTask, noAnimation, options,
+                        "sourceTaskToFront");
             }
             if (!addingToTask && (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
                 // In this case, we are adding the activity to an existing
@@ -2153,7 +2156,7 @@
                 return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
             }
             targetStack = inTask.stack;
-            targetStack.moveTaskToFrontLocked(inTask, r, options);
+            targetStack.moveTaskToFrontLocked(inTask, noAnimation, options, "inTaskToFront");
 
             // Check whether we should actually launch the new activity in to the task,
             // or just reuse the current activity on top.
@@ -2189,7 +2192,7 @@
             // of a new task...  just put it in the top task, though these days
             // this case should never happen.
             targetStack = adjustStackFocus(r, newTask);
-            targetStack.moveToFront();
+            targetStack.moveToFront("addingToTopTask");
             ActivityRecord prev = targetStack.topActivity();
             r.setTask(prev != null ? prev.task : targetStack.createTaskRecord(getNextTaskId(),
                             r.info, intent, null, null, true), null);
@@ -2212,7 +2215,7 @@
         targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
         if (!launchTaskBehind) {
             // Don't set focus on an activity that's going to the back.
-            mService.setFocusedActivityLocked(r);
+            mService.setFocusedActivityLocked(r, "startedActivity");
         }
         return ActivityManager.START_SUCCESS;
     }
@@ -2509,7 +2512,7 @@
         }
     }
 
-    void findTaskToMoveToFrontLocked(TaskRecord task, int flags, Bundle options) {
+    void findTaskToMoveToFrontLocked(TaskRecord task, int flags, Bundle options, String reason) {
         if ((flags & ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
             mUserLeaving = true;
         }
@@ -2518,7 +2521,7 @@
             // we'll just indicate that this task returns to the home task.
             task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
         }
-        task.stack.moveTaskToFrontLocked(task, null, options);
+        task.stack.moveTaskToFrontLocked(task, false /* noAnimation */, options, reason);
         if (DEBUG_STACK) Slog.d(TAG, "findTaskToMoveToFront: moved to front of stack="
                 + task.stack);
     }
@@ -2595,6 +2598,27 @@
         }
     }
 
+    void resizeStackLocked(int stackId, Rect bounds) {
+        final ActivityStack stack = getStack(stackId);
+        if (stack == null) {
+            Slog.w(TAG, "resizeStack: stackId " + stackId + " not found.");
+            return;
+        }
+        final Configuration overrideConfig = mWindowManager.resizeStack(stackId, bounds);
+        if (stack.updateOverrideConfiguration(overrideConfig)) {
+            final ActivityRecord r = stack.topRunningActivityLocked(null);
+            if (r != null) {
+                final boolean updated = stack.ensureActivityConfigurationLocked(r, 0);
+                // And we need to make sure at this point that all other activities
+                // are made visible with the correct configuration.
+                ensureActivitiesVisibleLocked(r, 0);
+                if (!updated) {
+                    resumeTopActivitiesLocked(stack, null, null);
+                }
+            }
+        }
+    }
+
     ActivityStack createStackOnDisplay(int stackId, int displayId) {
         ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
         if (activityDisplay == null) {
@@ -2643,7 +2667,7 @@
             // display.
             stack = createStackOnDisplay(getNextStackId(), Display.DEFAULT_DISPLAY);
             // Restore home stack to top.
-            moveHomeStack(true);
+            moveHomeStack(true, "restoreRecentTask");
             if (DEBUG_RECENTS)
                 Slog.v(TAG, "Created stack=" + stack + " for recents restoration.");
         }
@@ -2670,7 +2694,7 @@
         return true;
     }
 
-    void moveTaskToStack(int taskId, int stackId, boolean toTop) {
+    void moveTaskToStackLocked(int taskId, int stackId, boolean toTop) {
         final TaskRecord task = anyTaskForIdLocked(taskId);
         if (task == null) {
             return;
@@ -2680,7 +2704,7 @@
             Slog.w(TAG, "moveTaskToStack: no stack for id=" + stackId);
             return;
         }
-        task.stack.removeTask(task);
+        task.stack.removeTask(task, "moveTaskToStack");
         stack.addTask(task, toTop, true);
         mWindowManager.addTask(taskId, stackId, toTop);
         resumeTopActivitiesLocked();
@@ -3046,14 +3070,14 @@
         }
         final boolean homeInFront = stack.isHomeStack();
         if (stack.isOnHomeDisplay()) {
-            moveHomeStack(homeInFront);
+            moveHomeStack(homeInFront, "switchUserOnHomeDisplay");
             TaskRecord task = stack.topTask();
             if (task != null) {
                 mWindowManager.moveTaskToTop(task.taskId);
             }
         } else {
             // Stack was moved to another display while user was swapped out.
-            resumeHomeStackTask(HOME_ACTIVITY_TYPE, null);
+            resumeHomeStackTask(HOME_ACTIVITY_TYPE, null, "switchUserOnOtherDisplay");
         }
         return homeInFront;
     }
@@ -3448,7 +3472,7 @@
         mLockTaskNotify.showToast(mLockTaskIsLocked);
     }
 
-    void setLockTaskModeLocked(TaskRecord task, boolean isLocked) {
+    void setLockTaskModeLocked(TaskRecord task, boolean isLocked, String reason) {
         if (task == null) {
             // Take out of lock task mode if necessary
             if (mLockTaskModeTask != null) {
@@ -3465,7 +3489,7 @@
             return;
         }
         mLockTaskModeTask = task;
-        findTaskToMoveToFrontLocked(task, 0, null);
+        findTaskToMoveToFrontLocked(task, 0, null, reason);
         resumeTopActivitiesLocked();
 
         final Message lockTaskMsg = Message.obtain();
diff --git a/services/core/java/com/android/server/am/EventLogTags.logtags b/services/core/java/com/android/server/am/EventLogTags.logtags
index 41499be..c376744 100644
--- a/services/core/java/com/android/server/am/EventLogTags.logtags
+++ b/services/core/java/com/android/server/am/EventLogTags.logtags
@@ -94,4 +94,4 @@
 30043 am_focused_activity (User|1|5),(Component Name|3)
 
 # 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)
+30044 am_home_stack_moved (User|1|5),(To Front|1|5),(Top Stack Id|1|5),(Focused Stack Id|1|5),(Reason|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..664f541 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;
@@ -878,6 +879,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 +1468,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.
@@ -1490,6 +1521,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/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 77a1fa9..667d02a 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -117,7 +117,6 @@
     public void onStart() {
         publishBinderService(Context.MEDIA_SESSION_SERVICE, mSessionManagerImpl);
         Watchdog.getInstance().addMonitor(this);
-        updateUser();
         mKeyguardManager =
                 (KeyguardManager) getContext().getSystemService(Context.KEYGUARD_SERVICE);
         mAudioService = getAudioService();
@@ -125,6 +124,8 @@
         mContentResolver = getContext().getContentResolver();
         mSettingsObserver = new SettingsObserver();
         mSettingsObserver.observe();
+
+        updateUser();
     }
 
     private IAudioService getAudioService() {
@@ -501,6 +502,12 @@
         UserRecord user = mUserRecords.get(record.getUserId());
         if (receiver != null && user != null) {
             user.mLastMediaButtonReceiver = receiver;
+            ComponentName component = receiver.getIntent().getComponent();
+            if (component != null && record.getPackageName().equals(component.getPackageName())) {
+                Settings.Secure.putStringForUser(mContentResolver,
+                        Settings.System.MEDIA_BUTTON_RECEIVER, component.flattenToString(),
+                        record.getUserId());
+            }
         }
     }
 
@@ -511,14 +518,17 @@
     final class UserRecord {
         private final int mUserId;
         private final ArrayList<MediaSessionRecord> mSessions = new ArrayList<MediaSessionRecord>();
+        private final Context mContext;
         private PendingIntent mLastMediaButtonReceiver;
+        private ComponentName mRestoredMediaButtonReceiver;
 
         public UserRecord(Context context, int userId) {
+            mContext = context;
             mUserId = userId;
+            restoreMediaButtonReceiver();
         }
 
         public void startLocked() {
-            // nothing for now
         }
 
         public void stopLocked() {
@@ -548,6 +558,7 @@
             pw.println(prefix + "Record for user " + mUserId);
             String indent = prefix + "  ";
             pw.println(indent + "MediaButtonReceiver:" + mLastMediaButtonReceiver);
+            pw.println(indent + "Restored ButtonReceiver:" + mRestoredMediaButtonReceiver);
             int size = mSessions.size();
             pw.println(indent + size + " Sessions:");
             for (int i = 0; i < size; i++) {
@@ -556,6 +567,19 @@
                 pw.println(indent + mSessions.get(i).toString());
             }
         }
+
+        private void restoreMediaButtonReceiver() {
+            String receiverName = Settings.Secure.getStringForUser(mContentResolver,
+                    Settings.System.MEDIA_BUTTON_RECEIVER, UserHandle.USER_CURRENT);
+            if (!TextUtils.isEmpty(receiverName)) {
+                ComponentName eventReceiver = ComponentName.unflattenFromString(receiverName);
+                if (eventReceiver == null) {
+                    // an invalid name was persisted
+                    return;
+                }
+                mRestoredMediaButtonReceiver = eventReceiver;
+            }
+        }
     }
 
     final class SessionsListenerRecord implements IBinder.DeathRecipient {
@@ -723,8 +747,9 @@
                 synchronized (mLock) {
                     // If we don't have a media button receiver to fall back on
                     // include non-playing sessions for dispatching
-                    boolean useNotPlayingSessions = mUserRecords.get(
-                            ActivityManager.getCurrentUser()).mLastMediaButtonReceiver == null;
+                    UserRecord ur = mUserRecords.get(ActivityManager.getCurrentUser());
+                    boolean useNotPlayingSessions = ur.mLastMediaButtonReceiver == null
+                            && ur.mRestoredMediaButtonReceiver == null;
                     MediaSessionRecord session = mPriorityStack
                             .getDefaultMediaButtonSession(mCurrentUserId, useNotPlayingSessions);
                     if (isVoiceKey(keyEvent.getKeyCode())) {
@@ -929,9 +954,12 @@
                 // Launch the last PendingIntent we had with priority
                 int userId = ActivityManager.getCurrentUser();
                 UserRecord user = mUserRecords.get(userId);
-                if (user.mLastMediaButtonReceiver != null) {
+                if (user.mLastMediaButtonReceiver != null
+                        || user.mRestoredMediaButtonReceiver != null) {
                     if (DEBUG) {
-                        Log.d(TAG, "Sending media key to last known PendingIntent");
+                        Log.d(TAG, "Sending media key to last known PendingIntent "
+                                + user.mLastMediaButtonReceiver + " or restored Intent "
+                                + user.mRestoredMediaButtonReceiver);
                     }
                     if (needWakeLock) {
                         mKeyEventReceiver.aquireWakeLockLocked();
@@ -939,9 +967,15 @@
                     Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
                     mediaButtonIntent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent);
                     try {
-                        user.mLastMediaButtonReceiver.send(getContext(),
-                                needWakeLock ? mKeyEventReceiver.mLastTimeoutId : -1,
-                                mediaButtonIntent, mKeyEventReceiver, null);
+                        if (user.mLastMediaButtonReceiver != null) {
+                            user.mLastMediaButtonReceiver.send(getContext(),
+                                    needWakeLock ? mKeyEventReceiver.mLastTimeoutId : -1,
+                                    mediaButtonIntent, mKeyEventReceiver, null);
+                        } else {
+                            mediaButtonIntent.setComponent(user.mRestoredMediaButtonReceiver);
+                            getContext().sendBroadcastAsUser(mediaButtonIntent,
+                                    new UserHandle(userId));
+                        }
                     } catch (CanceledException e) {
                         Log.i(TAG, "Error sending key event to media button receiver "
                                 + user.mLastMediaButtonReceiver, e);
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/tv/TvInputHardwareManager.java b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
index 2af56fe..50b2262 100644
--- a/services/core/java/com/android/server/tv/TvInputHardwareManager.java
+++ b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
@@ -677,7 +677,9 @@
         private AudioDevicePort mAudioSource;
         private List<AudioDevicePort> mAudioSink = new ArrayList<>();
         private AudioPatch mAudioPatch = null;
-        private float mCommittedVolume = 0.0f;
+        // Set to an invalid value for a volume, so that current volume can be applied at the
+        // first call to updateAudioConfigLocked().
+        private float mCommittedVolume = -1f;
         private float mSourceVolume = 0.0f;
 
         private TvStreamConfig mActiveConfig = null;
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/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 3b27cd2..a04f6cb 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -52,7 +52,7 @@
 
     final boolean voiceInteraction;
 
-    int groupId = -1;
+    Task mTask;
     boolean appFullscreen;
     int requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
     boolean layoutConfigChanges;
@@ -256,7 +256,8 @@
         mIsExiting = false;
         removeAllWindows();
 
-        final Task task = service.mTaskIdToTask.get(groupId);
+        // Use local variable because removeAppToken will null out mTask.
+        final Task task = mTask;
         if (task != null) {
             if (!task.removeAppToken(this)) {
                 Slog.e(WindowManagerService.TAG, "removeAppFromTaskLocked: token=" + this
@@ -295,8 +296,8 @@
         if (allAppWindows.size() > 0) {
             pw.print(prefix); pw.print("allAppWindows="); pw.println(allAppWindows);
         }
-        pw.print(prefix); pw.print("groupId="); pw.print(groupId);
-                pw.print(" appFullscreen="); pw.print(appFullscreen);
+        pw.print(prefix); pw.print("task="); pw.println(mTask);
+        pw.print(prefix); pw.print(" appFullscreen="); pw.print(appFullscreen);
                 pw.print(" requestedOrientation="); pw.println(requestedOrientation);
         pw.print(prefix); pw.print("hiddenRequested="); pw.print(hiddenRequested);
                 pw.print(" clientHidden="); pw.print(clientHidden);
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index e3b53b0..8bbc5a9 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -379,7 +379,7 @@
             ArrayList<Task> tasks = stack.getTasks();
             for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
                 final Task task = tasks.get(taskNdx);
-                pw.print("    mTaskId="); pw.println(task.taskId);
+                pw.print("    mTaskId="); pw.println(task.mTaskId);
                 AppTokenList tokens = task.mAppTokens;
                 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx, ++ndx) {
                     final AppWindowToken wtoken = tokens.get(tokenNdx);
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/Task.java b/services/core/java/com/android/server/wm/Task.java
index 80d727d..a9b26e2 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -26,14 +26,13 @@
 class Task {
     TaskStack mStack;
     final AppTokenList mAppTokens = new AppTokenList();
-    final int taskId;
+    final int mTaskId;
     final int mUserId;
     boolean mDeferRemoval = false;
     final WindowManagerService mService;
 
-    Task(AppWindowToken wtoken, TaskStack stack, int userId, WindowManagerService service) {
-        taskId = wtoken.groupId;
-        mAppTokens.add(wtoken);
+    Task(int taskId, TaskStack stack, int userId, WindowManagerService service) {
+        mTaskId = taskId;
         mStack = stack;
         mUserId = userId;
         mService = service;
@@ -45,38 +44,47 @@
 
     void addAppToken(int addPos, AppWindowToken wtoken) {
         final int lastPos = mAppTokens.size();
-        for (int pos = 0; pos < lastPos && pos < addPos; ++pos) {
-            if (mAppTokens.get(pos).removed) {
-                // addPos assumes removed tokens are actually gone.
-                ++addPos;
+        if (addPos >= lastPos) {
+            addPos = lastPos;
+        } else {
+            for (int pos = 0; pos < lastPos && pos < addPos; ++pos) {
+                if (mAppTokens.get(pos).removed) {
+                    // addPos assumes removed tokens are actually gone.
+                    ++addPos;
+                }
             }
         }
         mAppTokens.add(addPos, wtoken);
+        wtoken.mTask = this;
         mDeferRemoval = false;
     }
 
     void removeLocked() {
         if (!mAppTokens.isEmpty() && mStack.isAnimating()) {
-            if (DEBUG_STACK) Slog.i(TAG, "removeTask: deferring removing taskId=" + taskId);
+            if (DEBUG_STACK) Slog.i(TAG, "removeTask: deferring removing taskId=" + mTaskId);
             mDeferRemoval = true;
             return;
         }
-        if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing taskId=" + taskId);
-        EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, taskId, "removeTask");
+        if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing taskId=" + mTaskId);
+        EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, mTaskId, "removeTask");
         mDeferRemoval = false;
         mStack.removeTask(this);
-        mService.mTaskIdToTask.delete(taskId);
+        mService.mTaskIdToTask.delete(mTaskId);
     }
 
     boolean removeAppToken(AppWindowToken wtoken) {
         boolean removed = mAppTokens.remove(wtoken);
         if (mAppTokens.size() == 0) {
-            EventLog.writeEvent(com.android.server.EventLogTags.WM_TASK_REMOVED, taskId,
+            EventLog.writeEvent(com.android.server.EventLogTags.WM_TASK_REMOVED, mTaskId,
                     "removeAppToken: last token");
             if (mDeferRemoval) {
                 removeLocked();
             }
         }
+        wtoken.mTask = null;
+        /* Leave mTaskId for now, it might be useful for debug
+        wtoken.mTaskId = -1;
+         */
         return removed;
     }
 
@@ -88,6 +96,6 @@
 
     @Override
     public String toString() {
-        return "{taskId=" + taskId + " appTokens=" + mAppTokens + " mdr=" + mDeferRemoval + "}";
+        return "{taskId=" + mTaskId + " appTokens=" + mAppTokens + " mdr=" + mDeferRemoval + "}";
     }
 }
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index d6741b3..5d73149 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -19,8 +19,10 @@
 import static com.android.server.wm.WindowManagerService.DEBUG_TASK_MOVEMENT;
 import static com.android.server.wm.WindowManagerService.TAG;
 
+import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.os.Debug;
+import android.util.DisplayMetrics;
 import android.util.EventLog;
 import android.util.Slog;
 import android.util.TypedValue;
@@ -78,9 +80,14 @@
     /** Detach this stack from its display when animation completes. */
     boolean mDeferDetach;
 
+    // Contains configurations settings that are different from the global configuration due to
+    // stack specific operations. E.g. {@link #setBounds}.
+    Configuration mOverrideConfig;
+
     TaskStack(WindowManagerService service, int stackId) {
         mService = service;
         mStackId = stackId;
+        mOverrideConfig = Configuration.EMPTY;
         // TODO: remove bounds from log, they are always 0.
         EventLog.writeEvent(EventLogTags.WM_STACK_CREATED, stackId, mBounds.left, mBounds.top,
                 mBounds.right, mBounds.bottom);
@@ -129,7 +136,7 @@
         mDimLayer.setBounds(bounds);
         mAnimationBackgroundSurface.setBounds(bounds);
         mBounds.set(bounds);
-
+        updateOverrideConfiguration();
         return true;
     }
 
@@ -137,6 +144,27 @@
         out.set(mBounds);
     }
 
+    void updateOverrideConfiguration() {
+        final Configuration serviceConfig = mService.mCurConfiguration;
+        if (mFullscreen) {
+            mOverrideConfig = Configuration.EMPTY;
+            return;
+        }
+
+        if (mOverrideConfig == Configuration.EMPTY) {
+            mOverrideConfig  = new Configuration();
+        }
+
+        // TODO(multidisplay): Update Dp to that of display stack is on.
+        final float density = serviceConfig.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;
+        mOverrideConfig.screenWidthDp =
+                Math.min((int)(mBounds.width() / density), serviceConfig.screenWidthDp);
+        mOverrideConfig.screenHeightDp =
+                Math.min((int)(mBounds.height() / density), serviceConfig.screenHeightDp);
+        mOverrideConfig.smallestScreenWidthDp =
+                Math.min(mOverrideConfig.screenWidthDp, mOverrideConfig.screenHeightDp);
+    }
+
     void updateDisplayInfo() {
         if (mFullscreen && mDisplayContent != null) {
             mDisplayContent.getLogicalDisplayRect(mTmpRect);
@@ -194,7 +222,7 @@
         if (toTop) {
             mDisplayContent.moveStack(this, true);
         }
-        EventLog.writeEvent(EventLogTags.WM_TASK_MOVED, task.taskId, toTop ? 1 : 0, stackNdx);
+        EventLog.writeEvent(EventLogTags.WM_TASK_MOVED, task.mTaskId, toTop ? 1 : 0, stackNdx);
     }
 
     void moveTaskToTop(Task task) {
@@ -224,10 +252,9 @@
             }
             mDisplayContent.layoutNeeded = true;
         }
-        final int taskId = task.taskId;
         for (int appNdx = mExitingAppTokens.size() - 1; appNdx >= 0; --appNdx) {
             final AppWindowToken wtoken = mExitingAppTokens.get(appNdx);
-            if (wtoken.groupId == taskId) {
+            if (wtoken.mTask == task) {
                 wtoken.mIsExiting = false;
                 mExitingAppTokens.remove(appNdx);
             }
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 2c05e93..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) {
@@ -3612,15 +3580,15 @@
         Binder.restoreCallingIdentity(origId);
     }
 
-    private Task createTask(int taskId, int stackId, int userId, AppWindowToken atoken) {
-        if (DEBUG_STACK) Slog.i(TAG, "createTask: taskId=" + taskId + " stackId=" + stackId
+    private Task createTaskLocked(int taskId, int stackId, int userId, AppWindowToken atoken) {
+        if (DEBUG_STACK) Slog.i(TAG, "createTaskLocked: taskId=" + taskId + " stackId=" + stackId
                 + " atoken=" + atoken);
         final TaskStack stack = mStackIdToStack.get(stackId);
         if (stack == null) {
             throw new IllegalArgumentException("addAppToken: invalid stackId=" + stackId);
         }
         EventLog.writeEvent(EventLogTags.WM_TASK_CREATED, taskId, stackId);
-        Task task = new Task(atoken, stack, userId, this);
+        Task task = new Task(taskId, stack, userId, this);
         mTaskIdToTask.put(taskId, task);
         stack.addTask(task, !atoken.mLaunchTaskBehind /* toTop */);
         return task;
@@ -3657,7 +3625,6 @@
             }
             atoken = new AppWindowToken(this, token, voiceInteraction);
             atoken.inputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
-            atoken.groupId = taskId;
             atoken.appFullscreen = fullscreen;
             atoken.showWhenLocked = showWhenLocked;
             atoken.requestedOrientation = requestedOrientation;
@@ -3669,10 +3636,9 @@
 
             Task task = mTaskIdToTask.get(taskId);
             if (task == null) {
-                createTask(taskId, stackId, userId, atoken);
-            } else {
-                task.addAppToken(addPos, atoken);
+                task = createTaskLocked(taskId, stackId, userId, atoken);
             }
+            task.addAppToken(addPos, atoken);
 
             mTokenMap.put(token.asBinder(), atoken);
 
@@ -3685,28 +3651,27 @@
     }
 
     @Override
-    public void setAppGroupId(IBinder token, int groupId) {
+    public void setAppTask(IBinder token, int taskId) {
         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
-                "setAppGroupId()")) {
+                "setAppTask()")) {
             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
         }
 
         synchronized(mWindowMap) {
             final AppWindowToken atoken = findAppWindowToken(token);
             if (atoken == null) {
-                Slog.w(TAG, "Attempted to set group id of non-existing app token: " + token);
+                Slog.w(TAG, "Attempted to set task id of non-existing app token: " + token);
                 return;
             }
-            final Task oldTask = mTaskIdToTask.get(atoken.groupId);
+            final Task oldTask = atoken.mTask;
             oldTask.removeAppToken(atoken);
 
-            atoken.groupId = groupId;
-            Task newTask = mTaskIdToTask.get(groupId);
+            Task newTask = mTaskIdToTask.get(taskId);
             if (newTask == null) {
-                newTask = createTask(groupId, oldTask.mStack.mStackId, oldTask.mUserId, atoken);
-            } else {
-                newTask.mAppTokens.add(atoken);
+                newTask =
+                        createTaskLocked(taskId, oldTask.mStack.mStackId, oldTask.mUserId, atoken);
             }
+            newTask.addAppToken(Integer.MAX_VALUE /* at top */, atoken);
         }
     }
 
@@ -3990,7 +3955,7 @@
     void setFocusedStackFrame() {
         final TaskStack stack;
         if (mFocusedApp != null) {
-            Task task = mTaskIdToTask.get(mFocusedApp.groupId);
+            final Task task = mFocusedApp.mTask;
             stack = task.mStack;
             final DisplayContent displayContent = task.getDisplayContent();
             if (displayContent != null) {
@@ -4812,7 +4777,7 @@
                         + " animating=" + wtoken.mAppAnimator.animating);
                 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, "removeAppToken: "
                         + wtoken + " delayed=" + delayed + " Callers=" + Debug.getCallers(4));
-                final TaskStack stack = mTaskIdToTask.get(wtoken.groupId).mStack;
+                final TaskStack stack = wtoken.mTask.mStack;
                 if (delayed && !wtoken.allAppWindows.isEmpty()) {
                     // set the token aside because it has an active animation to be finished
                     if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
@@ -4877,7 +4842,7 @@
             final int numTasks = tasks.size();
             for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
                 final Task task = tasks.get(taskNdx);
-                Slog.v(TAG, "    Task #" + task.taskId + " activities from bottom to top:");
+                Slog.v(TAG, "    Task #" + task.mTaskId + " activities from bottom to top:");
                 AppTokenList tokens = task.mAppTokens;
                 final int numTokens = tokens.size();
                 for (int tokenNdx = 0; tokenNdx < numTokens; ++tokenNdx) {
@@ -5128,7 +5093,12 @@
         }
     }
 
-    public void resizeStack(int stackId, Rect bounds) {
+    /**
+     * Re-sizes the specified stack and its containing windows.
+     * Returns a {@link Configuration} object that contains configurations settings
+     * that should be overridden due to the operation.
+     */
+    public Configuration resizeStack(int stackId, Rect bounds) {
         synchronized (mWindowMap) {
             final TaskStack stack = mStackIdToStack.get(stackId);
             if (stack == null) {
@@ -5140,6 +5110,7 @@
                 stack.getDisplayContent().layoutNeeded = true;
                 performLayoutAndPlaceSurfacesLocked();
             }
+            return new Configuration(stack.mOverrideConfig);
         }
     }
 
@@ -7068,7 +7039,7 @@
         return sw;
     }
 
-    boolean computeScreenConfigurationLocked(Configuration config) {
+    private boolean computeScreenConfigurationLocked(Configuration config) {
         if (!mDisplayReady) {
             return false;
         }
@@ -7951,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:
@@ -8476,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;
                 }
             }
@@ -8731,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.
@@ -8790,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");
@@ -8815,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;
@@ -10367,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/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 978f5c3..98f00de 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -130,7 +130,8 @@
 
     int mLayoutSeq = -1;
 
-    Configuration mConfiguration = null;
+    private Configuration mConfiguration = Configuration.EMPTY;
+    private Configuration mOverrideConfig = Configuration.EMPTY;
     // Sticky answer to isConfigChanged(), remains true until new Configuration is assigned.
     // Used only on {@link #TYPE_KEYGUARD}.
     private boolean mConfigHasChanged;
@@ -792,14 +793,14 @@
     TaskStack getStack() {
         AppWindowToken wtoken = mAppToken == null ? mService.mFocusedApp : mAppToken;
         if (wtoken != null) {
-            Task task = mService.mTaskIdToTask.get(wtoken.groupId);
+            Task task = wtoken.mTask;
             if (task != null) {
                 if (task.mStack != null) {
                     return task.mStack;
                 }
                 Slog.e(TAG, "getStack: mStack null for task=" + task);
             } else {
-                Slog.e(TAG, "getStack: " + this + " couldn't find taskId=" + wtoken.groupId
+                Slog.e(TAG, "getStack: " + this + " couldn't find task for " + wtoken
                     + " Callers=" + Debug.getCallers(4));
             }
         }
@@ -1076,9 +1077,13 @@
     }
 
     boolean isConfigChanged() {
-        boolean configChanged = mConfiguration != mService.mCurConfiguration
-                && (mConfiguration == null
-                        || (mConfiguration.diff(mService.mCurConfiguration) != 0));
+        final TaskStack stack = getStack();
+        final Configuration overrideConfig =
+                (stack != null) ? stack.mOverrideConfig : Configuration.EMPTY;
+        final Configuration serviceConfig = mService.mCurConfiguration;
+        boolean configChanged =
+                (mConfiguration != serviceConfig && mConfiguration.diff(serviceConfig) != 0)
+                || (mOverrideConfig != overrideConfig && !mOverrideConfig.equals(overrideConfig));
 
         if ((mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
             // Retain configuration changed status until resetConfiguration called.
@@ -1107,8 +1112,10 @@
         }
     }
 
-    void setConfiguration(final Configuration newConfig) {
+    private void setConfiguration(
+            final Configuration newConfig, final Configuration newOverrideConfig) {
         mConfiguration = newConfig;
+        mOverrideConfig = newOverrideConfig;
         mConfigHasChanged = false;
     }
 
@@ -1384,12 +1391,15 @@
             if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, "Reporting new frame to " + this
                     + ": " + mCompatFrame);
             boolean configChanged = isConfigChanged();
+            final TaskStack stack = getStack();
+            final Configuration overrideConfig =
+                    (stack != null) ? stack.mOverrideConfig : Configuration.EMPTY;
             if ((DEBUG_RESIZE || DEBUG_ORIENTATION || DEBUG_CONFIGURATION) && configChanged) {
                 Slog.i(TAG, "Sending new config to window " + this + ": "
-                        + mWinAnimator.mSurfaceW + "x" + mWinAnimator.mSurfaceH
-                        + " / " + mService.mCurConfiguration);
+                        + mWinAnimator.mSurfaceW + "x" + mWinAnimator.mSurfaceH + " / config="
+                        + mService.mCurConfiguration + " overrideConfig=" + overrideConfig);
             }
-            setConfiguration(mService.mCurConfiguration);
+            setConfiguration(mService.mCurConfiguration, overrideConfig);
             if (DEBUG_ORIENTATION && mWinAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING)
                 Slog.i(TAG, "Resizing " + this + " WITH DRAW PENDING");
 
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 7f0ab6b..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);
@@ -436,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/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 6621726..1a6b292 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -691,7 +691,7 @@
                 getTelecomService().clearAccounts(packageName);
             }
         } catch (RemoteException e) {
-            Log.e(TAG, "Error calling ITelecomService#clearAccountsForPackage()", e);
+            Log.e(TAG, "Error calling ITelecomService#clearAccountsForPackage", e);
         }
     }
 
@@ -726,7 +726,7 @@
                 return getTelecomService().isVoiceMailNumber(accountHandle, number);
             }
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException calling isInCall().", e);
+            Log.e(TAG, "RemoteException calling ITelecomService#isVoiceMailNumber.", e);
         }
         return false;
     }
@@ -746,12 +746,32 @@
                 return getTelecomService().hasVoiceMailNumber(accountHandle);
             }
         } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException calling isInCall().", e);
+            Log.e(TAG, "RemoteException calling ITelecomService#hasVoiceMailNumber.", e);
         }
         return false;
     }
 
     /**
+     * Return the line 1 phone number for given phone account.
+     *
+     * @param accountHandle The handle for the account retrieve a number for.
+     * @return A string representation of the line 1 phone number.
+     *
+     * @hide
+     */
+    @SystemApi
+    public String getLine1Number(PhoneAccountHandle accountHandle) {
+        try {
+            if (isServiceConnected()) {
+                return getTelecomService().getLine1Number(accountHandle);
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException calling ITelecomService#getLine1Number.", e);
+        }
+        return null;
+    }
+
+    /**
      * Returns whether there is an ongoing phone call (can be in dialing, ringing, active or holding
      * states).
      * <p>
diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
index f8d7539..d2030f2 100644
--- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
+++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
@@ -126,6 +126,11 @@
     boolean hasVoiceMailNumber(in PhoneAccountHandle accountHandle);
 
     /**
+     * @see TelecomServiceImpl#getLine1Number
+     */
+    String getLine1Number(in PhoneAccountHandle accountHandle);
+
+    /**
      * @see TelecomServiceImpl#getDefaultPhoneApp
      */
     ComponentName getDefaultPhoneApp();
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/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
index 62c92a1..e44969d 100644
--- a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
+++ b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
@@ -103,7 +103,7 @@
         }
         
         try {
-            mWm.setAppGroupId(null, 0);
+            mWm.setAppTask(null, 0);
             fail("IWindowManager.setAppGroupId did not throw SecurityException as"
                     + " expected");
         } catch (SecurityException e) {
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index 5176419..d90271b 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -293,7 +293,7 @@
     }
 
     @Override
-    public void setAppGroupId(IBinder arg0, int arg1) throws RemoteException {
+    public void setAppTask(IBinder arg0, int arg1) throws RemoteException {
         // TODO Auto-generated method stub
 
     }
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();