Merge "Add recorder address to all recording listerner apis." into lmp-mr1-dev
diff --git a/api/current.txt b/api/current.txt
index 481975d..979f2cf 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -4798,7 +4798,9 @@
     method public int getCustomSizePreset();
     method public android.app.PendingIntent getDisplayIntent();
     method public int getGravity();
+    method public boolean getHintAvoidBackgroundClipping();
     method public boolean getHintHideIcon();
+    method public int getHintScreenTimeout();
     method public boolean getHintShowBackgroundOnly();
     method public java.util.List<android.app.Notification> getPages();
     method public boolean getStartScrollBottom();
@@ -4811,9 +4813,13 @@
     method public android.app.Notification.WearableExtender setCustomSizePreset(int);
     method public android.app.Notification.WearableExtender setDisplayIntent(android.app.PendingIntent);
     method public android.app.Notification.WearableExtender setGravity(int);
+    method public android.app.Notification.WearableExtender setHintAvoidBackgroundClipping(boolean);
     method public android.app.Notification.WearableExtender setHintHideIcon(boolean);
+    method public android.app.Notification.WearableExtender setHintScreenTimeout(int);
     method public android.app.Notification.WearableExtender setHintShowBackgroundOnly(boolean);
     method public android.app.Notification.WearableExtender setStartScrollBottom(boolean);
+    field public static final int SCREEN_TIMEOUT_LONG = -1; // 0xffffffff
+    field public static final int SCREEN_TIMEOUT_SHORT = 0; // 0x0
     field public static final int SIZE_DEFAULT = 0; // 0x0
     field public static final int SIZE_FULL_SCREEN = 5; // 0x5
     field public static final int SIZE_LARGE = 4; // 0x4
@@ -30273,19 +30279,6 @@
     method public static java.text.DateFormat getMediumDateFormat(android.content.Context);
     method public static java.text.DateFormat getTimeFormat(android.content.Context);
     method public static boolean is24HourFormat(android.content.Context);
-    field public static final deprecated char AM_PM = 97; // 0x0061 'a'
-    field public static final deprecated char CAPITAL_AM_PM = 65; // 0x0041 'A'
-    field public static final deprecated char DATE = 100; // 0x0064 'd'
-    field public static final deprecated char DAY = 69; // 0x0045 'E'
-    field public static final deprecated char HOUR = 104; // 0x0068 'h'
-    field public static final deprecated char HOUR_OF_DAY = 107; // 0x006b 'k'
-    field public static final deprecated char MINUTE = 109; // 0x006d 'm'
-    field public static final deprecated char MONTH = 77; // 0x004d 'M'
-    field public static final deprecated char QUOTE = 39; // 0x0027 '\''
-    field public static final deprecated char SECONDS = 115; // 0x0073 's'
-    field public static final deprecated char STANDALONE_MONTH = 76; // 0x004c 'L'
-    field public static final deprecated char TIME_ZONE = 122; // 0x007a 'z'
-    field public static final deprecated char YEAR = 121; // 0x0079 'y'
   }
 
   public class DateUtils {
diff --git a/api/removed.txt b/api/removed.txt
index 8972679..1b69ee8 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -22,6 +22,26 @@
 
 }
 
+package android.text.format {
+
+  public class DateFormat {
+    field public static final deprecated char AM_PM = 97; // 0x0061 'a'
+    field public static final deprecated char CAPITAL_AM_PM = 65; // 0x0041 'A'
+    field public static final deprecated char DATE = 100; // 0x0064 'd'
+    field public static final deprecated char DAY = 69; // 0x0045 'E'
+    field public static final deprecated char HOUR = 104; // 0x0068 'h'
+    field public static final deprecated char HOUR_OF_DAY = 107; // 0x006b 'k'
+    field public static final deprecated char MINUTE = 109; // 0x006d 'm'
+    field public static final deprecated char MONTH = 77; // 0x004d 'M'
+    field public static final deprecated char QUOTE = 39; // 0x0027 '\''
+    field public static final deprecated char SECONDS = 115; // 0x0073 's'
+    field public static final deprecated char STANDALONE_MONTH = 76; // 0x004c 'L'
+    field public static final deprecated char TIME_ZONE = 122; // 0x007a 'z'
+    field public static final deprecated char YEAR = 121; // 0x0079 'y'
+  }
+
+}
+
 package android.view {
 
   public class View implements android.view.accessibility.AccessibilityEventSource android.graphics.drawable.Drawable.Callback android.view.KeyEvent.Callback {
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index 1e1b33f..a9eaf29 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -24,11 +24,9 @@
 import android.os.Message;
 import android.os.RemoteException;
 import android.util.Log;
-import android.view.Display;
 import android.view.KeyEvent;
-import android.view.View;
-import android.view.ViewGroup;
 import android.view.WindowManager;
+import android.view.WindowManagerGlobal;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityInteractionClient;
 import android.view.accessibility.AccessibilityNodeInfo;
@@ -620,18 +618,6 @@
         }
     }
 
-    @Override
-    public Object getSystemService(String name) {
-        if (Context.WINDOW_SERVICE.equals(name)) {
-            if (mWindowManager == null) {
-                WindowManager wrapped = (WindowManager) super.getSystemService(name);
-                mWindowManager = new LocalWindowManager(wrapped);
-            }
-            return mWindowManager;
-        }
-        return super.getSystemService(name);
-    }
-
     /**
      * Implement to return the implementation of the internal accessibility
      * service interface.
@@ -658,6 +644,9 @@
             public void init(int connectionId, IBinder windowToken) {
                 mConnectionId = connectionId;
                 mWindowToken = windowToken;
+
+                // Let the window manager know about our shiny new token.
+                WindowManagerGlobal.getInstance().setDefaultToken(mWindowToken);
             }
 
             @Override
@@ -812,53 +801,4 @@
             }
         }
     }
-
-    private class LocalWindowManager implements WindowManager {
-        private final WindowManager mImpl;
-
-        private LocalWindowManager(WindowManager impl) {
-            mImpl = impl;
-        }
-
-        @Override
-        public Display getDefaultDisplay() {
-            return mImpl.getDefaultDisplay();
-        }
-
-        @Override
-        public void addView(View view, ViewGroup.LayoutParams params) {
-            if (!(params instanceof WindowManager.LayoutParams)) {
-                throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
-            }
-            WindowManager.LayoutParams windowParams = (WindowManager.LayoutParams) params;
-            if (windowParams.type == LayoutParams.TYPE_ACCESSIBILITY_OVERLAY
-                    && windowParams.token == null) {
-                windowParams.token = mWindowToken;
-            }
-            mImpl.addView(view, params);
-        }
-
-        @Override
-        public void updateViewLayout(View view, ViewGroup.LayoutParams params) {
-            if (!(params instanceof WindowManager.LayoutParams)) {
-                throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
-            }
-            WindowManager.LayoutParams windowParams = (WindowManager.LayoutParams) params;
-            if (windowParams.type == LayoutParams.TYPE_ACCESSIBILITY_OVERLAY
-                    && windowParams.token == null) {
-                windowParams.token = mWindowToken;
-            }
-            mImpl.updateViewLayout(view, params);
-        }
-
-        @Override
-        public void removeViewImmediate(View view) {
-            mImpl.removeViewImmediate(view);
-        }
-
-        @Override
-        public void removeView(View view) {
-            mImpl.removeView(view);
-        }
-    }
 }
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 37e8aa4..a285932 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -1243,26 +1243,16 @@
     }
 
     /**
-     * If set, the process of the root activity of the task will be killed
-     * as part of removing the task.
-     * @hide
-     */
-    public static final int REMOVE_TASK_KILL_PROCESS = 0x0001;
-
-    /**
      * Completely remove the given task.
      *
      * @param taskId Identifier of the task to be removed.
-     * @param flags Additional operational flags.  May be 0 or
-     * {@link #REMOVE_TASK_KILL_PROCESS}.
      * @return Returns true if the given task was found and removed.
      *
      * @hide
      */
-    public boolean removeTask(int taskId, int flags)
-            throws SecurityException {
+    public boolean removeTask(int taskId) throws SecurityException {
         try {
-            return ActivityManagerNative.getDefault().removeTask(taskId, flags);
+            return ActivityManagerNative.getDefault().removeTask(taskId);
         } catch (RemoteException e) {
             // System dead, we will be dead too soon!
             return false;
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 4e2ff0b..bc7114b 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1884,8 +1884,7 @@
         {
             data.enforceInterface(IActivityManager.descriptor);
             int taskId = data.readInt();
-            int fl = data.readInt();
-            boolean result = removeTask(taskId, fl);
+            boolean result = removeTask(taskId);
             reply.writeNoException();
             reply.writeInt(result ? 1 : 0);
             return true;
@@ -4778,12 +4777,11 @@
         return result;
     }
 
-    public boolean removeTask(int taskId, int flags) throws RemoteException {
+    public boolean removeTask(int taskId) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
         data.writeInt(taskId);
-        data.writeInt(flags);
         mRemote.transact(REMOVE_TASK_TRANSACTION, data, reply, 0);
         reply.readException();
         boolean result = reply.readInt() != 0;
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index be26f30..efcb197 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -373,7 +373,7 @@
     public boolean isUserRunning(int userid, boolean orStopping) throws RemoteException;
     public int[] getRunningUserIds() throws RemoteException;
 
-    public boolean removeTask(int taskId, int flags) throws RemoteException;
+    public boolean removeTask(int taskId) throws RemoteException;
 
     public void registerProcessObserver(IProcessObserver observer) throws RemoteException;
     public void unregisterProcessObserver(IProcessObserver observer) throws RemoteException;
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 9849c51..c65f017 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -4340,6 +4340,19 @@
          */
         public static final int SIZE_FULL_SCREEN = 5;
 
+        /**
+         * Sentinel value for use with {@link #setHintScreenTimeout} to keep the screen on for a
+         * short amount of time when this notification is displayed on the screen. This
+         * is the default value.
+         */
+        public static final int SCREEN_TIMEOUT_SHORT = 0;
+
+        /**
+         * Sentinel value for use with {@link #setHintScreenTimeout} to keep the screen on
+         * for a longer amount of time when this notification is displayed on the screen.
+         */
+        public static final int SCREEN_TIMEOUT_LONG = -1;
+
         /** Notification extra which contains wearable extensions */
         private static final String EXTRA_WEARABLE_EXTENSIONS = "android.wearable.EXTENSIONS";
 
@@ -4355,12 +4368,14 @@
         private static final String KEY_CUSTOM_SIZE_PRESET = "customSizePreset";
         private static final String KEY_CUSTOM_CONTENT_HEIGHT = "customContentHeight";
         private static final String KEY_GRAVITY = "gravity";
+        private static final String KEY_HINT_SCREEN_TIMEOUT = "hintScreenTimeout";
 
         // Flags bitwise-ored to mFlags
         private static final int FLAG_CONTENT_INTENT_AVAILABLE_OFFLINE = 0x1;
         private static final int FLAG_HINT_HIDE_ICON = 1 << 1;
         private static final int FLAG_HINT_SHOW_BACKGROUND_ONLY = 1 << 2;
         private static final int FLAG_START_SCROLL_BOTTOM = 1 << 3;
+        private static final int FLAG_HINT_AVOID_BACKGROUND_CLIPPING = 1 << 4;
 
         // Default value for flags integer
         private static final int DEFAULT_FLAGS = FLAG_CONTENT_INTENT_AVAILABLE_OFFLINE;
@@ -4379,6 +4394,7 @@
         private int mCustomSizePreset = SIZE_DEFAULT;
         private int mCustomContentHeight;
         private int mGravity = DEFAULT_GRAVITY;
+        private int mHintScreenTimeout;
 
         /**
          * Create a {@link android.app.Notification.WearableExtender} with default
@@ -4414,6 +4430,7 @@
                         SIZE_DEFAULT);
                 mCustomContentHeight = wearableBundle.getInt(KEY_CUSTOM_CONTENT_HEIGHT);
                 mGravity = wearableBundle.getInt(KEY_GRAVITY, DEFAULT_GRAVITY);
+                mHintScreenTimeout = wearableBundle.getInt(KEY_HINT_SCREEN_TIMEOUT);
             }
         }
 
@@ -4461,6 +4478,9 @@
             if (mGravity != DEFAULT_GRAVITY) {
                 wearableBundle.putInt(KEY_GRAVITY, mGravity);
             }
+            if (mHintScreenTimeout != 0) {
+                wearableBundle.putInt(KEY_HINT_SCREEN_TIMEOUT, mHintScreenTimeout);
+            }
 
             builder.getExtras().putBundle(EXTRA_WEARABLE_EXTENSIONS, wearableBundle);
             return builder;
@@ -4480,6 +4500,7 @@
             that.mCustomSizePreset = this.mCustomSizePreset;
             that.mCustomContentHeight = this.mCustomContentHeight;
             that.mGravity = this.mGravity;
+            that.mHintScreenTimeout = this.mHintScreenTimeout;
             return that;
         }
 
@@ -4875,6 +4896,48 @@
             return (mFlags & FLAG_HINT_SHOW_BACKGROUND_ONLY) != 0;
         }
 
+        /**
+         * Set a hint that this notification's background should not be clipped if possible.
+         * @param hintAvoidBackgroundClipping {@code true} to avoid clipping if possible.
+         * @return this object for method chaining
+         */
+        public WearableExtender setHintAvoidBackgroundClipping(
+                boolean hintAvoidBackgroundClipping) {
+            setFlag(FLAG_HINT_AVOID_BACKGROUND_CLIPPING, hintAvoidBackgroundClipping);
+            return this;
+        }
+
+        /**
+         * Get a hint that this notification's background should not be clipped if possible.
+         * @return {@code true} if it's ok if the background is clipped on the screen, false
+         * otherwise. The default value is {@code false} if this was never set.
+         */
+        public boolean getHintAvoidBackgroundClipping() {
+            return (mFlags & FLAG_HINT_AVOID_BACKGROUND_CLIPPING) != 0;
+        }
+
+        /**
+         * Set a hint that the screen should remain on for at least this duration when
+         * this notification is displayed on the screen.
+         * @param timeout The requested screen timeout in milliseconds. Can also be either
+         *     {@link #SCREEN_TIMEOUT_SHORT} or {@link #SCREEN_TIMEOUT_LONG}.
+         * @return this object for method chaining
+         */
+        public WearableExtender setHintScreenTimeout(int timeout) {
+            mHintScreenTimeout = timeout;
+            return this;
+        }
+
+        /**
+         * Get the duration, in milliseconds, that the screen should remain on for
+         * when this notification is displayed.
+         * @return the duration in milliseconds if > 0, or either one of the sentinel values
+         *     {@link #SCREEN_TIMEOUT_SHORT} or {@link #SCREEN_TIMEOUT_LONG}.
+         */
+        public int getHintScreenTimeout() {
+            return mHintScreenTimeout;
+        }
+
         private void setFlag(int mask, boolean value) {
             if (value) {
                 mFlags |= mask;
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 7676e4b..e06f034 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -41,6 +41,7 @@
 import android.os.IBinder;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.Process;
 import android.os.StrictMode;
 import android.os.UserHandle;
 import android.provider.DocumentsContract;
@@ -7498,8 +7499,10 @@
      */
     public void prepareToEnterProcess() {
         if (mContentUserHint != UserHandle.USER_CURRENT) {
-            fixUris(mContentUserHint);
-            mContentUserHint = UserHandle.USER_CURRENT;
+            if (UserHandle.getAppId(Process.myUid()) != Process.SYSTEM_UID) {
+                fixUris(mContentUserHint);
+                mContentUserHint = UserHandle.USER_CURRENT;
+            }
         }
     }
 
diff --git a/core/java/android/text/format/DateFormat.java b/core/java/android/text/format/DateFormat.java
index 9fec9a1..933bcee 100755
--- a/core/java/android/text/format/DateFormat.java
+++ b/core/java/android/text/format/DateFormat.java
@@ -60,27 +60,45 @@
  * {@code SimpleDateFormat}.
  */
 public class DateFormat {
-    /** @deprecated Use a literal {@code '} instead. */
+    /**
+     * @deprecated Use a literal {@code '} instead.
+     * @removed
+     */
     @Deprecated
     public  static final char    QUOTE                  =    '\'';
 
-    /** @deprecated Use a literal {@code 'a'} instead. */
+    /**
+     * @deprecated Use a literal {@code 'a'} instead.
+     * @removed
+     */
     @Deprecated
     public  static final char    AM_PM                  =    'a';
 
-    /** @deprecated Use a literal {@code 'a'} instead; 'A' was always equivalent to 'a'. */
+    /**
+     * @deprecated Use a literal {@code 'a'} instead; 'A' was always equivalent to 'a'.
+     * @removed
+     */
     @Deprecated
     public  static final char    CAPITAL_AM_PM          =    'A';
 
-    /** @deprecated Use a literal {@code 'd'} instead. */
+    /**
+     * @deprecated Use a literal {@code 'd'} instead.
+     * @removed
+     */
     @Deprecated
     public  static final char    DATE                   =    'd';
 
-    /** @deprecated Use a literal {@code 'E'} instead. */
+    /**
+     * @deprecated Use a literal {@code 'E'} instead.
+     * @removed
+     */
     @Deprecated
     public  static final char    DAY                    =    'E';
 
-    /** @deprecated Use a literal {@code 'h'} instead. */
+    /**
+     * @deprecated Use a literal {@code 'h'} instead.
+     * @removed
+     */
     @Deprecated
     public  static final char    HOUR                   =    'h';
 
@@ -88,31 +106,51 @@
      * @deprecated Use a literal {@code 'H'} (for compatibility with {@link SimpleDateFormat}
      * and Unicode) or {@code 'k'} (for compatibility with Android releases up to and including
      * Jelly Bean MR-1) instead. Note that the two are incompatible.
+     *
+     * @removed
      */
     @Deprecated
     public  static final char    HOUR_OF_DAY            =    'k';
 
-    /** @deprecated Use a literal {@code 'm'} instead. */
+    /**
+     * @deprecated Use a literal {@code 'm'} instead.
+     * @removed
+     */
     @Deprecated
     public  static final char    MINUTE                 =    'm';
 
-    /** @deprecated Use a literal {@code 'M'} instead. */
+    /**
+     * @deprecated Use a literal {@code 'M'} instead.
+     * @removed
+     */
     @Deprecated
     public  static final char    MONTH                  =    'M';
 
-    /** @deprecated Use a literal {@code 'L'} instead. */
+    /**
+     * @deprecated Use a literal {@code 'L'} instead.
+     * @removed
+     */
     @Deprecated
     public  static final char    STANDALONE_MONTH       =    'L';
 
-    /** @deprecated Use a literal {@code 's'} instead. */
+    /**
+     * @deprecated Use a literal {@code 's'} instead.
+     * @removed
+     */
     @Deprecated
     public  static final char    SECONDS                =    's';
 
-    /** @deprecated Use a literal {@code 'z'} instead. */
+    /**
+     * @deprecated Use a literal {@code 'z'} instead.
+     * @removed
+     */
     @Deprecated
     public  static final char    TIME_ZONE              =    'z';
 
-    /** @deprecated Use a literal {@code 'y'} instead. */
+    /**
+     * @deprecated Use a literal {@code 'y'} instead.
+     * @removed
+     */
     @Deprecated
     public  static final char    YEAR                   =    'y';
 
@@ -306,9 +344,9 @@
     }
 
     /**
-     * Gets the current date format stored as a char array. The array will contain
-     * 3 elements ({@link #DATE}, {@link #MONTH}, and {@link #YEAR}) in the order
-     * specified by the user's format preference.  Note that this order is
+     * Gets the current date format stored as a char array. Returns a 3 element
+     * array containing the day ({@code 'd'}), month ({@code 'M'}), and year ({@code 'y'}))
+     * in the order specified by the user's format preference.  Note that this order is
      * <i>only</i> appropriate for all-numeric dates; spelled-out (MEDIUM and LONG)
      * dates will generally contain other punctuation, spaces, or words,
      * not just the day, month, and year, and not necessarily in the same
diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java
index 1cadf69..5e05683 100644
--- a/core/java/android/view/AccessibilityInteractionController.java
+++ b/core/java/android/view/AccessibilityInteractionController.java
@@ -1109,15 +1109,17 @@
                         || accessibilityViewId == providerHost.getAccessibilityViewId()) {
                     final AccessibilityNodeInfo parent;
                     if (virtualDescendantId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
-                        parent = provider.createAccessibilityNodeInfo(
-                                virtualDescendantId);
+                        parent = provider.createAccessibilityNodeInfo(virtualDescendantId);
                     } else {
-                        parent= provider.createAccessibilityNodeInfo(
+                        parent = provider.createAccessibilityNodeInfo(
                                 AccessibilityNodeProvider.HOST_VIEW_ID);
                     }
-                    if (parent != null) {
-                        outInfos.add(parent);
+                    if (parent == null) {
+                        // Couldn't obtain the parent, which means we have a
+                        // disconnected sub-tree. Abort prefetch immediately.
+                        return;
                     }
+                    outInfos.add(parent);
                     parentNodeId = parent.getParentNodeId();
                     accessibilityViewId = AccessibilityNodeInfo.getAccessibilityViewId(
                             parentNodeId);
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 6450146..ea0a077 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -728,8 +728,8 @@
                 }
 
                 final Rect insets = attrs.surfaceInsets;
-                final boolean hasSurfaceInsets = insets.left == 0 || insets.right == 0
-                        || insets.top == 0 || insets.bottom == 0;
+                final boolean hasSurfaceInsets = insets.left != 0 || insets.right != 0
+                        || insets.top != 0 || insets.bottom != 0;
                 final boolean translucent = attrs.format != PixelFormat.OPAQUE || hasSurfaceInsets;
                 mAttachInfo.mHardwareRenderer = HardwareRenderer.create(mContext, translucent);
                 if (mAttachInfo.mHardwareRenderer != null) {
@@ -1746,8 +1746,8 @@
                 if (hwInitialized ||
                         mWidth != mAttachInfo.mHardwareRenderer.getWidth() ||
                         mHeight != mAttachInfo.mHardwareRenderer.getHeight()) {
-                    final Rect surfaceInsets = params != null ? params.surfaceInsets : null;
-                    mAttachInfo.mHardwareRenderer.setup(mWidth, mHeight, surfaceInsets);
+                    mAttachInfo.mHardwareRenderer.setup(
+                            mWidth, mHeight, mWindowAttributes.surfaceInsets);
                     if (!hwInitialized) {
                         mAttachInfo.mHardwareRenderer.invalidate(mSurface);
                         mFullRedrawNeeded = true;
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
index 5926d5f..82b1073 100644
--- a/core/java/android/view/WindowManagerGlobal.java
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -118,6 +118,9 @@
 
     private Runnable mSystemPropertyUpdater;
 
+    /** Default token to apply to added views. */
+    private IBinder mDefaultToken;
+
     private WindowManagerGlobal() {
     }
 
@@ -169,6 +172,17 @@
         }
     }
 
+    /**
+     * Sets the default token to use in {@link #addView} when no parent window
+     * token is available and no token has been explicitly set in the view's
+     * layout params.
+     *
+     * @param token Default window token to apply to added views.
+     */
+    public void setDefaultToken(IBinder token) {
+        mDefaultToken = token;
+    }
+
     public String[] getViewRootNames() {
         synchronized (mLock) {
             final int numRoots = mRoots.size();
@@ -216,6 +230,10 @@
             }
         }
 
+        if (wparams.token == null && mDefaultToken != null) {
+            wparams.token = mDefaultToken;
+        }
+
         ViewRootImpl root;
         View panelParentView = null;
 
diff --git a/core/java/android/widget/DayPickerView.java b/core/java/android/widget/DayPickerView.java
index fcf66f6..f9544d0 100644
--- a/core/java/android/widget/DayPickerView.java
+++ b/core/java/android/widget/DayPickerView.java
@@ -107,9 +107,9 @@
 
         mAdapter.setRange(mMinDate, mMaxDate);
 
-        if (constrainCalendar(mSelectedDay, mMinDate, mMaxDate)) {
-            goTo(mSelectedDay, false, true, true);
-        }
+        // Changing the min/max date changes the selection position since we
+        // don't really have stable IDs.
+        goTo(mSelectedDay, false, true, true);
     }
 
     /**
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 0bc1a8d..64bd6b6 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -20,6 +20,7 @@
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.IntentSender;
+import android.content.pm.ActivityInfo;
 import android.os.Bundle;
 import android.os.Parcelable;
 import android.util.Log;
@@ -75,16 +76,21 @@
     }
 
     @Override
-    public Intent getReplacementIntent(String packageName, Intent defIntent) {
+    public Intent getReplacementIntent(ActivityInfo aInfo, Intent defIntent) {
+        Intent result = defIntent;
         if (mReplacementExtras != null) {
-            final Bundle replExtras = mReplacementExtras.getBundle(packageName);
+            final Bundle replExtras = mReplacementExtras.getBundle(aInfo.packageName);
             if (replExtras != null) {
-                final Intent result = new Intent(defIntent);
+                result = new Intent(defIntent);
                 result.putExtras(replExtras);
-                return result;
             }
         }
-        return defIntent;
+        if (aInfo.name.equals(IntentForwarderActivity.FORWARD_INTENT_TO_USER_OWNER)
+                || aInfo.name.equals(IntentForwarderActivity.FORWARD_INTENT_TO_MANAGED_PROFILE)) {
+            result = Intent.createChooser(result,
+                    getIntent().getCharSequenceExtra(Intent.EXTRA_TITLE));
+        }
+        return result;
     }
 
     @Override
diff --git a/core/java/com/android/internal/app/IntentForwarderActivity.java b/core/java/com/android/internal/app/IntentForwarderActivity.java
index 6e2f84a..9656a21 100644
--- a/core/java/com/android/internal/app/IntentForwarderActivity.java
+++ b/core/java/com/android/internal/app/IntentForwarderActivity.java
@@ -58,21 +58,22 @@
         Intent intentReceived = getIntent();
 
         String className = intentReceived.getComponent().getClassName();
-        final UserHandle userDest;
+        final int targetUserId;
         final int userMessageId;
 
         if (className.equals(FORWARD_INTENT_TO_USER_OWNER)) {
             userMessageId = com.android.internal.R.string.forward_intent_to_owner;
-            userDest = UserHandle.OWNER;
+            targetUserId = UserHandle.USER_OWNER;
         } else if (className.equals(FORWARD_INTENT_TO_MANAGED_PROFILE)) {
             userMessageId = com.android.internal.R.string.forward_intent_to_work;
-            userDest = getManagedProfile();
+            targetUserId = getManagedProfile();
         } else {
             Slog.wtf(TAG, IntentForwarderActivity.class.getName() + " cannot be called directly");
             userMessageId = -1;
-            userDest = null;
+            targetUserId = UserHandle.USER_NULL;
         }
-        if (userDest == null) { // This covers the case where there is no managed profile.
+        if (targetUserId == UserHandle.USER_NULL) {
+            // This covers the case where there is no managed profile.
             finish();
             return;
         }
@@ -83,31 +84,24 @@
         newIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT
                 |Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP);
         int callingUserId = getUserId();
-        IPackageManager ipm = AppGlobals.getPackageManager();
-        String resolvedType = newIntent.resolveTypeIfNeeded(getContentResolver());
-        boolean canForward = false;
-        Intent selector = newIntent.getSelector();
-        if (selector == null) {
-            selector = newIntent;
-        }
-        try {
-            canForward = ipm.canForwardTo(selector, resolvedType, callingUserId,
-                    userDest.getIdentifier());
-        } catch (RemoteException e) {
-            Slog.e(TAG, "PackageManagerService is dead?");
-        }
-        if (canForward) {
-            newIntent.setContentUserHint(callingUserId);
+
+        if (canForward(newIntent, targetUserId)) {
+            if (newIntent.getAction().equals(Intent.ACTION_CHOOSER)) {
+                Intent innerIntent = (Intent) newIntent.getParcelableExtra(Intent.EXTRA_INTENT);
+                innerIntent.setContentUserHint(callingUserId);
+            } else {
+                newIntent.setContentUserHint(callingUserId);
+            }
 
             final android.content.pm.ResolveInfo ri = getPackageManager().resolveActivityAsUser(
-                        newIntent, MATCH_DEFAULT_ONLY, userDest.getIdentifier());
+                        newIntent, MATCH_DEFAULT_ONLY, targetUserId);
 
             // Only show a disclosure if this is a normal (non-OS) app
             final boolean shouldShowDisclosure =
                     !UserHandle.isSameApp(ri.activityInfo.applicationInfo.uid, Process.SYSTEM_UID);
 
             try {
-                startActivityAsCaller(newIntent, null, userDest.getIdentifier());
+                startActivityAsCaller(newIntent, null, targetUserId);
             } catch (RuntimeException e) {
                 int launchedFromUid = -1;
                 String launchedFromPackage = "?";
@@ -129,26 +123,55 @@
             }
         } else {
             Slog.wtf(TAG, "the intent: " + newIntent + "cannot be forwarded from user "
-                    + callingUserId + " to user " + userDest.getIdentifier());
+                    + callingUserId + " to user " + targetUserId);
         }
         finish();
     }
 
+    boolean canForward(Intent intent, int targetUserId)  {
+        IPackageManager ipm = AppGlobals.getPackageManager();
+        if (intent.getAction().equals(Intent.ACTION_CHOOSER)) {
+            // The EXTRA_INITIAL_INTENTS may not be allowed to be forwarded.
+            if (intent.hasExtra(Intent.EXTRA_INITIAL_INTENTS)) {
+                Slog.wtf(TAG, "An chooser intent with extra initial intents cannot be forwarded to"
+                        + " a different user");
+                return false;
+            }
+            if (intent.hasExtra(Intent.EXTRA_REPLACEMENT_EXTRAS)) {
+                Slog.wtf(TAG, "A chooser intent with replacement extras cannot be forwarded to a"
+                        + " different user");
+                return false;
+            }
+            intent = (Intent) intent.getParcelableExtra(Intent.EXTRA_INTENT);
+        }
+        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
+        if (intent.getSelector() != null) {
+            intent = intent.getSelector();
+        }
+        try {
+            return ipm.canForwardTo(intent, resolvedType, getUserId(),
+                    targetUserId);
+        } catch (RemoteException e) {
+            Slog.e(TAG, "PackageManagerService is dead?");
+            return false;
+        }
+    }
+
     /**
-     * Returns the managed profile for this device or null if there is no managed
-     * profile.
+     * Returns the userId of the managed profile for this device or UserHandle.USER_NULL if there is
+     * no managed profile.
      *
      * TODO: Remove the assumption that there is only one managed profile
      * on the device.
      */
-    private UserHandle getManagedProfile() {
+    private int getManagedProfile() {
         UserManager userManager = (UserManager) getSystemService(Context.USER_SERVICE);
         List<UserInfo> relatedUsers = userManager.getProfiles(UserHandle.USER_OWNER);
         for (UserInfo userInfo : relatedUsers) {
-            if (userInfo.isManagedProfile()) return new UserHandle(userInfo.id);
+            if (userInfo.isManagedProfile()) return userInfo.id;
         }
         Slog.wtf(TAG, FORWARD_INTENT_TO_MANAGED_PROFILE
                 + " has been called, but there is no managed profile");
-        return null;
+        return UserHandle.USER_NULL;
     }
 }
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 7df76e5..376db6e 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -100,6 +100,7 @@
     private int mMaxColumns;
     private int mLastSelected = ListView.INVALID_POSITION;
     private boolean mResolvingHome = false;
+    private int mProfileSwitchMessageId = -1;
 
     private UsageStatsManager mUsm;
     private Map<String, UsageStats> mStats;
@@ -200,6 +201,11 @@
             List<ResolveInfo> rList, boolean alwaysUseOption) {
         setTheme(R.style.Theme_DeviceDefault_Resolver);
         super.onCreate(savedInstanceState);
+
+        // Determine whether we should show that intent is forwarded
+        // from managed profile to owner or other way around.
+        setProfileSwitchMessageId(intent.getContentUserHint());
+
         try {
             mLaunchedFromUid = ActivityManagerNative.getDefault().getLaunchedFromUid(
                     getActivityToken());
@@ -320,6 +326,22 @@
         }
     }
 
+    private void setProfileSwitchMessageId(int contentUserHint) {
+        if (contentUserHint != UserHandle.USER_CURRENT &&
+                contentUserHint != UserHandle.myUserId()) {
+            UserManager userManager = (UserManager) getSystemService(Context.USER_SERVICE);
+            UserInfo originUserInfo = userManager.getUserInfo(contentUserHint);
+            boolean originIsManaged = originUserInfo != null ? originUserInfo.isManagedProfile()
+                    : false;
+            boolean targetIsManaged = userManager.isManagedProfile();
+            if (originIsManaged && !targetIsManaged) {
+                mProfileSwitchMessageId = com.android.internal.R.string.forward_intent_to_owner;
+            } else if (!originIsManaged && targetIsManaged) {
+                mProfileSwitchMessageId = com.android.internal.R.string.forward_intent_to_work;
+            }
+        }
+    }
+
     /**
      * Turn on launch mode that is safe to use when forwarding intents received from
      * applications and running in system processes.  This mode uses Activity.startActivityAsCaller
@@ -529,7 +551,7 @@
     /**
      * Replace me in subclasses!
      */
-    public Intent getReplacementIntent(String packageName, Intent defIntent) {
+    public Intent getReplacementIntent(ActivityInfo aInfo, Intent defIntent) {
         return defIntent;
     }
 
@@ -642,6 +664,11 @@
     }
 
     public void safelyStartActivity(Intent intent) {
+        // If needed, show that intent is forwarded
+        // from managed profile to owner or other way around.
+        if (mProfileSwitchMessageId != -1) {
+            Toast.makeText(this, getString(mProfileSwitchMessageId), Toast.LENGTH_LONG).show();
+        }
         if (!mSafeForwardingMode) {
             startActivity(intent);
             onActivityStarted(intent);
@@ -943,7 +970,7 @@
             DisplayResolveInfo dri = filtered ? getItem(position) : mList.get(position);
 
             Intent intent = new Intent(dri.origIntent != null ? dri.origIntent :
-                    getReplacementIntent(dri.ri.activityInfo.packageName, mIntent));
+                    getReplacementIntent(dri.ri.activityInfo, mIntent));
             intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT
                     |Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP);
             ActivityInfo ai = dri.ri.activityInfo;
diff --git a/docs/html/images/emulator-wvga800l.png b/docs/html/images/emulator-wvga800l.png
deleted file mode 100644
index c92c1b9..0000000
--- a/docs/html/images/emulator-wvga800l.png
+++ /dev/null
Binary files differ
diff --git a/docs/html/images/emulator.png b/docs/html/images/emulator.png
new file mode 100644
index 0000000..96a2507
--- /dev/null
+++ b/docs/html/images/emulator.png
Binary files differ
diff --git a/docs/html/images/emulator@2x.png b/docs/html/images/emulator@2x.png
new file mode 100644
index 0000000..9b825a7
--- /dev/null
+++ b/docs/html/images/emulator@2x.png
Binary files differ
diff --git a/docs/html/tools/devices/emulator.jd b/docs/html/tools/devices/emulator.jd
index ea1549d..d7bb8c7 100644
--- a/docs/html/tools/devices/emulator.jd
+++ b/docs/html/tools/devices/emulator.jd
@@ -80,7 +80,9 @@
 provides a screen in which your application is displayed, together with any other
 active Android applications. </p>
 
-<img src="{@docRoot}images/emulator-wvga800l.png" width="367" height="349" />
+<img src="{@docRoot}images/emulator@2x.png"
+srcset="{@docRoot}images/emulator.png 1x, {@docRoot}images/emulator@2x.png 2x" alt=""
+  width="367" height="330"/>
 
 <p>To let you model and test your application more easily, the emulator utilizes
 Android Virtual Device (AVD) configurations. AVDs let you define certain hardware
diff --git a/docs/html/training/material/animations.jd b/docs/html/training/material/animations.jd
index e8291b8..efc0ee3 100644
--- a/docs/html/training/material/animations.jd
+++ b/docs/html/training/material/animations.jd
@@ -84,12 +84,14 @@
 int cy = (myView.getTop() + myView.getBottom()) / 2;
 
 // get the final radius for the clipping circle
-int finalRadius = myView.getWidth();
+int finalRadius = Math.max(myView.getWidth(), myView.getHeight());
 
-// create and start the animator for this view
-// (the start radius is zero)
+// create the animator for this view (the start radius is zero)
 Animator anim =
     ViewAnimationUtils.createCircularReveal(myView, cx, cy, 0, finalRadius);
+
+// make the view visible and start the animation
+myView.setVisibility(View.VISIBLE);
 anim.start();
 </pre>
 
diff --git a/docs/html/training/wearables/data-layer/accessing.jd b/docs/html/training/wearables/data-layer/accessing.jd
index 896a698..36e3daa 100644
--- a/docs/html/training/wearables/data-layer/accessing.jd
+++ b/docs/html/training/wearables/data-layer/accessing.jd
@@ -37,7 +37,7 @@
 implementing its callbacks, and handling error cases.</p>
 
 <pre style="clear:right">
-GoogleApiClient mGoogleAppiClient = new GoogleApiClient.Builder(this)
+GoogleApiClient mGoogleApiClient = new GoogleApiClient.Builder(this)
         .addConnectionCallbacks(new ConnectionCallbacks() {
                 &#64;Override
                 public void onConnected(Bundle connectionHint) {
@@ -64,4 +64,4 @@
 method, as described in
 <a href="{@docRoot}google/auth/api-client.html#Starting">Accessing Google Play services APIs</a>.
 When the system invokes the <code>onConnected()</code> callback for your client, you're ready
-to use the data layer API.</p>
\ No newline at end of file
+to use the data layer API.</p>
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index 1458238..94c7026 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -943,7 +943,11 @@
 
                     float radius = st.mGradientRadius;
                     if (st.mGradientRadiusType == RADIUS_TYPE_FRACTION) {
-                        radius *= Math.min(st.mWidth, st.mHeight);
+                        // Fall back to parent width or height if intrinsic
+                        // size is not specified.
+                        final float width = st.mWidth >= 0 ? st.mWidth : r.width();
+                        final float height = st.mHeight >= 0 ? st.mHeight : r.height();
+                        radius *= Math.min(width, height);
                     } else if (st.mGradientRadiusType == RADIUS_TYPE_FRACTION_PARENT) {
                         radius *= Math.min(r.width(), r.height());
                     }
@@ -954,9 +958,9 @@
 
                     mGradientRadius = radius;
 
-                    if (radius == 0) {
-                        // We can't have a shader with zero radius, so let's
-                        // have a very, very small radius.
+                    if (radius <= 0) {
+                        // We can't have a shader with non-positive radius, so
+                        // let's have a very, very small radius.
                         radius = 0.001f;
                     }
 
diff --git a/libs/hwui/PathTessellator.cpp b/libs/hwui/PathTessellator.cpp
index 281ca02..27ef06f 100644
--- a/libs/hwui/PathTessellator.cpp
+++ b/libs/hwui/PathTessellator.cpp
@@ -812,7 +812,7 @@
     // determine point shape
     SkPath path;
     float radius = paintInfo.halfStrokeWidth;
-    if (radius == 0.0f) radius = 0.25f;
+    if (radius == 0.0f) radius = 0.5f;
 
     if (paintInfo.cap == SkPaint::kRound_Cap) {
         path.addCircle(0, 0, radius);
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 1062880..29d4930 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -533,6 +533,8 @@
 
     private AudioOrientationEventListener mOrientationListener;
 
+    private static Long mLastDeviceConnectMsgTime = new Long(0);
+
     ///////////////////////////////////////////////////////////////////////////
     // Construction
     ///////////////////////////////////////////////////////////////////////////
@@ -3269,8 +3271,15 @@
         } else if (existingMsgPolicy == SENDMSG_NOOP && handler.hasMessages(msg)) {
             return;
         }
-
-        handler.sendMessageDelayed(handler.obtainMessage(msg, arg1, arg2, obj), delay);
+        synchronized (mLastDeviceConnectMsgTime) {
+            long time = SystemClock.uptimeMillis() + delay;
+            handler.sendMessageAtTime(handler.obtainMessage(msg, arg1, arg2, obj), time);
+            if (msg == MSG_SET_WIRED_DEVICE_CONNECTION_STATE ||
+                    msg == MSG_SET_A2DP_SRC_CONNECTION_STATE ||
+                    msg == MSG_SET_A2DP_SINK_CONNECTION_STATE) {
+                mLastDeviceConnectMsgTime = time;
+            }
+        }
     }
 
     boolean checkAudioSettingsPermission(String method) {
@@ -4587,7 +4596,12 @@
         if (mAudioHandler.hasMessages(MSG_SET_A2DP_SRC_CONNECTION_STATE) ||
                 mAudioHandler.hasMessages(MSG_SET_A2DP_SINK_CONNECTION_STATE) ||
                 mAudioHandler.hasMessages(MSG_SET_WIRED_DEVICE_CONNECTION_STATE)) {
-            delay = 1000;
+            synchronized (mLastDeviceConnectMsgTime) {
+                long time = SystemClock.uptimeMillis();
+                if (mLastDeviceConnectMsgTime > time) {
+                    delay = (int)(mLastDeviceConnectMsgTime - time);
+                }
+            }
         }
         return delay;
     }
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 1c6dc2c..aa5819e 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -518,7 +518,7 @@
          * Determine whether the device is plugged in (USB, power, or wireless).
          * @return true if the device is plugged in.
          */
-        boolean isPluggedIn() {
+        public boolean isPluggedIn() {
             return plugged == BatteryManager.BATTERY_PLUGGED_AC
                     || plugged == BatteryManager.BATTERY_PLUGGED_USB
                     || plugged == BatteryManager.BATTERY_PLUGGED_WIRELESS;
diff --git a/packages/SystemUI/res/anim/ic_landscape_from_auto_rotate_animation_arrow_bottom.xml b/packages/SystemUI/res/anim/ic_landscape_from_auto_rotate_animation_arrow_bottom.xml
new file mode 100644
index 0000000..9add90c
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_landscape_from_auto_rotate_animation_arrow_bottom.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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+    <set
+        android:ordering="sequentially" >
+        <objectAnimator
+            android:duration="567"
+            android:propertyName="fillAlpha"
+            android:valueFrom="1"
+            android:valueTo="1"
+            android:interpolator="@android:interpolator/linear" />
+        <objectAnimator
+            android:duration="33"
+            android:propertyName="fillAlpha"
+            android:valueFrom="1"
+            android:valueTo="0"
+            android:interpolator="@android:interpolator/linear" />
+    </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_landscape_from_auto_rotate_animation_arrow_top.xml b/packages/SystemUI/res/anim/ic_landscape_from_auto_rotate_animation_arrow_top.xml
new file mode 100644
index 0000000..9add90c
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_landscape_from_auto_rotate_animation_arrow_top.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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+    <set
+        android:ordering="sequentially" >
+        <objectAnimator
+            android:duration="567"
+            android:propertyName="fillAlpha"
+            android:valueFrom="1"
+            android:valueTo="1"
+            android:interpolator="@android:interpolator/linear" />
+        <objectAnimator
+            android:duration="33"
+            android:propertyName="fillAlpha"
+            android:valueFrom="1"
+            android:valueTo="0"
+            android:interpolator="@android:interpolator/linear" />
+    </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_landscape_from_auto_rotate_animation_arrows.xml b/packages/SystemUI/res/anim/ic_landscape_from_auto_rotate_animation_arrows.xml
new file mode 100644
index 0000000..6c4e133
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_landscape_from_auto_rotate_animation_arrows.xml
@@ -0,0 +1,63 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+    <set
+        android:ordering="sequentially" >
+        <objectAnimator
+            android:duration="317"
+            android:propertyName="scaleX"
+            android:valueFrom="1"
+            android:valueTo="1"
+            android:interpolator="@android:interpolator/linear" />
+        <objectAnimator
+            android:duration="333"
+            android:propertyName="scaleX"
+            android:valueFrom="1"
+            android:valueTo="0.9"
+            android:interpolator="@android:interpolator/linear" />
+    </set>
+    <set
+        android:ordering="sequentially" >
+        <objectAnimator
+            android:duration="317"
+            android:propertyName="scaleY"
+            android:valueFrom="1"
+            android:valueTo="1"
+            android:interpolator="@android:interpolator/linear" />
+        <objectAnimator
+            android:duration="333"
+            android:propertyName="scaleY"
+            android:valueFrom="1"
+            android:valueTo="0.9"
+            android:interpolator="@android:interpolator/linear" />
+    </set>
+    <set
+        android:ordering="sequentially" >
+        <objectAnimator
+            android:duration="200"
+            android:propertyName="rotation"
+            android:valueFrom="0"
+            android:valueTo="0"
+            android:interpolator="@android:interpolator/linear" />
+        <objectAnimator
+            android:duration="450"
+            android:propertyName="rotation"
+            android:valueFrom="0"
+            android:valueTo="-135"
+            android:interpolator="@interpolator/ic_landscape_from_auto_rotate_arrows_rotation_interpolator" />
+    </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_landscape_from_auto_rotate_animation_body.xml b/packages/SystemUI/res/anim/ic_landscape_from_auto_rotate_animation_body.xml
new file mode 100644
index 0000000..a8f5ce0
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_landscape_from_auto_rotate_animation_body.xml
@@ -0,0 +1,35 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+    <set
+        android:ordering="sequentially" >
+        <objectAnimator
+            android:duration="267"
+            android:propertyName="pathData"
+            android:valueFrom="M -3.5,-20.5 c -1.19999694824,-1.19999694824 -3.10000610352,-1.19999694824 -4.19999694824,0.0 c 0.0,0.0 -12.8000030518,12.6999969482 -12.8000030518,12.6999969482 c -1.19999694824,1.19999694824 -1.19999694824,3.10000610352 0.0,4.19999694824 c 0.0,0.0 24.0,24.0000152588 24.0,24.0000152588 c 1.19999694824,1.19999694824 3.10000610352,1.19999694824 4.19999694824,0.0 c 0.0,0.0 12.6999969482,-12.700012207 12.6999969482,-12.700012207 c 1.20001220703,-1.19999694824 1.20001220703,-3.09999084473 0.0,-4.19999694824 c 0.0,0.0 -23.8999938965,-24.0 -23.8999938965,-24.0 Z M 2.84999084473,15.5500183105 c 0.0,0.0 -18.6000061035,-18.5000457764 -18.6000061035,-18.5000457764 c 0.0,0.0 12.5999908447,-12.8000030518 12.5999908447,-12.8000030518 c 0.0,0.0 18.6000213623,18.5000457764 18.6000213623,18.5000457764 c 0.0,0.0 -12.6000061035,12.8000030518 -12.6000061035,12.8000030518 Z"
+            android:valueTo="M -3.5,-20.5 c -1.19999694824,-1.19999694824 -3.10000610352,-1.19999694824 -4.19999694824,0.0 c 0.0,0.0 -12.8000030518,12.6999969482 -12.8000030518,12.6999969482 c -1.19999694824,1.19999694824 -1.19999694824,3.10000610352 0.0,4.19999694824 c 0.0,0.0 24.0,24.0000152588 24.0,24.0000152588 c 1.19999694824,1.19999694824 3.10000610352,1.19999694824 4.19999694824,0.0 c 0.0,0.0 12.6999969482,-12.700012207 12.6999969482,-12.700012207 c 1.20001220703,-1.19999694824 1.20001220703,-3.09999084473 0.0,-4.19999694824 c 0.0,0.0 -23.8999938965,-24.0 -23.8999938965,-24.0 Z M 2.84999084473,15.5500183105 c 0.0,0.0 -18.6000061035,-18.5000457764 -18.6000061035,-18.5000457764 c 0.0,0.0 12.5999908447,-12.8000030518 12.5999908447,-12.8000030518 c 0.0,0.0 18.6000213623,18.5000457764 18.6000213623,18.5000457764 c 0.0,0.0 -12.6000061035,12.8000030518 -12.6000061035,12.8000030518 Z"
+            android:valueType="pathType"
+            android:interpolator="@android:interpolator/fast_out_slow_in" />
+        <objectAnimator
+            android:duration="217"
+            android:propertyName="pathData"
+            android:valueFrom="M -3.5,-20.5 c -1.19999694824,-1.19999694824 -3.10000610352,-1.19999694824 -4.19999694824,0.0 c 0.0,0.0 -12.8000030518,12.6999969482 -12.8000030518,12.6999969482 c -1.19999694824,1.19999694824 -1.19999694824,3.10000610352 0.0,4.19999694824 c 0.0,0.0 24.0,24.0000152588 24.0,24.0000152588 c 1.19999694824,1.19999694824 3.10000610352,1.19999694824 4.19999694824,0.0 c 0.0,0.0 12.6999969482,-12.700012207 12.6999969482,-12.700012207 c 1.20001220703,-1.19999694824 1.20001220703,-3.09999084473 0.0,-4.19999694824 c 0.0,0.0 -23.8999938965,-24.0 -23.8999938965,-24.0 Z M 2.84999084473,15.5500183105 c 0.0,0.0 -18.6000061035,-18.5000457764 -18.6000061035,-18.5000457764 c 0.0,0.0 12.5999908447,-12.8000030518 12.5999908447,-12.8000030518 c 0.0,0.0 18.6000213623,18.5000457764 18.6000213623,18.5000457764 c 0.0,0.0 -12.6000061035,12.8000030518 -12.6000061035,12.8000030518 Z"
+            android:valueTo="M -3.34053039551,-22.9980926514 c -1.3207244873,-1.3207244873 -3.46876525879,-1.26383972168 -4.74829101563,0.125762939453 c 0.0,0.0 -14.8512420654,14.7411804199 -14.8512420654,14.7411804199 c -1.39259338379,1.392578125 -1.44947814941,3.54061889648 -0.125762939453,4.74827575684 c 0.0,0.0 26.4143981934,26.4144134521 26.4143981934,26.4144134521 c 1.3207244873,1.3207244873 3.46876525879,1.26382446289 4.74829101562,-0.125762939453 c 0.0,0.0 14.7381896973,-14.7381896973 14.7381896973,-14.7381896973 c 1.392578125,-1.39259338379 1.44947814941,-3.54061889648 0.125762939453,-4.74829101562 c 0.0,0.0 -26.3013458252,-26.417388916 -26.3013458252,-26.417388916 Z M 2.87156677246,16.9857940674 c 0.0,0.0 -19.7573547363,-19.7573699951 -19.7573547363,-19.7573699951 c 0.0,0.0 14.0142059326,-14.2142181396 14.0142059326,-14.2142181396 c 0.0,0.0 19.7573699951,19.7573699951 19.7573699951,19.7573699951 c 0.0,0.0 -14.0142211914,14.2142181396 -14.0142211914,14.2142181396 Z"
+            android:valueType="pathType"
+            android:interpolator="@android:interpolator/fast_out_slow_in" />
+    </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_landscape_from_auto_rotate_animation_device.xml b/packages/SystemUI/res/anim/ic_landscape_from_auto_rotate_animation_device.xml
new file mode 100644
index 0000000..b9bb42d
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_landscape_from_auto_rotate_animation_device.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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+    <set
+        android:ordering="sequentially" >
+        <objectAnimator
+            android:duration="200"
+            android:propertyName="rotation"
+            android:valueFrom="0"
+            android:valueTo="0"
+            android:interpolator="@android:interpolator/fast_out_slow_in" />
+        <objectAnimator
+            android:duration="400"
+            android:propertyName="rotation"
+            android:valueFrom="0"
+            android:valueTo="-45"
+            android:interpolator="@android:interpolator/fast_out_slow_in" />
+    </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_landscape_to_auto_rotate_animation_arrow_bottom.xml b/packages/SystemUI/res/anim/ic_landscape_to_auto_rotate_animation_arrow_bottom.xml
new file mode 100644
index 0000000..b8823a9
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_landscape_to_auto_rotate_animation_arrow_bottom.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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+    <set
+        android:ordering="sequentially" >
+        <objectAnimator
+            android:duration="250"
+            android:propertyName="fillAlpha"
+            android:valueFrom="0"
+            android:valueTo="0"
+            android:interpolator="@android:interpolator/linear" />
+        <objectAnimator
+            android:duration="33"
+            android:propertyName="fillAlpha"
+            android:valueFrom="0"
+            android:valueTo="1"
+            android:interpolator="@android:interpolator/linear" />
+    </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_landscape_to_auto_rotate_animation_arrow_top.xml b/packages/SystemUI/res/anim/ic_landscape_to_auto_rotate_animation_arrow_top.xml
new file mode 100644
index 0000000..b8823a9
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_landscape_to_auto_rotate_animation_arrow_top.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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+    <set
+        android:ordering="sequentially" >
+        <objectAnimator
+            android:duration="250"
+            android:propertyName="fillAlpha"
+            android:valueFrom="0"
+            android:valueTo="0"
+            android:interpolator="@android:interpolator/linear" />
+        <objectAnimator
+            android:duration="33"
+            android:propertyName="fillAlpha"
+            android:valueFrom="0"
+            android:valueTo="1"
+            android:interpolator="@android:interpolator/linear" />
+    </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_landscape_to_auto_rotate_animation_arrows.xml b/packages/SystemUI/res/anim/ic_landscape_to_auto_rotate_animation_arrows.xml
new file mode 100644
index 0000000..14c2776
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_landscape_to_auto_rotate_animation_arrows.xml
@@ -0,0 +1,63 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+    <set
+        android:ordering="sequentially" >
+        <objectAnimator
+            android:duration="200"
+            android:propertyName="scaleX"
+            android:valueFrom="0.9"
+            android:valueTo="0.9"
+            android:interpolator="@android:interpolator/linear" />
+        <objectAnimator
+            android:duration="333"
+            android:propertyName="scaleX"
+            android:valueFrom="0.9"
+            android:valueTo="1"
+            android:interpolator="@android:interpolator/linear" />
+    </set>
+    <set
+        android:ordering="sequentially" >
+        <objectAnimator
+            android:duration="200"
+            android:propertyName="scaleY"
+            android:valueFrom="0.9"
+            android:valueTo="0.9"
+            android:interpolator="@android:interpolator/linear" />
+        <objectAnimator
+            android:duration="333"
+            android:propertyName="scaleY"
+            android:valueFrom="0.9"
+            android:valueTo="1"
+            android:interpolator="@android:interpolator/linear" />
+    </set>
+    <set
+        android:ordering="sequentially" >
+        <objectAnimator
+            android:duration="200"
+            android:propertyName="rotation"
+            android:valueFrom="-135"
+            android:valueTo="-135"
+            android:interpolator="@android:interpolator/linear" />
+        <objectAnimator
+            android:duration="450"
+            android:propertyName="rotation"
+            android:valueFrom="-135"
+            android:valueTo="0"
+            android:interpolator="@interpolator/ic_landscape_to_auto_rotate_arrows_rotation_interpolator" />
+    </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_landscape_to_auto_rotate_animation_body.xml b/packages/SystemUI/res/anim/ic_landscape_to_auto_rotate_animation_body.xml
new file mode 100644
index 0000000..ea8f979
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_landscape_to_auto_rotate_animation_body.xml
@@ -0,0 +1,35 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+    <set
+        android:ordering="sequentially" >
+        <objectAnimator
+            android:duration="267"
+            android:propertyName="pathData"
+            android:valueFrom="M -3.34053039551,-22.9980926514 c -1.3207244873,-1.3207244873 -3.46876525879,-1.26383972168 -4.74829101563,0.125762939453 c 0.0,0.0 -14.8512420654,14.7411804199 -14.8512420654,14.7411804199 c -1.39259338379,1.392578125 -1.44947814941,3.54061889648 -0.125762939453,4.74827575684 c 0.0,0.0 26.4143981934,26.4144134521 26.4143981934,26.4144134521 c 1.3207244873,1.3207244873 3.46876525879,1.26382446289 4.74829101562,-0.125762939453 c 0.0,0.0 14.7381896973,-14.7381896973 14.7381896973,-14.7381896973 c 1.392578125,-1.39259338379 1.44947814941,-3.54061889648 0.125762939453,-4.74829101562 c 0.0,0.0 -26.3013458252,-26.417388916 -26.3013458252,-26.417388916 Z M 2.87156677246,16.9857940674 c 0.0,0.0 -19.7573547363,-19.7573699951 -19.7573547363,-19.7573699951 c 0.0,0.0 14.0142059326,-14.2142181396 14.0142059326,-14.2142181396 c 0.0,0.0 19.7573699951,19.7573699951 19.7573699951,19.7573699951 c 0.0,0.0 -14.0142211914,14.2142181396 -14.0142211914,14.2142181396 Z"
+            android:valueTo="M -3.34053039551,-22.9980926514 c -1.3207244873,-1.3207244873 -3.46876525879,-1.26383972168 -4.74829101563,0.125762939453 c 0.0,0.0 -14.8512420654,14.7411804199 -14.8512420654,14.7411804199 c -1.39259338379,1.392578125 -1.44947814941,3.54061889648 -0.125762939453,4.74827575684 c 0.0,0.0 26.4143981934,26.4144134521 26.4143981934,26.4144134521 c 1.3207244873,1.3207244873 3.46876525879,1.26382446289 4.74829101562,-0.125762939453 c 0.0,0.0 14.7381896973,-14.7381896973 14.7381896973,-14.7381896973 c 1.392578125,-1.39259338379 1.44947814941,-3.54061889648 0.125762939453,-4.74829101562 c 0.0,0.0 -26.3013458252,-26.417388916 -26.3013458252,-26.417388916 Z M 2.87156677246,16.9857940674 c 0.0,0.0 -19.7573547363,-19.7573699951 -19.7573547363,-19.7573699951 c 0.0,0.0 14.0142059326,-14.2142181396 14.0142059326,-14.2142181396 c 0.0,0.0 19.7573699951,19.7573699951 19.7573699951,19.7573699951 c 0.0,0.0 -14.0142211914,14.2142181396 -14.0142211914,14.2142181396 Z"
+            android:valueType="pathType"
+            android:interpolator="@android:interpolator/fast_out_slow_in" />
+        <objectAnimator
+            android:duration="217"
+            android:propertyName="pathData"
+            android:valueFrom="M -3.34053039551,-22.9980926514 c -1.3207244873,-1.3207244873 -3.46876525879,-1.26383972168 -4.74829101563,0.125762939453 c 0.0,0.0 -14.8512420654,14.7411804199 -14.8512420654,14.7411804199 c -1.39259338379,1.392578125 -1.44947814941,3.54061889648 -0.125762939453,4.74827575684 c 0.0,0.0 26.4143981934,26.4144134521 26.4143981934,26.4144134521 c 1.3207244873,1.3207244873 3.46876525879,1.26382446289 4.74829101562,-0.125762939453 c 0.0,0.0 14.7381896973,-14.7381896973 14.7381896973,-14.7381896973 c 1.392578125,-1.39259338379 1.44947814941,-3.54061889648 0.125762939453,-4.74829101562 c 0.0,0.0 -26.3013458252,-26.417388916 -26.3013458252,-26.417388916 Z M 2.87156677246,16.9857940674 c 0.0,0.0 -19.7573547363,-19.7573699951 -19.7573547363,-19.7573699951 c 0.0,0.0 14.0142059326,-14.2142181396 14.0142059326,-14.2142181396 c 0.0,0.0 19.7573699951,19.7573699951 19.7573699951,19.7573699951 c 0.0,0.0 -14.0142211914,14.2142181396 -14.0142211914,14.2142181396 Z"
+            android:valueTo="M -3.5,-20.5 c -1.19999694824,-1.19999694824 -3.10000610352,-1.19999694824 -4.19999694824,0.0 c 0.0,0.0 -12.8000030518,12.6999969482 -12.8000030518,12.6999969482 c -1.19999694824,1.19999694824 -1.19999694824,3.10000610352 0.0,4.19999694824 c 0.0,0.0 24.0,24.0000152588 24.0,24.0000152588 c 1.19999694824,1.19999694824 3.10000610352,1.19999694824 4.19999694824,0.0 c 0.0,0.0 12.6999969482,-12.700012207 12.6999969482,-12.700012207 c 1.20001220703,-1.19999694824 1.20001220703,-3.09999084473 0.0,-4.19999694824 c 0.0,0.0 -23.8999938965,-24.0 -23.8999938965,-24.0 Z M 2.84999084473,15.5500183105 c 0.0,0.0 -18.6000061035,-18.5000457764 -18.6000061035,-18.5000457764 c 0.0,0.0 12.5999908447,-12.8000030518 12.5999908447,-12.8000030518 c 0.0,0.0 18.6000213623,18.5000457764 18.6000213623,18.5000457764 c 0.0,0.0 -12.6000061035,12.8000030518 -12.6000061035,12.8000030518 Z"
+            android:valueType="pathType"
+            android:interpolator="@android:interpolator/fast_out_slow_in" />
+    </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_landscape_to_auto_rotate_animation_device.xml b/packages/SystemUI/res/anim/ic_landscape_to_auto_rotate_animation_device.xml
new file mode 100644
index 0000000..4e3a356
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_landscape_to_auto_rotate_animation_device.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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+    <set
+        android:ordering="sequentially" >
+        <objectAnimator
+            android:duration="200"
+            android:propertyName="rotation"
+            android:valueFrom="-45"
+            android:valueTo="-45"
+            android:interpolator="@android:interpolator/fast_out_slow_in" />
+        <objectAnimator
+            android:duration="400"
+            android:propertyName="rotation"
+            android:valueFrom="-45"
+            android:valueTo="0"
+            android:interpolator="@android:interpolator/fast_out_slow_in" />
+    </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_portrait_from_auto_rotate_animation_arrow_bottom.xml b/packages/SystemUI/res/anim/ic_portrait_from_auto_rotate_animation_arrow_bottom.xml
new file mode 100644
index 0000000..d05c4e1
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_portrait_from_auto_rotate_animation_arrow_bottom.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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+    <set
+        android:ordering="sequentially" >
+        <objectAnimator
+            android:duration="600"
+            android:propertyName="fillAlpha"
+            android:valueFrom="1"
+            android:valueTo="1"
+            android:interpolator="@android:interpolator/linear" />
+        <objectAnimator
+            android:duration="83"
+            android:propertyName="fillAlpha"
+            android:valueFrom="1"
+            android:valueTo="0"
+            android:interpolator="@android:interpolator/linear" />
+    </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_portrait_from_auto_rotate_animation_arrow_top.xml b/packages/SystemUI/res/anim/ic_portrait_from_auto_rotate_animation_arrow_top.xml
new file mode 100644
index 0000000..d05c4e1
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_portrait_from_auto_rotate_animation_arrow_top.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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+    <set
+        android:ordering="sequentially" >
+        <objectAnimator
+            android:duration="600"
+            android:propertyName="fillAlpha"
+            android:valueFrom="1"
+            android:valueTo="1"
+            android:interpolator="@android:interpolator/linear" />
+        <objectAnimator
+            android:duration="83"
+            android:propertyName="fillAlpha"
+            android:valueFrom="1"
+            android:valueTo="0"
+            android:interpolator="@android:interpolator/linear" />
+    </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_portrait_from_auto_rotate_animation_arrows.xml b/packages/SystemUI/res/anim/ic_portrait_from_auto_rotate_animation_arrows.xml
new file mode 100644
index 0000000..8bcbf1e
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_portrait_from_auto_rotate_animation_arrows.xml
@@ -0,0 +1,63 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+    <set
+        android:ordering="sequentially" >
+        <objectAnimator
+            android:duration="317"
+            android:propertyName="scaleX"
+            android:valueFrom="1"
+            android:valueTo="1"
+            android:interpolator="@android:interpolator/linear" />
+        <objectAnimator
+            android:duration="333"
+            android:propertyName="scaleX"
+            android:valueFrom="1"
+            android:valueTo="0.9"
+            android:interpolator="@android:interpolator/linear" />
+    </set>
+    <set
+        android:ordering="sequentially" >
+        <objectAnimator
+            android:duration="317"
+            android:propertyName="scaleY"
+            android:valueFrom="1"
+            android:valueTo="1"
+            android:interpolator="@android:interpolator/linear" />
+        <objectAnimator
+            android:duration="333"
+            android:propertyName="scaleY"
+            android:valueFrom="1"
+            android:valueTo="0.9"
+            android:interpolator="@android:interpolator/linear" />
+    </set>
+    <set
+        android:ordering="sequentially" >
+        <objectAnimator
+            android:duration="200"
+            android:propertyName="rotation"
+            android:valueFrom="0"
+            android:valueTo="0"
+            android:interpolator="@android:interpolator/fast_out_slow_in" />
+        <objectAnimator
+            android:duration="617"
+            android:propertyName="rotation"
+            android:valueFrom="0"
+            android:valueTo="-221"
+            android:interpolator="@android:interpolator/fast_out_slow_in" />
+    </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_portrait_from_auto_rotate_animation_device.xml b/packages/SystemUI/res/anim/ic_portrait_from_auto_rotate_animation_device.xml
new file mode 100644
index 0000000..79b1827
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_portrait_from_auto_rotate_animation_device.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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+    <set
+        android:ordering="sequentially" >
+        <objectAnimator
+            android:duration="200"
+            android:propertyName="rotation"
+            android:valueFrom="0"
+            android:valueTo="0"
+            android:interpolator="@android:interpolator/fast_out_slow_in" />
+        <objectAnimator
+            android:duration="400"
+            android:propertyName="rotation"
+            android:valueFrom="0"
+            android:valueTo="-135"
+            android:interpolator="@android:interpolator/fast_out_slow_in" />
+    </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_portrait_from_auto_rotate_animation_device_1.xml b/packages/SystemUI/res/anim/ic_portrait_from_auto_rotate_animation_device_1.xml
new file mode 100644
index 0000000..a8f5ce0
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_portrait_from_auto_rotate_animation_device_1.xml
@@ -0,0 +1,35 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+    <set
+        android:ordering="sequentially" >
+        <objectAnimator
+            android:duration="267"
+            android:propertyName="pathData"
+            android:valueFrom="M -3.5,-20.5 c -1.19999694824,-1.19999694824 -3.10000610352,-1.19999694824 -4.19999694824,0.0 c 0.0,0.0 -12.8000030518,12.6999969482 -12.8000030518,12.6999969482 c -1.19999694824,1.19999694824 -1.19999694824,3.10000610352 0.0,4.19999694824 c 0.0,0.0 24.0,24.0000152588 24.0,24.0000152588 c 1.19999694824,1.19999694824 3.10000610352,1.19999694824 4.19999694824,0.0 c 0.0,0.0 12.6999969482,-12.700012207 12.6999969482,-12.700012207 c 1.20001220703,-1.19999694824 1.20001220703,-3.09999084473 0.0,-4.19999694824 c 0.0,0.0 -23.8999938965,-24.0 -23.8999938965,-24.0 Z M 2.84999084473,15.5500183105 c 0.0,0.0 -18.6000061035,-18.5000457764 -18.6000061035,-18.5000457764 c 0.0,0.0 12.5999908447,-12.8000030518 12.5999908447,-12.8000030518 c 0.0,0.0 18.6000213623,18.5000457764 18.6000213623,18.5000457764 c 0.0,0.0 -12.6000061035,12.8000030518 -12.6000061035,12.8000030518 Z"
+            android:valueTo="M -3.5,-20.5 c -1.19999694824,-1.19999694824 -3.10000610352,-1.19999694824 -4.19999694824,0.0 c 0.0,0.0 -12.8000030518,12.6999969482 -12.8000030518,12.6999969482 c -1.19999694824,1.19999694824 -1.19999694824,3.10000610352 0.0,4.19999694824 c 0.0,0.0 24.0,24.0000152588 24.0,24.0000152588 c 1.19999694824,1.19999694824 3.10000610352,1.19999694824 4.19999694824,0.0 c 0.0,0.0 12.6999969482,-12.700012207 12.6999969482,-12.700012207 c 1.20001220703,-1.19999694824 1.20001220703,-3.09999084473 0.0,-4.19999694824 c 0.0,0.0 -23.8999938965,-24.0 -23.8999938965,-24.0 Z M 2.84999084473,15.5500183105 c 0.0,0.0 -18.6000061035,-18.5000457764 -18.6000061035,-18.5000457764 c 0.0,0.0 12.5999908447,-12.8000030518 12.5999908447,-12.8000030518 c 0.0,0.0 18.6000213623,18.5000457764 18.6000213623,18.5000457764 c 0.0,0.0 -12.6000061035,12.8000030518 -12.6000061035,12.8000030518 Z"
+            android:valueType="pathType"
+            android:interpolator="@android:interpolator/fast_out_slow_in" />
+        <objectAnimator
+            android:duration="217"
+            android:propertyName="pathData"
+            android:valueFrom="M -3.5,-20.5 c -1.19999694824,-1.19999694824 -3.10000610352,-1.19999694824 -4.19999694824,0.0 c 0.0,0.0 -12.8000030518,12.6999969482 -12.8000030518,12.6999969482 c -1.19999694824,1.19999694824 -1.19999694824,3.10000610352 0.0,4.19999694824 c 0.0,0.0 24.0,24.0000152588 24.0,24.0000152588 c 1.19999694824,1.19999694824 3.10000610352,1.19999694824 4.19999694824,0.0 c 0.0,0.0 12.6999969482,-12.700012207 12.6999969482,-12.700012207 c 1.20001220703,-1.19999694824 1.20001220703,-3.09999084473 0.0,-4.19999694824 c 0.0,0.0 -23.8999938965,-24.0 -23.8999938965,-24.0 Z M 2.84999084473,15.5500183105 c 0.0,0.0 -18.6000061035,-18.5000457764 -18.6000061035,-18.5000457764 c 0.0,0.0 12.5999908447,-12.8000030518 12.5999908447,-12.8000030518 c 0.0,0.0 18.6000213623,18.5000457764 18.6000213623,18.5000457764 c 0.0,0.0 -12.6000061035,12.8000030518 -12.6000061035,12.8000030518 Z"
+            android:valueTo="M -3.34053039551,-22.9980926514 c -1.3207244873,-1.3207244873 -3.46876525879,-1.26383972168 -4.74829101563,0.125762939453 c 0.0,0.0 -14.8512420654,14.7411804199 -14.8512420654,14.7411804199 c -1.39259338379,1.392578125 -1.44947814941,3.54061889648 -0.125762939453,4.74827575684 c 0.0,0.0 26.4143981934,26.4144134521 26.4143981934,26.4144134521 c 1.3207244873,1.3207244873 3.46876525879,1.26382446289 4.74829101562,-0.125762939453 c 0.0,0.0 14.7381896973,-14.7381896973 14.7381896973,-14.7381896973 c 1.392578125,-1.39259338379 1.44947814941,-3.54061889648 0.125762939453,-4.74829101562 c 0.0,0.0 -26.3013458252,-26.417388916 -26.3013458252,-26.417388916 Z M 2.87156677246,16.9857940674 c 0.0,0.0 -19.7573547363,-19.7573699951 -19.7573547363,-19.7573699951 c 0.0,0.0 14.0142059326,-14.2142181396 14.0142059326,-14.2142181396 c 0.0,0.0 19.7573699951,19.7573699951 19.7573699951,19.7573699951 c 0.0,0.0 -14.0142211914,14.2142181396 -14.0142211914,14.2142181396 Z"
+            android:valueType="pathType"
+            android:interpolator="@android:interpolator/fast_out_slow_in" />
+    </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_portrait_to_auto_rotate_animation_arrow_bottom.xml b/packages/SystemUI/res/anim/ic_portrait_to_auto_rotate_animation_arrow_bottom.xml
new file mode 100644
index 0000000..c3ae6c1
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_portrait_to_auto_rotate_animation_arrow_bottom.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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+    <set
+        android:ordering="sequentially" >
+        <objectAnimator
+            android:duration="250"
+            android:propertyName="fillAlpha"
+            android:valueFrom="0"
+            android:valueTo="0"
+            android:interpolator="@android:interpolator/linear" />
+        <objectAnimator
+            android:duration="83"
+            android:propertyName="fillAlpha"
+            android:valueFrom="0"
+            android:valueTo="1"
+            android:interpolator="@android:interpolator/linear" />
+    </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_portrait_to_auto_rotate_animation_arrow_top.xml b/packages/SystemUI/res/anim/ic_portrait_to_auto_rotate_animation_arrow_top.xml
new file mode 100644
index 0000000..c3ae6c1
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_portrait_to_auto_rotate_animation_arrow_top.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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+    <set
+        android:ordering="sequentially" >
+        <objectAnimator
+            android:duration="250"
+            android:propertyName="fillAlpha"
+            android:valueFrom="0"
+            android:valueTo="0"
+            android:interpolator="@android:interpolator/linear" />
+        <objectAnimator
+            android:duration="83"
+            android:propertyName="fillAlpha"
+            android:valueFrom="0"
+            android:valueTo="1"
+            android:interpolator="@android:interpolator/linear" />
+    </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_portrait_to_auto_rotate_animation_arrows.xml b/packages/SystemUI/res/anim/ic_portrait_to_auto_rotate_animation_arrows.xml
new file mode 100644
index 0000000..fde172a
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_portrait_to_auto_rotate_animation_arrows.xml
@@ -0,0 +1,63 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+    <set
+        android:ordering="sequentially" >
+        <objectAnimator
+            android:duration="333"
+            android:propertyName="scaleX"
+            android:valueFrom="0.9"
+            android:valueTo="0.9"
+            android:interpolator="@android:interpolator/linear" />
+        <objectAnimator
+            android:duration="333"
+            android:propertyName="scaleX"
+            android:valueFrom="0.9"
+            android:valueTo="1"
+            android:interpolator="@android:interpolator/linear" />
+    </set>
+    <set
+        android:ordering="sequentially" >
+        <objectAnimator
+            android:duration="333"
+            android:propertyName="scaleY"
+            android:valueFrom="0.9"
+            android:valueTo="0.9"
+            android:interpolator="@android:interpolator/linear" />
+        <objectAnimator
+            android:duration="333"
+            android:propertyName="scaleY"
+            android:valueFrom="0.9"
+            android:valueTo="1"
+            android:interpolator="@android:interpolator/linear" />
+    </set>
+    <set
+        android:ordering="sequentially" >
+        <objectAnimator
+            android:duration="200"
+            android:propertyName="rotation"
+            android:valueFrom="-221"
+            android:valueTo="-221"
+            android:interpolator="@android:interpolator/fast_out_slow_in" />
+        <objectAnimator
+            android:duration="617"
+            android:propertyName="rotation"
+            android:valueFrom="-221"
+            android:valueTo="0"
+            android:interpolator="@android:interpolator/fast_out_slow_in" />
+    </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_portrait_to_auto_rotate_animation_device.xml b/packages/SystemUI/res/anim/ic_portrait_to_auto_rotate_animation_device.xml
new file mode 100644
index 0000000..accf16d
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_portrait_to_auto_rotate_animation_device.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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+    <set
+        android:ordering="sequentially" >
+        <objectAnimator
+            android:duration="250"
+            android:propertyName="rotation"
+            android:valueFrom="-135"
+            android:valueTo="-135"
+            android:interpolator="@android:interpolator/fast_out_slow_in" />
+        <objectAnimator
+            android:duration="400"
+            android:propertyName="rotation"
+            android:valueFrom="-135"
+            android:valueTo="0"
+            android:interpolator="@android:interpolator/fast_out_slow_in" />
+    </set>
+</set>
diff --git a/packages/SystemUI/res/anim/ic_portrait_to_auto_rotate_animation_device_1.xml b/packages/SystemUI/res/anim/ic_portrait_to_auto_rotate_animation_device_1.xml
new file mode 100644
index 0000000..15c6705
--- /dev/null
+++ b/packages/SystemUI/res/anim/ic_portrait_to_auto_rotate_animation_device_1.xml
@@ -0,0 +1,35 @@
+<?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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+    <set
+        android:ordering="sequentially" >
+        <objectAnimator
+            android:duration="250"
+            android:propertyName="pathData"
+            android:valueFrom="M -3.34053039551,-22.9980926514 c -1.3207244873,-1.3207244873 -3.46876525879,-1.26383972168 -4.74829101563,0.125762939453 c 0.0,0.0 -14.8512420654,14.7411804199 -14.8512420654,14.7411804199 c -1.39259338379,1.392578125 -1.44947814941,3.54061889648 -0.125762939453,4.74827575684 c 0.0,0.0 26.4143981934,26.4144134521 26.4143981934,26.4144134521 c 1.3207244873,1.3207244873 3.46876525879,1.26382446289 4.74829101562,-0.125762939453 c 0.0,0.0 14.7381896973,-14.7381896973 14.7381896973,-14.7381896973 c 1.392578125,-1.39259338379 1.44947814941,-3.54061889648 0.125762939453,-4.74829101562 c 0.0,0.0 -26.3013458252,-26.417388916 -26.3013458252,-26.417388916 Z M 2.87156677246,16.9857940674 c 0.0,0.0 -19.7573547363,-19.7573699951 -19.7573547363,-19.7573699951 c 0.0,0.0 14.0142059326,-14.2142181396 14.0142059326,-14.2142181396 c 0.0,0.0 19.7573699951,19.7573699951 19.7573699951,19.7573699951 c 0.0,0.0 -14.0142211914,14.2142181396 -14.0142211914,14.2142181396 Z"
+            android:valueTo="M -3.34053039551,-22.9980926514 c -1.3207244873,-1.3207244873 -3.46876525879,-1.26383972168 -4.74829101563,0.125762939453 c 0.0,0.0 -14.8512420654,14.7411804199 -14.8512420654,14.7411804199 c -1.39259338379,1.392578125 -1.44947814941,3.54061889648 -0.125762939453,4.74827575684 c 0.0,0.0 26.4143981934,26.4144134521 26.4143981934,26.4144134521 c 1.3207244873,1.3207244873 3.46876525879,1.26382446289 4.74829101562,-0.125762939453 c 0.0,0.0 14.7381896973,-14.7381896973 14.7381896973,-14.7381896973 c 1.392578125,-1.39259338379 1.44947814941,-3.54061889648 0.125762939453,-4.74829101562 c 0.0,0.0 -26.3013458252,-26.417388916 -26.3013458252,-26.417388916 Z M 2.87156677246,16.9857940674 c 0.0,0.0 -19.7573547363,-19.7573699951 -19.7573547363,-19.7573699951 c 0.0,0.0 14.0142059326,-14.2142181396 14.0142059326,-14.2142181396 c 0.0,0.0 19.7573699951,19.7573699951 19.7573699951,19.7573699951 c 0.0,0.0 -14.0142211914,14.2142181396 -14.0142211914,14.2142181396 Z"
+            android:valueType="pathType"
+            android:interpolator="@android:interpolator/fast_out_slow_in" />
+        <objectAnimator
+            android:duration="500"
+            android:propertyName="pathData"
+            android:valueFrom="M -3.34053039551,-22.9980926514 c -1.3207244873,-1.3207244873 -3.46876525879,-1.26383972168 -4.74829101563,0.125762939453 c 0.0,0.0 -14.8512420654,14.7411804199 -14.8512420654,14.7411804199 c -1.39259338379,1.392578125 -1.44947814941,3.54061889648 -0.125762939453,4.74827575684 c 0.0,0.0 26.4143981934,26.4144134521 26.4143981934,26.4144134521 c 1.3207244873,1.3207244873 3.46876525879,1.26382446289 4.74829101562,-0.125762939453 c 0.0,0.0 14.7381896973,-14.7381896973 14.7381896973,-14.7381896973 c 1.392578125,-1.39259338379 1.44947814941,-3.54061889648 0.125762939453,-4.74829101562 c 0.0,0.0 -26.3013458252,-26.417388916 -26.3013458252,-26.417388916 Z M 2.87156677246,16.9857940674 c 0.0,0.0 -19.7573547363,-19.7573699951 -19.7573547363,-19.7573699951 c 0.0,0.0 14.0142059326,-14.2142181396 14.0142059326,-14.2142181396 c 0.0,0.0 19.7573699951,19.7573699951 19.7573699951,19.7573699951 c 0.0,0.0 -14.0142211914,14.2142181396 -14.0142211914,14.2142181396 Z"
+            android:valueTo="M -3.5,-20.5 c -1.19999694824,-1.19999694824 -3.10000610352,-1.19999694824 -4.19999694824,0.0 c 0.0,0.0 -12.8000030518,12.6999969482 -12.8000030518,12.6999969482 c -1.19999694824,1.19999694824 -1.19999694824,3.10000610352 0.0,4.19999694824 c 0.0,0.0 24.0,24.0000152588 24.0,24.0000152588 c 1.19999694824,1.19999694824 3.10000610352,1.19999694824 4.19999694824,0.0 c 0.0,0.0 12.6999969482,-12.700012207 12.6999969482,-12.700012207 c 1.20001220703,-1.19999694824 1.20001220703,-3.09999084473 0.0,-4.19999694824 c 0.0,0.0 -23.8999938965,-24.0 -23.8999938965,-24.0 Z M 2.84999084473,15.5500183105 c 0.0,0.0 -18.6000061035,-18.5000457764 -18.6000061035,-18.5000457764 c 0.0,0.0 12.5999908447,-12.8000030518 12.5999908447,-12.8000030518 c 0.0,0.0 18.6000213623,18.5000457764 18.6000213623,18.5000457764 c 0.0,0.0 -12.6000061035,12.8000030518 -12.6000061035,12.8000030518 Z"
+            android:valueType="pathType"
+            android:interpolator="@android:interpolator/fast_out_slow_in" />
+    </set>
+</set>
diff --git a/packages/SystemUI/res/drawable/ic_landscape_from_auto_rotate.xml b/packages/SystemUI/res/drawable/ic_landscape_from_auto_rotate.xml
new file mode 100644
index 0000000..bc545ba
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_landscape_from_auto_rotate.xml
@@ -0,0 +1,62 @@
+<?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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:height="48dp"
+    android:width="48dp"
+    android:viewportHeight="48"
+    android:viewportWidth="48" >
+    <group
+        android:name="ic_screen_rotation_48px_outlines"
+        android:translateX="24"
+        android:translateY="24" >
+        <group
+            android:name="ic_screen_rotation_48px_outlines_pivot"
+            android:translateX="-24.15"
+            android:translateY="-24.25" >
+            <group
+                android:name="arrows"
+                android:translateX="24.1"
+                android:translateY="24.1" >
+                <group
+                    android:name="arrows_pivot"
+                    android:translateX="-24.1"
+                    android:translateY="-24.1" >
+                    <path
+                        android:name="arrow_top"
+                        android:pathData="M 33.1499938965,5.25 c 6.5,3.10000610352 11.1999969482,9.40000915527 11.8999938965,17.0 c 0.0,0.0 3.00001525879,0.0 3.00001525879,0.0 c -1.00001525879,-12.3000030518 -11.3000030518,-22.0 -23.9000091553,-22.0 c -0.399993896484,0.0 -0.899993896484,0.0 -1.30000305176,0.100006103516 c 0.0,0.0 7.60000610352,7.59999084473 7.60000610352,7.59999084473 c 0.0,0.0 2.69999694824,-2.69999694824 2.69999694824,-2.69999694824 Z"
+                        android:fillColor="#FFFFFFFF"
+                        android:fillAlpha="1" />
+                    <path
+                        android:name="arrow_bottom"
+                        android:pathData="M 15.1499938965,43.25 c -6.5,-3.09999084473 -11.1999969482,-9.5 -11.8999938965,-17.0 c 0.0,0.0 -3.0,0.0 -3.0,0.0 c 1.0,12.3000030518 11.299987793,22.0 23.8999938965,22.0 c 0.399993896484,0.0 0.899993896484,0.0 1.30000305176,-0.0999908447266 c 0.0,0.0 -7.60000610352,-7.60000610352 -7.60000610352,-7.60000610352 c 0.0,0.0 -2.69999694824,2.69999694824 -2.69999694824,2.69999694824 Z"
+                        android:fillColor="#FFFFFFFF"
+                        android:fillAlpha="1" />
+                </group>
+            </group>
+            <group
+                android:name="device"
+                android:translateX="24.14999"
+                android:translateY="24.25" >
+                <path
+                    android:name="body"
+                    android:pathData="M -3.5,-20.5 c -1.19999694824,-1.19999694824 -3.10000610352,-1.19999694824 -4.19999694824,0.0 c 0.0,0.0 -12.8000030518,12.6999969482 -12.8000030518,12.6999969482 c -1.19999694824,1.19999694824 -1.19999694824,3.10000610352 0.0,4.19999694824 c 0.0,0.0 24.0,24.0000152588 24.0,24.0000152588 c 1.19999694824,1.19999694824 3.10000610352,1.19999694824 4.19999694824,0.0 c 0.0,0.0 12.6999969482,-12.700012207 12.6999969482,-12.700012207 c 1.20001220703,-1.19999694824 1.20001220703,-3.09999084473 0.0,-4.19999694824 c 0.0,0.0 -23.8999938965,-24.0 -23.8999938965,-24.0 Z M 2.84999084473,15.5500183105 c 0.0,0.0 -18.6000061035,-18.5000457764 -18.6000061035,-18.5000457764 c 0.0,0.0 12.5999908447,-12.8000030518 12.5999908447,-12.8000030518 c 0.0,0.0 18.6000213623,18.5000457764 18.6000213623,18.5000457764 c 0.0,0.0 -12.6000061035,12.8000030518 -12.6000061035,12.8000030518 Z"
+                    android:fillColor="#FFFFFFFF"
+                    android:fillAlpha="1" />
+            </group>
+        </group>
+    </group>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_landscape_from_auto_rotate_animation.xml b/packages/SystemUI/res/drawable/ic_landscape_from_auto_rotate_animation.xml
new file mode 100644
index 0000000..400a28b
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_landscape_from_auto_rotate_animation.xml
@@ -0,0 +1,34 @@
+<?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.
+-->
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:drawable="@drawable/ic_landscape_from_auto_rotate" >
+    <target
+        android:name="arrows"
+        android:animation="@anim/ic_landscape_from_auto_rotate_animation_arrows" />
+    <target
+        android:name="arrow_top"
+        android:animation="@anim/ic_landscape_from_auto_rotate_animation_arrow_top" />
+    <target
+        android:name="arrow_bottom"
+        android:animation="@anim/ic_landscape_from_auto_rotate_animation_arrow_bottom" />
+    <target
+        android:name="device"
+        android:animation="@anim/ic_landscape_from_auto_rotate_animation_device" />
+    <target
+        android:name="body"
+        android:animation="@anim/ic_landscape_from_auto_rotate_animation_body" />
+</animated-vector>
diff --git a/packages/SystemUI/res/drawable/ic_landscape_to_auto_rotate.xml b/packages/SystemUI/res/drawable/ic_landscape_to_auto_rotate.xml
new file mode 100644
index 0000000..0bd75d1
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_landscape_to_auto_rotate.xml
@@ -0,0 +1,66 @@
+<?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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:height="48dp"
+    android:width="48dp"
+    android:viewportHeight="48"
+    android:viewportWidth="48" >
+    <group
+        android:name="ic_screen_rotation_48px_outlines"
+        android:translateX="24"
+        android:translateY="24" >
+        <group
+            android:name="ic_screen_rotation_48px_outlines_pivot"
+            android:translateX="-24.15"
+            android:translateY="-24.25" >
+            <group
+                android:name="arrows"
+                android:translateX="24.1"
+                android:translateY="24.1"
+                android:scaleX="0.9"
+                android:scaleY="0.9"
+                android:rotation="-135" >
+                <group
+                    android:name="arrows_pivot"
+                    android:translateX="-24.1"
+                    android:translateY="-24.1" >
+                    <path
+                        android:name="arrow_top"
+                        android:pathData="M 33.1499938965,5.25 c 6.5,3.10000610352 11.1999969482,9.40000915527 11.8999938965,17.0 c 0.0,0.0 3.00001525879,0.0 3.00001525879,0.0 c -1.00001525879,-12.3000030518 -11.3000030518,-22.0 -23.9000091553,-22.0 c -0.399993896484,0.0 -0.899993896484,0.0 -1.30000305176,0.100006103516 c 0.0,0.0 7.60000610352,7.59999084473 7.60000610352,7.59999084473 c 0.0,0.0 2.69999694824,-2.69999694824 2.69999694824,-2.69999694824 Z"
+                        android:fillColor="#FFFFFFFF"
+                        android:fillAlpha="0" />
+                    <path
+                        android:name="arrow_bottom"
+                        android:pathData="M 15.1499938965,43.25 c -6.5,-3.09999084473 -11.1999969482,-9.5 -11.8999938965,-17.0 c 0.0,0.0 -3.0,0.0 -3.0,0.0 c 1.0,12.3000030518 11.299987793,22.0 23.8999938965,22.0 c 0.399993896484,0.0 0.899993896484,0.0 1.30000305176,-0.0999908447266 c 0.0,0.0 -7.60000610352,-7.60000610352 -7.60000610352,-7.60000610352 c 0.0,0.0 -2.69999694824,2.69999694824 -2.69999694824,2.69999694824 Z"
+                        android:fillColor="#FFFFFFFF"
+                        android:fillAlpha="0" />
+                </group>
+            </group>
+            <group
+                android:name="device"
+                android:translateX="24.14999"
+                android:translateY="24.25"
+                android:rotation="-45" >
+                <path
+                    android:name="body"
+                    android:pathData="M -3.34053039551,-22.9980926514 c -1.3207244873,-1.3207244873 -3.46876525879,-1.26383972168 -4.74829101563,0.125762939453 c 0.0,0.0 -14.8512420654,14.7411804199 -14.8512420654,14.7411804199 c -1.39259338379,1.392578125 -1.44947814941,3.54061889648 -0.125762939453,4.74827575684 c 0.0,0.0 26.4143981934,26.4144134521 26.4143981934,26.4144134521 c 1.3207244873,1.3207244873 3.46876525879,1.26382446289 4.74829101562,-0.125762939453 c 0.0,0.0 14.7381896973,-14.7381896973 14.7381896973,-14.7381896973 c 1.392578125,-1.39259338379 1.44947814941,-3.54061889648 0.125762939453,-4.74829101562 c 0.0,0.0 -26.3013458252,-26.417388916 -26.3013458252,-26.417388916 Z M 2.87156677246,16.9857940674 c 0.0,0.0 -19.7573547363,-19.7573699951 -19.7573547363,-19.7573699951 c 0.0,0.0 14.0142059326,-14.2142181396 14.0142059326,-14.2142181396 c 0.0,0.0 19.7573699951,19.7573699951 19.7573699951,19.7573699951 c 0.0,0.0 -14.0142211914,14.2142181396 -14.0142211914,14.2142181396 Z"
+                    android:fillColor="#FFFFFFFF"
+                    android:fillAlpha="1" />
+            </group>
+        </group>
+    </group>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_landscape_to_auto_rotate_animation.xml b/packages/SystemUI/res/drawable/ic_landscape_to_auto_rotate_animation.xml
new file mode 100644
index 0000000..5263eb4
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_landscape_to_auto_rotate_animation.xml
@@ -0,0 +1,34 @@
+<?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.
+-->
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:drawable="@drawable/ic_landscape_to_auto_rotate" >
+    <target
+        android:name="arrows"
+        android:animation="@anim/ic_landscape_to_auto_rotate_animation_arrows" />
+    <target
+        android:name="arrow_top"
+        android:animation="@anim/ic_landscape_to_auto_rotate_animation_arrow_top" />
+    <target
+        android:name="arrow_bottom"
+        android:animation="@anim/ic_landscape_to_auto_rotate_animation_arrow_bottom" />
+    <target
+        android:name="device"
+        android:animation="@anim/ic_landscape_to_auto_rotate_animation_device" />
+    <target
+        android:name="body"
+        android:animation="@anim/ic_landscape_to_auto_rotate_animation_body" />
+</animated-vector>
diff --git a/packages/SystemUI/res/drawable/ic_portrait_from_auto_rotate.xml b/packages/SystemUI/res/drawable/ic_portrait_from_auto_rotate.xml
new file mode 100644
index 0000000..1805a8e
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_portrait_from_auto_rotate.xml
@@ -0,0 +1,62 @@
+<?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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:height="48dp"
+    android:width="48dp"
+    android:viewportHeight="48"
+    android:viewportWidth="48" >
+    <group
+        android:name="ic_screen_rotation_48px_outlines"
+        android:translateX="24"
+        android:translateY="24" >
+        <group
+            android:name="ic_screen_rotation_48px_outlines_pivot"
+            android:translateX="-24.15"
+            android:translateY="-24.25" >
+            <group
+                android:name="arrows"
+                android:translateX="24.1"
+                android:translateY="24.1" >
+                <group
+                    android:name="arrows_pivot"
+                    android:translateX="-24.1"
+                    android:translateY="-24.1" >
+                    <path
+                        android:name="arrow_top"
+                        android:pathData="M 33.1499938965,5.25 c 6.5,3.10000610352 11.1999969482,9.40000915527 11.8999938965,17.0 c 0.0,0.0 3.00001525879,0.0 3.00001525879,0.0 c -1.00001525879,-12.3000030518 -11.3000030518,-22.0 -23.9000091553,-22.0 c -0.399993896484,0.0 -0.899993896484,0.0 -1.30000305176,0.100006103516 c 0.0,0.0 7.60000610352,7.59999084473 7.60000610352,7.59999084473 c 0.0,0.0 2.69999694824,-2.69999694824 2.69999694824,-2.69999694824 Z"
+                        android:fillColor="#FFFFFFFF"
+                        android:fillAlpha="1" />
+                    <path
+                        android:name="arrow_bottom"
+                        android:pathData="M 15.1499938965,43.25 c -6.5,-3.09999084473 -11.1999969482,-9.5 -11.8999938965,-17.0 c 0.0,0.0 -3.0,0.0 -3.0,0.0 c 1.0,12.3000030518 11.299987793,22.0 23.8999938965,22.0 c 0.399993896484,0.0 0.899993896484,0.0 1.30000305176,-0.0999908447266 c 0.0,0.0 -7.60000610352,-7.60000610352 -7.60000610352,-7.60000610352 c 0.0,0.0 -2.69999694824,2.69999694824 -2.69999694824,2.69999694824 Z"
+                        android:fillColor="#FFFFFFFF"
+                        android:fillAlpha="1" />
+                </group>
+            </group>
+            <group
+                android:name="device"
+                android:translateX="24.14999"
+                android:translateY="24.25" >
+                <path
+                    android:name="device_1"
+                    android:pathData="M -3.5,-20.5 c -1.19999694824,-1.19999694824 -3.10000610352,-1.19999694824 -4.19999694824,0.0 c 0.0,0.0 -12.8000030518,12.6999969482 -12.8000030518,12.6999969482 c -1.19999694824,1.19999694824 -1.19999694824,3.10000610352 0.0,4.19999694824 c 0.0,0.0 24.0,24.0000152588 24.0,24.0000152588 c 1.19999694824,1.19999694824 3.10000610352,1.19999694824 4.19999694824,0.0 c 0.0,0.0 12.6999969482,-12.700012207 12.6999969482,-12.700012207 c 1.20001220703,-1.19999694824 1.20001220703,-3.09999084473 0.0,-4.19999694824 c 0.0,0.0 -23.8999938965,-24.0 -23.8999938965,-24.0 Z M 2.84999084473,15.5500183105 c 0.0,0.0 -18.6000061035,-18.5000457764 -18.6000061035,-18.5000457764 c 0.0,0.0 12.5999908447,-12.8000030518 12.5999908447,-12.8000030518 c 0.0,0.0 18.6000213623,18.5000457764 18.6000213623,18.5000457764 c 0.0,0.0 -12.6000061035,12.8000030518 -12.6000061035,12.8000030518 Z"
+                    android:fillColor="#FFFFFFFF"
+                    android:fillAlpha="1" />
+            </group>
+        </group>
+    </group>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_portrait_from_auto_rotate_animation.xml b/packages/SystemUI/res/drawable/ic_portrait_from_auto_rotate_animation.xml
new file mode 100644
index 0000000..565ef26
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_portrait_from_auto_rotate_animation.xml
@@ -0,0 +1,34 @@
+<?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.
+-->
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:drawable="@drawable/ic_portrait_from_auto_rotate" >
+    <target
+        android:name="arrows"
+        android:animation="@anim/ic_portrait_from_auto_rotate_animation_arrows" />
+    <target
+        android:name="arrow_top"
+        android:animation="@anim/ic_portrait_from_auto_rotate_animation_arrow_top" />
+    <target
+        android:name="arrow_bottom"
+        android:animation="@anim/ic_portrait_from_auto_rotate_animation_arrow_bottom" />
+    <target
+        android:name="device"
+        android:animation="@anim/ic_portrait_from_auto_rotate_animation_device" />
+    <target
+        android:name="device_1"
+        android:animation="@anim/ic_portrait_from_auto_rotate_animation_device_1" />
+</animated-vector>
diff --git a/packages/SystemUI/res/drawable/ic_portrait_to_auto_rotate.xml b/packages/SystemUI/res/drawable/ic_portrait_to_auto_rotate.xml
new file mode 100644
index 0000000..feb3025
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_portrait_to_auto_rotate.xml
@@ -0,0 +1,66 @@
+<?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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:height="48dp"
+    android:width="48dp"
+    android:viewportHeight="48"
+    android:viewportWidth="48" >
+    <group
+        android:name="ic_screen_rotation_48px_outlines"
+        android:translateX="24"
+        android:translateY="24" >
+        <group
+            android:name="ic_screen_rotation_48px_outlines_pivot"
+            android:translateX="-24.15"
+            android:translateY="-24.25" >
+            <group
+                android:name="arrows"
+                android:translateX="24.1"
+                android:translateY="24.1"
+                android:scaleX="0.9"
+                android:scaleY="0.9"
+                android:rotation="-221" >
+                <group
+                    android:name="arrows_pivot"
+                    android:translateX="-24.1"
+                    android:translateY="-24.1" >
+                    <path
+                        android:name="arrow_top"
+                        android:pathData="M 33.1499938965,5.25 c 6.5,3.10000610352 11.1999969482,9.40000915527 11.8999938965,17.0 c 0.0,0.0 3.00001525879,0.0 3.00001525879,0.0 c -1.00001525879,-12.3000030518 -11.3000030518,-22.0 -23.9000091553,-22.0 c -0.399993896484,0.0 -0.899993896484,0.0 -1.30000305176,0.100006103516 c 0.0,0.0 7.60000610352,7.59999084473 7.60000610352,7.59999084473 c 0.0,0.0 2.69999694824,-2.69999694824 2.69999694824,-2.69999694824 Z"
+                        android:fillColor="#FFFFFFFF"
+                        android:fillAlpha="0" />
+                    <path
+                        android:name="arrow_bottom"
+                        android:pathData="M 15.1499938965,43.25 c -6.5,-3.09999084473 -11.1999969482,-9.5 -11.8999938965,-17.0 c 0.0,0.0 -3.0,0.0 -3.0,0.0 c 1.0,12.3000030518 11.299987793,22.0 23.8999938965,22.0 c 0.399993896484,0.0 0.899993896484,0.0 1.30000305176,-0.0999908447266 c 0.0,0.0 -7.60000610352,-7.60000610352 -7.60000610352,-7.60000610352 c 0.0,0.0 -2.69999694824,2.69999694824 -2.69999694824,2.69999694824 Z"
+                        android:fillColor="#FFFFFFFF"
+                        android:fillAlpha="0" />
+                </group>
+            </group>
+            <group
+                android:name="device"
+                android:translateX="24.14999"
+                android:translateY="24.25"
+                android:rotation="-135" >
+                <path
+                    android:name="device_1"
+                    android:pathData="M -3.34053039551,-22.9980926514 c -1.3207244873,-1.3207244873 -3.46876525879,-1.26383972168 -4.74829101563,0.125762939453 c 0.0,0.0 -14.8512420654,14.7411804199 -14.8512420654,14.7411804199 c -1.39259338379,1.392578125 -1.44947814941,3.54061889648 -0.125762939453,4.74827575684 c 0.0,0.0 26.4143981934,26.4144134521 26.4143981934,26.4144134521 c 1.3207244873,1.3207244873 3.46876525879,1.26382446289 4.74829101562,-0.125762939453 c 0.0,0.0 14.7381896973,-14.7381896973 14.7381896973,-14.7381896973 c 1.392578125,-1.39259338379 1.44947814941,-3.54061889648 0.125762939453,-4.74829101562 c 0.0,0.0 -26.3013458252,-26.417388916 -26.3013458252,-26.417388916 Z M 2.87156677246,16.9857940674 c 0.0,0.0 -19.7573547363,-19.7573699951 -19.7573547363,-19.7573699951 c 0.0,0.0 14.0142059326,-14.2142181396 14.0142059326,-14.2142181396 c 0.0,0.0 19.7573699951,19.7573699951 19.7573699951,19.7573699951 c 0.0,0.0 -14.0142211914,14.2142181396 -14.0142211914,14.2142181396 Z"
+                    android:fillColor="#FFFFFFFF"
+                    android:fillAlpha="1" />
+            </group>
+        </group>
+    </group>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_portrait_to_auto_rotate_animation.xml b/packages/SystemUI/res/drawable/ic_portrait_to_auto_rotate_animation.xml
new file mode 100644
index 0000000..f75617f
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_portrait_to_auto_rotate_animation.xml
@@ -0,0 +1,34 @@
+<?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.
+-->
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:drawable="@drawable/ic_portrait_to_auto_rotate" >
+    <target
+        android:name="arrows"
+        android:animation="@anim/ic_portrait_to_auto_rotate_animation_arrows" />
+    <target
+        android:name="arrow_top"
+        android:animation="@anim/ic_portrait_to_auto_rotate_animation_arrow_top" />
+    <target
+        android:name="arrow_bottom"
+        android:animation="@anim/ic_portrait_to_auto_rotate_animation_arrow_bottom" />
+    <target
+        android:name="device"
+        android:animation="@anim/ic_portrait_to_auto_rotate_animation_device" />
+    <target
+        android:name="device_1"
+        android:animation="@anim/ic_portrait_to_auto_rotate_animation_device_1" />
+</animated-vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_rotation_landscape.xml b/packages/SystemUI/res/drawable/ic_qs_rotation_landscape.xml
deleted file mode 100644
index 4bb3668..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_rotation_landscape.xml
+++ /dev/null
@@ -1,25 +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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="64dp"
-        android:height="64dp"
-        android:viewportWidth="48.0"
-        android:viewportHeight="48.0">
-
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M2.0,14.0l0.0,20.0c0.0,2.2 1.8,4.0 4.0,4.0l36.0,0.0c2.2,0.0 4.0,-1.8 4.0,-4.0L46.0,14.0c0.0,-2.2 -1.8,-4.0 -4.0,-4.0L6.0,10.0C3.8,10.0 2.0,11.8 2.0,14.0zM38.0,14.0l0.0,20.0L10.0,34.0L10.0,14.0L38.0,14.0z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_rotation_portrait.xml b/packages/SystemUI/res/drawable/ic_qs_rotation_portrait.xml
deleted file mode 100644
index f0878c7..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_rotation_portrait.xml
+++ /dev/null
@@ -1,25 +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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="64dp"
-        android:height="64dp"
-        android:viewportWidth="48.0"
-        android:viewportHeight="48.0">
-
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M34.0,2.0L14.0,2.0c-2.2,0.0 -4.0,1.8 -4.0,4.0l0.0,36.0c0.0,2.2 1.8,4.0 4.0,4.0l20.0,0.0c2.2,0.0 4.0,-1.8 4.0,-4.0L38.0,6.0C38.0,3.8 36.2,2.0 34.0,2.0zM34.0,38.0L14.0,38.0L14.0,10.0l20.0,0.0L34.0,38.0z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_rotation_unlocked.xml b/packages/SystemUI/res/drawable/ic_qs_rotation_unlocked.xml
deleted file mode 100644
index 94b3a6b..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_rotation_unlocked.xml
+++ /dev/null
@@ -1,24 +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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="64dp"
-        android:height="64dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M16.600000,2.500000c3.300000,1.500000 5.600000,4.700000 6.000000,8.500000l1.500000,0.000000c-0.600000,-6.200000 -5.700000,-11.000000 -12.000000,-11.000000c-0.200000,0.000000 -0.400000,0.000000 -0.700000,0.000000l3.800000,3.800000L16.600000,2.500000zM10.300000,1.700000c-0.600000,-0.600000 -1.500000,-0.600000 -2.100000,0.000000L1.800000,8.100000c-0.600000,0.600000 -0.600000,1.500000 0.000000,2.100000l12.000000,12.000000c0.600000,0.600000 1.500000,0.600000 2.100000,0.000000l6.400000,-6.400000c0.600000,-0.600000 0.600000,-1.500000 0.000000,-2.100000L10.300000,1.700000zM13.400000,19.700001l-9.200000,-9.200000l6.400000,-6.400000l9.200000,9.200000L13.400000,19.700001zM7.600000,21.500000C4.300000,20.000000 2.000000,16.799999 1.600000,13.000000L0.200000,13.000000c0.500000,6.200000 5.600000,11.000000 11.900000,11.000000c0.200000,0.000000 0.400000,0.000000 0.700000,0.000000L9.000000,20.200001L7.600000,21.500000z"/>
-</vector>
diff --git a/packages/SystemUI/res/interpolator/ic_landscape_from_auto_rotate_arrows_rotation_interpolator.xml b/packages/SystemUI/res/interpolator/ic_landscape_from_auto_rotate_arrows_rotation_interpolator.xml
new file mode 100644
index 0000000..76f5667
--- /dev/null
+++ b/packages/SystemUI/res/interpolator/ic_landscape_from_auto_rotate_arrows_rotation_interpolator.xml
@@ -0,0 +1,18 @@
+<?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.
+-->
+<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
+    android:pathData="M 0,0 c 0.458031162,0 0.299442342,0.748308635 1,1" />
diff --git a/packages/SystemUI/res/interpolator/ic_landscape_to_auto_rotate_arrows_rotation_interpolator.xml b/packages/SystemUI/res/interpolator/ic_landscape_to_auto_rotate_arrows_rotation_interpolator.xml
new file mode 100644
index 0000000..ac27e4d
--- /dev/null
+++ b/packages/SystemUI/res/interpolator/ic_landscape_to_auto_rotate_arrows_rotation_interpolator.xml
@@ -0,0 +1,18 @@
+<?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.
+-->
+<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
+    android:pathData="M 0,0 c 0.4,0.143709151 0.2,1 1,1" />
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
index 4e93cd8..4a9eb55 100644
--- a/packages/SystemUI/res/values/ids.xml
+++ b/packages/SystemUI/res/values/ids.xml
@@ -35,5 +35,6 @@
     <item type="id" name="top_inset_animator_start_value_tag"/>
     <item type="id" name="height_animator_start_value_tag"/>
     <item type="id" name="doze_saved_filter_tag"/>
+    <item type="id" name="qs_icon_tag"/>
 </resources>
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 54a8414..1ddd352 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -203,7 +203,7 @@
         }
     }
 
-    private void refreshAllTiles() {
+    public void refreshAllTiles() {
         for (TileRecord r : mRecords) {
             r.tile.refreshState();
         }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
index 6ef6e9e..2a66484 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
@@ -18,11 +18,13 @@
 
 import android.content.Context;
 import android.content.Intent;
+import android.graphics.drawable.AnimatedVectorDrawable;
 import android.graphics.drawable.Drawable;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
 import android.util.Log;
+import android.util.SparseArray;
 import android.view.View;
 import android.view.ViewGroup;
 
@@ -299,10 +301,91 @@
         }
     }
 
+    public static abstract class Icon {
+        abstract public Drawable getDrawable(Context context);
+
+        @Override
+        public int hashCode() {
+            return Icon.class.hashCode();
+        }
+    }
+
+    public static class ResourceIcon extends Icon {
+        private static final SparseArray<Icon> ICONS = new SparseArray<Icon>();
+
+        private final int mResId;
+
+        private ResourceIcon(int resId) {
+            mResId = resId;
+        }
+
+        public static Icon get(int resId) {
+            Icon icon = ICONS.get(resId);
+            if (icon == null) {
+                icon = new ResourceIcon(resId);
+                ICONS.put(resId, icon);
+            }
+            return icon;
+        }
+
+        @Override
+        public Drawable getDrawable(Context context) {
+            return context.getDrawable(mResId);
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            return o instanceof ResourceIcon && ((ResourceIcon) o).mResId == mResId;
+        }
+
+        @Override
+        public String toString() {
+            return String.format("ResourceIcon[resId=0x%08x]", mResId);
+        }
+    }
+
+    protected class AnimationIcon extends ResourceIcon {
+        private boolean mAllowAnimation;
+
+        public AnimationIcon(int resId) {
+            super(resId);
+        }
+
+        public void setAllowAnimation(boolean allowAnimation) {
+            mAllowAnimation = allowAnimation;
+        }
+
+        @Override
+        public Drawable getDrawable(Context context) {
+            // workaround: get a clean state for every new AVD
+            final AnimatedVectorDrawable d = (AnimatedVectorDrawable) super.getDrawable(context)
+                    .getConstantState().newDrawable();
+            d.start();
+            if (mAllowAnimation) {
+                mAllowAnimation = false;
+            } else {
+                d.stop(); // skip directly to end state
+            }
+            return d;
+        }
+    }
+
+    protected enum UserBoolean {
+        USER_TRUE(true, true),
+        USER_FALSE(true, false),
+        BACKGROUND_TRUE(false, true),
+        BACKGROUND_FALSE(false, false);
+        public final boolean value;
+        public final boolean userInitiated;
+        private UserBoolean(boolean userInitiated, boolean value) {
+            this.value = value;
+            this.userInitiated = userInitiated;
+        }
+    }
+
     public static class State {
         public boolean visible;
-        public int iconId;
-        public Drawable icon;
+        public Icon icon;
         public String label;
         public String contentDescription;
         public String dualLabelContentDescription;
@@ -312,7 +395,6 @@
             if (other == null) throw new IllegalArgumentException();
             if (!other.getClass().equals(getClass())) throw new IllegalArgumentException();
             final boolean changed = other.visible != visible
-                    || other.iconId != iconId
                     || !Objects.equals(other.icon, icon)
                     || !Objects.equals(other.label, label)
                     || !Objects.equals(other.contentDescription, contentDescription)
@@ -320,7 +402,6 @@
                     || !Objects.equals(other.dualLabelContentDescription,
                     dualLabelContentDescription);
             other.visible = visible;
-            other.iconId = iconId;
             other.icon = icon;
             other.label = label;
             other.contentDescription = contentDescription;
@@ -335,9 +416,8 @@
         }
 
         protected StringBuilder toStringBuilder() {
-            final StringBuilder sb = new StringBuilder(  getClass().getSimpleName()).append('[');
+            final StringBuilder sb = new StringBuilder(getClass().getSimpleName()).append('[');
             sb.append("visible=").append(visible);
-            sb.append(",iconId=").append(iconId);
             sb.append(",icon=").append(icon);
             sb.append(",label=").append(label);
             sb.append(",contentDescription=").append(contentDescription);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
index d5c90d0..3d0f47c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
@@ -21,6 +21,7 @@
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.graphics.Typeface;
+import android.graphics.drawable.Animatable;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.RippleDrawable;
 import android.os.Handler;
@@ -39,6 +40,8 @@
 import com.android.systemui.R;
 import com.android.systemui.qs.QSTile.State;
 
+import java.util.Objects;
+
 /** View that represents a standard quick settings tile. **/
 public class QSTileView extends ViewGroup {
     private static final Typeface CONDENSED = Typeface.create("sans-serif-condensed",
@@ -60,6 +63,7 @@
     private boolean mDual;
     private OnClickListener mClickPrimary;
     private OnClickListener mClickSecondary;
+    private Drawable mTileBackground;
     private RippleDrawable mRipple;
 
     public QSTileView(Context context) {
@@ -72,6 +76,7 @@
         mTilePaddingBelowIconPx =  res.getDimensionPixelSize(R.dimen.qs_tile_padding_below_icon);
         mDualTileVerticalPaddingPx =
                 res.getDimensionPixelSize(R.dimen.qs_dual_tile_padding_vertical);
+        mTileBackground = newTileBackground();
         recreateLabel();
         setClipChildren(false);
 
@@ -172,22 +177,21 @@
         if (changed) {
             recreateLabel();
         }
-        Drawable tileBackground = getTileBackground();
-        if (tileBackground instanceof RippleDrawable) {
-            setRipple((RippleDrawable) tileBackground);
+        if (mTileBackground instanceof RippleDrawable) {
+            setRipple((RippleDrawable) mTileBackground);
         }
         if (dual) {
             mTopBackgroundView.setOnClickListener(mClickPrimary);
             setOnClickListener(null);
             setClickable(false);
             setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
-            mTopBackgroundView.setBackground(tileBackground);
+            mTopBackgroundView.setBackground(mTileBackground);
         } else {
             mTopBackgroundView.setOnClickListener(null);
             mTopBackgroundView.setClickable(false);
             setOnClickListener(mClickPrimary);
             setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
-            setBackground(tileBackground);
+            setBackground(mTileBackground);
         }
         mTopBackgroundView.setFocusable(dual);
         setFocusable(!dual);
@@ -214,7 +218,7 @@
         return icon;
     }
 
-    private Drawable getTileBackground() {
+    private Drawable newTileBackground() {
         final int[] attrs = new int[] { android.R.attr.selectableItemBackgroundBorderless };
         final TypedArray ta = mContext.obtainStyledAttributes(attrs);
         final Drawable d = ta.getDrawable(0);
@@ -285,16 +289,7 @@
 
     protected void handleStateChanged(QSTile.State state) {
         if (mIcon instanceof ImageView) {
-            ImageView iv = (ImageView) mIcon;
-            if (state.icon != null) {
-                iv.setImageDrawable(state.icon);
-            } else if (state.iconId > 0) {
-                iv.setImageResource(state.iconId);
-            }
-            Drawable drawable = iv.getDrawable();
-            if (state.autoMirrorDrawable && drawable != null) {
-                drawable.setAutoMirrored(true);
-            }
+            setIcon((ImageView) mIcon, state);
         }
         if (mDual) {
             mDualLabel.setText(state.label);
@@ -306,6 +301,22 @@
         }
     }
 
+    protected void setIcon(ImageView iv, QSTile.State state) {
+        if (!Objects.equals(state.icon, iv.getTag(R.id.qs_icon_tag))) {
+            Drawable d = state.icon != null ? state.icon.getDrawable(mContext) : null;
+            if (d != null && state.autoMirrorDrawable) {
+                d.setAutoMirrored(true);
+            }
+            iv.setImageDrawable(d);
+            iv.setTag(R.id.qs_icon_tag, state.icon);
+            if (d instanceof Animatable) {
+                if (!iv.isShown()) {
+                    ((Animatable) d).stop(); // skip directly to end state
+                }
+            }
+        }
+    }
+
     public void onStateChanged(QSTile.State state) {
         mHandler.obtainMessage(H.STATE_CHANGED, state).sendToTarget();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java b/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java
index cfcd74e..9ac7944 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java
@@ -104,7 +104,7 @@
     protected void handleStateChanged(QSTile.State state) {
         super.handleStateChanged(state);
         final SignalState s = (SignalState) state;
-        mSignal.setImageResource(s.iconId);
+        setIcon(mSignal, s);
         if (s.overlayIconId > 0) {
             mOverlay.setVisibility(VISIBLE);
             mOverlay.setImageResource(s.overlayIconId);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
index 51401c8..cd44a2b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
@@ -68,11 +68,11 @@
         state.visible = true;
         state.label = mContext.getString(R.string.quick_settings_airplane_mode_label);
         if (airplaneMode) {
-            state.iconId =  R.drawable.ic_qs_airplane_on;
+            state.icon = ResourceIcon.get(R.drawable.ic_qs_airplane_on);
             state.contentDescription =  mContext.getString(
                     R.string.accessibility_quick_settings_airplane_on);
         } else {
-            state.iconId = R.drawable.ic_qs_airplane_off;
+            state.icon = ResourceIcon.get(R.drawable.ic_qs_airplane_off);
             state.contentDescription =  mContext.getString(
                     R.string.accessibility_quick_settings_airplane_off);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
index 84bfb8f..4d77348 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -92,17 +92,17 @@
         if (enabled) {
             state.label = null;
             if (connected) {
-                state.iconId = R.drawable.ic_qs_bluetooth_connected;
+                state.icon = ResourceIcon.get(R.drawable.ic_qs_bluetooth_connected);
                 state.contentDescription = mContext.getString(
                         R.string.accessibility_quick_settings_bluetooth_connected);
                 state.label = mController.getLastDeviceName();
             } else if (connecting) {
-                state.iconId = R.drawable.ic_qs_bluetooth_connecting;
+                state.icon = ResourceIcon.get(R.drawable.ic_qs_bluetooth_connecting);
                 state.contentDescription = mContext.getString(
                         R.string.accessibility_quick_settings_bluetooth_connecting);
                 state.label = mContext.getString(R.string.quick_settings_bluetooth_label);
             } else {
-                state.iconId = R.drawable.ic_qs_bluetooth_on;
+                state.icon = ResourceIcon.get(R.drawable.ic_qs_bluetooth_on);
                 state.contentDescription = mContext.getString(
                         R.string.accessibility_quick_settings_bluetooth_on);
             }
@@ -110,7 +110,7 @@
                 state.label = mContext.getString(R.string.quick_settings_bluetooth_label);
             }
         } else {
-            state.iconId = R.drawable.ic_qs_bluetooth_off;
+            state.icon = ResourceIcon.get(R.drawable.ic_qs_bluetooth_off);
             state.label = mContext.getString(R.string.quick_settings_bluetooth_label);
             state.contentDescription = mContext.getString(
                     R.string.accessibility_quick_settings_bluetooth_off);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
index 8304291..5bf6fb5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
@@ -107,7 +107,8 @@
         if (!state.value && connecting) {
             state.label = mContext.getString(R.string.quick_settings_connecting);
         }
-        state.iconId = state.value ? R.drawable.ic_qs_cast_on : R.drawable.ic_qs_cast_off;
+        state.icon = ResourceIcon.get(state.value ? R.drawable.ic_qs_cast_on
+                : R.drawable.ic_qs_cast_off);
         mDetailAdapter.updateItems(devices);
     }
 
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 359a259..178590b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -87,16 +87,17 @@
         if (cb == null) return;
 
         final Resources r = mContext.getResources();
-        state.iconId = cb.noSim ? R.drawable.ic_qs_no_sim
+        final int iconId = cb.noSim ? R.drawable.ic_qs_no_sim
                 : !cb.enabled || cb.airplaneModeEnabled ? R.drawable.ic_qs_signal_disabled
                 : cb.mobileSignalIconId > 0 ? cb.mobileSignalIconId
                 : R.drawable.ic_qs_signal_no_signal;
+        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.filter = state.iconId != R.drawable.ic_qs_no_sim;
+        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/qs/tiles/ColorInversionTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
index 7ba1dc0..b24f8bf 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
@@ -88,7 +88,8 @@
         state.visible = enabled || mUsageTracker.isRecentlyUsed();
         state.value = enabled;
         state.label = mContext.getString(R.string.quick_settings_inversion_label);
-        state.iconId = enabled ? R.drawable.ic_qs_inversion_on : R.drawable.ic_qs_inversion_off;
+        state.icon = ResourceIcon.get(enabled ? R.drawable.ic_qs_inversion_on
+                : R.drawable.ic_qs_inversion_off);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
index e6b7f02..055a6b7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
@@ -92,8 +92,8 @@
         // the camera is not available while it is being used for the flashlight.
         state.visible = mWasLastOn != 0 || mFlashlightController.isAvailable();
         state.label = mHost.getContext().getString(R.string.quick_settings_flashlight_label);
-        state.iconId = state.value
-                ? R.drawable.ic_qs_flashlight_on : R.drawable.ic_qs_flashlight_off;
+        state.icon = ResourceIcon.get(state.value ? R.drawable.ic_qs_flashlight_on
+                : R.drawable.ic_qs_flashlight_off);
         int onOrOffId = state.value
                 ? R.string.accessibility_quick_settings_flashlight_on
                 : R.string.accessibility_quick_settings_flashlight_off;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
index b30a1d3..64dab85 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
@@ -71,8 +71,8 @@
         state.label = mContext.getString(R.string.quick_settings_hotspot_label);
 
         state.value = mController.isHotspotEnabled();
-        state.iconId = state.visible && state.value ? R.drawable.ic_qs_hotspot_on
-                : R.drawable.ic_qs_hotspot_off;
+        state.icon = ResourceIcon.get(state.visible && state.value ? R.drawable.ic_qs_hotspot_on
+                : R.drawable.ic_qs_hotspot_off);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
index 58587e6..6fb9cd8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
@@ -31,6 +31,9 @@
 
 import com.android.systemui.qs.QSTile;
 
+import java.util.Arrays;
+import java.util.Objects;
+
 public class IntentTile extends QSTile<QSTile.State> {
     public static final String PREFIX = "intent(";
 
@@ -96,13 +99,11 @@
         state.visible = intent.getBooleanExtra("visible", true);
         state.contentDescription = intent.getStringExtra("contentDescription");
         state.label = intent.getStringExtra("label");
-        state.iconId = 0;
         state.icon = null;
         final byte[] iconBitmap = intent.getByteArrayExtra("iconBitmap");
         if (iconBitmap != null) {
             try {
-                final Bitmap b = BitmapFactory.decodeByteArray(iconBitmap, 0, iconBitmap.length);
-                state.icon = new BitmapDrawable(mContext.getResources(), b);
+                state.icon = new BytesIcon(iconBitmap);
             } catch (Throwable t) {
                 Log.w(TAG, "Error loading icon bitmap, length " + iconBitmap.length, t);
             }
@@ -111,9 +112,9 @@
             if (iconId != 0) {
                 final String iconPackage = intent.getStringExtra("iconPackage");
                 if (!TextUtils.isEmpty(iconPackage)) {
-                    state.icon = getPackageDrawable(iconPackage, iconId);
+                    state.icon = new PackageDrawableIcon(iconPackage, iconId);
                 } else {
-                    state.iconId = iconId;
+                    state.icon = ResourceIcon.get(iconId);
                 }
             }
         }
@@ -121,19 +122,66 @@
         mOnClickUri = intent.getStringExtra("onClickUri");
     }
 
-    private Drawable getPackageDrawable(String pkg, int id) {
-        try {
-            return mContext.createPackageContext(pkg, 0).getDrawable(id);
-        } catch (Throwable t) {
-            Log.w(TAG, "Error loading package drawable pkg=" + pkg + " id=" + id, t);
-            return null;
-        }
-    }
-
     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
             refreshState(intent);
         }
     };
+
+    private static class BytesIcon extends Icon {
+        private final byte[] mBytes;
+
+        public BytesIcon(byte[] bytes) {
+            mBytes = bytes;
+        }
+
+        @Override
+        public Drawable getDrawable(Context context) {
+            final Bitmap b = BitmapFactory.decodeByteArray(mBytes, 0, mBytes.length);
+            return new BitmapDrawable(context.getResources(), b);
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            return o instanceof BytesIcon && Arrays.equals(((BytesIcon) o).mBytes, mBytes);
+        }
+
+        @Override
+        public String toString() {
+            return String.format("BytesIcon[len=%s]", mBytes.length);
+        }
+    }
+
+    private class PackageDrawableIcon extends Icon {
+        private final String mPackage;
+        private final int mResId;
+
+        public PackageDrawableIcon(String pkg, int resId) {
+            mPackage = pkg;
+            mResId = resId;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (!(o instanceof PackageDrawableIcon)) return false;
+            final PackageDrawableIcon other = (PackageDrawableIcon) o;
+            return Objects.equals(other.mPackage, mPackage) && other.mResId == mResId;
+        }
+
+        @Override
+        public Drawable getDrawable(Context context) {
+            try {
+                return context.createPackageContext(mPackage, 0).getDrawable(mResId);
+            } catch (Throwable t) {
+                Log.w(TAG, "Error loading package drawable pkg=" + mPackage + " id=" + mResId, t);
+                return null;
+            }
+        }
+
+        @Override
+        public String toString() {
+            return String.format("PackageDrawableIcon[pkg=%s,id=0x%08x]", mPackage, mResId);
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
index d1dc5d2..81741ce 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
@@ -67,12 +67,12 @@
         state.visible = !mKeyguard.isShowing();
         state.value = locationEnabled;
         if (locationEnabled) {
-            state.iconId = R.drawable.ic_qs_location_on;
+            state.icon = ResourceIcon.get(R.drawable.ic_qs_location_on);
             state.label = mContext.getString(R.string.quick_settings_location_label);
             state.contentDescription = mContext.getString(
                     R.string.accessibility_quick_settings_location_on);
         } else {
-            state.iconId = R.drawable.ic_qs_location_off;
+            state.icon = ResourceIcon.get(R.drawable.ic_qs_location_off);
             state.label = mContext.getString(R.string.quick_settings_location_label);
             state.contentDescription = mContext.getString(
                     R.string.accessibility_quick_settings_location_off);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
index ae40a4d..49cd14a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
@@ -17,7 +17,6 @@
 package com.android.systemui.qs.tiles;
 
 import android.content.res.Configuration;
-import android.content.res.Resources;
 
 import com.android.systemui.R;
 import com.android.systemui.qs.QSTile;
@@ -26,6 +25,15 @@
 
 /** Quick settings tile: Rotation **/
 public class RotationLockTile extends QSTile<QSTile.BooleanState> {
+    private final AnimationIcon PORTRAIT_TO_AUTO
+            = new AnimationIcon(R.drawable.ic_portrait_to_auto_rotate_animation);
+    private final AnimationIcon AUTO_TO_PORTRAIT
+            = new AnimationIcon(R.drawable.ic_portrait_from_auto_rotate_animation);
+
+    private final AnimationIcon LANDSCAPE_TO_AUTO
+            = new AnimationIcon(R.drawable.ic_landscape_to_auto_rotate_animation);
+    private final AnimationIcon AUTO_TO_LANDSCAPE
+            = new AnimationIcon(R.drawable.ic_landscape_from_auto_rotate_animation);
 
     private final RotationLockController mController;
 
@@ -51,30 +59,34 @@
     @Override
     protected void handleClick() {
         if (mController == null) return;
-        mController.setRotationLocked(!mState.value);
+        final boolean newState = !mState.value;
+        mController.setRotationLocked(newState);
+        refreshState(newState ? UserBoolean.USER_TRUE : UserBoolean.USER_FALSE);
     }
 
     @Override
     protected void handleUpdateState(BooleanState state, Object arg) {
         if (mController == null) return;
-        final boolean rotationLocked = mController.isRotationLocked();
+        final boolean rotationLocked = arg != null ? ((UserBoolean) arg).value
+                : mController.isRotationLocked();
+        final boolean userInitiated = arg != null ? ((UserBoolean) arg).userInitiated : false;
         state.visible = mController.isRotationLockAffordanceVisible();
-        final Resources res = mContext.getResources();
         state.value = rotationLocked;
+        final boolean portrait = mContext.getResources().getConfiguration().orientation
+                != Configuration.ORIENTATION_LANDSCAPE;
+        final AnimationIcon icon;
         if (rotationLocked) {
-            final boolean portrait = res.getConfiguration().orientation
-                    != Configuration.ORIENTATION_LANDSCAPE;
             final int label = portrait ? R.string.quick_settings_rotation_locked_portrait_label
                     : R.string.quick_settings_rotation_locked_landscape_label;
-            final int icon = portrait ? R.drawable.ic_qs_rotation_portrait
-                    : R.drawable.ic_qs_rotation_landscape;
             state.label = mContext.getString(label);
-            state.icon = mContext.getDrawable(icon);
+            icon = portrait ? AUTO_TO_PORTRAIT : AUTO_TO_LANDSCAPE;
         } else {
             state.label = mContext.getString(R.string.quick_settings_rotation_unlocked_label);
-            state.icon = res.getDrawable(R.drawable.ic_qs_rotation_unlocked);
+            icon = portrait ? PORTRAIT_TO_AUTO : LANDSCAPE_TO_AUTO;
         }
-        state.contentDescription = getAccessibilityString(
+        icon.setAllowAnimation(userInitiated);
+        state.icon = icon;
+        state.contentDescription = getAccessibilityString(rotationLocked,
                 R.string.accessibility_rotation_lock_on_portrait,
                 R.string.accessibility_rotation_lock_on_landscape,
                 R.string.accessibility_rotation_lock_off);
@@ -83,14 +95,16 @@
     /**
      * Get the correct accessibility string based on the state
      *
+     * @param locked Whether or not rotation is locked.
      * @param idWhenPortrait The id which should be used when locked in portrait.
      * @param idWhenLandscape The id which should be used when locked in landscape.
      * @param idWhenOff The id which should be used when the rotation lock is off.
      * @return
      */
-    private String getAccessibilityString(int idWhenPortrait, int idWhenLandscape, int idWhenOff) {
+    private String getAccessibilityString(boolean locked, int idWhenPortrait, int idWhenLandscape,
+            int idWhenOff) {
         int stringID;
-        if (mState.value) {
+        if (locked) {
             final boolean portrait = mContext.getResources().getConfiguration().orientation
                     != Configuration.ORIENTATION_LANDSCAPE;
             stringID = portrait ? idWhenPortrait: idWhenLandscape;
@@ -102,7 +116,7 @@
 
     @Override
     protected String composeChangeAnnouncement() {
-        return getAccessibilityString(
+        return getAccessibilityString(mState.value,
                 R.string.accessibility_rotation_lock_on_portrait_changed,
                 R.string.accessibility_rotation_lock_on_landscape_changed,
                 R.string.accessibility_rotation_lock_off_changed);
@@ -111,7 +125,8 @@
     private final RotationLockControllerCallback mCallback = new RotationLockControllerCallback() {
         @Override
         public void onRotationLockStateChanged(boolean rotationLocked, boolean affordanceVisible) {
-            refreshState();
+            refreshState(rotationLocked ? UserBoolean.BACKGROUND_TRUE
+                    : UserBoolean.BACKGROUND_FALSE);
         }
     };
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index 20c4ee8..7aa884e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -120,19 +120,19 @@
         final String signalContentDescription;
         final Resources r = mContext.getResources();
         if (!state.enabled) {
-            state.iconId = R.drawable.ic_qs_wifi_disabled;
+            state.icon = ResourceIcon.get(R.drawable.ic_qs_wifi_disabled);
             state.label = r.getString(R.string.quick_settings_wifi_label);
             signalContentDescription = r.getString(R.string.accessibility_wifi_off);
         } else if (wifiConnected) {
-            state.iconId = cb.wifiSignalIconId;
+            state.icon = ResourceIcon.get(cb.wifiSignalIconId);
             state.label = removeDoubleQuotes(cb.enabledDesc);
             signalContentDescription = cb.wifiSignalContentDescription;
         } else if (wifiNotConnected) {
-            state.iconId = R.drawable.ic_qs_wifi_0;
+            state.icon = ResourceIcon.get(R.drawable.ic_qs_wifi_0);
             state.label = r.getString(R.string.quick_settings_wifi_label);
             signalContentDescription = r.getString(R.string.accessibility_no_wifi);
         } else {
-            state.iconId = R.drawable.ic_qs_wifi_no_network;
+            state.icon = ResourceIcon.get(R.drawable.ic_qs_wifi_no_network);
             state.label = r.getString(R.string.quick_settings_wifi_label);
             signalContentDescription = r.getString(R.string.accessibility_wifi_off);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
index 2a782cc..4c3460e 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
@@ -728,7 +728,7 @@
         final ActivityManager am = (ActivityManager)
                 getContext().getSystemService(Context.ACTIVITY_SERVICE);
         if (am != null) {
-            am.removeTask(ad.persistentTaskId, ActivityManager.REMOVE_TASK_KILL_PROCESS);
+            am.removeTask(ad.persistentTaskId);
 
             // Accessibility feedback
             setContentDescription(
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index 71a3ef1..b661385 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -291,18 +291,18 @@
         }
     }
 
-    /** Removes the task and kills the process */
-    public void removeTask(int taskId, boolean isDocument) {
+    /** Removes the task */
+    public void removeTask(int taskId) {
         if (mAm == null) return;
         if (Constants.DebugFlags.App.EnableSystemServicesProxy) return;
 
-        // Remove the task, and only kill the process if it is not a document
-        mAm.removeTask(taskId, isDocument ? 0 : ActivityManager.REMOVE_TASK_KILL_PROCESS);
+        // Remove the task.
+        mAm.removeTask(taskId);
     }
 
     /**
      * Returns the activity info for a given component name.
-     * 
+     *
      * @param cn The component name of the activity.
      * @param userId The userId of the user that this is for.
      */
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java b/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java
index a0dee07..e1179fa 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java
@@ -17,7 +17,6 @@
 package com.android.systemui.recents.misc;
 
 import android.animation.Animator;
-import android.content.Intent;
 import android.graphics.Color;
 import android.graphics.Matrix;
 import android.graphics.Rect;
@@ -184,12 +183,6 @@
         sPropertyMethod.invoke(null, property, value);
     }
 
-    /** Returns whether the specified intent is a document. */
-    public static boolean isDocument(Intent intent) {
-        int flags = intent.getFlags();
-        return (flags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) == Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
-    }
-
     /**
      * Cancels an animation ensuring that if it has listeners, onCancel and onEnd
      * are not called.
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index 6b0d306..ff0330d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -34,7 +34,6 @@
 import com.android.systemui.recents.Constants;
 import com.android.systemui.recents.RecentsConfiguration;
 import com.android.systemui.recents.misc.SystemServicesProxy;
-import com.android.systemui.recents.misc.Utilities;
 import com.android.systemui.recents.model.RecentsPackageMonitor;
 import com.android.systemui.recents.model.RecentsTaskLoader;
 import com.android.systemui.recents.model.Task;
@@ -522,8 +521,7 @@
         loader.deleteTaskData(t, false);
 
         // Remove the old task from activity manager
-        RecentsTaskLoader.getInstance().getSystemServicesProxy().removeTask(t.key.id,
-                Utilities.isDocument(t.key.baseIntent));
+        RecentsTaskLoader.getInstance().getSystemServicesProxy().removeTask(t.key.id);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index ce35e4b..992aa9f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -162,8 +162,9 @@
     KeyguardUpdateMonitorCallback mUpdateMonitor = new KeyguardUpdateMonitorCallback() {
         @Override
         public void onRefreshBatteryInfo(KeyguardUpdateMonitor.BatteryStatus status) {
-            mPowerPluggedIn = status.status == BatteryManager.BATTERY_STATUS_CHARGING
+            boolean isChargingOrFull = status.status == BatteryManager.BATTERY_STATUS_CHARGING
                     || status.status == BatteryManager.BATTERY_STATUS_FULL;
+            mPowerPluggedIn = status.isPluggedIn() && isChargingOrFull;
             mPowerCharged = status.isCharged();
             updateIndication();
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
index 32fb567..e89e15d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
@@ -45,6 +45,7 @@
     public static final int MODE_LIGHTS_OUT = 3;
     public static final int MODE_TRANSPARENT = 4;
     public static final int MODE_WARNING = 5;
+    public static final int MODE_LIGHTS_OUT_TRANSPARENT = 6;
 
     public static final int LIGHTS_IN_DURATION = 250;
     public static final int LIGHTS_OUT_DURATION = 750;
@@ -75,6 +76,9 @@
                 || mode == MODE_TRANSPARENT)) {
             mode = MODE_OPAQUE;
         }
+        if (!HIGH_END && (mode == MODE_LIGHTS_OUT_TRANSPARENT)) {
+            mode = MODE_LIGHTS_OUT;
+        }
         if (mMode == mode) return;
         int oldMode = mMode;
         mMode = mode;
@@ -102,6 +106,7 @@
         if (mode == MODE_LIGHTS_OUT) return "MODE_LIGHTS_OUT";
         if (mode == MODE_TRANSPARENT) return "MODE_TRANSPARENT";
         if (mode == MODE_WARNING) return "MODE_WARNING";
+        if (mode == MODE_LIGHTS_OUT_TRANSPARENT) return "MODE_LIGHTS_OUT_TRANSPARENT";
         throw new IllegalArgumentException("Unknown mode " + mode);
     }
 
@@ -109,6 +114,10 @@
         mBarBackground.finishAnimation();
     }
 
+    protected boolean isLightsOut(int mode) {
+        return mode == MODE_LIGHTS_OUT || mode == MODE_LIGHTS_OUT_TRANSPARENT;
+    }
+
     private static class BarBackgroundDrawable extends Drawable {
         private final int mOpaque;
         private final int mSemiTransparent;
@@ -196,7 +205,7 @@
                 targetColor = mSemiTransparent;
             } else if (mMode == MODE_SEMI_TRANSPARENT) {
                 targetColor = mSemiTransparent;
-            } else if (mMode == MODE_TRANSPARENT) {
+            } else if (mMode == MODE_TRANSPARENT || mMode == MODE_LIGHTS_OUT_TRANSPARENT) {
                 targetColor = mTransparent;
             } else {
                 targetColor = mOpaque;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
index 052b6c6..15f6dc2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
@@ -84,7 +84,7 @@
         applyBackButtonQuiescentAlpha(mode, animate);
 
         // apply to lights out
-        applyLightsOut(mode == MODE_LIGHTS_OUT, animate, force);
+        applyLightsOut(isLightsOut(mode), animate, force);
     }
 
     private float alphaForMode(int mode) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index d9e44c3..bb992b0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -291,8 +291,8 @@
         } else {
             setQsExpansion(mQsMinExpansionHeight + mLastOverscroll);
             mNotificationStackScroller.setStackHeight(getExpandedHeight());
-            updateHeader();
         }
+        updateHeader();
         mNotificationStackScroller.updateIsSmallScreen(
                 mHeader.getCollapsedHeight() + mQsPeekHeight);
     }
@@ -1329,6 +1329,16 @@
         float notificationHeight = mNotificationStackScroller.getHeight()
                 - mNotificationStackScroller.getEmptyBottomMargin()
                 - mNotificationStackScroller.getTopPadding();
+
+        // When only empty shade view is visible in QS collapsed state, simulate that we would have
+        // it in expanded QS state as well so we don't run into troubles when fading the view in/out
+        // and expanding/collapsing the whole panel from/to quick settings.
+        if (mNotificationStackScroller.getNotGoneChildCount() == 0
+                && mShadeEmpty) {
+            notificationHeight = mNotificationStackScroller.getEmptyShadeViewHeight()
+                    + mNotificationStackScroller.getBottomStackPeekSize()
+                    + mNotificationStackScroller.getCollapseSecondCardPadding();
+        }
         float totalHeight = Math.max(
                 mQsMaxExpansionHeight + mNotificationStackScroller.getNotificationTopPadding(),
                 mClockPositionResult.stackScrollerPadding - mTopPaddingAdjustment)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 72dfee6..142791d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -23,6 +23,7 @@
 import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
 import static android.app.StatusBarManager.windowStateToString;
 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT;
+import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT;
 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_OPAQUE;
 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_SEMI_TRANSPARENT;
 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSLUCENT;
@@ -2600,8 +2601,10 @@
     }
 
     private int barMode(int vis, int transientFlag, int translucentFlag) {
+        int lightsOutTransparent = View.SYSTEM_UI_FLAG_LOW_PROFILE | View.SYSTEM_UI_TRANSPARENT;
         return (vis & transientFlag) != 0 ? MODE_SEMI_TRANSPARENT
                 : (vis & translucentFlag) != 0 ? MODE_TRANSLUCENT
+                : (vis & lightsOutTransparent) == lightsOutTransparent ? MODE_LIGHTS_OUT_TRANSPARENT
                 : (vis & View.SYSTEM_UI_TRANSPARENT) != 0 ? MODE_TRANSPARENT
                 : (vis & View.SYSTEM_UI_FLAG_LOW_PROFILE) != 0 ? MODE_LIGHTS_OUT
                 : MODE_OPAQUE;
@@ -3597,6 +3600,12 @@
             instantCollapseNotificationPanel();
         }
         updateKeyguardState(staying, false /* fromShadeLocked */);
+
+        // Keyguard state has changed, but QS is not listening anymore. Make sure to update the tile
+        // visibilities so next time we open the panel we know the correct height already.
+        if (mQSPanel != null) {
+            mQSPanel.refreshAllTiles();
+        }
         return staying;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java
index 8520f40..fb1addf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java
@@ -57,19 +57,19 @@
     }
 
     private float getNonBatteryClockAlphaFor(int mode) {
-        return mode == MODE_LIGHTS_OUT ? ICON_ALPHA_WHEN_LIGHTS_OUT_NON_BATTERY_CLOCK
+        return isLightsOut(mode) ? ICON_ALPHA_WHEN_LIGHTS_OUT_NON_BATTERY_CLOCK
                 : !isOpaque(mode) ? ICON_ALPHA_WHEN_NOT_OPAQUE
                 : mIconAlphaWhenOpaque;
     }
 
     private float getBatteryClockAlpha(int mode) {
-        return mode == MODE_LIGHTS_OUT ? ICON_ALPHA_WHEN_LIGHTS_OUT_BATTERY_CLOCK
+        return isLightsOut(mode) ? ICON_ALPHA_WHEN_LIGHTS_OUT_BATTERY_CLOCK
                 : getNonBatteryClockAlphaFor(mode);
     }
 
     private boolean isOpaque(int mode) {
         return !(mode == MODE_SEMI_TRANSPARENT || mode == MODE_TRANSLUCENT
-                || mode == MODE_TRANSPARENT);
+                || mode == MODE_TRANSPARENT || mode == MODE_LIGHTS_OUT_TRANSPARENT);
     }
 
     @Override
@@ -94,7 +94,7 @@
                     animateTransitionTo(mBattery, newAlphaBC),
                     animateTransitionTo(mClock, newAlphaBC)
                     );
-            if (mode == MODE_LIGHTS_OUT) {
+            if (isLightsOut(mode)) {
                 anims.setDuration(LIGHTS_OUT_DURATION);
             }
             anims.start();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
index a4db46a..45a1386 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
@@ -21,6 +21,7 @@
 import android.content.res.Resources;
 import android.database.ContentObserver;
 import android.net.Uri;
+import android.os.Process;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Looper;
@@ -108,7 +109,8 @@
         mKeyguard = keyguard;
         mSecurity = security;
 
-        final HandlerThread ht = new HandlerThread(QSTileHost.class.getSimpleName());
+        final HandlerThread ht = new HandlerThread(QSTileHost.class.getSimpleName(),
+                Process.THREAD_PRIORITY_BACKGROUND);
         ht.start();
         mLooper = ht.getLooper();
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 87ce565..d543cff 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -2272,6 +2272,10 @@
         return height;
     }
 
+    public int getEmptyShadeViewHeight() {
+        return mEmptyShadeView.getHeight();
+    }
+
     public float getBottomMostNotificationBottom() {
         final int count = getChildCount();
         float max = 0;
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index b708c3f..11ba8e8 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -18,49 +18,38 @@
 
 import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
-import android.content.ContentValues;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.PackageManager;
 import android.content.pm.UserInfo;
 
+import static android.Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE;
 import static android.content.Context.USER_SERVICE;
 import static android.Manifest.permission.READ_PROFILE;
-import android.database.Cursor;
+
 import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteOpenHelper;
-import android.database.sqlite.SQLiteStatement;
 import android.os.Binder;
-import android.os.Environment;
 import android.os.IBinder;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.storage.IMountService;
 import android.os.ServiceManager;
-import android.os.storage.StorageManager;
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
 import android.provider.Settings.Secure;
 import android.provider.Settings.SettingNotFoundException;
-import android.security.KeyChain;
-import android.security.KeyChain.KeyChainConnection;
 import android.security.KeyStore;
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.Slog;
 
-import com.android.internal.os.BackgroundThread;
 import com.android.internal.widget.ILockSettings;
 import com.android.internal.widget.ILockSettingsObserver;
 import com.android.internal.widget.LockPatternUtils;
 
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.RandomAccessFile;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -73,27 +62,17 @@
  */
 public class LockSettingsService extends ILockSettings.Stub {
 
-    private static final String PERMISSION = "android.permission.ACCESS_KEYGUARD_SECURE_STORAGE";
+    private static final String PERMISSION = ACCESS_KEYGUARD_SECURE_STORAGE;
 
     private static final String SYSTEM_DEBUGGABLE = "ro.debuggable";
 
-    private final DatabaseHelper mOpenHelper;
+
     private static final String TAG = "LockSettingsService";
 
-    private static final String TABLE = "locksettings";
-    private static final String COLUMN_KEY = "name";
-    private static final String COLUMN_USERID = "user";
-    private static final String COLUMN_VALUE = "value";
-
-    private static final String[] COLUMNS_FOR_QUERY = {
-        COLUMN_VALUE
-    };
-
-    private static final String SYSTEM_DIRECTORY = "/system/";
-    private static final String LOCK_PATTERN_FILE = "gesture.key";
-    private static final String LOCK_PASSWORD_FILE = "password.key";
-
     private final Context mContext;
+
+    private final LockSettingsStorage mStorage;
+
     private LockPatternUtils mLockPatternUtils;
     private boolean mFirstCallToVold;
 
@@ -102,7 +81,6 @@
     public LockSettingsService(Context context) {
         mContext = context;
         // Open the database
-        mOpenHelper = new DatabaseHelper(mContext);
 
         mLockPatternUtils = new LockPatternUtils(context);
         mFirstCallToVold = true;
@@ -110,6 +88,18 @@
         IntentFilter filter = new IntentFilter();
         filter.addAction(Intent.ACTION_USER_ADDED);
         mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null);
+
+        mStorage = new LockSettingsStorage(context, new LockSettingsStorage.Callback() {
+            @Override
+            public void initialize(SQLiteDatabase db) {
+                // Get the lockscreen default from a system property, if available
+                boolean lockScreenDisable = SystemProperties.getBoolean(
+                        "ro.lockscreen.disable.default", false);
+                if (lockScreenDisable) {
+                    mStorage.writeKeyValue(db, LockPatternUtils.DISABLE_LOCKSCREEN_KEY, "1", 0);
+                }
+            }
+        });
     }
 
     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@@ -220,29 +210,31 @@
     @Override
     public void setBoolean(String key, boolean value, int userId) throws RemoteException {
         checkWritePermission(userId);
-
-        writeToDb(key, value ? "1" : "0", userId);
+        setStringUnchecked(key, userId, value ? "1" : "0");
     }
 
     @Override
     public void setLong(String key, long value, int userId) throws RemoteException {
         checkWritePermission(userId);
-
-        writeToDb(key, Long.toString(value), userId);
+        setStringUnchecked(key, userId, Long.toString(value));
     }
 
     @Override
     public void setString(String key, String value, int userId) throws RemoteException {
         checkWritePermission(userId);
+        setStringUnchecked(key, userId, value);
+    }
 
-        writeToDb(key, value, userId);
+    private void setStringUnchecked(String key, int userId, String value) {
+        mStorage.writeKeyValue(key, value, userId);
+        notifyObservers(key, userId);
     }
 
     @Override
     public boolean getBoolean(String key, boolean defaultValue, int userId) throws RemoteException {
         checkReadPermission(key, userId);
 
-        String value = readFromDb(key, null, userId);
+        String value = mStorage.readKeyValue(key, null, userId);
         return TextUtils.isEmpty(value) ?
                 defaultValue : (value.equals("1") || value.equals("true"));
     }
@@ -251,7 +243,7 @@
     public long getLong(String key, long defaultValue, int userId) throws RemoteException {
         checkReadPermission(key, userId);
 
-        String value = readFromDb(key, null, userId);
+        String value = mStorage.readKeyValue(key, null, userId);
         return TextUtils.isEmpty(value) ? defaultValue : Long.parseLong(value);
     }
 
@@ -259,7 +251,7 @@
     public String getString(String key, String defaultValue, int userId) throws RemoteException {
         checkReadPermission(key, userId);
 
-        return readFromDb(key, defaultValue, userId);
+        return mStorage.readKeyValue(key, defaultValue, userId);
     }
 
     @Override
@@ -308,57 +300,18 @@
         }
     }
 
-    private int getUserParentOrSelfId(int userId) {
-        if (userId != 0) {
-            final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
-            final UserInfo pi = um.getProfileParent(userId);
-            if (pi != null) {
-                return pi.id;
-            }
-        }
-        return userId;
-    }
-
-    private String getLockPatternFilename(int userId) {
-        String dataSystemDirectory =
-                android.os.Environment.getDataDirectory().getAbsolutePath() +
-                SYSTEM_DIRECTORY;
-        userId = getUserParentOrSelfId(userId);
-        if (userId == 0) {
-            // Leave it in the same place for user 0
-            return dataSystemDirectory + LOCK_PATTERN_FILE;
-        } else {
-            return  new File(Environment.getUserSystemDirectory(userId), LOCK_PATTERN_FILE)
-                    .getAbsolutePath();
-        }
-    }
-
-    private String getLockPasswordFilename(int userId) {
-        userId = getUserParentOrSelfId(userId);
-        String dataSystemDirectory =
-                android.os.Environment.getDataDirectory().getAbsolutePath() +
-                SYSTEM_DIRECTORY;
-        if (userId == 0) {
-            // Leave it in the same place for user 0
-            return dataSystemDirectory + LOCK_PASSWORD_FILE;
-        } else {
-            return new File(Environment.getUserSystemDirectory(userId), LOCK_PASSWORD_FILE)
-                    .getAbsolutePath();
-        }
-    }
-
     @Override
     public boolean havePassword(int userId) throws RemoteException {
         // Do we need a permissions check here?
 
-        return new File(getLockPasswordFilename(userId)).length() > 0;
+        return mStorage.hasPassword(userId);
     }
 
     @Override
     public boolean havePattern(int userId) throws RemoteException {
         // Do we need a permissions check here?
 
-        return new File(getLockPatternFilename(userId)).length() > 0;
+        return mStorage.hasPattern(userId);
     }
 
     private void maybeUpdateKeystore(String password, int userHandle) {
@@ -394,7 +347,7 @@
 
         final byte[] hash = LockPatternUtils.patternToHash(
                 LockPatternUtils.stringToPattern(pattern));
-        writeFile(getLockPatternFilename(userId), hash);
+        mStorage.writePatternHash(hash, userId);
     }
 
     @Override
@@ -403,68 +356,46 @@
 
         maybeUpdateKeystore(password, userId);
 
-        writeFile(getLockPasswordFilename(userId),
-                mLockPatternUtils.passwordToHash(password, userId));
+        mStorage.writePasswordHash(mLockPatternUtils.passwordToHash(password, userId), userId);
     }
 
     @Override
     public boolean checkPattern(String pattern, int userId) throws RemoteException {
         checkPasswordReadPermission(userId);
-        try {
-            // Read all the bytes from the file
-            RandomAccessFile raf = new RandomAccessFile(getLockPatternFilename(userId), "r");
-            final byte[] stored = new byte[(int) raf.length()];
-            int got = raf.read(stored, 0, stored.length);
-            raf.close();
-            if (got <= 0) {
-                return true;
-            }
-            // Compare the hash from the file with the entered pattern's hash
-            final byte[] hash = LockPatternUtils.patternToHash(
-                    LockPatternUtils.stringToPattern(pattern));
-            final boolean matched = Arrays.equals(stored, hash);
-            if (matched && !TextUtils.isEmpty(pattern)) {
-                maybeUpdateKeystore(pattern, userId);
-            }
-            return matched;
-        } catch (FileNotFoundException fnfe) {
-            Slog.e(TAG, "Cannot read file " + fnfe);
-        } catch (IOException ioe) {
-            Slog.e(TAG, "Cannot read file " + ioe);
+        byte[] hash = LockPatternUtils.patternToHash(LockPatternUtils.stringToPattern(pattern));
+        byte[] storedHash = mStorage.readPatternHash(userId);
+
+        if (storedHash == null) {
+            return true;
         }
-        return true;
+
+        boolean matched = Arrays.equals(hash, storedHash);
+        if (matched && !TextUtils.isEmpty(pattern)) {
+            maybeUpdateKeystore(pattern, userId);
+        }
+        return matched;
     }
 
     @Override
     public boolean checkPassword(String password, int userId) throws RemoteException {
         checkPasswordReadPermission(userId);
 
-        try {
-            // Read all the bytes from the file
-            RandomAccessFile raf = new RandomAccessFile(getLockPasswordFilename(userId), "r");
-            final byte[] stored = new byte[(int) raf.length()];
-            int got = raf.read(stored, 0, stored.length);
-            raf.close();
-            if (got <= 0) {
-                return true;
-            }
-            // Compare the hash from the file with the entered password's hash
-            final byte[] hash = mLockPatternUtils.passwordToHash(password, userId);
-            final boolean matched = Arrays.equals(stored, hash);
-            if (matched && !TextUtils.isEmpty(password)) {
-                maybeUpdateKeystore(password, userId);
-            }
-            return matched;
-        } catch (FileNotFoundException fnfe) {
-            Slog.e(TAG, "Cannot read file " + fnfe);
-        } catch (IOException ioe) {
-            Slog.e(TAG, "Cannot read file " + ioe);
+        byte[] hash = mLockPatternUtils.passwordToHash(password, userId);
+        byte[] storedHash = mStorage.readPasswordHash(userId);
+
+        if (storedHash == null) {
+            return true;
         }
-        return true;
+
+        boolean matched = Arrays.equals(hash, storedHash);
+        if (matched && !TextUtils.isEmpty(password)) {
+            maybeUpdateKeystore(password, userId);
+        }
+        return matched;
     }
 
     @Override
-        public boolean checkVoldPassword(int userId) throws RemoteException {
+    public boolean checkVoldPassword(int userId) throws RemoteException {
         if (!mFirstCallToVold) {
             return false;
         }
@@ -512,166 +443,14 @@
     public void removeUser(int userId) {
         checkWritePermission(userId);
 
-        SQLiteDatabase db = mOpenHelper.getWritableDatabase();
-        try {
-            final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
-            final UserInfo parentInfo = um.getProfileParent(userId);
-            if (parentInfo == null) {
-                // This user owns its lock settings files - safe to delete them
-                File file = new File(getLockPasswordFilename(userId));
-                if (file.exists()) {
-                    file.delete();
-                }
-                file = new File(getLockPatternFilename(userId));
-                if (file.exists()) {
-                    file.delete();
-                }
-            }
-
-            db.beginTransaction();
-            db.delete(TABLE, COLUMN_USERID + "='" + userId + "'", null);
-            db.setTransactionSuccessful();
-        } finally {
-            db.endTransaction();
-        }
+        mStorage.removeUser(userId);
+        notifyObservers(null /* key */, userId);
 
         final KeyStore ks = KeyStore.getInstance();
         final int userUid = UserHandle.getUid(userId, Process.SYSTEM_UID);
         ks.resetUid(userUid);
     }
 
-    private void writeFile(String name, byte[] hash) {
-        try {
-            // Write the hash to file
-            RandomAccessFile raf = new RandomAccessFile(name, "rw");
-            // Truncate the file if pattern is null, to clear the lock
-            if (hash == null || hash.length == 0) {
-                raf.setLength(0);
-            } else {
-                raf.write(hash, 0, hash.length);
-            }
-            raf.close();
-        } catch (IOException ioe) {
-            Slog.e(TAG, "Error writing to file " + ioe);
-        }
-    }
-
-    private void writeToDb(String key, String value, int userId) {
-        writeToDb(mOpenHelper.getWritableDatabase(), key, value, userId);
-        notifyObservers(key, userId);
-    }
-
-    private void writeToDb(SQLiteDatabase db, String key, String value, int userId) {
-        ContentValues cv = new ContentValues();
-        cv.put(COLUMN_KEY, key);
-        cv.put(COLUMN_USERID, userId);
-        cv.put(COLUMN_VALUE, value);
-
-        db.beginTransaction();
-        try {
-            db.delete(TABLE, COLUMN_KEY + "=? AND " + COLUMN_USERID + "=?",
-                    new String[] {key, Integer.toString(userId)});
-            db.insert(TABLE, null, cv);
-            db.setTransactionSuccessful();
-        } finally {
-            db.endTransaction();
-        }
-    }
-
-    private String readFromDb(String key, String defaultValue, int userId) {
-        Cursor cursor;
-        String result = defaultValue;
-        SQLiteDatabase db = mOpenHelper.getReadableDatabase();
-        if ((cursor = db.query(TABLE, COLUMNS_FOR_QUERY,
-                COLUMN_USERID + "=? AND " + COLUMN_KEY + "=?",
-                new String[] { Integer.toString(userId), key },
-                null, null, null)) != null) {
-            if (cursor.moveToFirst()) {
-                result = cursor.getString(0);
-            }
-            cursor.close();
-        }
-        return result;
-    }
-
-    class DatabaseHelper extends SQLiteOpenHelper {
-        private static final String TAG = "LockSettingsDB";
-        private static final String DATABASE_NAME = "locksettings.db";
-
-        private static final int DATABASE_VERSION = 2;
-
-        public DatabaseHelper(Context context) {
-            super(context, DATABASE_NAME, null, DATABASE_VERSION);
-            setWriteAheadLoggingEnabled(true);
-        }
-
-        private void createTable(SQLiteDatabase db) {
-            db.execSQL("CREATE TABLE " + TABLE + " (" +
-                    "_id INTEGER PRIMARY KEY AUTOINCREMENT," +
-                    COLUMN_KEY + " TEXT," +
-                    COLUMN_USERID + " INTEGER," +
-                    COLUMN_VALUE + " TEXT" +
-                    ");");
-        }
-
-        @Override
-        public void onCreate(SQLiteDatabase db) {
-            createTable(db);
-            initializeDefaults(db);
-        }
-
-        private void initializeDefaults(SQLiteDatabase db) {
-            // Get the lockscreen default from a system property, if available
-            boolean lockScreenDisable = SystemProperties.getBoolean("ro.lockscreen.disable.default",
-                    false);
-            if (lockScreenDisable) {
-                writeToDb(db, LockPatternUtils.DISABLE_LOCKSCREEN_KEY, "1", 0);
-            }
-        }
-
-        @Override
-        public void onUpgrade(SQLiteDatabase db, int oldVersion, int currentVersion) {
-            int upgradeVersion = oldVersion;
-            if (upgradeVersion == 1) {
-                // Set the initial value for {@link LockPatternUtils#LOCKSCREEN_WIDGETS_ENABLED}
-                // during upgrade based on whether each user previously had widgets in keyguard.
-                maybeEnableWidgetSettingForUsers(db);
-                upgradeVersion = 2;
-            }
-
-            if (upgradeVersion != DATABASE_VERSION) {
-                Log.w(TAG, "Failed to upgrade database!");
-            }
-        }
-
-        private void maybeEnableWidgetSettingForUsers(SQLiteDatabase db) {
-            final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
-            final ContentResolver cr = mContext.getContentResolver();
-            final List<UserInfo> users = um.getUsers();
-            for (int i = 0; i < users.size(); i++) {
-                final int userId = users.get(i).id;
-                final boolean enabled = mLockPatternUtils.hasWidgetsEnabledInKeyguard(userId);
-                Log.v(TAG, "Widget upgrade uid=" + userId + ", enabled="
-                        + enabled + ", w[]=" + mLockPatternUtils.getAppWidgets());
-                loadSetting(db, LockPatternUtils.LOCKSCREEN_WIDGETS_ENABLED, userId, enabled);
-            }
-        }
-
-        private void loadSetting(SQLiteDatabase db, String key, int userId, boolean value) {
-            SQLiteStatement stmt = null;
-            try {
-                stmt = db.compileStatement(
-                        "INSERT OR REPLACE INTO locksettings(name,user,value) VALUES(?,?,?);");
-                stmt.bindString(1, key);
-                stmt.bindLong(2, userId);
-                stmt.bindLong(3, value ? 1 : 0);
-                stmt.execute();
-            } finally {
-                if (stmt != null) stmt.close();
-            }
-        }
-    }
-
     private static final String[] VALID_SETTINGS = new String[] {
         LockPatternUtils.LOCKOUT_PERMANENT_KEY,
         LockPatternUtils.LOCKOUT_ATTEMPT_DEADLINE,
diff --git a/services/core/java/com/android/server/LockSettingsStorage.java b/services/core/java/com/android/server/LockSettingsStorage.java
new file mode 100644
index 0000000..acbf8ef
--- /dev/null
+++ b/services/core/java/com/android/server/LockSettingsStorage.java
@@ -0,0 +1,307 @@
+/*
+ * 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 com.android.server;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.pm.UserInfo;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.os.Environment;
+import android.os.UserManager;
+import android.util.ArrayMap;
+import android.util.Log;
+import android.util.Slog;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+
+import static android.content.Context.USER_SERVICE;
+
+/**
+ * Storage for the lock settings service.
+ */
+class LockSettingsStorage {
+
+    private static final String TAG = "LockSettingsStorage";
+    private static final String TABLE = "locksettings";
+
+    private static final String COLUMN_KEY = "name";
+    private static final String COLUMN_USERID = "user";
+    private static final String COLUMN_VALUE = "value";
+
+    private static final String[] COLUMNS_FOR_QUERY = {
+            COLUMN_VALUE
+    };
+
+    private static final String SYSTEM_DIRECTORY = "/system/";
+    private static final String LOCK_PATTERN_FILE = "gesture.key";
+    private static final String LOCK_PASSWORD_FILE = "password.key";
+
+    private final DatabaseHelper mOpenHelper;
+    private final Context mContext;
+    private final Object mFileWriteLock = new Object();
+
+    LockSettingsStorage(Context context, Callback callback) {
+        mContext = context;
+        mOpenHelper = new DatabaseHelper(context, callback);
+    }
+
+    void writeKeyValue(String key, String value, int userId) {
+        writeKeyValue(mOpenHelper.getWritableDatabase(), key, value, userId);
+    }
+
+    void writeKeyValue(SQLiteDatabase db, String key, String value, int userId) {
+        ContentValues cv = new ContentValues();
+        cv.put(COLUMN_KEY, key);
+        cv.put(COLUMN_USERID, userId);
+        cv.put(COLUMN_VALUE, value);
+
+        db.beginTransaction();
+        try {
+            db.delete(TABLE, COLUMN_KEY + "=? AND " + COLUMN_USERID + "=?",
+                    new String[] {key, Integer.toString(userId)});
+            db.insert(TABLE, null, cv);
+            db.setTransactionSuccessful();
+        } finally {
+            db.endTransaction();
+        }
+
+    }
+
+    String readKeyValue(String key, String defaultValue, int userId) {
+        Cursor cursor;
+        String result = defaultValue;
+        SQLiteDatabase db = mOpenHelper.getReadableDatabase();
+        if ((cursor = db.query(TABLE, COLUMNS_FOR_QUERY,
+                COLUMN_USERID + "=? AND " + COLUMN_KEY + "=?",
+                new String[] { Integer.toString(userId), key },
+                null, null, null)) != null) {
+            if (cursor.moveToFirst()) {
+                result = cursor.getString(0);
+            }
+            cursor.close();
+        }
+        return result;
+    }
+
+    byte[] readPasswordHash(int userId) {
+        final byte[] stored = readFile(getLockPasswordFilename(userId), userId);
+        if (stored != null && stored.length > 0) {
+            return stored;
+        }
+        return null;
+    }
+
+    byte[] readPatternHash(int userId) {
+        final byte[] stored = readFile(getLockPatternFilename(userId), userId);
+        if (stored != null && stored.length > 0) {
+            return stored;
+        }
+        return null;
+    }
+
+    boolean hasPassword(int userId) {
+        return hasFile(getLockPasswordFilename(userId), userId);
+    }
+
+    boolean hasPattern(int userId) {
+        return hasFile(getLockPatternFilename(userId), userId);
+    }
+
+    private boolean hasFile(String name, int userId) {
+        byte[] contents = readFile(name, userId);
+        return contents != null && contents.length > 0;
+    }
+
+    private byte[] readFile(String name, int userId) {
+        RandomAccessFile raf = null;
+        byte[] stored = null;
+        try {
+            raf = new RandomAccessFile(name, "r");
+            stored = new byte[(int) raf.length()];
+            raf.readFully(stored, 0, stored.length);
+            raf.close();
+        } catch (IOException e) {
+            Slog.e(TAG, "Cannot read file " + e);
+        } finally {
+            if (raf != null) {
+                try {
+                    raf.close();
+                } catch (IOException e) {
+                    Slog.e(TAG, "Error closing file " + e);
+                }
+            }
+        }
+        return stored;
+    }
+
+    private void writeFile(String name, byte[] hash, int userId) {
+        synchronized (mFileWriteLock) {
+            RandomAccessFile raf = null;
+            try {
+                // Write the hash to file
+                raf = new RandomAccessFile(name, "rw");
+                // Truncate the file if pattern is null, to clear the lock
+                if (hash == null || hash.length == 0) {
+                    raf.setLength(0);
+                } else {
+                    raf.write(hash, 0, hash.length);
+                }
+                raf.close();
+            } catch (IOException e) {
+                Slog.e(TAG, "Error writing to file " + e);
+            } finally {
+                if (raf != null) {
+                    try {
+                        raf.close();
+                    } catch (IOException e) {
+                        Slog.e(TAG, "Error closing file " + e);
+                    }
+                }
+            }
+        }
+    }
+
+    public void writePatternHash(byte[] hash, int userId) {
+        writeFile(getLockPatternFilename(userId), hash, userId);
+    }
+
+    public void writePasswordHash(byte[] hash, int userId) {
+        writeFile(getLockPasswordFilename(userId), hash, userId);
+    }
+
+
+    private String getLockPatternFilename(int userId) {
+        String dataSystemDirectory =
+                android.os.Environment.getDataDirectory().getAbsolutePath() +
+                        SYSTEM_DIRECTORY;
+        userId = getUserParentOrSelfId(userId);
+        if (userId == 0) {
+            // Leave it in the same place for user 0
+            return dataSystemDirectory + LOCK_PATTERN_FILE;
+        } else {
+            return new File(Environment.getUserSystemDirectory(userId), LOCK_PATTERN_FILE)
+                    .getAbsolutePath();
+        }
+    }
+
+    private String getLockPasswordFilename(int userId) {
+        userId = getUserParentOrSelfId(userId);
+        String dataSystemDirectory =
+                android.os.Environment.getDataDirectory().getAbsolutePath() +
+                        SYSTEM_DIRECTORY;
+        if (userId == 0) {
+            // Leave it in the same place for user 0
+            return dataSystemDirectory + LOCK_PASSWORD_FILE;
+        } else {
+            return new File(Environment.getUserSystemDirectory(userId), LOCK_PASSWORD_FILE)
+                    .getAbsolutePath();
+        }
+    }
+
+    private int getUserParentOrSelfId(int userId) {
+        if (userId != 0) {
+            final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
+            final UserInfo pi = um.getProfileParent(userId);
+            if (pi != null) {
+                return pi.id;
+            }
+        }
+        return userId;
+    }
+
+
+    public void removeUser(int userId) {
+        SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+
+        final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
+        final UserInfo parentInfo = um.getProfileParent(userId);
+
+        synchronized (mFileWriteLock) {
+            if (parentInfo == null) {
+                // This user owns its lock settings files - safe to delete them
+                File file = new File(getLockPasswordFilename(userId));
+                if (file.exists()) {
+                    file.delete();
+                }
+                file = new File(getLockPatternFilename(userId));
+                if (file.exists()) {
+                    file.delete();
+                }
+            }
+        }
+
+        try {
+            db.beginTransaction();
+            db.delete(TABLE, COLUMN_USERID + "='" + userId + "'", null);
+            db.setTransactionSuccessful();
+        } finally {
+            db.endTransaction();
+        }
+    }
+
+
+    interface Callback {
+        void initialize(SQLiteDatabase db);
+    }
+
+    class DatabaseHelper extends SQLiteOpenHelper {
+        private static final String TAG = "LockSettingsDB";
+        private static final String DATABASE_NAME = "locksettings.db";
+
+        private static final int DATABASE_VERSION = 2;
+
+        private final Callback mCallback;
+
+        public DatabaseHelper(Context context, Callback callback) {
+            super(context, DATABASE_NAME, null, DATABASE_VERSION);
+            setWriteAheadLoggingEnabled(true);
+            mCallback = callback;
+        }
+
+        private void createTable(SQLiteDatabase db) {
+            db.execSQL("CREATE TABLE " + TABLE + " (" +
+                    "_id INTEGER PRIMARY KEY AUTOINCREMENT," +
+                    COLUMN_KEY + " TEXT," +
+                    COLUMN_USERID + " INTEGER," +
+                    COLUMN_VALUE + " TEXT" +
+                    ");");
+        }
+
+        @Override
+        public void onCreate(SQLiteDatabase db) {
+            createTable(db);
+            mCallback.initialize(db);
+        }
+
+        @Override
+        public void onUpgrade(SQLiteDatabase db, int oldVersion, int currentVersion) {
+            int upgradeVersion = oldVersion;
+            if (upgradeVersion == 1) {
+                // Previously migrated lock screen widget settings. Now defunct.
+                upgradeVersion = 2;
+            }
+
+            if (upgradeVersion != DATABASE_VERSION) {
+                Log.w(TAG, "Failed to upgrade database!");
+            }
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 9179cc4..91e2df0 100755
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1836,8 +1836,8 @@
 
                     ComponentName cn = tr.intent.getComponent();
                     if (cn != null && cn.getPackageName().equals(packageName)) {
-                        // If the package name matches, remove the task and kill the process
-                        removeTaskByIdLocked(tr.taskId, ActivityManager.REMOVE_TASK_KILL_PROCESS);
+                        // If the package name matches, remove the task
+                        removeTaskByIdLocked(tr.taskId, true);
                     }
                 }
             }
@@ -1891,9 +1891,7 @@
             // Prune all the tasks with removed components from the list of recent tasks
             synchronized (ActivityManagerService.this) {
                 for (int i = tasksToRemove.size() - 1; i >= 0; i--) {
-                    // Remove the task but don't kill the process (since other components in that
-                    // package may still be running and in the background)
-                    removeTaskByIdLocked(tasksToRemove.get(i), 0);
+                    removeTaskByIdLocked(tasksToRemove.get(i), false);
                 }
             }
         }
@@ -4313,9 +4311,9 @@
                 boolean res;
                 if (finishTask && r == rootR) {
                     // If requested, remove the task that is associated to this activity only if it
-                    // was the root activity in the task.  The result code and data is ignored because
-                    // we don't support returning them across task boundaries.
-                    res = removeTaskByIdLocked(tr.taskId, 0);
+                    // was the root activity in the task. The result code and data is ignored
+                    // because we don't support returning them across task boundaries.
+                    res = removeTaskByIdLocked(tr.taskId, false);
                 } else {
                     res = tr.stack.requestFinishActivityLocked(token, resultCode,
                             resultData, "app-request", true);
@@ -5142,7 +5140,7 @@
                             tr.getBaseIntent().getComponent().getPackageName();
                     if (tr.userId != userId) continue;
                     if (!taskPackageName.equals(packageName)) continue;
-                    removeTaskByIdLocked(tr.taskId, 0);
+                    removeTaskByIdLocked(tr.taskId, false);
                 }
             }
 
@@ -8287,52 +8285,65 @@
         return mTaskPersister.getTaskDescriptionIcon(filename);
     }
 
-    private void cleanUpRemovedTaskLocked(TaskRecord tr, int flags) {
+    private void cleanUpRemovedTaskLocked(TaskRecord tr, boolean killProcess) {
         mRecentTasks.remove(tr);
         tr.removedFromRecents(mTaskPersister);
-        final boolean killProcesses = (flags&ActivityManager.REMOVE_TASK_KILL_PROCESS) != 0;
-        Intent baseIntent = new Intent(
-                tr.intent != null ? tr.intent : tr.affinityIntent);
-        ComponentName component = baseIntent.getComponent();
+        ComponentName component = tr.getBaseIntent().getComponent();
         if (component == null) {
-            Slog.w(TAG, "Now component for base intent of task: " + tr);
+            Slog.w(TAG, "No component for base intent of task: " + tr);
             return;
         }
 
-        // Find any running services associated with this app.
-        mServices.cleanUpRemovedTaskLocked(tr, component, baseIntent);
+        if (!killProcess) {
+            return;
+        }
 
-        if (killProcesses) {
-            // Find any running processes associated with this app.
-            final String pkg = component.getPackageName();
-            ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
-            ArrayMap<String, SparseArray<ProcessRecord>> pmap = mProcessNames.getMap();
-            for (int i=0; i<pmap.size(); i++) {
-                SparseArray<ProcessRecord> uids = pmap.valueAt(i);
-                for (int j=0; j<uids.size(); j++) {
-                    ProcessRecord proc = uids.valueAt(j);
-                    if (proc.userId != tr.userId) {
-                        continue;
-                    }
-                    if (!proc.pkgList.containsKey(pkg)) {
-                        continue;
-                    }
-                    procs.add(proc);
+        // Determine if the process(es) for this task should be killed.
+        final String pkg = component.getPackageName();
+        ArrayList<ProcessRecord> procsToKill = new ArrayList<ProcessRecord>();
+        ArrayMap<String, SparseArray<ProcessRecord>> pmap = mProcessNames.getMap();
+        for (int i = 0; i < pmap.size(); i++) {
+
+            SparseArray<ProcessRecord> uids = pmap.valueAt(i);
+            for (int j = 0; j < uids.size(); j++) {
+                ProcessRecord proc = uids.valueAt(j);
+                if (proc.userId != tr.userId) {
+                    // Don't kill process for a different user.
+                    continue;
                 }
-            }
-
-            // Kill the running processes.
-            for (int i=0; i<procs.size(); i++) {
-                ProcessRecord pr = procs.get(i);
-                if (pr == mHomeProcess) {
+                if (proc == mHomeProcess) {
                     // Don't kill the home process along with tasks from the same package.
                     continue;
                 }
-                if (pr.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {
-                    pr.kill("remove task", true);
-                } else {
-                    pr.waitingToKill = "remove task";
+                if (!proc.pkgList.containsKey(pkg)) {
+                    // Don't kill process that is not associated with this task.
+                    continue;
                 }
+
+                for (int k = 0; k < proc.activities.size(); k++) {
+                    TaskRecord otherTask = proc.activities.get(k).task;
+                    if (tr.taskId != otherTask.taskId && otherTask.inRecents) {
+                        // Don't kill process(es) that has an activity in a different task that is
+                        // also in recents.
+                        return;
+                    }
+                }
+
+                // Add process to kill list.
+                procsToKill.add(proc);
+            }
+        }
+
+        // Find any running services associated with this app and stop if needed.
+        mServices.cleanUpRemovedTaskLocked(tr, component, new Intent(tr.getBaseIntent()));
+
+        // Kill the running processes.
+        for (int i = 0; i < procsToKill.size(); i++) {
+            ProcessRecord pr = procsToKill.get(i);
+            if (pr.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {
+                pr.kill("remove task", true);
+            } else {
+                pr.waitingToKill = "remove task";
             }
         }
     }
@@ -8341,15 +8352,14 @@
      * Removes the task with the specified task id.
      *
      * @param taskId Identifier of the task to be removed.
-     * @param flags Additional operational flags.  May be 0 or
-     * {@link ActivityManager#REMOVE_TASK_KILL_PROCESS}.
+     * @param killProcess Kill any process associated with the task if possible.
      * @return Returns true if the given task was found and removed.
      */
-    private boolean removeTaskByIdLocked(int taskId, int flags) {
+    private boolean removeTaskByIdLocked(int taskId, boolean killProcess) {
         TaskRecord tr = recentTaskForIdLocked(taskId);
         if (tr != null) {
             tr.removeTaskActivitiesLocked();
-            cleanUpRemovedTaskLocked(tr, flags);
+            cleanUpRemovedTaskLocked(tr, killProcess);
             if (tr.isPersistable) {
                 notifyTaskPersisterLocked(null, true);
             }
@@ -8359,19 +8369,19 @@
     }
 
     @Override
-    public boolean removeTask(int taskId, int flags) {
+    public boolean removeTask(int taskId) {
         synchronized (this) {
             enforceCallingPermission(android.Manifest.permission.REMOVE_TASKS,
                     "removeTask()");
             long ident = Binder.clearCallingIdentity();
             try {
-                return removeTaskByIdLocked(taskId, flags);
+                return removeTaskByIdLocked(taskId, true);
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
         }
     }
-    
+
     /**
      * TODO: Add mController hook
      */
@@ -19167,16 +19177,9 @@
             synchronized (ActivityManagerService.this) {
                 long origId = Binder.clearCallingIdentity();
                 try {
-                    TaskRecord tr = recentTaskForIdLocked(mTaskId);
-                    if (tr == null) {
+                    if (!removeTaskByIdLocked(mTaskId, false)) {
                         throw new IllegalArgumentException("Unable to find task ID " + mTaskId);
                     }
-                    // Only kill the process if we are not a new document
-                    int flags = tr.getBaseIntent().getFlags();
-                    boolean isDocument = (flags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) ==
-                            Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
-                    removeTaskByIdLocked(mTaskId,
-                            !isDocument ? ActivityManager.REMOVE_TASK_KILL_PROCESS : 0);
                 } finally {
                     Binder.restoreCallingIdentity(origId);
                 }
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index e1b8278..b61bd8a 100755
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -835,7 +835,7 @@
         prev.task.touchActiveTime();
         clearLaunchTime(prev);
         final ActivityRecord next = mStackSupervisor.topRunningActivityLocked();
-        if (mService.mHasRecents && (next == null || next.noDisplay || next.task != prev.task)) {
+        if (mService.mHasRecents && (next == null || next.noDisplay || next.task != prev.task || uiSleeping)) {
             prev.updateThumbnail(screenshotActivities(prev), null);
         }
         stopFullyDrawnTraceIfNeeded();
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 5b22255..843a0cb 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -235,22 +235,16 @@
             Slog.i("XXXXXX", "minfree_adj=" + minfree_adj + " minfree_abs=" + minfree_abs);
         }
 
-        // We've now baked in the increase to the basic oom values above, since
-        // they seem to be useful more generally for devices that are tight on
-        // memory than just for 64 bit.  This should probably have some more
-        // tuning done, so not deleting it quite yet...
-        final boolean is64bit = false; //Build.SUPPORTED_64_BIT_ABIS.length > 0;
+        if (Build.SUPPORTED_64_BIT_ABIS.length > 0) {
+            // Increase the high min-free levels for cached processes for 64-bit
+            mOomMinFreeHigh[4] = 225000;
+            mOomMinFreeHigh[5] = 325000;
+        }
 
         for (int i=0; i<mOomAdj.length; i++) {
             int low = mOomMinFreeLow[i];
             int high = mOomMinFreeHigh[i];
             mOomMinFree[i] = (int)(low + ((high-low)*scale));
-            if (is64bit) {
-                // On 64 bit devices, we consume more baseline RAM, because 64 bit is cool!
-                // To avoid being all pagey and stuff, scale up the memory levels to
-                // give us some breathing room.
-                mOomMinFree[i] = (3*mOomMinFree[i])/2;
-            }
         }
 
         if (minfree_abs >= 0) {
diff --git a/services/core/java/com/android/server/connectivity/PermissionMonitor.java b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
index 238402f..debda14 100644
--- a/services/core/java/com/android/server/connectivity/PermissionMonitor.java
+++ b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
@@ -191,8 +191,8 @@
         }
         try {
             if (add) {
-                mNetd.setPermission(CHANGE_NETWORK_STATE, toIntArray(network));
-                mNetd.setPermission(CONNECTIVITY_INTERNAL, toIntArray(system));
+                mNetd.setPermission("NETWORK", toIntArray(network));
+                mNetd.setPermission("SYSTEM", toIntArray(system));
             } else {
                 mNetd.clearPermission(toIntArray(network));
                 mNetd.clearPermission(toIntArray(system));
diff --git a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
index 11da380..098b3ef 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
@@ -119,6 +119,7 @@
                 if (!files.valueAt(start).getBaseFile().getName().endsWith("-c")) {
                     break;
                 }
+                start++;
             }
 
             if (start == fileCount - 1) {
diff --git a/telephony/java/android/telephony/SubInfoRecord.java b/telephony/java/android/telephony/SubInfoRecord.java
index 0966ddb..e08f255 100644
--- a/telephony/java/android/telephony/SubInfoRecord.java
+++ b/telephony/java/android/telephony/SubInfoRecord.java
@@ -222,7 +222,7 @@
             int id = source.readInt();
             String iccId = source.readString();
             int simSlotIndex = source.readInt();
-            String displayName = source.readString();
+            CharSequence displayName = source.readCharSequence();
             int nameSource = source.readInt();
             int color = source.readInt();
             String number = source.readString();
@@ -247,7 +247,7 @@
         dest.writeInt(mId);
         dest.writeString(mIccId);
         dest.writeInt(mSimSlotIndex);
-        dest.writeString(mDisplayName.toString());
+        dest.writeCharSequence(mDisplayName);
         dest.writeInt(mNameSource);
         dest.writeInt(mColor);
         dest.writeString(mNumber.toString());
diff --git a/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java b/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
index 6837d22..94874c8 100644
--- a/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
+++ b/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
@@ -127,7 +127,7 @@
             @Override
             public boolean onLongClick(View v) {
                 if (task.id >= 0 && thumbs != null) {
-                    mAm.removeTask(task.id, ActivityManager.REMOVE_TASK_KILL_PROCESS);
+                    mAm.removeTask(task.id);
                     buildUi();
                     return true;
                 }