Merge "Abort accessibility node prefetch if parent node is null" into lmp-mr1-dev
diff --git a/api/current.txt b/api/current.txt
index 6851bbf..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
@@ -28391,6 +28397,7 @@
     method public void addNewIncomingCall(android.telecom.PhoneAccountHandle, android.os.Bundle);
     method public void cancelMissedCallsNotification();
     method public void clearAccounts();
+    method public android.net.Uri getAdnUriForPhoneAccount(android.telecom.PhoneAccountHandle);
     method public android.telecom.PhoneAccountHandle getConnectionManager();
     method public android.telecom.PhoneAccount getPhoneAccount(android.telecom.PhoneAccountHandle);
     method public java.util.List<android.telecom.PhoneAccountHandle> getPhoneAccountsForPackage();
@@ -28849,26 +28856,20 @@
   }
 
   public class SubInfoRecord implements android.os.Parcelable {
-    ctor public SubInfoRecord();
-    ctor public SubInfoRecord(int, java.lang.String, int, java.lang.String, int, int, java.lang.String, int, int, int[], int, int);
     method public int describeContents();
     method public int getColor();
-    method public android.graphics.drawable.BitmapDrawable getIconDrawable();
-    method public java.lang.String getLabel();
+    method public int getDataRoaming();
+    method public java.lang.CharSequence getDisplayName();
+    method public java.lang.String getIccId();
+    method public android.graphics.drawable.BitmapDrawable getIcon();
+    method public int getMcc();
+    method public int getMnc();
+    method public int getNameSource();
+    method public java.lang.String getNumber();
+    method public int getSimSlotIndex();
+    method public int getSubscriptionId();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.telephony.SubInfoRecord> CREATOR;
-    field public int color;
-    field public int dataRoaming;
-    field public java.lang.String displayName;
-    field public int displayNumberFormat;
-    field public java.lang.String iccId;
-    field public int mcc;
-    field public int mnc;
-    field public int nameSource;
-    field public java.lang.String number;
-    field public int[] simIconRes;
-    field public int slotId;
-    field public int subId;
   }
 
   public class SubscriptionManager implements android.provider.BaseColumns {
@@ -30278,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/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/os/Debug.java b/core/java/android/os/Debug.java
index 084ca30..3f42d25 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -165,7 +165,7 @@
         public int otherSwappedOut;
 
         /** @hide */
-        public static final int NUM_OTHER_STATS = 16;
+        public static final int NUM_OTHER_STATS = 17;
 
         /** @hide */
         public static final int NUM_DVK_STATS = 5;
@@ -296,23 +296,24 @@
                 case 1: return "Stack";
                 case 2: return "Cursor";
                 case 3: return "Ashmem";
-                case 4: return "Other dev";
-                case 5: return ".so mmap";
-                case 6: return ".jar mmap";
-                case 7: return ".apk mmap";
-                case 8: return ".ttf mmap";
-                case 9: return ".dex mmap";
-                case 10: return "code mmap";
-                case 11: return "image mmap";
-                case 12: return "Other mmap";
-                case 13: return "Graphics";
-                case 14: return "GL";
-                case 15: return "Memtrack";
-                case 16: return ".Heap";
-                case 17: return ".LOS";
-                case 18: return ".LinearAlloc";
-                case 19: return ".GC";
-                case 20: return ".JITCache";
+                case 4: return "Gfx driver";
+                case 5: return "Other dev";
+                case 6: return ".so mmap";
+                case 7: return ".jar mmap";
+                case 8: return ".apk mmap";
+                case 9: return ".ttf mmap";
+                case 10: return ".dex mmap";
+                case 11: return ".oat mmap";
+                case 12: return ".art mmap";
+                case 13: return "Other mmap";
+                case 14: return "Graphics";
+                case 15: return "GL";
+                case 16: return "Memtrack";
+                case 17: return ".Heap";
+                case 18: return ".LOS";
+                case 19: return ".LinearAlloc";
+                case 20: return ".GC";
+                case 21: return ".JITCache";
                 default: return "????";
             }
         }
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/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 6450146..e464e77 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -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/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/android/widget/Toolbar.java b/core/java/android/widget/Toolbar.java
index d4d186c..f90d64a 100644
--- a/core/java/android/widget/Toolbar.java
+++ b/core/java/android/widget/Toolbar.java
@@ -1752,6 +1752,17 @@
     }
 
     /**
+     * Accessor to enable LayoutLib to get ActionMenuPresenter directly.
+     */
+    ActionMenuPresenter getOuterActionMenuPresenter() {
+        return mOuterActionMenuPresenter;
+    }
+
+    Context getPopupContext() {
+        return mPopupContext;
+    }
+
+    /**
      * Interface responsible for receiving menu item click events if the items themselves
      * do not have individual item click listeners.
      */
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/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index 9ec9993..178bab6 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -46,10 +46,12 @@
     HEAP_UNKNOWN,
     HEAP_DALVIK,
     HEAP_NATIVE,
+
     HEAP_DALVIK_OTHER,
     HEAP_STACK,
     HEAP_CURSOR,
     HEAP_ASHMEM,
+    HEAP_GL_DEV,
     HEAP_UNKNOWN_DEV,
     HEAP_SO,
     HEAP_JAR,
@@ -297,7 +299,11 @@
             } else if (strncmp(name, "[stack", 6) == 0) {
                 whichHeap = HEAP_STACK;
             } else if (strncmp(name, "/dev/", 5) == 0) {
-                whichHeap = HEAP_UNKNOWN_DEV;
+                if (strncmp(name, "/dev/kgsl-3d0", 13) == 0) {
+                    whichHeap = HEAP_GL_DEV;
+                } else {
+                    whichHeap = HEAP_UNKNOWN_DEV;
+                }
             } else if (nameLen > 3 && strcmp(name+nameLen-3, ".so") == 0) {
                 whichHeap = HEAP_SO;
                 is_swappable = true;
diff --git a/docs/html/design/tv/index.jd b/docs/html/design/tv/index.jd
index 483c24f..d79e279 100644
--- a/docs/html/design/tv/index.jd
+++ b/docs/html/design/tv/index.jd
@@ -1,4 +1,7 @@
-page.title=Android TV
+page.title=Designing for Android TV
+page.tags="tv", "leanback","designguidelines"
+page.metaDescription=Guidelines to help you create a great leanback experience on Android TV.
+page.image=design/tv/images/apps-games-rows.jpg
 @jd:body
 
 
@@ -6,12 +9,15 @@
   experience. It's important to understand how your app is presented in the main user interface and
   how your app can help users get to the content they want quickly.</p>
 
-<p class="note">
+<p class="caution">
   <strong>Important:</strong> There are specific design requirements your app must meet to qualify
   as an Android TV app on Google Play. For more information, see the requirements listed in
   <a href="{@docRoot}distribute/essentials/quality/tv.html">TV App Quality</a>.
 </p>
 
+<p class="note"><strong>Note:</strong> For information about how to publish your TV apps in Google Play,
+see <a href="/distribute/googleplay/tv.html">Distributing to Android TV</a>.</p>
+
 <h2>Home Screen</h2>
 
 <p>The Home Screen is the start of the user experience, providing search, content
diff --git a/docs/html/distribute/essentials/quality/tv.jd b/docs/html/distribute/essentials/quality/tv.jd
index b13307e..20018c3 100644
--- a/docs/html/distribute/essentials/quality/tv.jd
+++ b/docs/html/distribute/essentials/quality/tv.jd
@@ -47,11 +47,9 @@
   qualify as an Android TV app on Google Play.
 </p>
 
-<p class="note">
-  <strong>Note:</strong> You will be able to submit TV apps to Google Play with the public release
-  of Android 5.0 on November 3. Stay tuned for more information about how to submit your TV apps
-  through the Google Play Developer Console.
-</p>
+<p class="note"><strong>Note:</strong> For information about how to publish your TV apps in Google Play,
+see <a href="{@docRoot}distribute/googleplay/tv.html">Distributing to Android TV</a>.</p>
+
 
 
 <div class="headerLine">
diff --git a/docs/html/distribute/googleplay/edu/start.jd b/docs/html/distribute/googleplay/edu/start.jd
index 3c3a175..f4c9717 100644
--- a/docs/html/distribute/googleplay/edu/start.jd
+++ b/docs/html/distribute/googleplay/edu/start.jd
@@ -1,4 +1,4 @@
-page.title=Publish Apps
+page.title=Publish Education Apps
 page.image=/distribute/images/play-education.jpg
 meta.tags="education", "guidelines", "quality"
 page.tags="education", "addendum"
diff --git a/docs/html/distribute/googleplay/googleplay_toc.cs b/docs/html/distribute/googleplay/googleplay_toc.cs
index 45464c7..fc7cd11 100644
--- a/docs/html/distribute/googleplay/googleplay_toc.cs
+++ b/docs/html/distribute/googleplay/googleplay_toc.cs
@@ -18,6 +18,12 @@
     </div>
   </li>
   <li class="nav-section">
+    <div class="nav-section empty" style="font-weight:normal"><a href="<?cs var:toroot?>distribute/googleplay/tv.html">
+          <span class="en">Distributing to <span style="white-space:nowrap">Android TV</span></span>
+        </a>
+    </div>
+  </li>
+  <li class="nav-section">
     <div class="nav-section-header" style="font-weight:normal"><a href="<?cs var:toroot?>distribute/googleplay/edu/about.html">
           <span class="en">Google Play for Education</span>
         </a>
diff --git a/docs/html/distribute/googleplay/index.jd b/docs/html/distribute/googleplay/index.jd
index a215930..20f07fa 100644
--- a/docs/html/distribute/googleplay/index.jd
+++ b/docs/html/distribute/googleplay/index.jd
@@ -21,7 +21,7 @@
     data-maxResults="3">
   </div>
 
-  <h3>Google Play for Education</h3>
+  <h3>Distribute Your Apps</h3>
 
   <div class="resource-widget resource-flow-layout landing col-16"
     data-query="collection:distribute/gp/gpfelanding"
diff --git a/docs/html/distribute/googleplay/tv.jd b/docs/html/distribute/googleplay/tv.jd
new file mode 100644
index 0000000..37cbe26
--- /dev/null
+++ b/docs/html/distribute/googleplay/tv.jd
@@ -0,0 +1,320 @@
+page.title=Distributing to Android TV
+page.image=/design/tv/images/atv-home.jpg
+meta.tags="tv", "publish", "quality"
+page.tags="tv", "publish", "googleplay"
+page.metaDescription=Distribute your apps, games, and content to Android TV.
+
+@jd:body
+
+<div id="qv-wrapper"><div id="qv">
+<h2>How to Participate</h2>
+<ol>
+<li><a href="#understand_guidelines">Understand the guidelines</a></li>
+<li><a href="#develop_app">Develop a great app for TV</a></li>
+<li><a href="#test_app">Test for TV App Quality</a></li>
+<li><a href="#opt_in">Opt-in</a></li>
+<li><a href="#track_review">Track your review</a></li>
+</ol>
+
+<h2>You Should Also Read</h2>
+<ol>
+<li><a href="{@docRoot}distribute/essentials/quality/tv.html">TV App Quality</a></li>
+<li><a href="{@docRoot}distribute/essentials/quality/core.html">Core App Quality</a></li>
+</ol>
+
+</div></div>
+
+<p>
+  If you've got a great app or game, Android TV and Google Play can help you
+  bring it to users right in their living rooms. You'll be able to offer your
+  apps and games in a storefront experience that’s optimized for TV. You can
+  extend your new or existing apps for TV and then publish them using familiar
+  tools and processes in Google Play.
+</p>
+
+<p>
+  To get started, review the sections in this document to learn how to
+  distribute your TV apps to users through Google Play. Be sure to read
+  <a href="{@docRoot}distribute/essentials/quality/tv.html">TV App Quality</a>
+  for information on the usability and quality standards that your apps should
+  meet. When your app is ready, you can opt-in to publishing in the Android TV
+  storefront from the Developer Console.
+</p>
+
+<h2 id="how_to_participate">
+  How to Participate
+</h2>
+
+<p>
+  Google Play lets you put your TV apps in front of a new audience of users in
+  their living rooms. You can develop and publish using your existing Developer
+  Console account and your current distribution and pricing settings. It's easy
+  to participate — the sections below outline the process.
+</p>
+
+<div style="float:right;margin:1em 0 1.5em 2em;">
+  <img src="{@docRoot}images/gp-tv-process.png">
+</div>
+
+<h3 id="understand_guidelines">
+  1. Understand guidelines and requirements
+</h3>
+
+<p>
+  To prepare for a successful launch on Android TV, start by reviewing the
+  guidelines for creating great app experiences on TV. See the <a href=
+  "{@docRoot}design/tv/index.html">Android TV design guidelines</a> for ideas
+  on extending your app for TV and details on design and usability.
+</p>
+
+<p>
+  As you get started designing your TV experience, make sure to read and
+  understand the quality criteria for TV apps. The Google Play experience for
+  Android TV <strong>showcases only apps that are usable on the TV</strong>
+  &mdash; your apps can participate if they meet a set of basic quality
+  criteria. See <a href="{@docRoot}distribute/essentials/quality/tv.html">TV
+  App Quality</a> for details.
+</p>
+
+<h3 id="develop_app">2. Develop a great app for TV</h3>
+
+<p>
+  A great app for TV is designed for living room use and takes advantage of the
+  capabilities of Android TV and related input accessories such as game
+  controllers, D-pads, and remotes. The app is refined to offer a polished,
+  high-quality experience on large screens and delivers a compelling feature
+  set for users.
+</p>
+
+<p>
+  As you consider your TV app, review the <a href=
+  "{@docRoot}training/tv/start/index.html">developer documentation</a> and
+  usability guidelines and plan on supporting them to the greatest extent
+  possible. Make sure to design a great leanback experience for users and build
+  it with the leanback library included in the SDK. You’ll want to optimize
+  other parts of your app for the TV use case and it's a good idea to identify
+  those early in your development process.
+</p>
+
+<p>
+  In most cases, we recommend delivering your TV experience as part of your
+  existing app for phones, tablets, and other devices, using the same package
+  name and store listing. This approach lets users upgrade to your TV experience
+  seamlessly and also lets you take advantage of the reviews and ratings you’ve
+  earned in your app for phones and tablets.
+</p>
+
+<p>
+  You can bundle your TV intents, leanback library, and TV-specific code and
+  resources as part of a single APK solution for all supported devices. If
+  necessary, you can use <a href=
+  "{@docRoot}google/play/publishing/multiple-apks.html">Multiple APK
+  Support</a> to deliver a custom binary to Android TV devices under the same
+  package name and store listing that you use for phones and tablets.
+</p>
+
+<p>
+  Throughout design and development, it's important to have a suitable device
+  on which to prototype and test your user experience. You should acquire one
+  or more Android TV devices or emulators and set up your testing environment
+  as early as possible. The recommended hardware device for testing in the
+  Android TV environment is Nexus Player, which is <a href=
+  "http://www.google.com/intl/all/nexus/player/">available from Google Play</a>
+  and other stores, and you should also acquire a game controller and other TV
+  input devices.
+</p>
+
+<h3 id="test_app">3. Test for TV App Quality</h3>
+
+<p>
+  Your TV apps should be designed to perform well, look great on Android TV,
+  and offer the best user experience possible. Google Play showcases
+  high-quality apps for easy discovery by users in Google Play. Here’s how you
+  can participate and deliver an Android TV app that users will enjoy.
+</p>
+
+<ul>
+  <li>Meet Core App Quality guidelines
+    <ul>
+      <li>Follow <a href="{@docRoot}design/index.html">Android Design
+      guidelines</a>. Pay special attention to using <a href=
+      "http://www.google.com/design/spec/material-design/introduction.html">material
+      design</a> in your app.
+      </li>
+
+      <li>Test your apps against the <a href=
+      "{@docRoot}distribute/essentials/quality/core.html">Core App Quality
+      guidelines</a>.
+      </li>
+    </ul>
+  </li>
+  <li>Meet <a href="{@docRoot}distribute/essentials/quality/tv.html">TV App
+  Quality</a> guidelines
+    <ul>
+      <li>Follow our best practices for <a href="{@docRoot}training/tv/index.html">
+      TV app development</a></li>
+      <li>Make sure your app meets all of the <a href=
+      "{@docRoot}distribute/essentials/quality/tv.html">TV App Quality</a> criteria</li>
+    </ul>
+  </li>
+  <li>Strive for simplicity and highest usability</li>
+</ul>
+
+<h3 id="opt_in">4. Opt-in to Android TV and publish</h3>
+
+<p>
+  When you've built your release-ready APK and tested to ensure that it meets
+  all of the <a href="{@docRoot}distribute/essentials/quality/tv.html">TV App
+  Quality</a> guidelines, upload it to the Developer Console. Update your store
+  listing with TV screenshots and TV banner, and set distribution options as
+  needed. If you aren't familiar with how to prepare for launch on Google Play,
+  see the <a href=
+  "{@docRoot}distribute/googleplay/publish/preparing.html">Launch
+  Checklist.</a>
+</p>
+
+<p>
+  Before you can publish to Android TV users, you need to opt-in to Android
+  TV from the <strong>Pricing and Distribution</strong> section of the
+  Developer Console. Opt-in means that you want your app to be made available
+  to Android TV users through Google Play, and that
+  your app meets <a href="{@docRoot}distribute/essentials/quality/tv.html">TV
+  App Quality</a> guidelines.
+</p>
+
+<p>
+  You can opt-in only if your app meets two preliminary quality
+  criteria that are automatically checked on APK upload:
+</p>
+
+<ul>
+  <li>Your app manifest must include an intent type of <a href=
+  "{@docRoot}reference/android/content/Intent.html#ACTION_MAIN"><code>ACTION_MAIN</code></a>
+  with category <a href=
+  "{@docRoot}reference/android/content/Intent.html#CATEGORY_LEANBACK_LAUNCHER">
+    <code>CATEGORY_LEANBACK_LAUNCHER</code></a>. Learn more <a href=
+    "{@docRoot}training/tv/start/start.html#tv-activity">here</a>.
+  </li>
+
+  <li>Your app must declare that it does not require a touchscreen. The
+  manifest must declare the <code>android.hardware.touchscreen</code> hardware
+  with <code>android:required="false”</code>. Learn more <a href=
+  "{@docRoot}training/tv/start/hardware.html#declare-hardware-requirements">here</a>.
+  </li>
+</ul>
+
+<p>
+  If your app meets the preliminary criteria, you’ll see an opt-in checkbox for
+  Android TV, as shown below. If the opt-in checkbox is not enabled, review
+  your APK to ensure it meets the preliminary criteria.
+</p>
+
+<p>
+  After you opt-in and save the changes, you can publish your app as usual.
+  Before making the app available to Android TV users, Google Play submits
+  your app for review against the <a href=
+  "{@docRoot}distribute/essentials/quality/tv.html">TV App Quality</a> criteria
+  and notifies you of the result. See the next section for details on how to
+  track the approval status of your app.
+</p>
+
+<p>
+  If your app meet <a href="{@docRoot}distribute/essentials/quality/tv.html">TV
+  App Quality</a> criteria, Google Play makes that app available to Android TV
+  users. Your app is alsoeligible for higher-visibility featuring in app
+  collections and promotions. To let users everywhere know that your app is
+  designed for Android TV, Google Play decorates the app’s store listing with a
+  TV badge.
+</p>
+
+<p>
+  Note that opt-in and review do not affect the availability of your app to
+  other devices in Google Play Store &mdash; on phones and tablets, for
+  example, your app is available as soon as you publish.
+</p>
+
+<p>
+  Here are the steps to opt-in to Android TV in the Developer Console:
+</p>
+
+<ol>
+  <li>Make sure your app meets all <a href=
+  "{@docRoot}distribute/essentials/quality/tv.html">TV App Quality</a> criteria
+  </li>
+
+  <li>Add TV screenshots and banner graphic to the app’s store listing
+  </li>
+
+  <li>In the <strong>All Applications</strong> page, click the app you want to opt-in.
+  </li>
+
+  <li>Under <strong>Pricing and Distribution</strong>, scroll down to find <em>Android TV</em> and the
+  opt-in checkbox.
+  </li>
+
+  <li>Click the checkbox next to <em>Distribute your app to Android TV</em>.
+  </li>
+
+  <li>Click <strong>Save</strong> to save your changes.
+  </li>
+</ol>
+
+<div style="padding-top:1em">
+  <img style="border:2px solid #ddd;" src="{@docRoot}images/gp-tv-opt-in.png">
+  <p class="caption">
+    <strong>Opt-in for TV:</strong> Include your app in Android TV by opting-in from the
+    Developer Console.
+  </p>
+</div>
+
+<h3 id="track_review">5. Track your review and approval</h3>
+
+<p>
+  If your app meets the technical and quality criteria for Android TV, as described above,
+  your app will be available for users to enjoy on Android TV. If your app doesn’t meet
+  the criteria, you’ll receive a <strong>notification email sent to your developer account
+  address</strong>, with a summary of the areas that you need to address. When you’ve made
+  the necessary adjustments, you can upload a new version of your app to the Developer
+  Console. 
+</p>
+
+<p>
+  At any time, you can check the review and approval status of your app in the
+  Developer Console, under <em>Android TV</em> in the app's <strong>Pricing and Distribution</strong>
+  page.
+</p>
+
+<p>
+  There are three approval states:
+</p>
+
+<ul>
+  <li>
+    <em>Pending</em> — Your app was sent for review and the review is not yet
+    complete.
+  </li>
+
+  <li>
+    <em>Approved</em> — Your app was reviewed and approved. The app will be
+    made available directly to Android TV users. 
+  </li>
+
+  <li>
+    <em>Not approved</em> — Your app was reviewed and not approved. Check the
+    notification email for information about why the app was not approved. You
+    can address any issues and opt-in and publish again to initiate another
+    review.
+  </li>
+</ul>
+
+<p>To understand how your apps are evaluated, please see the <a href=
+"{@docRoot}distribute/essentials/quality/tv.html">TV App Quality</a> document. </p>
+
+
+  <h3>Related resources</h3>
+
+  <div class="resource-widget resource-flow-layout col-16"
+    data-query="collection:tvlanding"
+    data-cardSizes="9x6, 6x3x2"
+    data-maxResults="6">
+  </div>
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/images/games/game-controller-buttons_2x_crop.png b/docs/html/images/games/game-controller-buttons_2x_crop.png
new file mode 100644
index 0000000..54dc2fa
--- /dev/null
+++ b/docs/html/images/games/game-controller-buttons_2x_crop.png
Binary files differ
diff --git a/docs/html/images/gp-tv-opt-in.png b/docs/html/images/gp-tv-opt-in.png
new file mode 100644
index 0000000..a815818
--- /dev/null
+++ b/docs/html/images/gp-tv-opt-in.png
Binary files differ
diff --git a/docs/html/images/gp-tv-process.png b/docs/html/images/gp-tv-process.png
new file mode 100644
index 0000000..a530777
--- /dev/null
+++ b/docs/html/images/gp-tv-process.png
Binary files differ
diff --git a/docs/html/jd_collections.js b/docs/html/jd_collections.js
index 08c0090..d63580e 100644
--- a/docs/html/jd_collections.js
+++ b/docs/html/jd_collections.js
@@ -57,8 +57,8 @@
   },
   "distribute/gp/gpfelanding": {
     "resources": [
+      "distribute/googleplay/tv.html",
       "distribute/googleplay/edu/about.html",
-      "distribute/googleplay/edu/start.html",
       "distribute/googleplay/edu/videos.html"
     ]
   },
@@ -773,6 +773,14 @@
       "https://support.google.com/googleplay/answer/2651410"
     ]
   },
+  "tvlanding": {
+    "title": "",
+    "resources": [
+      "tv/index.html",
+      "design/tv/index.html",
+      "training/tv/index.html"
+    ]
+  },
   "distribute/stories/games": {
     "title": "",
     "resources": [
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/tv/discovery/index.jd b/docs/html/training/tv/discovery/index.jd
index fbc8c9f..5849149 100644
--- a/docs/html/training/tv/discovery/index.jd
+++ b/docs/html/training/tv/discovery/index.jd
@@ -1,4 +1,5 @@
-page.title=Helping Users Find Content on TV
+page.title=Helping Users Find Your Content on TV
+page.tags="tv", "leanback"
 
 startpage=true
 
diff --git a/docs/html/training/tv/games/index.jd b/docs/html/training/tv/games/index.jd
index 8a998e0..5276d7f 100644
--- a/docs/html/training/tv/games/index.jd
+++ b/docs/html/training/tv/games/index.jd
@@ -1,5 +1,7 @@
 page.title=Building TV Games
-page.tags="controller"
+page.tags="tv", "games", "controller"
+page.image=images/games/game-controller-buttons_2x_crop.png
+page.metaDescription=How to bring your games to Android TV, including recommendations and examples.
 page.article=true
 
 @jd:body
@@ -180,7 +182,7 @@
 It includes a white controller on black background and a black controller on white background
 (shown in figure 1), as a PNG file and an Adobe&reg; Illustrator&reg; file.</p>
 
-<img src="{@docRoot}images/games/game-controller-buttons_2x.png" width="700"
+<img itemprop="image" src="{@docRoot}images/games/game-controller-buttons_2x.png" width="700"
      srcset="{@docRoot}images/games/game-controller-buttons_2x.png 2x,
              {@docRoot}images/games/game-controller-buttons.png 1x" />
 <p class="img-caption"><b>Figure 1.</b> Example controller instructions using the
diff --git a/docs/html/training/tv/index.jd b/docs/html/training/tv/index.jd
index 56667a9..d52e1e8 100644
--- a/docs/html/training/tv/index.jd
+++ b/docs/html/training/tv/index.jd
@@ -1,8 +1,11 @@
 page.title=Building Apps for TV
 page.trainingcourse=true
-
+page.metaDescription=Starting point for building apps and games for Android TV, with guidelines, information, and examples.
+page.image=design/tv/images/focus.png
 @jd:body
 
 
 
-<p>These classes teach you how to build apps for TV devices.</p>
\ No newline at end of file
+<p>These classes teach you how to build apps for TV devices.</p>
+
+<p class="note"><strong>Note:</strong> For details on how to publish your TV apps in Google Play,  see <a href="{docRoot}distribute/googleplay/tv.html">Distributing to Android TV</a>.</p>
\ No newline at end of file
diff --git a/docs/html/training/tv/playback/index.jd b/docs/html/training/tv/playback/index.jd
index 118fc6c..09c3f24 100644
--- a/docs/html/training/tv/playback/index.jd
+++ b/docs/html/training/tv/playback/index.jd
@@ -1,5 +1,5 @@
 page.title=Building TV Playback Apps
-page.tags="leanback"
+page.tags="tv","leanback"
 
 startpage=true
 
diff --git a/docs/html/training/tv/start/index.jd b/docs/html/training/tv/start/index.jd
index ceefea1..fb478a8 100644
--- a/docs/html/training/tv/start/index.jd
+++ b/docs/html/training/tv/start/index.jd
@@ -1,4 +1,5 @@
 page.title=Building TV Apps
+page.tags="tv", "leanback"
 startpage=true
 
 @jd:body
diff --git a/docs/html/training/tv/tif/index.jd b/docs/html/training/tv/tif/index.jd
index 4746e42..cde8ba7 100644
--- a/docs/html/training/tv/tif/index.jd
+++ b/docs/html/training/tv/tif/index.jd
@@ -1,5 +1,5 @@
 page.title=Building Live TV Apps
-page.tags=tif
+page.tags="tv", "tif"
 page.article=true
 
 @jd:body
diff --git a/docs/html/training/wearables/apps/bt-debugging.jd b/docs/html/training/wearables/apps/bt-debugging.jd
index 8d09c43..98cf804 100644
--- a/docs/html/training/wearables/apps/bt-debugging.jd
+++ b/docs/html/training/wearables/apps/bt-debugging.jd
@@ -58,7 +58,8 @@
 </li>
 <li>Connect the handheld to your machine over USB and run:
 <pre>
-adb forward tcp:4444 localabstract:/adb-hub; adb connect localhost:4444
+adb forward tcp:4444 localabstract:/adb-hub
+adb connect localhost:4444
 </pre>
 
 <p class="note"><b>Note</b>: You can use any available port that you have access to.</p>
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/docs/html/tv/index.jd b/docs/html/tv/index.jd
index 71e177b..e4d7f7a 100644
--- a/docs/html/tv/index.jd
+++ b/docs/html/tv/index.jd
@@ -1,5 +1,9 @@
-page.title=Android TV
+page.title=About Android TV
+page.type=about
+page.image=tv/images/hero.jpg
 page.viewport_width=970
+page.tags="tv", "leanback"
+page.metaDescription=Bring your apps, games, and content to the biggest screen in the house.
 fullpage=true
 no_footer_links=true
 page.type=about
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/include/androidfw/ResourceTypes.h b/include/androidfw/ResourceTypes.h
index 85e442da..6b84494 100644
--- a/include/androidfw/ResourceTypes.h
+++ b/include/androidfw/ResourceTypes.h
@@ -36,6 +36,17 @@
 
 namespace android {
 
+/**
+ * In C++11, char16_t is defined as *at least* 16 bits. We do a lot of
+ * casting on raw data and expect char16_t to be exactly 16 bits.
+ */
+#if __cplusplus >= 201103L
+struct __assertChar16Size {
+    static_assert(sizeof(char16_t) == sizeof(uint16_t), "char16_t is not 16 bits");
+    static_assert(alignof(char16_t) == alignof(uint16_t), "char16_t is not 16-bit aligned");
+};
+#endif
+
 /** ********************************************************************
  *  PNG Extensions
  *
@@ -702,25 +713,25 @@
 
     // These are available for all nodes:
     int32_t getCommentID() const;
-    const uint16_t* getComment(size_t* outLen) const;
+    const char16_t* getComment(size_t* outLen) const;
     uint32_t getLineNumber() const;
     
     // This is available for TEXT:
     int32_t getTextID() const;
-    const uint16_t* getText(size_t* outLen) const;
+    const char16_t* getText(size_t* outLen) const;
     ssize_t getTextValue(Res_value* outValue) const;
     
     // These are available for START_NAMESPACE and END_NAMESPACE:
     int32_t getNamespacePrefixID() const;
-    const uint16_t* getNamespacePrefix(size_t* outLen) const;
+    const char16_t* getNamespacePrefix(size_t* outLen) const;
     int32_t getNamespaceUriID() const;
-    const uint16_t* getNamespaceUri(size_t* outLen) const;
+    const char16_t* getNamespaceUri(size_t* outLen) const;
     
     // These are available for START_TAG and END_TAG:
     int32_t getElementNamespaceID() const;
-    const uint16_t* getElementNamespace(size_t* outLen) const;
+    const char16_t* getElementNamespace(size_t* outLen) const;
     int32_t getElementNameID() const;
-    const uint16_t* getElementName(size_t* outLen) const;
+    const char16_t* getElementName(size_t* outLen) const;
     
     // Remaining methods are for retrieving information about attributes
     // associated with a START_TAG:
@@ -729,10 +740,10 @@
     
     // Returns -1 if no namespace, -2 if idx out of range.
     int32_t getAttributeNamespaceID(size_t idx) const;
-    const uint16_t* getAttributeNamespace(size_t idx, size_t* outLen) const;
+    const char16_t* getAttributeNamespace(size_t idx, size_t* outLen) const;
 
     int32_t getAttributeNameID(size_t idx) const;
-    const uint16_t* getAttributeName(size_t idx, size_t* outLen) const;
+    const char16_t* getAttributeName(size_t idx, size_t* outLen) const;
     uint32_t getAttributeNameResID(size_t idx) const;
 
     // These will work only if the underlying string pool is UTF-8.
@@ -740,7 +751,7 @@
     const char* getAttributeName8(size_t idx, size_t* outLen) const;
 
     int32_t getAttributeValueStringID(size_t idx) const;
-    const uint16_t* getAttributeStringValue(size_t idx, size_t* outLen) const;
+    const char16_t* getAttributeStringValue(size_t idx, size_t* outLen) const;
     
     int32_t getAttributeDataType(size_t idx) const;
     int32_t getAttributeData(size_t idx) const;
@@ -845,7 +856,7 @@
     uint32_t id;
 
     // Actual name of this package, \0-terminated.
-    char16_t name[128];
+    uint16_t name[128];
 
     // Offset to a ResStringPool_header defining the resource
     // type symbol table.  If zero, this package is inheriting from
@@ -1450,7 +1461,7 @@
     uint32_t packageId;
 
     // The package name of the shared library. \0 terminated.
-    char16_t packageName[128];
+    uint16_t packageName[128];
 };
 
 /**
@@ -1681,7 +1692,7 @@
                                size_t defPackageLen = 0,
                                uint32_t* outTypeSpecFlags = NULL) const;
 
-    static bool expandResourceRef(const uint16_t* refStr, size_t refLen,
+    static bool expandResourceRef(const char16_t* refStr, size_t refLen,
                                   String16* outPackage,
                                   String16* outType,
                                   String16* outName,
diff --git a/libs/androidfw/Android.mk b/libs/androidfw/Android.mk
index dbee7ed..20d5470 100644
--- a/libs/androidfw/Android.mk
+++ b/libs/androidfw/Android.mk
@@ -14,7 +14,7 @@
 
 LOCAL_PATH:= $(call my-dir)
 
-# libandroidfw is partially built for the host (used by obbtool and others)
+# libandroidfw is partially built for the host (used by obbtool, aapt, and others)
 # These files are common to host and target builds.
 
 commonSources := \
@@ -35,26 +35,17 @@
     BackupHelpers.cpp \
     CursorWindow.cpp
 
-hostSources := \
-    $(commonSources)
+hostSources := $(commonSources)
 
 # For the host
 # =====================================================
-
 include $(CLEAR_VARS)
 
-LOCAL_SRC_FILES:= $(hostSources)
-
 LOCAL_MODULE:= libandroidfw
-
 LOCAL_MODULE_TAGS := optional
-
 LOCAL_CFLAGS += -DSTATIC_ANDROIDFW_FOR_TOOLS
-
-LOCAL_C_INCLUDES := \
-	external/zlib
-
-LOCAL_STATIC_LIBRARIES := liblog libziparchive-host libutils
+LOCAL_SRC_FILES:= $(hostSources)
+LOCAL_C_INCLUDES := external/zlib
 
 include $(BUILD_HOST_STATIC_LIBRARY)
 
@@ -64,8 +55,13 @@
 
 include $(CLEAR_VARS)
 
+LOCAL_MODULE:= libandroidfw
+LOCAL_MODULE_TAGS := optional
 LOCAL_SRC_FILES:= $(deviceSources)
-
+LOCAL_C_INCLUDES := \
+    external/zlib \
+    system/core/include
+LOCAL_STATIC_LIBRARIES := libziparchive
 LOCAL_SHARED_LIBRARIES := \
 	libbinder \
 	liblog \
@@ -73,16 +69,6 @@
 	libutils \
 	libz
 
-LOCAL_STATIC_LIBRARIES := libziparchive
-
-LOCAL_C_INCLUDES := \
-    external/zlib \
-    system/core/include
-
-LOCAL_MODULE:= libandroidfw
-
-LOCAL_MODULE_TAGS := optional
-
 include $(BUILD_SHARED_LIBRARY)
 
 
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 3bbca1a..f1e4858 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -87,11 +87,11 @@
 // range checked; guaranteed to NUL-terminate within the stated number of available slots
 // NOTE: if this truncates the dst string due to running out of space, no attempt is
 // made to avoid splitting surrogate pairs.
-static void strcpy16_dtoh(uint16_t* dst, const uint16_t* src, size_t avail)
+static void strcpy16_dtoh(char16_t* dst, const uint16_t* src, size_t avail)
 {
-    uint16_t* last = dst + avail - 1;
+    char16_t* last = dst + avail - 1;
     while (*src && (dst < last)) {
-        char16_t s = dtohs(*src);
+        char16_t s = dtohs(static_cast<char16_t>(*src));
         *dst++ = s;
         src++;
     }
@@ -501,7 +501,7 @@
         if (mHeader->flags&ResStringPool_header::UTF8_FLAG) {
             charSize = sizeof(uint8_t);
         } else {
-            charSize = sizeof(char16_t);
+            charSize = sizeof(uint16_t);
         }
 
         // There should be at least space for the smallest string
@@ -547,8 +547,8 @@
                 e[i] = dtohl(mEntries[i]);
             }
             if (!(mHeader->flags&ResStringPool_header::UTF8_FLAG)) {
-                const char16_t* strings = (const char16_t*)mStrings;
-                char16_t* s = const_cast<char16_t*>(strings);
+                const uint16_t* strings = (const uint16_t*)mStrings;
+                uint16_t* s = const_cast<uint16_t*>(strings);
                 for (i=0; i<mStringPoolSize; i++) {
                     s[i] = dtohs(strings[i]);
                 }
@@ -558,7 +558,7 @@
         if ((mHeader->flags&ResStringPool_header::UTF8_FLAG &&
                 ((uint8_t*)mStrings)[mStringPoolSize-1] != 0) ||
                 (!mHeader->flags&ResStringPool_header::UTF8_FLAG &&
-                ((char16_t*)mStrings)[mStringPoolSize-1] != 0)) {
+                ((uint16_t*)mStrings)[mStringPoolSize-1] != 0)) {
             ALOGW("Bad string block: last string is not 0-terminated\n");
             return (mError=BAD_TYPE);
         }
@@ -656,7 +656,7 @@
  * add it together with the next character.
  */
 static inline size_t
-decodeLength(const char16_t** str)
+decodeLength(const uint16_t** str)
 {
     size_t len = **str;
     if ((len & 0x8000) != 0) {
@@ -689,19 +689,19 @@
     return len;
 }
 
-const uint16_t* ResStringPool::stringAt(size_t idx, size_t* u16len) const
+const char16_t* ResStringPool::stringAt(size_t idx, size_t* u16len) const
 {
     if (mError == NO_ERROR && idx < mHeader->stringCount) {
         const bool isUTF8 = (mHeader->flags&ResStringPool_header::UTF8_FLAG) != 0;
-        const uint32_t off = mEntries[idx]/(isUTF8?sizeof(char):sizeof(char16_t));
+        const uint32_t off = mEntries[idx]/(isUTF8?sizeof(uint8_t):sizeof(uint16_t));
         if (off < (mStringPoolSize-1)) {
             if (!isUTF8) {
-                const char16_t* strings = (char16_t*)mStrings;
-                const char16_t* str = strings+off;
+                const uint16_t* strings = (uint16_t*)mStrings;
+                const uint16_t* str = strings+off;
 
                 *u16len = decodeLength(&str);
                 if ((uint32_t)(str+*u16len-strings) < mStringPoolSize) {
-                    return str;
+                    return reinterpret_cast<const char16_t*>(str);
                 } else {
                     ALOGW("Bad string block: string #%d extends to %d, past end at %d\n",
                             (int)idx, (int)(str+*u16len-strings), (int)mStringPoolSize);
@@ -1013,7 +1013,7 @@
     return mCurNode != NULL ? dtohl(mCurNode->comment.index) : -1;
 }
 
-const uint16_t* ResXMLParser::getComment(size_t* outLen) const
+const char16_t* ResXMLParser::getComment(size_t* outLen) const
 {
     int32_t id = getCommentID();
     return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL;
@@ -1032,7 +1032,7 @@
     return -1;
 }
 
-const uint16_t* ResXMLParser::getText(size_t* outLen) const
+const char16_t* ResXMLParser::getText(size_t* outLen) const
 {
     int32_t id = getTextID();
     return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL;
@@ -1055,7 +1055,7 @@
     return -1;
 }
 
-const uint16_t* ResXMLParser::getNamespacePrefix(size_t* outLen) const
+const char16_t* ResXMLParser::getNamespacePrefix(size_t* outLen) const
 {
     int32_t id = getNamespacePrefixID();
     //printf("prefix=%d  event=%p\n", id, mEventCode);
@@ -1070,7 +1070,7 @@
     return -1;
 }
 
-const uint16_t* ResXMLParser::getNamespaceUri(size_t* outLen) const
+const char16_t* ResXMLParser::getNamespaceUri(size_t* outLen) const
 {
     int32_t id = getNamespaceUriID();
     //printf("uri=%d  event=%p\n", id, mEventCode);
@@ -1088,7 +1088,7 @@
     return -1;
 }
 
-const uint16_t* ResXMLParser::getElementNamespace(size_t* outLen) const
+const char16_t* ResXMLParser::getElementNamespace(size_t* outLen) const
 {
     int32_t id = getElementNamespaceID();
     return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL;
@@ -1105,7 +1105,7 @@
     return -1;
 }
 
-const uint16_t* ResXMLParser::getElementName(size_t* outLen) const
+const char16_t* ResXMLParser::getElementName(size_t* outLen) const
 {
     int32_t id = getElementNameID();
     return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL;
@@ -1134,7 +1134,7 @@
     return -2;
 }
 
-const uint16_t* ResXMLParser::getAttributeNamespace(size_t idx, size_t* outLen) const
+const char16_t* ResXMLParser::getAttributeNamespace(size_t idx, size_t* outLen) const
 {
     int32_t id = getAttributeNamespaceID(idx);
     //printf("attribute namespace=%d  idx=%d  event=%p\n", id, idx, mEventCode);
@@ -1165,7 +1165,7 @@
     return -1;
 }
 
-const uint16_t* ResXMLParser::getAttributeName(size_t idx, size_t* outLen) const
+const char16_t* ResXMLParser::getAttributeName(size_t idx, size_t* outLen) const
 {
     int32_t id = getAttributeNameID(idx);
     //printf("attribute name=%d  idx=%d  event=%p\n", id, idx, mEventCode);
@@ -1205,7 +1205,7 @@
     return -1;
 }
 
-const uint16_t* ResXMLParser::getAttributeStringValue(size_t idx, size_t* outLen) const
+const char16_t* ResXMLParser::getAttributeStringValue(size_t idx, size_t* outLen) const
 {
     int32_t id = getAttributeValueStringID(idx);
     //XML_NOISY(printf("getAttributeValue 0x%x=0x%x\n", idx, id));
@@ -4239,7 +4239,7 @@
     return 0;
 }
 
-bool ResTable::expandResourceRef(const uint16_t* refStr, size_t refLen,
+bool ResTable::expandResourceRef(const char16_t* refStr, size_t refLen,
                                  String16* outPackage,
                                  String16* outType,
                                  String16* outName,
@@ -5665,8 +5665,8 @@
     if (idx == 0) {
         idx = mPackageGroups.size() + 1;
 
-        char16_t tmpName[sizeof(pkg->name)/sizeof(char16_t)];
-        strcpy16_dtoh(tmpName, pkg->name, sizeof(pkg->name)/sizeof(char16_t));
+        char16_t tmpName[sizeof(pkg->name)/sizeof(pkg->name[0])];
+        strcpy16_dtoh(tmpName, pkg->name, sizeof(pkg->name)/sizeof(pkg->name[0]));
         group = new PackageGroup(this, String16(tmpName), id);
         if (group == NULL) {
             delete package;
@@ -6036,7 +6036,10 @@
     *outSize += 2 * sizeof(uint16_t);
 
     // overlay packages are assumed to contain only one package group
-    const String16 overlayPackage(overlay.mPackageGroups[0]->packages[0]->package->name);
+    const ResTable_package* overlayPackageStruct = overlay.mPackageGroups[0]->packages[0]->package;
+    char16_t tmpName[sizeof(overlayPackageStruct->name)/sizeof(overlayPackageStruct->name[0])];
+    strcpy16_dtoh(tmpName, overlayPackageStruct->name, sizeof(overlayPackageStruct->name)/sizeof(overlayPackageStruct->name[0]));
+    const String16 overlayPackage(tmpName);
 
     for (size_t typeIndex = 0; typeIndex < pg->types.size(); ++typeIndex) {
         const TypeList& typeList = pg->types[typeIndex];
@@ -6345,8 +6348,10 @@
             // Use a package's real ID, since the ID may have been assigned
             // if this package is a shared library.
             packageId = pkg->package->id;
+            char16_t tmpName[sizeof(pkg->package->name)/sizeof(pkg->package->name[0])];
+            strcpy16_dtoh(tmpName, pkg->package->name, sizeof(pkg->package->name)/sizeof(pkg->package->name[0]));
             printf("  Package %d id=0x%02x name=%s\n", (int)pkgIndex,
-                    pkg->package->id, String8(String16(pkg->package->name)).string());
+                    pkg->package->id, String8(tmpName).string());
         }
 
         for (size_t typeIndex=0; typeIndex < pg->types.size(); typeIndex++) {
diff --git a/libs/androidfw/misc.cpp b/libs/androidfw/misc.cpp
index 29686ef..ea54cc5 100644
--- a/libs/androidfw/misc.cpp
+++ b/libs/androidfw/misc.cpp
@@ -22,9 +22,9 @@
 #include <androidfw/misc.h>
 
 #include <sys/stat.h>
-#include <string.h>
+#include <cstring>
 #include <errno.h>
-#include <stdio.h>
+#include <cstdio>
 
 using namespace android;
 
diff --git a/libs/androidfw/tests/Android.mk b/libs/androidfw/tests/Android.mk
index b2e465c..2d7906f 100644
--- a/libs/androidfw/tests/Android.mk
+++ b/libs/androidfw/tests/Android.mk
@@ -37,7 +37,6 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE := libandroidfw_tests
-
 LOCAL_SRC_FILES := $(testFiles)
 LOCAL_STATIC_LIBRARIES := \
     libandroidfw \
@@ -55,11 +54,9 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE := libandroidfw_tests
-
 LOCAL_SRC_FILES := $(testFiles) \
     BackupData_test.cpp \
     ObbFile_test.cpp
-
 LOCAL_SHARED_LIBRARIES := \
     libandroidfw \
     libcutils \
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 2f68382..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
     ///////////////////////////////////////////////////////////////////////////
@@ -740,15 +742,17 @@
     }
 
     private void checkAllAliasStreamVolumes() {
-        int numStreamTypes = AudioSystem.getNumStreamTypes();
-        for (int streamType = 0; streamType < numStreamTypes; streamType++) {
-            if (streamType != mStreamVolumeAlias[streamType]) {
-                mStreamStates[streamType].
+        synchronized (VolumeStreamState.class) {
+            int numStreamTypes = AudioSystem.getNumStreamTypes();
+            for (int streamType = 0; streamType < numStreamTypes; streamType++) {
+                if (streamType != mStreamVolumeAlias[streamType]) {
+                    mStreamStates[streamType].
                                     setAllIndexes(mStreamStates[mStreamVolumeAlias[streamType]]);
-            }
-            // apply stream volume
-            if (!mStreamStates[streamType].isMuted()) {
-                mStreamStates[streamType].applyAllVolumes();
+                }
+                // apply stream volume
+                if (!mStreamStates[streamType].isMuted_syncVSS()) {
+                    mStreamStates[streamType].applyAllVolumes();
+                }
             }
         }
     }
@@ -1520,7 +1524,9 @@
 
     /** get stream mute state. */
     public boolean isStreamMute(int streamType) {
-        return mStreamStates[streamType].isMuted();
+        synchronized (VolumeStreamState.class) {
+            return mStreamStates[streamType].isMuted_syncVSS();
+        }
     }
 
     private class RmtSbmxFullVolDeathHandler implements IBinder.DeathRecipient {
@@ -1658,17 +1664,19 @@
     public int getStreamVolume(int streamType) {
         ensureValidStreamType(streamType);
         int device = getDeviceForStream(streamType);
-        int index = mStreamStates[streamType].getIndex(device);
+        synchronized (VolumeStreamState.class) {
+            int index = mStreamStates[streamType].getIndex(device);
 
-        // by convention getStreamVolume() returns 0 when a stream is muted.
-        if (mStreamStates[streamType].isMuted()) {
-            index = 0;
+            // by convention getStreamVolume() returns 0 when a stream is muted.
+            if (mStreamStates[streamType].isMuted_syncVSS()) {
+                index = 0;
+            }
+            if (index != 0 && (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) &&
+                    (device & mFixedVolumeDevices) != 0) {
+                index = mStreamStates[streamType].getMaxIndex();
+            }
+            return (index + 5) / 10;
         }
-        if (index != 0 && (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) &&
-                (device & mFixedVolumeDevices) != 0) {
-            index = mStreamStates[streamType].getMaxIndex();
-        }
-        return (index + 5) / 10;
     }
 
     public int getMasterVolume() {
@@ -1822,7 +1830,7 @@
                     // on voice capable devices
                     if (isPlatformVoice() &&
                             mStreamVolumeAlias[streamType] == AudioSystem.STREAM_RING) {
-                        synchronized (mStreamStates[streamType]) {
+                        synchronized (VolumeStreamState.class) {
                             Set set = mStreamStates[streamType].mIndex.entrySet();
                             Iterator i = set.iterator();
                             while (i.hasNext()) {
@@ -2321,16 +2329,15 @@
                 continue;
             }
 
-            synchronized (streamState) {
-                streamState.readSettings();
-
+            streamState.readSettings();
+            synchronized (VolumeStreamState.class) {
                 // unmute stream that was muted but is not affect by mute anymore
-                if (streamState.isMuted() && ((!isStreamAffectedByMute(streamType) &&
+                if (streamState.isMuted_syncVSS() && ((!isStreamAffectedByMute(streamType) &&
                         !isStreamMutedByRingerMode(streamType)) || mUseFixedVolume)) {
                     int size = streamState.mDeathHandlers.size();
                     for (int i = 0; i < size; i++) {
                         streamState.mDeathHandlers.get(i).mMuteCount = 1;
-                        streamState.mDeathHandlers.get(i).mute(false);
+                        streamState.mDeathHandlers.get(i).mute_syncVSS(false);
                     }
                 }
             }
@@ -3264,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) {
@@ -3344,6 +3358,12 @@
     // Inner classes
     ///////////////////////////////////////////////////////////////////////////
 
+    // NOTE: Locking order for synchronized objects related to volume or ringer mode management:
+    //  1 mScoclient OR mSafeMediaVolumeState
+    //  2   mSetModeDeathHandlers
+    //  3     mSettingsLock
+    //  4       VolumeStreamState.class
+    //  5         mCameraSoundForced
     public class VolumeStreamState {
         private final int mStreamType;
 
@@ -3425,9 +3445,10 @@
             }
         }
 
-        public void applyDeviceVolume(int device) {
+        // must be called while synchronized VolumeStreamState.class
+        public void applyDeviceVolume_syncVSS(int device) {
             int index;
-            if (isMuted()) {
+            if (isMuted_syncVSS()) {
                 index = 0;
             } else if (((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 && mAvrcpAbsVolSupported)
                     || ((device & mFullVolumeDevices) != 0)) {
@@ -3443,7 +3464,7 @@
                 // apply default volume first: by convention this will reset all
                 // devices volumes in audio policy manager to the supplied value
                 int index;
-                if (isMuted()) {
+                if (isMuted_syncVSS()) {
                     index = 0;
                 } else {
                     index = (getIndex(AudioSystem.DEVICE_OUT_DEFAULT) + 5)/10;
@@ -3456,7 +3477,7 @@
                     Map.Entry entry = (Map.Entry)i.next();
                     int device = ((Integer)entry.getKey()).intValue();
                     if (device != AudioSystem.DEVICE_OUT_DEFAULT) {
-                        if (isMuted()) {
+                        if (isMuted_syncVSS()) {
                             index = 0;
                         } else if (((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 &&
                                 mAvrcpAbsVolSupported)
@@ -3568,12 +3589,12 @@
 
         public void mute(IBinder cb, boolean state) {
             synchronized (VolumeStreamState.class) {
-                VolumeDeathHandler handler = getDeathHandler(cb, state);
+                VolumeDeathHandler handler = getDeathHandler_syncVSS(cb, state);
                 if (handler == null) {
                     Log.e(TAG, "Could not get client death handler for stream: "+mStreamType);
                     return;
                 }
-                handler.mute(state);
+                handler.mute_syncVSS(state);
             }
         }
 
@@ -3595,7 +3616,7 @@
                                 || (((device & mFixedVolumeDevices) != 0) && index != 0)) {
                             entry.setValue(mIndexMax);
                         }
-                        applyDeviceVolume(device);
+                        applyDeviceVolume_syncVSS(device);
                     }
                 }
             }
@@ -3619,8 +3640,8 @@
                 mICallback = cb;
             }
 
-            // must be called while synchronized on parent VolumeStreamState
-            public void mute(boolean state) {
+            // must be called while synchronized VolumeStreamState.class
+            public void mute_syncVSS(boolean state) {
                 boolean updateVolume = false;
                 if (state) {
                     if (mMuteCount == 0) {
@@ -3632,7 +3653,7 @@
                             }
                             VolumeStreamState.this.mDeathHandlers.add(this);
                             // If the stream is not yet muted by any client, set level to 0
-                            if (!VolumeStreamState.this.isMuted()) {
+                            if (!VolumeStreamState.this.isMuted_syncVSS()) {
                                 updateVolume = true;
                             }
                         } catch (RemoteException e) {
@@ -3656,7 +3677,7 @@
                             if (mICallback != null) {
                                 mICallback.unlinkToDeath(this, 0);
                             }
-                            if (!VolumeStreamState.this.isMuted()) {
+                            if (!VolumeStreamState.this.isMuted_syncVSS()) {
                                 updateVolume = true;
                             }
                         }
@@ -3674,15 +3695,17 @@
 
             public void binderDied() {
                 Log.w(TAG, "Volume service client died for stream: "+mStreamType);
-                if (mMuteCount != 0) {
-                    // Reset all active mute requests from this client.
-                    mMuteCount = 1;
-                    mute(false);
+                synchronized (VolumeStreamState.class) {
+                    if (mMuteCount != 0) {
+                        // Reset all active mute requests from this client.
+                        mMuteCount = 1;
+                        mute_syncVSS(false);
+                    }
                 }
             }
         }
 
-        private synchronized int muteCount() {
+        private int muteCount() {
             int count = 0;
             int size = mDeathHandlers.size();
             for (int i = 0; i < size; i++) {
@@ -3691,12 +3714,13 @@
             return count;
         }
 
-        private synchronized boolean isMuted() {
+        // must be called while synchronized VolumeStreamState.class
+        private boolean isMuted_syncVSS() {
             return muteCount() != 0;
         }
 
-        // only called by mute() which is already synchronized
-        private VolumeDeathHandler getDeathHandler(IBinder cb, boolean state) {
+        // must be called while synchronized VolumeStreamState.class
+        private VolumeDeathHandler getDeathHandler_syncVSS(IBinder cb, boolean state) {
             VolumeDeathHandler handler;
             int size = mDeathHandlers.size();
             for (int i = 0; i < size; i++) {
@@ -3773,25 +3797,26 @@
 
         private void setDeviceVolume(VolumeStreamState streamState, int device) {
 
-            // Apply volume
-            streamState.applyDeviceVolume(device);
+            synchronized (VolumeStreamState.class) {
+                // Apply volume
+                streamState.applyDeviceVolume_syncVSS(device);
 
-            // Apply change to all streams using this one as alias
-            int numStreamTypes = AudioSystem.getNumStreamTypes();
-            for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
-                if (streamType != streamState.mStreamType &&
-                        mStreamVolumeAlias[streamType] == streamState.mStreamType) {
-                    // Make sure volume is also maxed out on A2DP device for aliased stream
-                    // that may have a different device selected
-                    int streamDevice = getDeviceForStream(streamType);
-                    if ((device != streamDevice) && mAvrcpAbsVolSupported &&
-                            ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0)) {
-                        mStreamStates[streamType].applyDeviceVolume(device);
+                // Apply change to all streams using this one as alias
+                int numStreamTypes = AudioSystem.getNumStreamTypes();
+                for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
+                    if (streamType != streamState.mStreamType &&
+                            mStreamVolumeAlias[streamType] == streamState.mStreamType) {
+                        // Make sure volume is also maxed out on A2DP device for aliased stream
+                        // that may have a different device selected
+                        int streamDevice = getDeviceForStream(streamType);
+                        if ((device != streamDevice) && mAvrcpAbsVolSupported &&
+                                ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0)) {
+                            mStreamStates[streamType].applyDeviceVolume_syncVSS(device);
+                        }
+                        mStreamStates[streamType].applyDeviceVolume_syncVSS(streamDevice);
                     }
-                    mStreamStates[streamType].applyDeviceVolume(streamDevice);
                 }
             }
-
             // Post a persist volume msg
             sendMsg(mAudioHandler,
                     MSG_PERSIST_VOLUME,
@@ -4571,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;
     }
@@ -5032,42 +5062,45 @@
             boolean cameraSoundForced = mContext.getResources().getBoolean(
                     com.android.internal.R.bool.config_camera_sound_forced);
             synchronized (mSettingsLock) {
+                boolean cameraSoundForcedChanged = false;
                 synchronized (mCameraSoundForced) {
                     if (cameraSoundForced != mCameraSoundForced) {
                         mCameraSoundForced = cameraSoundForced;
-
-                        if (!isPlatformTelevision()) {
-                            VolumeStreamState s = mStreamStates[AudioSystem.STREAM_SYSTEM_ENFORCED];
-                            if (cameraSoundForced) {
-                                s.setAllIndexesToMax();
-                                mRingerModeAffectedStreams &=
-                                        ~(1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
-                            } else {
-                                s.setAllIndexes(mStreamStates[AudioSystem.STREAM_SYSTEM]);
-                                mRingerModeAffectedStreams |=
-                                        (1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
-                            }
-                            // take new state into account for streams muted by ringer mode
-                            setRingerModeInt(getRingerMode(), false);
-                        }
-
-                        sendMsg(mAudioHandler,
-                                MSG_SET_FORCE_USE,
-                                SENDMSG_QUEUE,
-                                AudioSystem.FOR_SYSTEM,
-                                cameraSoundForced ?
-                                        AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE,
-                                null,
-                                0);
-
-                        sendMsg(mAudioHandler,
-                                MSG_SET_ALL_VOLUMES,
-                                SENDMSG_QUEUE,
-                                0,
-                                0,
-                                mStreamStates[AudioSystem.STREAM_SYSTEM_ENFORCED], 0);
+                        cameraSoundForcedChanged = true;
                     }
                 }
+                if (cameraSoundForcedChanged) {
+                    if (!isPlatformTelevision()) {
+                        VolumeStreamState s = mStreamStates[AudioSystem.STREAM_SYSTEM_ENFORCED];
+                        if (cameraSoundForced) {
+                            s.setAllIndexesToMax();
+                            mRingerModeAffectedStreams &=
+                                    ~(1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
+                        } else {
+                            s.setAllIndexes(mStreamStates[AudioSystem.STREAM_SYSTEM]);
+                            mRingerModeAffectedStreams |=
+                                    (1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
+                        }
+                        // take new state into account for streams muted by ringer mode
+                        setRingerModeInt(getRingerMode(), false);
+                    }
+
+                    sendMsg(mAudioHandler,
+                            MSG_SET_FORCE_USE,
+                            SENDMSG_QUEUE,
+                            AudioSystem.FOR_SYSTEM,
+                            cameraSoundForced ?
+                                    AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE,
+                            null,
+                            0);
+
+                    sendMsg(mAudioHandler,
+                            MSG_SET_ALL_VOLUMES,
+                            SENDMSG_QUEUE,
+                            0,
+                            0,
+                            mStreamStates[AudioSystem.STREAM_SYSTEM_ENFORCED], 0);
+                }
             }
             mVolumeController.setLayoutDirection(config.getLayoutDirection());
         } catch (Exception e) {
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index 0ca5810..93cca2f 100644
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -159,15 +159,6 @@
     }
 
     /**
-     * Get the number of callbacks that are registered.
-     * @hide
-     */
-    @VisibleForTesting
-    public final int getRegisteredCallbackCount() {
-        return mCallbacks.getRegisteredCallbackCount();
-    }
-
-    /**
      * Returns a concrete implementation of {@link Session}.
      * <p>
      * May return {@code null} if this TV input service fails to create a session for some reason.
@@ -550,13 +541,14 @@
          * @param left Left position in pixels, relative to the overlay view.
          * @param top Top position in pixels, relative to the overlay view.
          * @param right Right position in pixels, relative to the overlay view.
-         * @param bottm Bottom position in pixels, relative to the overlay view.
+         * @param bottom Bottom position in pixels, relative to the overlay view.
          * @see #onOverlayViewSizeChanged
          * @hide
          */
         @SystemApi
-        public void layoutSurface(final int left, final int top, final int right, final int bottm) {
-            if (left > right || top > bottm) {
+        public void layoutSurface(final int left, final int top, final int right,
+                final int bottom) {
+            if (left > right || top > bottom) {
                 throw new IllegalArgumentException("Invalid parameter");
             }
             executeOrPostRunnable(new Runnable() {
@@ -564,8 +556,8 @@
                 public void run() {
                     try {
                         if (DEBUG) Log.d(TAG, "layoutSurface (l=" + left + ", t=" + top + ", r="
-                                + right + ", b=" + bottm + ",)");
-                        mSessionCallback.onLayoutSurface(left, top, right, bottm);
+                                + right + ", b=" + bottom + ",)");
+                        mSessionCallback.onLayoutSurface(left, top, right, bottom);
                     } catch (RemoteException e) {
                         Log.w(TAG, "error in layoutSurface");
                     }
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 fc7081b..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;
     }
 
@@ -3630,9 +3639,7 @@
     }
 
     private void updatePublicMode() {
-        setLockscreenPublicMode(
-                (mStatusBarKeyguardViewManager.isShowing() ||
-                        mStatusBarKeyguardViewManager.isOccluded())
+        setLockscreenPublicMode(mStatusBarKeyguardViewManager.isShowing()
                 && mStatusBarKeyguardViewManager.isSecure());
     }
 
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/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index bf5cdff..b516f00 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -116,6 +116,7 @@
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.HashSet;
+import java.util.List;
 
 import static android.view.WindowManager.LayoutParams.*;
 import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_ABSENT;
@@ -2299,24 +2300,19 @@
             boolean goingToNotificationShade) {
         if (goingToNotificationShade) {
             return AnimationUtils.loadAnimation(mContext, R.anim.lock_screen_behind_enter_fade_in);
-        } else if (onWallpaper) {
-            Animation a = AnimationUtils.loadAnimation(mContext,
-                    R.anim.lock_screen_behind_enter_wallpaper);
-            AnimationSet set = (AnimationSet) a;
-
-            // TODO: Use XML interpolators when we have log interpolators available in XML.
-            set.getAnimations().get(0).setInterpolator(mLogDecelerateInterpolator);
-            set.getAnimations().get(1).setInterpolator(mLogDecelerateInterpolator);
-            return set;
-        } else {
-            Animation a = AnimationUtils.loadAnimation(mContext,
-                    R.anim.lock_screen_behind_enter);
-            AnimationSet set = (AnimationSet) a;
-
-            // TODO: Use XML interpolators when we have log interpolators available in XML.
-            set.getAnimations().get(0).setInterpolator(mLogDecelerateInterpolator);
-            return set;
         }
+
+        AnimationSet set = (AnimationSet) AnimationUtils.loadAnimation(mContext, onWallpaper ?
+                    R.anim.lock_screen_behind_enter_wallpaper :
+                    R.anim.lock_screen_behind_enter);
+
+        // TODO: Use XML interpolators when we have log interpolators available in XML.
+        final List<Animation> animations = set.getAnimations();
+        for (int i = animations.size() - 1; i >= 0; --i) {
+            animations.get(i).setInterpolator(mLogDecelerateInterpolator);
+        }
+
+        return set;
     }
 
 
@@ -4767,18 +4763,39 @@
     @Override
     public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) {
         if ((policyFlags & FLAG_WAKE) != 0) {
-            wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotion);
-            return 0;
+            if (wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotion)) {
+                return 0;
+            }
         }
+
         if (shouldDispatchInputWhenNonInteractive()) {
             return ACTION_PASS_TO_USER;
         }
+
         return 0;
     }
 
     private boolean shouldDispatchInputWhenNonInteractive() {
-        return keyguardIsShowingTq() && mDisplay != null &&
-                mDisplay.getState() != Display.STATE_OFF;
+        // Send events to keyguard while the screen is on.
+        if (keyguardIsShowingTq() && mDisplay != null && mDisplay.getState() != Display.STATE_OFF) {
+            return true;
+        }
+
+        // Send events to a dozing dream even if the screen is off since the dream
+        // is in control of the state of the screen.
+        IDreamManager dreamManager = getDreamManager();
+
+        try {
+            if (dreamManager != null && dreamManager.isDreaming()) {
+                return true;
+            }
+        } catch (RemoteException e) {
+            Slog.e(TAG, "RemoteException when checking if dreaming", e);
+        }
+
+        // Otherwise, consume events since the user can't see what is being
+        // interacted with.
+        return false;
     }
 
     void dispatchMediaKeyWithWakeLock(KeyEvent event) {
@@ -4949,12 +4966,13 @@
         wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey);
     }
 
-    private void wakeUp(long wakeTime, boolean wakeInTheaterMode) {
+    private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode) {
         if (!wakeInTheaterMode && isTheaterModeEnabled()) {
-            return;
+            return false;
         }
 
         mPowerManager.wakeUp(wakeTime);
+        return true;
     }
 
     // Called on the PowerManager's Notifier thread.
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/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/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index 61ea1e8..8d93141 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -91,6 +91,9 @@
     boolean mKeyguardGoingAwayToNotificationShade;
     boolean mKeyguardGoingAwayDisableWindowAnimations;
 
+    /** Use one animation for all entering activities after keyguard is dismissed. */
+    Animation mPostKeyguardExitAnimation;
+
     // forceHiding states.
     static final int KEYGUARD_NOT_SHOWN     = 0;
     static final int KEYGUARD_ANIMATING_IN  = 1;
@@ -220,9 +223,6 @@
         ++mAnimTransactionSequence;
 
         final WindowList windows = mService.getWindowListLocked(displayId);
-        ArrayList<WindowStateAnimator> unForceHiding = null;
-        boolean wallpaperInUnForceHiding = false;
-        WindowState wallpaper = null;
 
         if (mKeyguardGoingAway) {
             for (int i = windows.size() - 1; i >= 0; i--) {
@@ -261,6 +261,9 @@
         final AppWindowToken appShowWhenLocked = winShowWhenLocked == null ?
                 null : winShowWhenLocked.mAppToken;
 
+        boolean wallpaperInUnForceHiding = false;
+        ArrayList<WindowStateAnimator> unForceHiding = null;
+        WindowState wallpaper = null;
         for (int i = windows.size() - 1; i >= 0; i--) {
             WindowState win = windows.get(i);
             WindowStateAnimator winAnimator = win.mWinAnimator;
@@ -327,40 +330,53 @@
                 } else if (mPolicy.canBeForceHidden(win, win.mAttrs)) {
                     final boolean hideWhenLocked = !((win.mIsImWindow && showImeOverKeyguard) ||
                             (appShowWhenLocked != null && appShowWhenLocked == win.mAppToken));
-                    final boolean changed;
                     if (((mForceHiding == KEYGUARD_ANIMATING_IN)
                                 && (!winAnimator.isAnimating() || hideWhenLocked))
                             || ((mForceHiding == KEYGUARD_SHOWN) && hideWhenLocked)) {
-                        changed = win.hideLw(false, false);
-                        if ((DEBUG_KEYGUARD || WindowManagerService.DEBUG_VISIBILITY)
-                                && changed) Slog.v(TAG, "Now policy hidden: " + win);
+                        if (!win.hideLw(false, false)) {
+                            // Was already hidden
+                            continue;
+                        }
+                        if (DEBUG_KEYGUARD || WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
+                                "Now policy hidden: " + win);
                     } else {
-                        changed = win.showLw(false, false);
-                        if ((DEBUG_KEYGUARD || WindowManagerService.DEBUG_VISIBILITY)
-                                && changed) Slog.v(TAG, "Now policy shown: " + win);
-                        if (changed) {
-                            if ((mBulkUpdateParams & SET_FORCE_HIDING_CHANGED) != 0
-                                    && win.isVisibleNow() /*w.isReadyForDisplay()*/) {
-                                if (unForceHiding == null) {
-                                    unForceHiding = new ArrayList<WindowStateAnimator>();
-                                }
-                                unForceHiding.add(winAnimator);
-                                if ((flags & FLAG_SHOW_WALLPAPER) != 0) {
-                                    wallpaperInUnForceHiding = true;
-                                }
+                        if (!win.showLw(false, false)) {
+                            // Was already showing.
+                            continue;
+                        }
+                        final boolean visibleNow = win.isVisibleNow();
+                        if (!visibleNow) {
+                            // Couldn't really show, must showLw() again when win becomes visible.
+                            win.hideLw(false, false);
+                            continue;
+                        }
+                        if (DEBUG_KEYGUARD || WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
+                                "Now policy shown: " + win);
+                        if ((mBulkUpdateParams & SET_FORCE_HIDING_CHANGED) != 0) {
+                            if (unForceHiding == null) {
+                                unForceHiding = new ArrayList<>();
                             }
-                            final WindowState currentFocus = mService.mCurrentFocus;
-                            if (currentFocus == null || currentFocus.mLayer < win.mLayer) {
-                                // We are showing on to of the current
-                                // focus, so re-evaluate focus to make
-                                // sure it is correct.
-                                if (WindowManagerService.DEBUG_FOCUS_LIGHT) Slog.v(TAG,
-                                        "updateWindowsLocked: setting mFocusMayChange true");
-                                mService.mFocusMayChange = true;
+                            unForceHiding.add(winAnimator);
+                            if ((flags & FLAG_SHOW_WALLPAPER) != 0) {
+                                wallpaperInUnForceHiding = true;
                             }
+                        } else if (mPostKeyguardExitAnimation != null) {
+                            // We're already in the middle of an animation. Use the existing
+                            // animation to bring in this window.
+                            winAnimator.setAnimation(mPostKeyguardExitAnimation);
+                            winAnimator.keyguardGoingAwayAnimation = true;
+                        }
+                        final WindowState currentFocus = mService.mCurrentFocus;
+                        if (currentFocus == null || currentFocus.mLayer < win.mLayer) {
+                            // We are showing on top of the current
+                            // focus, so re-evaluate focus to make
+                            // sure it is correct.
+                            if (WindowManagerService.DEBUG_FOCUS_LIGHT) Slog.v(TAG,
+                                    "updateWindowsLocked: setting mFocusMayChange true");
+                            mService.mFocusMayChange = true;
                         }
                     }
-                    if (changed && (flags & FLAG_SHOW_WALLPAPER) != 0) {
+                    if ((flags & FLAG_SHOW_WALLPAPER) != 0) {
                         mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
                         setPendingLayoutChanges(Display.DEFAULT_DISPLAY,
                                 WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
@@ -403,42 +419,44 @@
         // If we have windows that are being show due to them no longer
         // being force-hidden, apply the appropriate animation to them.
         if (unForceHiding != null) {
-            boolean startKeyguardExit = true;
-            for (int i=unForceHiding.size()-1; i>=0; i--) {
-                Animation a = null;
-                if (!mKeyguardGoingAwayDisableWindowAnimations) {
-                    a = mPolicy.createForceHideEnterAnimation(wallpaperInUnForceHiding,
-                            mKeyguardGoingAwayToNotificationShade);
-                    if (DEBUG_KEYGUARD) Slog.d(TAG, "updateWindowsLocked: created anim=" + a
-                            + " for win=" + unForceHiding.get(i));
-                } else {
-                    if (DEBUG_KEYGUARD) Slog.d(TAG, "updateWindowsLocked: skipping anim for win="
-                            + unForceHiding.get(i));
-                }
-                if (a != null) {
+            // This only happens the first time that we detect the keyguard is animating out.
+            if (mKeyguardGoingAwayDisableWindowAnimations) {
+                if (DEBUG_KEYGUARD) Slog.d(TAG, "updateWindowsLocked: skipping anim for windows");
+            } else {
+                if (DEBUG_KEYGUARD) Slog.d(TAG, "updateWindowsLocked: created anim for windows");
+                mPostKeyguardExitAnimation = mPolicy.createForceHideEnterAnimation(
+                        wallpaperInUnForceHiding, mKeyguardGoingAwayToNotificationShade);
+            }
+            if (mPostKeyguardExitAnimation != null) {
+                for (int i=unForceHiding.size()-1; i>=0; i--) {
                     final WindowStateAnimator winAnimator = unForceHiding.get(i);
-                    winAnimator.setAnimation(a);
+                    winAnimator.setAnimation(mPostKeyguardExitAnimation);
                     winAnimator.keyguardGoingAwayAnimation = true;
-                    if (startKeyguardExit && mKeyguardGoingAway) {
-                        // Do one time only.
-                        mPolicy.startKeyguardExitAnimation(mCurrentTime + a.getStartOffset(),
-                                a.getDuration());
-                        mKeyguardGoingAway = false;
-                        startKeyguardExit = false;
-                    }
                 }
             }
+        }
 
-            // Wallpaper is going away in un-force-hide motion, animate it as well.
-            if (!wallpaperInUnForceHiding && wallpaper != null
-                    && !mKeyguardGoingAwayDisableWindowAnimations) {
-                if (DEBUG_KEYGUARD) Slog.d(TAG, "updateWindowsLocked: wallpaper animating away");
-                Animation a = mPolicy.createForceHideWallpaperExitAnimation(
-                        mKeyguardGoingAwayToNotificationShade);
-                if (a != null) {
-                    WindowStateAnimator animator = wallpaper.mWinAnimator;
-                    animator.setAnimation(a);
-                }
+        if (mPostKeyguardExitAnimation != null) {
+            // We're in the midst of a keyguard exit animation.
+            if (mKeyguardGoingAway) {
+                mPolicy.startKeyguardExitAnimation(mCurrentTime +
+                        mPostKeyguardExitAnimation.getStartOffset(),
+                        mPostKeyguardExitAnimation.getDuration());
+                mKeyguardGoingAway = false;
+            } else if (mPostKeyguardExitAnimation.hasEnded()) {
+                // Done with the animation, reset.
+                mPostKeyguardExitAnimation = null;
+            }
+        }
+
+        // Wallpaper is going away in un-force-hide motion, animate it as well.
+        if (!wallpaperInUnForceHiding && wallpaper != null
+                && !mKeyguardGoingAwayDisableWindowAnimations) {
+            if (DEBUG_KEYGUARD) Slog.d(TAG, "updateWindowsLocked: wallpaper animating away");
+            Animation a = mPolicy.createForceHideWallpaperExitAnimation(
+                    mKeyguardGoingAwayToNotificationShade);
+            if (a != null) {
+                wallpaper.mWinAnimator.setAnimation(a);
             }
         }
     }
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/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 4eac5ac..d98a255 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -17,6 +17,7 @@
 import android.annotation.SystemApi;
 import android.content.ComponentName;
 import android.content.Context;
+import android.net.Uri;
 import android.os.Bundle;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -926,7 +927,6 @@
      * @param accountHandle The handle for the account the MMI code should apply to.
      * @param dialString The digits to dial.
      * @return True if the digits were processed as an MMI code, false otherwise.
-     *
      */
     public boolean handleMmi(PhoneAccountHandle accountHandle, String dialString) {
         ITelecomService service = getTelecomService();
@@ -941,6 +941,24 @@
     }
 
     /**
+     * @param accountHandle The handle for the account to derive an adn query URI for or
+     * {@code null} to return a URI which will use the default account.
+     * @return The URI (with the content:// scheme) specific to the specified {@link PhoneAccount}
+     * for the the content retrieve.
+     */
+    public Uri getAdnUriForPhoneAccount(PhoneAccountHandle accountHandle) {
+        ITelecomService service = getTelecomService();
+        if (service != null && accountHandle != null) {
+            try {
+                return service.getAdnUriForPhoneAccount(accountHandle);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Error calling ITelecomService#getAdnUriForPhoneAccount", e);
+            }
+        }
+        return Uri.parse("content://icc/adn");
+    }
+
+    /**
      * Removes the missed-call notification if one is present.
      * <p>
      * Requires that the method-caller be set as the system dialer app.
diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
index fd47213..cbd9d69 100644
--- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
+++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
@@ -18,6 +18,7 @@
 
 import android.content.ComponentName;
 import android.telecom.PhoneAccountHandle;
+import android.net.Uri;
 import android.os.Bundle;
 import android.telecom.PhoneAccount;
 
@@ -174,6 +175,11 @@
     boolean handlePinMmiForPhoneAccount(in PhoneAccountHandle accountHandle, String dialString);
 
     /**
+     * @see TelecomServiceImpl#getAdnUriForPhoneAccount
+     */
+    Uri getAdnUriForPhoneAccount(in PhoneAccountHandle accountHandle);
+
+    /**
      * @see TelecomServiceImpl#isTtySupported
      */
     boolean isTtySupported();
diff --git a/telephony/java/android/telephony/SubInfoRecord.java b/telephony/java/android/telephony/SubInfoRecord.java
index 4a3d67e..e08f255 100644
--- a/telephony/java/android/telephony/SubInfoRecord.java
+++ b/telephony/java/android/telephony/SubInfoRecord.java
@@ -29,98 +29,138 @@
      * Subscription Identifier, this is a device unique number
      * and not an index into an array
      */
-    public int subId;
-    /** The GID for a SIM that maybe associated with this subscription, empty if unknown */
-    public String iccId;
+    private int mId;
+
     /**
-     * The slot identifier for that currently contains the subscription
+     * The GID for a SIM that maybe associated with this subscription, empty if unknown
+     */
+    private String mIccId;
+
+    /**
+     * The index of the slot that currently contains the subscription
      * and not necessarily unique and maybe INVALID_SLOT_ID if unknown
      */
-    public int slotId;
+    private int mSimSlotIndex;
+
     /**
-     * The string displayed to the user that identifies this subscription
+     * The name displayed to the user that identifies this subscription
      */
-    public String displayName;
+    private CharSequence mDisplayName;
+
     /**
      * The source of the name, NAME_SOURCE_UNDEFINED, NAME_SOURCE_DEFAULT_SOURCE,
      * NAME_SOURCE_SIM_SOURCE or NAME_SOURCE_USER_INPUT.
      */
-    public int nameSource;
+    private int mNameSource;
+
     /**
      * The color to be used for when displaying to the user
      */
-    public int color;
+    private int mColor;
+
     /**
      * A number presented to the user identify this subscription
      */
-    public String number;
-    /**
-     * How to display the phone number, DISPLAY_NUMBER_NONE, DISPLAY_NUMBER_FIRST,
-     * DISPLAY_NUMBER_LAST
-     */
-    public int displayNumberFormat;
+    private String mNumber;
+
     /**
      * Data roaming state, DATA_RAOMING_ENABLE, DATA_RAOMING_DISABLE
      */
-    public int dataRoaming;
+    private int mDataRoaming;
+
     /**
      * SIM Icon resource identifiers. FIXME: Check with MTK what it really is
      */
-    public int[] simIconRes;
+    private int[] mSimIconRes;
+
     /**
      * Mobile Country Code
      */
-    public int mcc;
+    private int mMcc;
+
     /**
      * Mobile Network Code
      */
-    public int mnc;
+    private int mMnc;
 
+    /**
+     * @hide
     public SubInfoRecord() {
-        this.subId = SubscriptionManager.INVALID_SUB_ID;
-        this.iccId = "";
-        this.slotId = SubscriptionManager.INVALID_SLOT_ID;
-        this.displayName = "";
-        this.nameSource = 0;
-        this.color = 0;
-        this.number = "";
-        this.displayNumberFormat = 0;
-        this.dataRoaming = 0;
-        this.simIconRes = new int[2];
-        this.mcc = 0;
-        this.mnc = 0;
+        this.mId = SubscriptionManager.INVALID_SUB_ID;
+        this.mIccId = "";
+        this.mSimSlotIndex = SubscriptionManager.INVALID_SLOT_ID;
+        this.mDisplayName = "";
+        this.mNameSource = 0;
+        this.mColor = 0;
+        this.mNumber = "";
+        this.mDataRoaming = 0;
+        this.mSimIconRes = new int[2];
+        this.mMcc = 0;
+        this.mMnc = 0;
     }
+     */
 
-    public SubInfoRecord(int subId, String iccId, int slotId, String displayName, int nameSource,
-            int color, String number, int displayFormat, int roaming, int[] iconRes,
-            int mcc, int mnc) {
-        this.subId = subId;
-        this.iccId = iccId;
-        this.slotId = slotId;
-        this.displayName = displayName;
-        this.nameSource = nameSource;
-        this.color = color;
-        this.number = number;
-        this.displayNumberFormat = displayFormat;
-        this.dataRoaming = roaming;
-        this.simIconRes = iconRes;
-        this.mcc = mcc;
-        this.mnc = mnc;
+    /**
+     * @hide
+     */
+    public SubInfoRecord(int id, String iccId, int simSlotIndex, CharSequence displayName,
+            int nameSource, int color, String number, int roaming, int[] iconRes, int mcc,
+            int mnc) {
+        this.mId = id;
+        this.mIccId = iccId;
+        this.mSimSlotIndex = simSlotIndex;
+        this.mDisplayName = displayName;
+        this.mNameSource = nameSource;
+        this.mColor = color;
+        this.mNumber = number;
+        this.mDataRoaming = roaming;
+        this.mSimIconRes = iconRes;
+        this.mMcc = mcc;
+        this.mMnc = mnc;
     }
 
     /**
-     * Returns the string displayed to the user that identifies this subscription
+     * Returns the subscription ID.
      */
-    public String getLabel() {
-        return this.displayName;
+    public int getSubscriptionId() {
+        return this.mId;
     }
 
     /**
-     * Return the icon used to identify this SIM.
-     * TODO: return the correct drawable.
+     * Returns the ICC ID.
      */
-    public BitmapDrawable getIconDrawable() {
-        return new BitmapDrawable();
+    public String getIccId() {
+        return this.mIccId;
+    }
+
+    /**
+     * Returns the slot index of this Subscription's SIM card.
+     */
+    public int getSimSlotIndex() {
+        return this.mSimSlotIndex;
+    }
+
+    /**
+     * Returns the name displayed to the user that identifies this subscription
+     */
+    public CharSequence getDisplayName() {
+        return this.mDisplayName;
+    }
+
+    /**
+     * Sets the name displayed to the user that identifies this subscription
+     * @hide
+     */
+    public void setDisplayName(CharSequence name) {
+        this.mDisplayName = name;
+    }
+
+    /**
+     * Return the source of the name, eg NAME_SOURCE_UNDEFINED, NAME_SOURCE_DEFAULT_SOURCE,
+     * NAME_SOURCE_SIM_SOURCE or NAME_SOURCE_USER_INPUT.
+     */
+    public int getNameSource() {
+        return this.mNameSource;
     }
 
     /**
@@ -130,28 +170,70 @@
     public int getColor() {
         // Note: This color is currently an index into a list of drawables, but this is soon to
         // change.
-        return this.color;
+        return this.mColor;
+    }
+
+    /**
+     * Sets the color displayed to the user that identifies this subscription
+     * @hide
+     */
+    public void setColor(int color) {
+        this.mColor = color;
+    }
+
+    /**
+     * Returns the number of this subscription.
+     */
+    public String getNumber() {
+        return mNumber;
+    }
+
+    /**
+     * Return the data roaming value.
+     */
+    public int getDataRoaming() {
+        return this.mDataRoaming;
+    }
+
+    /**
+     * Return the icon used to identify this subscription.
+     */
+    public BitmapDrawable getIcon() {
+        return new BitmapDrawable();
+    }
+
+    /**
+     * Returns the MCC.
+     */
+    public int getMcc() {
+        return this.mMcc;
+    }
+
+    /**
+     * Returns the MNC.
+     */
+    public int getMnc() {
+        return this.mMnc;
     }
 
     public static final Parcelable.Creator<SubInfoRecord> CREATOR = new Parcelable.Creator<SubInfoRecord>() {
         @Override
         public SubInfoRecord createFromParcel(Parcel source) {
-            int subId = source.readInt();
+            int id = source.readInt();
             String iccId = source.readString();
-            int slotId = source.readInt();
-            String displayName = source.readString();
+            int simSlotIndex = source.readInt();
+            CharSequence displayName = source.readCharSequence();
             int nameSource = source.readInt();
             int color = source.readInt();
             String number = source.readString();
-            int displayNumberFormat = source.readInt();
             int dataRoaming = source.readInt();
             int[] iconRes = new int[2];
             source.readIntArray(iconRes);
             int mcc = source.readInt();
             int mnc = source.readInt();
 
-            return new SubInfoRecord(subId, iccId, slotId, displayName, nameSource, color, number,
-                displayNumberFormat, dataRoaming, iconRes, mcc, mnc);
+            return new SubInfoRecord(id, iccId, simSlotIndex, displayName, nameSource, color, number,
+                    dataRoaming, iconRes, mcc, mnc);
         }
 
         @Override
@@ -162,18 +244,17 @@
 
     @Override
     public void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(subId);
-        dest.writeString(iccId);
-        dest.writeInt(slotId);
-        dest.writeString(displayName);
-        dest.writeInt(nameSource);
-        dest.writeInt(color);
-        dest.writeString(number);
-        dest.writeInt(displayNumberFormat);
-        dest.writeInt(dataRoaming);
-        dest.writeIntArray(simIconRes);
-        dest.writeInt(mcc);
-        dest.writeInt(mnc);
+        dest.writeInt(mId);
+        dest.writeString(mIccId);
+        dest.writeInt(mSimSlotIndex);
+        dest.writeCharSequence(mDisplayName);
+        dest.writeInt(mNameSource);
+        dest.writeInt(mColor);
+        dest.writeString(mNumber.toString());
+        dest.writeInt(mDataRoaming);
+        dest.writeIntArray(mSimIconRes);
+        dest.writeInt(mMcc);
+        dest.writeInt(mMnc);
     }
 
     @Override
@@ -183,10 +264,9 @@
 
     @Override
     public String toString() {
-        return "{mSubId=" + subId + ", mIccId=" + iccId + " mSlotId=" + slotId
-                + " mDisplayName=" + displayName + " mNameSource=" + nameSource
-                + " mColor=" + color + " mNumber=" + number
-                + " mDisplayNumberFormat=" + displayNumberFormat + " mDataRoaming=" + dataRoaming
-                + " mSimIconRes=" + simIconRes + " mMcc " + mcc + " mMnc " + mnc + "}";
+        return "{id=" + mId + ", iccId=" + mIccId + " simSlotIndex=" + mSimSlotIndex
+                + " displayName=" + mDisplayName + " nameSource=" + mNameSource + " color=" + mColor
+                + " number=" + mNumber + " dataRoaming=" + mDataRoaming + " simIconRes=" + mSimIconRes
+                + " mcc " + mMcc + " mnc " + mMnc + "}";
     }
 }
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index edfddc7..9cd533d 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -209,7 +209,7 @@
     public static final int DISPLAY_NUMBER_LAST = 2;
 
     /** @hide */
-    public static final int DISLPAY_NUMBER_DEFAULT = DISPLAY_NUMBER_FIRST;
+    public static final int DISPLAY_NUMBER_DEFAULT = DISPLAY_NUMBER_FIRST;
 
     /**
      * TelephonyProvider column name for permission for data roaming of a SIM.
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;
                 }
diff --git a/tools/aapt/AaptUtil.h b/tools/aapt/AaptUtil.h
index 47a704a..89e1ee8 100644
--- a/tools/aapt/AaptUtil.h
+++ b/tools/aapt/AaptUtil.h
@@ -14,9 +14,11 @@
  * limitations under the License.
  */
 
-#ifndef __AAPT_UTIL_H
-#define __AAPT_UTIL_H
+#ifndef H_AAPT_UTIL
+#define H_AAPT_UTIL
 
+#include <utils/KeyedVector.h>
+#include <utils/SortedVector.h>
 #include <utils/String8.h>
 #include <utils/Vector.h>
 
@@ -25,6 +27,38 @@
 android::Vector<android::String8> split(const android::String8& str, const char sep);
 android::Vector<android::String8> splitAndLowerCase(const android::String8& str, const char sep);
 
+template <typename KEY, typename VALUE>
+void appendValue(android::KeyedVector<KEY, android::Vector<VALUE> >& keyedVector,
+        const KEY& key, const VALUE& value);
+
+template <typename KEY, typename VALUE>
+void appendValue(android::KeyedVector<KEY, android::SortedVector<VALUE> >& keyedVector,
+        const KEY& key, const VALUE& value);
+
+//
+// Implementations
+//
+
+template <typename KEY, typename VALUE>
+void appendValue(android::KeyedVector<KEY, android::Vector<VALUE> >& keyedVector,
+        const KEY& key, const VALUE& value) {
+    ssize_t idx = keyedVector.indexOfKey(key);
+    if (idx < 0) {
+        idx = keyedVector.add(key, android::Vector<VALUE>());
+    }
+    keyedVector.editValueAt(idx).add(value);
+}
+
+template <typename KEY, typename VALUE>
+void appendValue(android::KeyedVector<KEY, android::SortedVector<VALUE> >& keyedVector,
+        const KEY& key, const VALUE& value) {
+    ssize_t idx = keyedVector.indexOfKey(key);
+    if (idx < 0) {
+        idx = keyedVector.add(key, android::SortedVector<VALUE>());
+    }
+    keyedVector.editValueAt(idx).add(value);
+}
+
 } // namespace AaptUtil
 
-#endif // __AAPT_UTIL_H
+#endif // H_AAPT_UTIL
diff --git a/tools/aapt/AaptXml.cpp b/tools/aapt/AaptXml.cpp
index 708e405..b04a55d 100644
--- a/tools/aapt/AaptXml.cpp
+++ b/tools/aapt/AaptXml.cpp
@@ -41,7 +41,7 @@
     }
 
     size_t len;
-    const uint16_t* str = tree.getAttributeStringValue(attrIndex, &len);
+    const char16_t* str = tree.getAttributeStringValue(attrIndex, &len);
     return str ? String8(str, len) : String8();
 }
 
@@ -103,7 +103,7 @@
     if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
         if (value.dataType == Res_value::TYPE_STRING) {
             size_t len;
-            const uint16_t* str = tree.getAttributeStringValue(idx, &len);
+            const char16_t* str = tree.getAttributeStringValue(idx, &len);
             return str ? String8(str, len) : String8();
         }
         resTable.resolveReference(&value, 0);
diff --git a/tools/aapt/Android.mk b/tools/aapt/Android.mk
index 2cbabe1..bc9c1f7 100644
--- a/tools/aapt/Android.mk
+++ b/tools/aapt/Android.mk
@@ -33,20 +33,20 @@
     Command.cpp \
     CrunchCache.cpp \
     FileFinder.cpp \
+    Images.cpp \
     Package.cpp \
-    StringPool.cpp \
-    XMLNode.cpp \
+    pseudolocalize.cpp \
+    qsort_r_compat.c \
+    Resource.cpp \
     ResourceFilter.cpp \
     ResourceIdCache.cpp \
     ResourceTable.cpp \
-    Images.cpp \
-    Resource.cpp \
-    pseudolocalize.cpp \
     SourcePos.cpp \
+    StringPool.cpp \
     WorkQueue.cpp \
+    XMLNode.cpp \
     ZipEntry.cpp \
-    ZipFile.cpp \
-    qsort_r_compat.c
+    ZipFile.cpp
 
 aaptTests := \
     tests/AaptConfig_test.cpp \
@@ -88,16 +88,13 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE := libaapt
-
-LOCAL_SRC_FILES := $(aaptSources)
-LOCAL_C_INCLUDES += $(aaptCIncludes)
-
-LOCAL_CFLAGS += -Wno-format-y2k
-LOCAL_CFLAGS += -DSTATIC_ANDROIDFW_FOR_TOOLS
-LOCAL_CFLAGS += $(aaptCFlags)
+LOCAL_CFLAGS += -Wno-format-y2k -DSTATIC_ANDROIDFW_FOR_TOOLS $(aaptCFlags)
+LOCAL_CPPFLAGS += $(aaptCppFlags)
 ifeq (darwin,$(HOST_OS))
 LOCAL_CFLAGS += -D_DARWIN_UNLIMITED_STREAMS
 endif
+LOCAL_C_INCLUDES += $(aaptCIncludes)
+LOCAL_SRC_FILES := $(aaptSources)
 
 include $(BUILD_HOST_STATIC_LIBRARY)
 
@@ -108,15 +105,11 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE := aapt
-
-LOCAL_SRC_FILES := $(aaptMain)
-
-LOCAL_STATIC_LIBRARIES += \
-    libaapt \
-    $(aaptHostStaticLibs)
-
-LOCAL_LDLIBS += $(aaptHostLdLibs)
 LOCAL_CFLAGS += $(aaptCFlags)
+LOCAL_CPPFLAGS += $(aaptCppFlags)
+LOCAL_LDLIBS += $(aaptHostLdLibs)
+LOCAL_SRC_FILES := $(aaptMain)
+LOCAL_STATIC_LIBRARIES += libaapt $(aaptHostStaticLibs)
 
 include $(BUILD_HOST_EXECUTABLE)
 
@@ -127,16 +120,12 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE := libaapt_tests
-
+LOCAL_CFLAGS += $(aaptCFlags)
+LOCAL_CPPFLAGS += $(aaptCppFlags)
+LOCAL_LDLIBS += $(aaptHostLdLibs)
 LOCAL_SRC_FILES += $(aaptTests)
 LOCAL_C_INCLUDES += $(LOCAL_PATH)
-
-LOCAL_STATIC_LIBRARIES += \
-    libaapt \
-    $(aaptHostStaticLibs)
-
-LOCAL_LDLIBS += $(aaptHostLdLibs)
-LOCAL_CFLAGS += $(aaptCFlags)
+LOCAL_STATIC_LIBRARIES += libaapt $(aaptHostStaticLibs)
 
 include $(BUILD_HOST_NATIVE_TEST)
 
@@ -148,13 +137,12 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE := aapt
-
+LOCAL_CFLAGS += $(aaptCFlags)
 LOCAL_SRC_FILES := $(aaptSources) $(aaptMain)
 LOCAL_C_INCLUDES += \
     $(aaptCIncludes) \
     bionic \
     external/stlport/stlport
-
 LOCAL_SHARED_LIBRARIES := \
     libandroidfw \
     libutils \
@@ -162,14 +150,10 @@
     libpng \
     liblog \
     libz
-
 LOCAL_STATIC_LIBRARIES := \
     libstlport_static \
     libexpat_static
 
-LOCAL_CFLAGS += $(aaptCFlags)
-LOCAL_CPPFLAGS += -Wno-non-virtual-dtor
-
 include $(BUILD_EXECUTABLE)
 
 endif # Not SDK_ONLY
diff --git a/tools/aapt/CacheUpdater.h b/tools/aapt/CacheUpdater.h
index efb2453..fade53a 100644
--- a/tools/aapt/CacheUpdater.h
+++ b/tools/aapt/CacheUpdater.h
@@ -30,6 +30,8 @@
  */
 class CacheUpdater {
 public:
+    virtual ~CacheUpdater() {}
+
     // Make sure all the directories along this path exist
     virtual void ensureDirectoriesExist(String8 path) = 0;
 
@@ -107,4 +109,4 @@
     Bundle* bundle;
 };
 
-#endif // CACHE_UPDATER_H
\ No newline at end of file
+#endif // CACHE_UPDATER_H
diff --git a/tools/aapt/Main.cpp b/tools/aapt/Main.cpp
index 2857b59..18b8e1e 100644
--- a/tools/aapt/Main.cpp
+++ b/tools/aapt/Main.cpp
@@ -11,9 +11,9 @@
 #include <utils/List.h>
 #include <utils/Errors.h>
 
-#include <stdlib.h>
+#include <cstdlib>
 #include <getopt.h>
-#include <assert.h>
+#include <cassert>
 
 using namespace android;
 
diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp
index a4c9dab..b9bd03a 100644
--- a/tools/aapt/Resource.cpp
+++ b/tools/aapt/Resource.cpp
@@ -261,7 +261,7 @@
                 ssize_t minSdkIndex = block.indexOfAttribute(RESOURCES_ANDROID_NAMESPACE,
                                                              "minSdkVersion");
                 if (minSdkIndex >= 0) {
-                    const uint16_t* minSdk16 = block.getAttributeStringValue(minSdkIndex, &len);
+                    const char16_t* minSdk16 = block.getAttributeStringValue(minSdkIndex, &len);
                     const char* minSdk8 = strdup(String8(minSdk16).string());
                     bundle->setManifestMinSdkVersion(minSdk8);
                 }
@@ -450,7 +450,7 @@
     size_t len;
 
     ssize_t index = parser.indexOfAttribute(ns, attr);
-    const uint16_t* str;
+    const char16_t* str;
     Res_value value;
     if (index >= 0 && parser.getAttributeValue(index, &value) >= 0) {
         const ResStringPool* pool = &parser.getStrings();
@@ -503,7 +503,7 @@
         }
         if (validChars) {
             for (size_t i=0; i<len; i++) {
-                uint16_t c = str[i];
+                char16_t c = str[i];
                 const char* p = validChars;
                 bool okay = false;
                 while (*p) {
@@ -1710,7 +1710,7 @@
                 }
                 size_t len;
                 ssize_t index = block.indexOfAttribute(RESOURCES_ANDROID_NAMESPACE, "name");
-                const uint16_t* id = block.getAttributeStringValue(index, &len);
+                const char16_t* id = block.getAttributeStringValue(index, &len);
                 if (id == NULL) {
                     fprintf(stderr, "%s:%d: missing name attribute in element <%s>.\n", 
                             manifestPath.string(), block.getLineNumber(),
@@ -1753,7 +1753,7 @@
                   hasErrors = true;
                 }
                 syms->addStringSymbol(String8(e), idStr, srcPos);
-                const uint16_t* cmt = block.getComment(&len);
+                const char16_t* cmt = block.getComment(&len);
                 if (cmt != NULL && *cmt != 0) {
                     //printf("Comment of %s: %s\n", String8(e).string(),
                     //        String8(cmt).string());
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index 4587a4b..0f94f85 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -399,7 +399,7 @@
 
     ssize_t l10nIdx = block.indexOfAttribute(NULL, "localization");
     if (l10nIdx >= 0) {
-        const uint16_t* str = block.getAttributeStringValue(l10nIdx, &len);
+        const char16_t* str = block.getAttributeStringValue(l10nIdx, &len);
         bool error;
         uint32_t l10n_required = parse_flags(str, len, l10nRequiredFlags, &error);
         if (error) {
@@ -1325,7 +1325,7 @@
                 size_t n = block.getAttributeCount();
                 for (size_t i = 0; i < n; i++) {
                     size_t length;
-                    const uint16_t* attr = block.getAttributeName(i, &length);
+                    const char16_t* attr = block.getAttributeName(i, &length);
                     if (strcmp16(attr, name16.string()) == 0) {
                         name.setTo(block.getAttributeStringValue(i, &length));
                     } else if (strcmp16(attr, translatable16.string()) == 0) {
@@ -1441,14 +1441,14 @@
                 // translatable.
                 for (size_t i = 0; i < n; i++) {
                     size_t length;
-                    const uint16_t* attr = block.getAttributeName(i, &length);
+                    const char16_t* attr = block.getAttributeName(i, &length);
                     if (strcmp16(attr, formatted16.string()) == 0) {
-                        const uint16_t* value = block.getAttributeStringValue(i, &length);
+                        const char16_t* value = block.getAttributeStringValue(i, &length);
                         if (strcmp16(value, false16.string()) == 0) {
                             curIsFormatted = false;
                         }
                     } else if (strcmp16(attr, translatable16.string()) == 0) {
-                        const uint16_t* value = block.getAttributeStringValue(i, &length);
+                        const char16_t* value = block.getAttributeStringValue(i, &length);
                         if (strcmp16(value, false16.string()) == 0) {
                             isTranslatable = false;
                         }
diff --git a/tools/aapt/StringPool.cpp b/tools/aapt/StringPool.cpp
index 06769e4..2727b3d 100644
--- a/tools/aapt/StringPool.cpp
+++ b/tools/aapt/StringPool.cpp
@@ -21,7 +21,8 @@
 
 #define NOISY(x) //x
 
-void strcpy16_htod(uint16_t* dst, const uint16_t* src)
+#if __cplusplus >= 201103L
+void strcpy16_htod(char16_t* dst, const char16_t* src)
 {
     while (*src) {
         char16_t s = htods(*src);
@@ -30,6 +31,17 @@
     }
     *dst = 0;
 }
+#endif
+
+void strcpy16_htod(uint16_t* dst, const char16_t* src)
+{
+    while (*src) {
+        uint16_t s = htods(static_cast<uint16_t>(*src));
+        *dst++ = s;
+        src++;
+    }
+    *dst = 0;
+}
 
 void printStringPool(const ResStringPool* pool)
 {
@@ -416,7 +428,7 @@
         return NO_MEMORY;
     }
 
-    const size_t charSize = mUTF8 ? sizeof(uint8_t) : sizeof(char16_t);
+    const size_t charSize = mUTF8 ? sizeof(uint8_t) : sizeof(uint16_t);
 
     size_t strPos = 0;
     for (i=0; i<STRINGS; i++) {
diff --git a/tools/aapt/StringPool.h b/tools/aapt/StringPool.h
index 1b3abfd..a9c7bec 100644
--- a/tools/aapt/StringPool.h
+++ b/tools/aapt/StringPool.h
@@ -26,7 +26,10 @@
 
 #define PRINT_STRING_METRICS 0
 
-void strcpy16_htod(uint16_t* dst, const uint16_t* src);
+#if __cplusplus >= 201103L
+void strcpy16_htod(char16_t* dst, const char16_t* src);
+#endif
+void strcpy16_htod(uint16_t* dst, const char16_t* src);
 
 void printStringPool(const ResStringPool* pool);
 
diff --git a/tools/aapt/XMLNode.cpp b/tools/aapt/XMLNode.cpp
index 51a4154..899fb63 100644
--- a/tools/aapt/XMLNode.cpp
+++ b/tools/aapt/XMLNode.cpp
@@ -234,9 +234,9 @@
             const String8 element8(element16);
 
             size_t nslen;
-            const uint16_t* ns = inXml->getElementNamespace(&nslen);
+            const char16_t* ns = inXml->getElementNamespace(&nslen);
             if (ns == NULL) {
-                ns = (const uint16_t*)"\0\0";
+                ns = (const char16_t*)"\0\0";
                 nslen = 0;
             }
             const String8 nspace(String16(ns, nslen));
@@ -291,9 +291,9 @@
 
         } else if (code == ResXMLTree::END_TAG) {
             size_t nslen;
-            const uint16_t* ns = inXml->getElementNamespace(&nslen);
+            const char16_t* ns = inXml->getElementNamespace(&nslen);
             if (ns == NULL) {
-                ns = (const uint16_t*)"\0\0";
+                ns = (const char16_t*)"\0\0";
                 nslen = 0;
             }
             const String8 nspace(String16(ns, nslen));
@@ -422,7 +422,7 @@
 }
 
 static String8 build_namespace(const Vector<namespace_entry>& namespaces,
-        const uint16_t* ns)
+        const char16_t* ns)
 {
     String8 str;
     if (ns != NULL) {
@@ -453,9 +453,9 @@
         int i;
         if (code == ResXMLTree::START_TAG) {
             size_t len;
-            const uint16_t* ns16 = block->getElementNamespace(&len);
+            const char16_t* ns16 = block->getElementNamespace(&len);
             String8 elemNs = build_namespace(namespaces, ns16);
-            const uint16_t* com16 = block->getComment(&len);
+            const char16_t* com16 = block->getComment(&len);
             if (com16) {
                 printf("%s <!-- %s -->\n", prefix.string(), String8(com16).string());
             }
@@ -503,7 +503,7 @@
         } else if (code == ResXMLTree::START_NAMESPACE) {
             namespace_entry ns;
             size_t len;
-            const uint16_t* prefix16 = block->getNamespacePrefix(&len);
+            const char16_t* prefix16 = block->getNamespacePrefix(&len);
             if (prefix16) {
                 ns.prefix = String8(prefix16);
             } else {
@@ -518,7 +518,7 @@
             depth--;
             const namespace_entry& ns = namespaces.top();
             size_t len;
-            const uint16_t* prefix16 = block->getNamespacePrefix(&len);
+            const char16_t* prefix16 = block->getNamespacePrefix(&len);
             String8 pr;
             if (prefix16) {
                 pr = String8(prefix16);
diff --git a/tools/layoutlib/bridge/src/android/view/WindowCallback.java b/tools/layoutlib/bridge/src/android/view/WindowCallback.java
new file mode 100644
index 0000000..78242a8
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/view/WindowCallback.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.view.ActionMode.Callback;
+import android.view.WindowManager.LayoutParams;
+import android.view.accessibility.AccessibilityEvent;
+
+/**
+ * An empty implementation of {@link Window.Callback} that always returns null/false.
+ */
+public class WindowCallback implements Window.Callback {
+    @Override
+    public boolean dispatchKeyEvent(KeyEvent event) {
+        return false;
+    }
+
+    @Override
+    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
+        return false;
+    }
+
+    @Override
+    public boolean dispatchTouchEvent(MotionEvent event) {
+        return false;
+    }
+
+    @Override
+    public boolean dispatchTrackballEvent(MotionEvent event) {
+        return false;
+    }
+
+    @Override
+    public boolean dispatchGenericMotionEvent(MotionEvent event) {
+        return false;
+    }
+
+    @Override
+    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
+        return false;
+    }
+
+    @Override
+    public View onCreatePanelView(int featureId) {
+        return null;
+    }
+
+    @Override
+    public boolean onCreatePanelMenu(int featureId, Menu menu) {
+        return false;
+    }
+
+    @Override
+    public boolean onPreparePanel(int featureId, View view, Menu menu) {
+        return false;
+    }
+
+    @Override
+    public boolean onMenuOpened(int featureId, Menu menu) {
+        return false;
+    }
+
+    @Override
+    public boolean onMenuItemSelected(int featureId, MenuItem item) {
+        return false;
+    }
+
+    @Override
+    public void onWindowAttributesChanged(LayoutParams attrs) {
+
+    }
+
+    @Override
+    public void onContentChanged() {
+
+    }
+
+    @Override
+    public void onWindowFocusChanged(boolean hasFocus) {
+
+    }
+
+    @Override
+    public void onAttachedToWindow() {
+
+    }
+
+    @Override
+    public void onDetachedFromWindow() {
+
+    }
+
+    @Override
+    public void onPanelClosed(int featureId, Menu menu) {
+
+    }
+
+    @Override
+    public boolean onSearchRequested() {
+        return false;
+    }
+
+    @Override
+    public ActionMode onWindowStartingActionMode(Callback callback) {
+        return null;
+    }
+
+    @Override
+    public void onActionModeStarted(ActionMode mode) {
+
+    }
+
+    @Override
+    public void onActionModeFinished(ActionMode mode) {
+
+    }
+}
diff --git a/tools/layoutlib/bridge/src/android/widget/Toolbar_Accessor.java b/tools/layoutlib/bridge/src/android/widget/Toolbar_Accessor.java
new file mode 100644
index 0000000..fdd1779
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/widget/Toolbar_Accessor.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.widget;
+
+import android.content.Context;
+
+/**
+ * To access non public members of classes in {@link Toolbar}
+ */
+public class Toolbar_Accessor {
+    public static ActionMenuPresenter getActionMenuPresenter(Toolbar toolbar) {
+        return toolbar.getOuterActionMenuPresenter();
+    }
+
+    public static Context getPopupContext(Toolbar toolbar) {
+        return toolbar.getPopupContext();
+    }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
index 825731b..ec78712 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
@@ -19,6 +19,7 @@
 import static com.android.ide.common.rendering.api.Result.Status.ERROR_UNKNOWN;
 import static com.android.ide.common.rendering.api.Result.Status.SUCCESS;
 
+import com.android.annotations.NonNull;
 import com.android.ide.common.rendering.api.Capability;
 import com.android.ide.common.rendering.api.DrawableParams;
 import com.android.ide.common.rendering.api.LayoutLog;
@@ -459,7 +460,7 @@
 
     public static void setLog(LayoutLog log) {
         // check only the thread currently owning the lock can do this.
-        if (sLock.isHeldByCurrentThread() == false) {
+        if (!sLock.isHeldByCurrentThread()) {
             throw new IllegalStateException("scene must be acquired first. see #acquire(long)");
         }
 
@@ -489,7 +490,6 @@
 
     /**
      * Returns the name of a framework resource whose value is an int array.
-     * @param array
      */
     public static String resolveResourceId(int[] array) {
         sIntArrayWrapper.set(array);
@@ -502,6 +502,7 @@
      * @param name the name of the resource.
      * @return an {@link Integer} containing the resource id, or null if no resource were found.
      */
+    @NonNull
     public static Integer getResourceId(ResourceType type, String name) {
         Map<String, Integer> map = sRevRMap.get(type);
         Integer value = null;
@@ -509,11 +510,8 @@
             value = map.get(name);
         }
 
-        if (value == null) {
-            value = sDynamicIds.getId(type, name);
-        }
+        return value == null ? sDynamicIds.getId(type, name) : value;
 
-        return value;
     }
 
     /**
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index d804230..3d3afa4 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -52,7 +52,6 @@
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.content.res.Resources.Theme;
-import android.content.res.TypedArray;
 import android.database.DatabaseErrorHandler;
 import android.database.sqlite.SQLiteDatabase;
 import android.database.sqlite.SQLiteDatabase.CursorFactory;
@@ -127,7 +126,6 @@
      * @param metrics the {@link DisplayMetrics}.
      * @param renderResources the configured resources (both framework and projects) for this
      * render.
-     * @param projectCallback
      * @param config the Configuration object for this render.
      * @param targetSdkVersion the targetSdkVersion of the application.
      */
@@ -331,7 +329,7 @@
             boolean attachToRoot, boolean skipCallbackParser) {
         boolean isPlatformLayout = resource.isFramework();
 
-        if (isPlatformLayout == false && skipCallbackParser == false) {
+        if (!isPlatformLayout && !skipCallbackParser) {
             // check if the project callback can provide us with a custom parser.
             ILayoutPullParser parser = getParser(resource);
 
@@ -663,7 +661,7 @@
                 }
 
                 String attrName = attribute.getFirst();
-                boolean frameworkAttr = attribute.getSecond().booleanValue();
+                boolean frameworkAttr = attribute.getSecond();
                 String value = null;
                 if (set != null) {
                     value = set.getAttributeValue(
@@ -672,7 +670,7 @@
 
                     // if this is an app attribute, and the first get fails, try with the
                     // new res-auto namespace as well
-                    if (frameworkAttr == false && value == null) {
+                    if (!frameworkAttr && value == null) {
                         value = set.getAttributeValue(BridgeConstants.NS_APP_RES_AUTO, attrName);
                     }
                 }
@@ -789,13 +787,13 @@
         List<Pair<String, Boolean>> results = new ArrayList<Pair<String, Boolean>>(attrs.length);
 
         // for each attribute, get its name so that we can search it in the style
-        for (int i = 0 ; i < attrs.length ; i++) {
-            Pair<ResourceType, String> resolvedResource = Bridge.resolveResourceId(attrs[i]);
+        for (int attr : attrs) {
+            Pair<ResourceType, String> resolvedResource = Bridge.resolveResourceId(attr);
             boolean isFramework = false;
             if (resolvedResource != null) {
                 isFramework = true;
             } else {
-                resolvedResource = mProjectCallback.resolveResourceId(attrs[i]);
+                resolvedResource = mProjectCallback.resolveResourceId(attr);
             }
 
             if (resolvedResource != null) {
@@ -841,7 +839,7 @@
 
         if (id == null) {
             // generate a new id
-            id = Integer.valueOf(++mDynamicIdGenerator);
+            id = ++mDynamicIdGenerator;
 
             // and add it to the maps.
             mDynamicIdToStyleMap.put(id, resValue);
@@ -860,19 +858,24 @@
     }
 
     public int getFrameworkResourceValue(ResourceType resType, String resName, int defValue) {
-        Integer value = Bridge.getResourceId(resType, resName);
-        if (value != null) {
-            return value.intValue();
+        if (getRenderResources().getFrameworkResource(resType, resName) != null) {
+            // Bridge.getResourceId creates a new resource id if an existing one isn't found. So,
+            // we check for the existence of the resource before calling it.
+            return Bridge.getResourceId(resType, resName);
         }
 
         return defValue;
     }
 
     public int getProjectResourceValue(ResourceType resType, String resName, int defValue) {
-        if (mProjectCallback != null) {
-            Integer value = mProjectCallback.getResourceId(resType, resName);
-            if (value != null) {
-                return value.intValue();
+        // getResourceId creates a new resource id if an existing resource id isn't found. So, we
+        // check for the existence of the resource before calling it.
+        if (getRenderResources().getProjectResource(resType, resName) != null) {
+            if (mProjectCallback != null) {
+                Integer value = mProjectCallback.getResourceId(resType, resName);
+                if (value != null) {
+                    return value;
+                }
             }
         }
 
@@ -1455,9 +1458,6 @@
         return null;
     }
 
-    /**
-     * @hide
-     */
     @Override
     public int getUserId() {
         return 0; // not used
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/ActionBarLayout.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/ActionBarLayout.java
index d95c815..57fd68e 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/ActionBarLayout.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/ActionBarLayout.java
@@ -18,36 +18,24 @@
 
 import com.android.annotations.NonNull;
 import com.android.annotations.Nullable;
-import com.android.ide.common.rendering.api.ActionBarCallback;
-import com.android.ide.common.rendering.api.ActionBarCallback.HomeButtonStyle;
-import com.android.ide.common.rendering.api.RenderResources;
 import com.android.ide.common.rendering.api.ResourceValue;
 import com.android.ide.common.rendering.api.SessionParams;
 import com.android.internal.R;
-import com.android.internal.app.WindowDecorActionBar;
 import com.android.internal.view.menu.MenuBuilder;
 import com.android.internal.view.menu.MenuItemImpl;
-import com.android.internal.widget.ActionBarAccessor;
-import com.android.internal.widget.ActionBarContainer;
-import com.android.internal.widget.ActionBarView;
 import com.android.layoutlib.bridge.android.BridgeContext;
 import com.android.layoutlib.bridge.impl.ResourceHelper;
-import com.android.resources.ResourceType;
 
-import android.app.ActionBar;
-import android.app.ActionBar.Tab;
-import android.app.ActionBar.TabListener;
-import android.app.FragmentTransaction;
 import android.content.Context;
 import android.content.res.TypedArray;
-import android.graphics.drawable.Drawable;
 import android.util.DisplayMetrics;
 import android.util.TypedValue;
-import android.view.Gravity;
 import android.view.LayoutInflater;
-import android.view.MenuInflater;
 import android.view.View;
+import android.view.View.MeasureSpec;
 import android.view.ViewGroup;
+import android.view.ViewGroup.LayoutParams;
+import android.widget.ActionMenuPresenter;
 import android.widget.FrameLayout;
 import android.widget.LinearLayout;
 import android.widget.ListAdapter;
@@ -56,172 +44,72 @@
 
 import java.util.ArrayList;
 
-/**
- * A layout representing the action bar.
- */
-public class ActionBarLayout extends LinearLayout {
+public class ActionBarLayout {
+
+    private static final String LAYOUT_ATTR_NAME = "windowActionBarFullscreenDecorLayout";
+
+    // The Action Bar
+    @NonNull private CustomActionBarWrapper mActionBar;
 
     // Store another reference to the context so that we don't have to cast it repeatedly.
     @NonNull private final BridgeContext mBridgeContext;
-    @NonNull private final Context mThemedContext;
 
-    @NonNull private final ActionBar mActionBar;
-
-    // Data for Action Bar.
-    @Nullable private final String mIcon;
-    @Nullable private final String mTitle;
-    @Nullable private final String mSubTitle;
-    private final boolean mSplit;
-    private final boolean mShowHomeAsUp;
-    private final int mNavMode;
-
-    // Helper fields.
-    @NonNull private final MenuBuilder mMenuBuilder;
-    private final int mPopupMaxWidth;
-    @NonNull private final RenderResources res;
-    @Nullable private final ActionBarView mActionBarView;
-    @Nullable private FrameLayout mContentRoot;
-    @NonNull private final ActionBarCallback mCallback;
+    @NonNull private FrameLayout mContentRoot;
 
     // A fake parent for measuring views.
     @Nullable private ViewGroup mMeasureParent;
 
-    public ActionBarLayout(@NonNull BridgeContext context, @NonNull SessionParams params) {
+    /**
+     * Inflate the action bar and attach it to {@code parentView}
+     */
+    public ActionBarLayout(@NonNull BridgeContext context, @NonNull SessionParams params,
+            @NonNull ViewGroup parentView) {
 
-        super(context);
-        setOrientation(LinearLayout.HORIZONTAL);
-        setGravity(Gravity.CENTER_VERTICAL);
-
-        // Inflate action bar layout.
-        LayoutInflater.from(context).inflate(R.layout.screen_action_bar, this,
-                true /*attachToRoot*/);
-        mActionBar = new WindowDecorActionBar(this);
-
-        // Set contexts.
         mBridgeContext = context;
-        mThemedContext = mActionBar.getThemedContext();
 
-        // Set data for action bar.
-        mCallback = params.getProjectCallback().getActionBarCallback();
-        mIcon = params.getAppIcon();
-        mTitle = params.getAppLabel();
-        // Split Action Bar when the screen size is narrow and the application requests split action
-        // bar when narrow.
-        mSplit = context.getResources().getBoolean(R.bool.split_action_bar_is_narrow) &&
-                mCallback.getSplitActionBarWhenNarrow();
-        mNavMode = mCallback.getNavigationMode();
-        // TODO: Support Navigation Drawer Indicator.
-        mShowHomeAsUp = mCallback.getHomeButtonStyle() == HomeButtonStyle.SHOW_HOME_AS_UP;
-        mSubTitle = mCallback.getSubTitle();
-
-
-        // Set helper fields.
-        mMenuBuilder = new MenuBuilder(mThemedContext);
-        res = mBridgeContext.getRenderResources();
-        mPopupMaxWidth = Math.max(mBridgeContext.getMetrics().widthPixels / 2,
-                mThemedContext.getResources().getDimensionPixelSize(
-                        R.dimen.config_prefDialogWidth));
-        mActionBarView = (ActionBarView) findViewById(R.id.action_bar);
-        mContentRoot = (FrameLayout) findViewById(android.R.id.content);
-
-        setupActionBar();
-    }
-
-    /**
-     * Sets up the action bar by filling the appropriate data.
-     */
-    private void setupActionBar() {
-        // Add title and sub title.
-        ResourceValue titleValue = res.findResValue(mTitle, false /*isFramework*/);
-        if (titleValue != null && titleValue.getValue() != null) {
-            mActionBar.setTitle(titleValue.getValue());
+        ResourceValue layoutName = context.getRenderResources()
+                .findItemInTheme(LAYOUT_ATTR_NAME, true);
+        if (layoutName != null) {
+            // We may need to resolve the reference obtained.
+            layoutName = context.getRenderResources().findResValue(layoutName.getValue(),
+                    layoutName.isFramework());
+        }
+        int layoutId = 0;
+        String error = null;
+        if (layoutName == null) {
+            error = "Unable to find action bar layout (" + LAYOUT_ATTR_NAME
+                    + ") in the current theme.";
         } else {
-            mActionBar.setTitle(mTitle);
-        }
-        if (mSubTitle != null) {
-            mActionBar.setSubtitle(mSubTitle);
-        }
-
-        // Add show home as up icon.
-        if (mShowHomeAsUp) {
-            mActionBar.setDisplayOptions(0xFF, ActionBar.DISPLAY_HOME_AS_UP);
-        }
-
-        // Set the navigation mode.
-        mActionBar.setNavigationMode(mNavMode);
-        if (mNavMode == ActionBar.NAVIGATION_MODE_TABS) {
-            setupTabs(3);
-        }
-
-        if (mActionBarView != null) {
-            // If the action bar style doesn't specify an icon, set the icon obtained from the session
-            // params.
-            if (!mActionBarView.hasIcon() && mIcon != null) {
-                Drawable iconDrawable = getDrawable(mIcon, false /*isFramework*/);
-                if (iconDrawable != null) {
-                    mActionBar.setIcon(iconDrawable);
-                }
-            }
-
-            // Set action bar to be split, if needed.
-            ActionBarContainer splitView = (ActionBarContainer) findViewById(R.id.split_action_bar);
-            mActionBarView.setSplitView(splitView);
-            mActionBarView.setSplitToolbar(mSplit);
-
-            inflateMenus();
-        }
-    }
-
-    /**
-     * Gets the menus to add to the action bar from the callback, resolves them, inflates them and
-     * adds them to the action bar.
-     */
-    private void inflateMenus() {
-        if (mActionBarView == null) {
-            return;
-        }
-        final MenuInflater inflater = new MenuInflater(mThemedContext);
-        for (String name : mCallback.getMenuIdNames()) {
-            if (mBridgeContext.getRenderResources().getProjectResource(ResourceType.MENU, name)
-                    != null) {
-                int id = mBridgeContext.getProjectResourceValue(ResourceType.MENU, name, -1);
-                if (id > -1) {
-                    inflater.inflate(id, mMenuBuilder);
-                }
+            layoutId = context.getFrameworkResourceValue(layoutName.getResourceType(),
+                    layoutName.getName(), 0);
+            if (layoutId == 0) {
+                error = String.format("Unable to resolve attribute \"%s\" of type \"%s\"",
+                        layoutName.getName(), layoutName.getResourceType());
             }
         }
-        mActionBarView.setMenu(mMenuBuilder, null /*callback*/);
-    }
-
-    // TODO: Use an adapter, like List View to set up tabs.
-    private void setupTabs(int num) {
-        for (int i = 1; i <= num; i++) {
-            Tab tab = mActionBar.newTab().setText("Tab" + i).setTabListener(new TabListener() {
-                @Override
-                public void onTabUnselected(Tab t, FragmentTransaction ft) {
-                    // pass
-                }
-                @Override
-                public void onTabSelected(Tab t, FragmentTransaction ft) {
-                    // pass
-                }
-                @Override
-                public void onTabReselected(Tab t, FragmentTransaction ft) {
-                    // pass
-                }
-            });
-            mActionBar.addTab(tab);
+        if (layoutId == 0) {
+            throw new RuntimeException(error);
         }
-    }
+        // Inflate action bar layout.
+        View decorContent = LayoutInflater.from(context).inflate(layoutId, parentView, true);
 
-    @Nullable
-    private Drawable getDrawable(@NonNull String name, boolean isFramework) {
-        ResourceValue value = res.findResValue(name, isFramework);
-        value = res.resolveResValue(value);
-        if (value != null) {
-            return ResourceHelper.getDrawable(value, mBridgeContext);
+        mActionBar = CustomActionBarWrapper.getActionBarWrapper(context, params, decorContent);
+
+        FrameLayout contentRoot = (FrameLayout) parentView.findViewById(android.R.id.content);
+
+        // If something went wrong and we were not able to initialize the content root,
+        // just add a frame layout inside this and return.
+        if (contentRoot == null) {
+            contentRoot = new FrameLayout(context);
+            contentRoot.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
+                    LayoutParams.MATCH_PARENT));
+            parentView.addView(contentRoot);
+            mContentRoot = contentRoot;
+        } else {
+            mContentRoot = contentRoot;
+            mActionBar.setupActionBar();
+            mActionBar.inflateMenus();
         }
-        return null;
     }
 
     /**
@@ -229,7 +117,7 @@
      * the content frame which shall serve as the new content root.
      */
     public void createMenuPopup() {
-        assert mContentRoot != null && findViewById(android.R.id.content) == mContentRoot
+        assert mContentRoot.getId() == android.R.id.content
                 : "Action Bar Menus have already been created.";
 
         if (!isOverflowPopupNeeded()) {
@@ -237,7 +125,7 @@
         }
 
         // Create a layout to hold the menus and the user's content.
-        RelativeLayout layout = new RelativeLayout(mThemedContext);
+        RelativeLayout layout = new RelativeLayout(mActionBar.getPopupContext());
         layout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
                 LayoutParams.MATCH_PARENT));
         mContentRoot.addView(layout);
@@ -259,13 +147,14 @@
     @NonNull
     private View createMenuView() {
         DisplayMetrics metrics = mBridgeContext.getMetrics();
-        OverflowMenuAdapter adapter = new OverflowMenuAdapter(mMenuBuilder, mThemedContext);
+        MenuBuilder menu = mActionBar.getMenuBuilder();
+        OverflowMenuAdapter adapter = new OverflowMenuAdapter(menu, mActionBar.getPopupContext());
 
-        LinearLayout layout = new LinearLayout(mThemedContext);
+        LinearLayout layout = new LinearLayout(mActionBar.getPopupContext());
         RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(
                 measureContentWidth(adapter), LayoutParams.WRAP_CONTENT);
         layoutParams.addRule(RelativeLayout.ALIGN_PARENT_END);
-        if (mSplit) {
+        if (mActionBar.isSplit()) {
             layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
             // TODO: Find correct value instead of hardcoded 10dp.
             layoutParams.bottomMargin = getPixelValue("-10dp", metrics);
@@ -273,7 +162,7 @@
             layoutParams.topMargin = getPixelValue("-10dp", metrics);
         }
         layout.setLayoutParams(layoutParams);
-        final TypedArray a = mThemedContext.obtainStyledAttributes(null,
+        final TypedArray a = mActionBar.getPopupContext().obtainStyledAttributes(null,
                 R.styleable.PopupWindow, R.attr.popupMenuStyle, 0);
         layout.setBackground(a.getDrawable(R.styleable.PopupWindow_popupBackground));
         layout.setDividerDrawable(a.getDrawable(R.attr.actionBarDivider));
@@ -282,20 +171,25 @@
         layout.setDividerPadding(getPixelValue("12dp", metrics));
         layout.setShowDividers(LinearLayout.SHOW_DIVIDER_MIDDLE);
 
-        ListView listView = new ListView(mThemedContext, null, R.attr.dropDownListViewStyle);
+        ListView listView = new ListView(mActionBar.getPopupContext(), null,
+                R.attr.dropDownListViewStyle);
         listView.setAdapter(adapter);
         layout.addView(listView);
         return layout;
     }
 
     private boolean isOverflowPopupNeeded() {
-        boolean needed = mCallback.isOverflowPopupNeeded();
+        boolean needed = mActionBar.isOverflowPopupNeeded();
         if (!needed) {
             return false;
         }
         // Copied from android.widget.ActionMenuPresenter.updateMenuView()
-        ArrayList<MenuItemImpl> menus = mMenuBuilder.getNonActionItems();
-        if (ActionBarAccessor.getActionMenuPresenter(mActionBarView).isOverflowReserved() &&
+        ArrayList<MenuItemImpl> menus = mActionBar.getMenuBuilder().getNonActionItems();
+        ActionMenuPresenter presenter = mActionBar.getActionMenuPresenter();
+        if (presenter == null) {
+            throw new RuntimeException("Failed to create a Presenter for Action Bar Menus.");
+        }
+        if (presenter.isOverflowReserved() &&
                 menus != null) {
             final int count = menus.size();
             if (count == 1) {
@@ -307,7 +201,7 @@
         return needed;
     }
 
-    @Nullable
+    @NonNull
     public FrameLayout getContentRoot() {
         return mContentRoot;
     }
@@ -319,6 +213,7 @@
         View itemView = null;
         int itemType = 0;
 
+        Context context = mActionBar.getPopupContext();
         final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
         final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
         final int count = adapter.getCount();
@@ -330,15 +225,17 @@
             }
 
             if (mMeasureParent == null) {
-                mMeasureParent = new FrameLayout(mThemedContext);
+                mMeasureParent = new FrameLayout(context);
             }
 
             itemView = adapter.getView(i, itemView, mMeasureParent);
             itemView.measure(widthMeasureSpec, heightMeasureSpec);
 
             final int itemWidth = itemView.getMeasuredWidth();
-            if (itemWidth >= mPopupMaxWidth) {
-                return mPopupMaxWidth;
+            int popupMaxWidth = Math.max(mBridgeContext.getMetrics().widthPixels / 2,
+                    context.getResources().getDimensionPixelSize(R.dimen.config_prefDialogWidth));
+            if (itemWidth >= popupMaxWidth) {
+                return popupMaxWidth;
             } else if (itemWidth > maxWidth) {
                 maxWidth = itemWidth;
             }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomActionBarWrapper.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomActionBarWrapper.java
new file mode 100644
index 0000000..70b9cc3
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomActionBarWrapper.java
@@ -0,0 +1,351 @@
+/*
+ * 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.layoutlib.bridge.bars;
+
+import com.android.annotations.NonNull;
+import com.android.annotations.Nullable;
+import com.android.ide.common.rendering.api.ActionBarCallback;
+import com.android.ide.common.rendering.api.ActionBarCallback.HomeButtonStyle;
+import com.android.ide.common.rendering.api.RenderResources;
+import com.android.ide.common.rendering.api.ResourceValue;
+import com.android.ide.common.rendering.api.SessionParams;
+import com.android.internal.R;
+import com.android.internal.app.ToolbarActionBar;
+import com.android.internal.app.WindowDecorActionBar;
+import com.android.internal.view.menu.MenuBuilder;
+import com.android.internal.widget.ActionBarAccessor;
+import com.android.internal.widget.ActionBarView;
+import com.android.internal.widget.DecorToolbar;
+import com.android.layoutlib.bridge.android.BridgeContext;
+import com.android.layoutlib.bridge.impl.ResourceHelper;
+
+import android.app.ActionBar;
+import android.app.ActionBar.Tab;
+import android.app.ActionBar.TabListener;
+import android.app.FragmentTransaction;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
+import android.view.MenuInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowCallback;
+import android.widget.ActionMenuPresenter;
+import android.widget.Toolbar;
+import android.widget.Toolbar_Accessor;
+
+import static com.android.SdkConstants.ANDROID_NS_NAME_PREFIX;
+import static com.android.resources.ResourceType.MENU;
+
+/**
+ * A common API to access {@link ToolbarActionBar} and {@link WindowDecorActionBar}.
+ */
+public abstract class CustomActionBarWrapper {
+
+    @NonNull protected ActionBar mActionBar;
+    @NonNull protected SessionParams mParams;
+    @NonNull protected ActionBarCallback mCallback;
+    @NonNull protected BridgeContext mContext;
+
+    /**
+     * Returns a wrapper around different implementations of the Action Bar to provide a common API.
+     *
+     * @param decorContent the top level view returned by inflating
+                     * ?attr/windowActionBarFullscreenDecorLayout
+     */
+    @NonNull
+    public static CustomActionBarWrapper getActionBarWrapper(@NonNull BridgeContext context,
+            @NonNull SessionParams params, @NonNull View decorContent) {
+        View view = decorContent.findViewById(R.id.action_bar);
+        if (view instanceof Toolbar) {
+            return new ToolbarWrapper(context, params, ((Toolbar) view)
+            );
+        } else if (view instanceof ActionBarView) {
+            return new WindowActionBarWrapper(context, params, decorContent, ((ActionBarView) view)
+            );
+        } else {
+            throw new IllegalStateException("Can't make an action bar out of " +
+                    view.getClass().getSimpleName());
+        }
+    }
+
+    CustomActionBarWrapper(@NonNull BridgeContext context, @NonNull SessionParams params,
+            @NonNull ActionBar actionBar) {
+        mActionBar = actionBar;
+        mParams = params;
+        mCallback = params.getProjectCallback().getActionBarCallback();
+        mContext = context;
+    }
+
+    protected void setupActionBar() {
+        // Do the things that are common to all implementations.
+        RenderResources res = mContext.getRenderResources();
+
+        String title = mParams.getAppLabel();
+        ResourceValue titleValue = res.findResValue(title, false);
+        if (titleValue != null && titleValue.getValue() != null) {
+            mActionBar.setTitle(titleValue.getValue());
+        } else {
+            mActionBar.setTitle(title);
+        }
+
+        String subTitle = mCallback.getSubTitle();
+        if (subTitle != null) {
+            mActionBar.setSubtitle(subTitle);
+        }
+
+        // Add show home as up icon.
+        if (mCallback.getHomeButtonStyle() == HomeButtonStyle.SHOW_HOME_AS_UP) {
+            mActionBar.setDisplayOptions(0xFF, ActionBar.DISPLAY_HOME_AS_UP);
+        }
+    }
+
+    protected boolean isSplit() {
+        return getDecorToolbar().isSplit();
+    }
+
+    protected boolean isOverflowPopupNeeded() {
+        return mCallback.isOverflowPopupNeeded();
+    }
+
+    /**
+     * Gets the menus to add to the action bar from the callback, resolves them, inflates them and
+     * adds them to the action bar.
+     */
+    protected void inflateMenus() {
+        MenuInflater inflater = new MenuInflater(getActionMenuContext());
+        MenuBuilder menuBuilder = getMenuBuilder();
+        for (String name : mCallback.getMenuIdNames()) {
+            int id;
+            if (name.startsWith(ANDROID_NS_NAME_PREFIX)) {
+                // Framework menu.
+                name = name.substring(ANDROID_NS_NAME_PREFIX.length());
+                id = mContext.getFrameworkResourceValue(MENU, name, -1);
+            } else {
+                // Project menu.
+                id = mContext.getProjectResourceValue(MENU, name, -1);
+            }
+            if (id > -1) {
+                inflater.inflate(id, menuBuilder);
+            }
+        }
+    }
+
+    /**
+     * The context used for the ActionBar and the menus in the ActionBarView.
+     */
+    @NonNull
+    protected Context getActionMenuContext() {
+        return mActionBar.getThemedContext();
+    }
+
+    /**
+     * The context used to inflate the popup menu.
+     */
+    @NonNull
+    abstract Context getPopupContext();
+
+    /**
+     * The Menu in which to inflate the user's menus.
+     */
+    @NonNull
+    abstract MenuBuilder getMenuBuilder();
+
+    @Nullable
+    abstract ActionMenuPresenter getActionMenuPresenter();
+
+    /**
+     * Framework's wrapper over two ActionBar implementations.
+     */
+    @NonNull
+    abstract DecorToolbar getDecorToolbar();
+
+    // ---- The implementations ----
+
+    /**
+     * Material theme uses {@link Toolbar} as the action bar. This wrapper provides access to
+     * Toolbar using a common API.
+     */
+    private static class ToolbarWrapper extends CustomActionBarWrapper {
+
+        @NonNull
+        private final Toolbar mToolbar;  // This is the view.
+
+        ToolbarWrapper(@NonNull BridgeContext context, @NonNull SessionParams params,
+                @NonNull Toolbar toolbar) {
+            super(context, params, new ToolbarActionBar(toolbar, "", new WindowCallback())
+            );
+            mToolbar = toolbar;
+        }
+
+        @Override
+        protected void inflateMenus() {
+            super.inflateMenus();
+            // Inflating the menus doesn't initialize the ActionMenuPresenter. Setting a fake menu
+            // and then setting it back does the trick.
+            MenuBuilder menu = getMenuBuilder();
+            DecorToolbar decorToolbar = getDecorToolbar();
+            decorToolbar.setMenu(new MenuBuilder(getActionMenuContext()), null);
+            decorToolbar.setMenu(menu, null);
+        }
+
+        @NonNull
+        @Override
+        Context getPopupContext() {
+            return Toolbar_Accessor.getPopupContext(mToolbar);
+        }
+
+        @NonNull
+        @Override
+        MenuBuilder getMenuBuilder() {
+            return (MenuBuilder) mToolbar.getMenu();
+        }
+
+        @Nullable
+        @Override
+        ActionMenuPresenter getActionMenuPresenter() {
+            return Toolbar_Accessor.getActionMenuPresenter(mToolbar);
+        }
+
+        @NonNull
+        @Override
+        DecorToolbar getDecorToolbar() {
+            return mToolbar.getWrapper();
+        }
+    }
+
+    /**
+     * Holo theme uses {@link WindowDecorActionBar} as the action bar. This wrapper provides
+     * access to it using a common API.
+     */
+    private static class WindowActionBarWrapper extends CustomActionBarWrapper{
+
+        @NonNull
+        private final WindowDecorActionBar mActionBar;
+        private final ActionBarView mActionBarView;
+        private MenuBuilder mMenuBuilder;
+
+        public WindowActionBarWrapper(@NonNull BridgeContext context, @NonNull SessionParams params,
+                @NonNull View decorContentRoot, @NonNull ActionBarView actionBarView) {
+            super(context, params, new WindowDecorActionBar(decorContentRoot)
+            );
+            mActionBarView = actionBarView;
+            mActionBar = ((WindowDecorActionBar) super.mActionBar);
+        }
+
+        @Override
+        protected void setupActionBar() {
+            super.setupActionBar();
+
+            // Set the navigation mode.
+            int navMode = mCallback.getNavigationMode();
+            mActionBar.setNavigationMode(navMode);
+            //noinspection deprecation
+            if (navMode == ActionBar.NAVIGATION_MODE_TABS) {
+                setupTabs(3);
+            }
+
+            String icon = mParams.getAppIcon();
+            // If the action bar style doesn't specify an icon, set the icon obtained from the
+            // session params.
+            if (!mActionBar.hasIcon() && icon != null) {
+                Drawable iconDrawable = getDrawable(icon, false);
+                if (iconDrawable != null) {
+                    mActionBar.setIcon(iconDrawable);
+                }
+            }
+
+            // Set action bar to be split, if needed.
+            ViewGroup splitView = (ViewGroup) mActionBarView.findViewById(R.id.split_action_bar);
+            if (splitView != null) {
+                mActionBarView.setSplitView(splitView);
+                Resources res = mContext.getResources();
+                boolean split = res.getBoolean(R.bool.split_action_bar_is_narrow)
+                        && mCallback.getSplitActionBarWhenNarrow();
+                mActionBarView.setSplitToolbar(split);
+            }
+        }
+
+        @Override
+        protected void inflateMenus() {
+            super.inflateMenus();
+            // The super implementation doesn't set the menu on the view. Set it here.
+            mActionBarView.setMenu(getMenuBuilder(), null);
+        }
+
+        @NonNull
+        @Override
+        Context getPopupContext() {
+            return getActionMenuContext();
+        }
+
+        @NonNull
+        @Override
+        MenuBuilder getMenuBuilder() {
+            if (mMenuBuilder == null) {
+                mMenuBuilder = new MenuBuilder(getActionMenuContext());
+            }
+            return mMenuBuilder;
+        }
+
+        @Nullable
+        @Override
+        ActionMenuPresenter getActionMenuPresenter() {
+            return ActionBarAccessor.getActionMenuPresenter(mActionBarView);
+        }
+
+        @NonNull
+        @Override
+        ActionBarView getDecorToolbar() {
+            return mActionBarView;
+        }
+
+        // TODO: Use an adapter, like List View to set up tabs.
+        @SuppressWarnings("deprecation")  // For Tab
+        private void setupTabs(int num) {
+            for (int i = 1; i <= num; i++) {
+                Tab tab = mActionBar.newTab().setText("Tab" + i).setTabListener(new TabListener() {
+                    @Override
+                    public void onTabUnselected(Tab t, FragmentTransaction ft) {
+                        // pass
+                    }
+                    @Override
+                    public void onTabSelected(Tab t, FragmentTransaction ft) {
+                        // pass
+                    }
+                    @Override
+                    public void onTabReselected(Tab t, FragmentTransaction ft) {
+                        // pass
+                    }
+                });
+                mActionBar.addTab(tab);
+            }
+        }
+
+        @Nullable
+        private Drawable getDrawable(@NonNull String name, boolean isFramework) {
+            RenderResources res = mContext.getRenderResources();
+            ResourceValue value = res.findResValue(name, isFramework);
+            value = res.resolveResValue(value);
+            if (value != null) {
+                return ResourceHelper.getDrawable(value, mContext);
+            }
+            return null;
+        }
+
+    }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
index b8dce70..a2eed9a 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
@@ -353,8 +353,7 @@
 
                 // if the theme says no title/action bar, then the size will be 0
                 if (mActionBarSize > 0) {
-                    ActionBarLayout actionBar = createActionBar(context, params);
-                    backgroundLayout.addView(actionBar);
+                    ActionBarLayout actionBar = createActionBar(context, params, backgroundLayout);
                     actionBar.createMenuPopup();
                     mContentRoot = actionBar.getContentRoot();
                 } else if (mTitleBarSize > 0) {
@@ -1624,11 +1623,9 @@
     /**
      * Creates the action bar. Also queries the project callback for missing information.
      */
-    private ActionBarLayout createActionBar(BridgeContext context, SessionParams params) {
-        ActionBarLayout actionBar = new ActionBarLayout(context, params);
-        actionBar.setLayoutParams(new LinearLayout.LayoutParams(
-                LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
-        return actionBar;
+    private ActionBarLayout createActionBar(BridgeContext context, SessionParams params,
+            ViewGroup parentView) {
+        return new ActionBarLayout(context, params, parentView);
     }
 
     public BufferedImage getImage() {
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/DynamicIdMap.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/DynamicIdMap.java
index a1fae95..979aa33 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/DynamicIdMap.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/DynamicIdMap.java
@@ -16,6 +16,7 @@
 
 package com.android.layoutlib.bridge.util;
 
+import com.android.annotations.NonNull;
 import com.android.resources.ResourceType;
 import com.android.util.Pair;
 
@@ -48,6 +49,7 @@
      * @param name the name of the resource
      * @return an integer.
      */
+    @NonNull
     public Integer getId(ResourceType type, String name) {
         return getId(Pair.of(type, name));
     }
@@ -59,10 +61,11 @@
      * @param resource the type/name of the resource
      * @return an integer.
      */
+    @NonNull
     public Integer getId(Pair<ResourceType, String> resource) {
         Integer value = mDynamicIds.get(resource);
         if (value == null) {
-            value = Integer.valueOf(++mDynamicSeed);
+            value = ++mDynamicSeed;
             mDynamicIds.put(resource, value);
             mRevDynamicIds.put(value, resource);
         }
diff --git a/tools/split-select/Abi.cpp b/tools/split-select/Abi.cpp
index 20654b6..180dd8f 100644
--- a/tools/split-select/Abi.cpp
+++ b/tools/split-select/Abi.cpp
@@ -16,42 +16,58 @@
 
 #include "Abi.h"
 
+using namespace android;
+
 namespace split {
 namespace abi {
 
-static const std::vector<Variant> sNoneVariants = {};
-static const std::vector<Variant> sArmVariants =
-        {Variant::armeabi, Variant::armeabi_v7a, Variant::arm64_v8a};
-static const std::vector<Variant> sIntelVariants = {Variant::x86, Variant::x86_64};
-static const std::vector<Variant> sMipsVariants = {Variant::mips, Variant::mips64};
+static Vector<Variant> buildVariants(Variant v1, Variant v2) {
+    Vector<Variant> v;
+    v.add(v1);
+    v.add(v2);
+    return v;
+}
+
+static Vector<Variant> buildVariants(Variant v1, Variant v2, Variant v3) {
+    Vector<Variant> v;
+    v.add(v1);
+    v.add(v2);
+    v.add(v3);
+    return v;
+}
+
+static const Vector<Variant> sNoneVariants;
+static const Vector<Variant> sArmVariants = buildVariants(Variant_armeabi, Variant_armeabi_v7a, Variant_arm64_v8a);
+static const Vector<Variant> sIntelVariants = buildVariants(Variant_x86, Variant_x86_64);
+static const Vector<Variant> sMipsVariants = buildVariants(Variant_mips, Variant_mips64);
 
 Family getFamily(Variant variant) {
     switch (variant) {
-        case Variant::none:
-            return Family::none;
-        case Variant::armeabi:
-        case Variant::armeabi_v7a:
-        case Variant::arm64_v8a:
-            return Family::arm;
-        case Variant::x86:
-        case Variant::x86_64:
-            return Family::intel;
-        case Variant::mips:
-        case Variant::mips64:
-            return Family::mips;
+        case Variant_none:
+            return Family_none;
+        case Variant_armeabi:
+        case Variant_armeabi_v7a:
+        case Variant_arm64_v8a:
+            return Family_arm;
+        case Variant_x86:
+        case Variant_x86_64:
+            return Family_intel;
+        case Variant_mips:
+        case Variant_mips64:
+            return Family_mips;
     }
-    return Family::none;
+    return Family_none;
 }
 
-const std::vector<Variant>& getVariants(Family family) {
+const Vector<Variant>& getVariants(Family family) {
     switch (family) {
-        case Family::none:
+        case Family_none:
             return sNoneVariants;
-        case Family::arm:
+        case Family_arm:
             return sArmVariants;
-        case Family::intel:
+        case Family_intel:
             return sIntelVariants;
-        case Family::mips:
+        case Family_mips:
             return sMipsVariants;
     }
     return sNoneVariants;
@@ -59,21 +75,21 @@
 
 const char* toString(Variant variant) {
     switch (variant) {
-        case Variant::none:
+        case Variant_none:
             return "";
-        case Variant::armeabi:
+        case Variant_armeabi:
             return "armeabi";
-        case Variant::armeabi_v7a:
+        case Variant_armeabi_v7a:
             return "armeabi-v7a";
-        case Variant::arm64_v8a:
+        case Variant_arm64_v8a:
             return "arm64-v8a";
-        case Variant::x86:
+        case Variant_x86:
             return "x86";
-        case Variant::x86_64:
+        case Variant_x86_64:
             return "x86_64";
-        case Variant::mips:
+        case Variant_mips:
             return "mips";
-        case Variant::mips64:
+        case Variant_mips64:
             return "mips64";
     }
     return "";
diff --git a/tools/split-select/Abi.h b/tools/split-select/Abi.h
index 3e00eba..85b4d62 100644
--- a/tools/split-select/Abi.h
+++ b/tools/split-select/Abi.h
@@ -17,31 +17,31 @@
 #ifndef H_ANDROID_SPLIT_ABI
 #define H_ANDROID_SPLIT_ABI
 
-#include <vector>
+#include <utils/Vector.h>
 
 namespace split {
 namespace abi {
 
-enum class Variant {
-    none = 0,
-    armeabi,
-    armeabi_v7a,
-    arm64_v8a,
-    x86,
-    x86_64,
-    mips,
-    mips64,
+enum Variant {
+    Variant_none = 0,
+    Variant_armeabi,
+    Variant_armeabi_v7a,
+    Variant_arm64_v8a,
+    Variant_x86,
+    Variant_x86_64,
+    Variant_mips,
+    Variant_mips64,
 };
 
-enum class Family {
-    none,
-    arm,
-    intel,
-    mips,
+enum Family {
+    Family_none,
+    Family_arm,
+    Family_intel,
+    Family_mips,
 };
 
 Family getFamily(Variant variant);
-const std::vector<Variant>& getVariants(Family family);
+const android::Vector<Variant>& getVariants(Family family);
 const char* toString(Variant variant);
 
 } // namespace abi
diff --git a/tools/split-select/Android.mk b/tools/split-select/Android.mk
index d0b7287..dc48ea8 100644
--- a/tools/split-select/Android.mk
+++ b/tools/split-select/Android.mk
@@ -17,10 +17,6 @@
 # This tool is prebuilt if we're doing an app-only build.
 ifeq ($(TARGET_BUILD_APPS)$(filter true,$(TARGET_BUILD_PDK)),)
 
-# TODO(adamlesinski): Enable OS X builds when I figure out how
-# to build with clang and libc++
-ifneq ($(HOST_OS),darwin)
-
 # ==========================================================
 # Setup some common variables for the different build
 # targets here.
@@ -55,7 +51,7 @@
     libexpat \
     libziparchive-host
 
-cFlags := -std=c++11 -Wall -Werror
+cFlags := -Wall -Werror
 
 ifeq ($(HOST_OS),linux)
     hostLdLibs += -lrt -ldl -lpthread
@@ -115,5 +111,4 @@
 
 include $(BUILD_HOST_EXECUTABLE)
 
-endif # Not OS X
 endif # No TARGET_BUILD_APPS or TARGET_BUILD_PDK
diff --git a/tools/split-select/Grouper.cpp b/tools/split-select/Grouper.cpp
index 15edf89..22685cd 100644
--- a/tools/split-select/Grouper.cpp
+++ b/tools/split-select/Grouper.cpp
@@ -16,25 +16,17 @@
 
 #include "Grouper.h"
 
+#include "aapt/AaptUtil.h"
 #include "SplitDescription.h"
 
 #include <utils/KeyedVector.h>
 #include <utils/Vector.h>
 
 using namespace android;
+using AaptUtil::appendValue;
 
 namespace split {
 
-template <typename Key, typename Value>
-static void addToVector(KeyedVector<Key, SortedVector<Value> >& group,
-        const Key& key, const Value& value) {
-    ssize_t idx = group.indexOfKey(key);
-    if (idx < 0) {
-        idx = group.add(key, SortedVector<Value>());
-    }
-    group.editValueAt(idx).add(value);
-}
-
 Vector<SortedVector<SplitDescription> >
 groupByMutualExclusivity(const Vector<SplitDescription>& splits) {
     Vector<SortedVector<SplitDescription> > groups;
@@ -43,20 +35,22 @@
     KeyedVector<SplitDescription, SortedVector<SplitDescription> > densityGroups;
     KeyedVector<SplitDescription, SortedVector<SplitDescription> > abiGroups;
     KeyedVector<SplitDescription, SortedVector<SplitDescription> > localeGroups;
-    for (const SplitDescription& split : splits) {
+    const size_t splitCount = splits.size();
+    for (size_t i = 0; i < splitCount; i++) {
+        const SplitDescription& split = splits[i];
         if (split.config.density != 0) {
             SplitDescription key(split);
             key.config.density = 0;
             key.config.sdkVersion = 0; // Ignore density so we can support anydpi.
-            addToVector(densityGroups, key, split);
-        } else if (split.abi != abi::Variant::none) {
+            appendValue(densityGroups, key, split);
+        } else if (split.abi != abi::Variant_none) {
             SplitDescription key(split);
-            key.abi = abi::Variant::none;
-            addToVector(abiGroups, key, split);
+            key.abi = abi::Variant_none;
+            appendValue(abiGroups, key, split);
         } else if (split.config.locale != 0) {
             SplitDescription key(split);
             key.config.clearLocale();
-            addToVector(localeGroups, key, split);
+            appendValue(localeGroups, key, split);
         } else {
             groups.add();
             groups.editTop().add(split);
diff --git a/tools/split-select/Grouper_test.cpp b/tools/split-select/Grouper_test.cpp
index 4d146cd..a5f9c5a 100644
--- a/tools/split-select/Grouper_test.cpp
+++ b/tools/split-select/Grouper_test.cpp
@@ -19,7 +19,6 @@
 #include "SplitDescription.h"
 
 #include <gtest/gtest.h>
-#include <initializer_list>
 #include <utils/String8.h>
 #include <utils/Vector.h>
 
@@ -55,7 +54,11 @@
     }
 
     void addSplit(Vector<SplitDescription>& splits, const char* str);
-    void expectHasGroupWithSplits(std::initializer_list<const char*> l);
+    void expectHasGroupWithSplits(const char* a);
+    void expectHasGroupWithSplits(const char* a, const char* b);
+    void expectHasGroupWithSplits(const char* a, const char* b, const char* c);
+    void expectHasGroupWithSplits(const char* a, const char* b, const char* c, const char* d);
+    void expectHasGroupWithSplits(const Vector<const char*>& expectedStrs);
 
     Vector<SortedVector<SplitDescription> > mGroups;
 };
@@ -65,39 +68,70 @@
 }
 
 TEST_F(GrouperTest, shouldGroupDensities) {
-    expectHasGroupWithSplits({"en-rUS-sw300dp-hdpi", "en-rUS-sw300dp-xhdpi"});
-    expectHasGroupWithSplits({"en-rUS-sw600dp-hdpi", "en-rUS-sw600dp-xhdpi"});
-    expectHasGroupWithSplits({"fr-rFR-sw600dp-hdpi", "fr-rFR-sw600dp-xhdpi"});
-    expectHasGroupWithSplits({"hdpi", "xhdpi", "xxhdpi", "anydpi"});
+    expectHasGroupWithSplits("en-rUS-sw300dp-hdpi", "en-rUS-sw300dp-xhdpi");
+    expectHasGroupWithSplits("en-rUS-sw600dp-hdpi", "en-rUS-sw600dp-xhdpi");
+    expectHasGroupWithSplits("fr-rFR-sw600dp-hdpi", "fr-rFR-sw600dp-xhdpi");
+    expectHasGroupWithSplits("hdpi", "xhdpi", "xxhdpi", "anydpi");
 }
 
 TEST_F(GrouperTest, shouldGroupAbi) {
-    expectHasGroupWithSplits({":armeabi", ":x86"});
+    expectHasGroupWithSplits(":armeabi", ":x86");
 }
 
 TEST_F(GrouperTest, shouldGroupLocale) {
-    expectHasGroupWithSplits({"pl-rPL", "de-rDE"});
+    expectHasGroupWithSplits("pl-rPL", "de-rDE");
 }
 
 TEST_F(GrouperTest, shouldGroupEachSplitIntoItsOwnGroup) {
-    expectHasGroupWithSplits({"large"});
-    expectHasGroupWithSplits({"xlarge"});
-    expectHasGroupWithSplits({"v7"});
-    expectHasGroupWithSplits({"v8"});
-    expectHasGroupWithSplits({"sw600dp"});
-    expectHasGroupWithSplits({"sw300dp"});
+    expectHasGroupWithSplits("large");
+    expectHasGroupWithSplits("xlarge");
+    expectHasGroupWithSplits("v7");
+    expectHasGroupWithSplits("v8");
+    expectHasGroupWithSplits("sw600dp");
+    expectHasGroupWithSplits("sw300dp");
 }
 
 //
 // Helper methods
 //
 
-void GrouperTest::expectHasGroupWithSplits(std::initializer_list<const char*> l) {
+void GrouperTest::expectHasGroupWithSplits(const char* a) {
+    Vector<const char*> expected;
+    expected.add(a);
+    expectHasGroupWithSplits(expected);
+}
+
+void GrouperTest::expectHasGroupWithSplits(const char* a, const char* b) {
+    Vector<const char*> expected;
+    expected.add(a);
+    expected.add(b);
+    expectHasGroupWithSplits(expected);
+}
+
+void GrouperTest::expectHasGroupWithSplits(const char* a, const char* b, const char* c) {
+    Vector<const char*> expected;
+    expected.add(a);
+    expected.add(b);
+    expected.add(c);
+    expectHasGroupWithSplits(expected);
+}
+
+void GrouperTest::expectHasGroupWithSplits(const char* a, const char* b, const char* c, const char* d) {
+    Vector<const char*> expected;
+    expected.add(a);
+    expected.add(b);
+    expected.add(c);
+    expected.add(d);
+    expectHasGroupWithSplits(expected);
+}
+
+void GrouperTest::expectHasGroupWithSplits(const Vector<const char*>& expectedStrs) {
     Vector<SplitDescription> splits;
-    for (const char* str : l) {
+    const size_t expectedStrCount = expectedStrs.size();
+    for (size_t i = 0; i < expectedStrCount; i++) {
         splits.add();
-        if (!SplitDescription::parse(String8(str), &splits.editTop())) {
-            ADD_FAILURE() << "Failed to parse SplitDescription " << str;
+        if (!SplitDescription::parse(String8(expectedStrs[i]), &splits.editTop())) {
+            ADD_FAILURE() << "Failed to parse SplitDescription " << expectedStrs[i];
             return;
         }
     }
diff --git a/tools/split-select/Main.cpp b/tools/split-select/Main.cpp
index d6251c3..434494e 100644
--- a/tools/split-select/Main.cpp
+++ b/tools/split-select/Main.cpp
@@ -63,7 +63,7 @@
 
 class SplitSelector {
 public:
-    SplitSelector() = default;
+    SplitSelector();
     SplitSelector(const Vector<SplitDescription>& splits);
 
     Vector<SplitDescription> getBestSplits(const SplitDescription& target) const;
@@ -75,6 +75,9 @@
     Vector<SortedVector<SplitDescription> > mGroups;
 };
 
+SplitSelector::SplitSelector() {
+}
+
 SplitSelector::SplitSelector(const Vector<SplitDescription>& splits)
     : mGroups(groupByMutualExclusivity(splits)) {
 }
diff --git a/tools/split-select/RuleGenerator.cpp b/tools/split-select/RuleGenerator.cpp
index 669ae78..b8f3bcb 100644
--- a/tools/split-select/RuleGenerator.cpp
+++ b/tools/split-select/RuleGenerator.cpp
@@ -65,12 +65,12 @@
 
 sp<Rule> RuleGenerator::generateAbi(const Vector<abi::Variant>& splitAbis, size_t index) {
     const abi::Variant thisAbi = splitAbis[index];
-    const std::vector<abi::Variant>& familyVariants = abi::getVariants(abi::getFamily(thisAbi));
+    const Vector<abi::Variant>& familyVariants = abi::getVariants(abi::getFamily(thisAbi));
 
-    std::vector<abi::Variant>::const_iterator start =
+    Vector<abi::Variant>::const_iterator start =
             std::find(familyVariants.begin(), familyVariants.end(), thisAbi);
 
-    std::vector<abi::Variant>::const_iterator end = familyVariants.end();
+    Vector<abi::Variant>::const_iterator end = familyVariants.end();
     if (index + 1 < splitAbis.size()) {
         end = std::find(start, familyVariants.end(), splitAbis[index + 1]);
     }
@@ -127,7 +127,7 @@
         rootRule->subrules.add(generateDensity(allDensities, densityIndex));
     }
 
-    if (group[index].abi != abi::Variant::none) {
+    if (group[index].abi != abi::Variant_none) {
         size_t abiIndex = 0;
         Vector<abi::Variant> allVariants;
         allVariants.add(group[index].abi);
diff --git a/tools/split-select/RuleGenerator_test.cpp b/tools/split-select/RuleGenerator_test.cpp
index 60baabe..ee387be 100644
--- a/tools/split-select/RuleGenerator_test.cpp
+++ b/tools/split-select/RuleGenerator_test.cpp
@@ -25,19 +25,19 @@
 namespace split {
 
 static void expectDensityRule(const Vector<int>& densities, int density, int greaterThan, int lessThan);
-static void expectAbiRule(const Vector<abi::Variant>& abis, abi::Variant variant,
-        std::initializer_list<const char*> matches);
+static void expectAbiRule(const Vector<abi::Variant>& abis, abi::Variant variant, const char* a);
+static void expectAbiRule(const Vector<abi::Variant>& abis, abi::Variant variant, const char* a, const char* b);
 
 TEST(RuleGeneratorTest, testAbiRules) {
     Vector<abi::Variant> abis;
-    abis.add(abi::Variant::armeabi);
-    abis.add(abi::Variant::armeabi_v7a);
-    abis.add(abi::Variant::x86);
+    abis.add(abi::Variant_armeabi);
+    abis.add(abi::Variant_armeabi_v7a);
+    abis.add(abi::Variant_x86);
     std::sort(abis.begin(), abis.end());
 
-    expectAbiRule(abis, abi::Variant::armeabi, {"armeabi"});
-    expectAbiRule(abis, abi::Variant::armeabi_v7a, {"armeabi-v7a", "arm64-v8a"});
-    expectAbiRule(abis, abi::Variant::x86, {"x86", "x86_64"});
+    expectAbiRule(abis, abi::Variant_armeabi, "armeabi");
+    expectAbiRule(abis, abi::Variant_armeabi_v7a, "armeabi-v7a", "arm64-v8a");
+    expectAbiRule(abis, abi::Variant_x86, "x86", "x86_64");
 }
 
 TEST(RuleGeneratorTest, testDensityRules) {
@@ -126,8 +126,7 @@
     }
 }
 
-static void expectAbiRule(const Vector<abi::Variant>& abis, abi::Variant variant,
-        std::initializer_list<const char*> matches) {
+static void expectAbiRule(const Vector<abi::Variant>& abis, abi::Variant variant, const Vector<const char*>& matches) {
     const abi::Variant* iter = std::find(abis.begin(), abis.end(), variant);
     if (abis.end() == iter) {
         ADD_FAILURE() << abi::toString(variant) << " was not in the abi list.";
@@ -143,7 +142,9 @@
     EXPECT_EQ(matches.size(), rule->stringArgs.size())
             << " for " << abi::toString(variant) << " rule";
 
-    for (const char* match : matches) {
+    const size_t matchCount = matches.size();
+    for (size_t i = 0; i < matchCount; i++) {
+        const char* match = matches[i];
         if (rule->stringArgs.end() ==
                 std::find(rule->stringArgs.begin(), rule->stringArgs.end(), String8(match))) {
             ADD_FAILURE() << "Rule for abi " << abi::toString(variant)
@@ -152,4 +153,17 @@
     }
 }
 
+static void expectAbiRule(const Vector<abi::Variant>& abis, abi::Variant variant, const char* a) {
+    Vector<const char*> matches;
+    matches.add(a);
+    expectAbiRule(abis, variant, matches);
+}
+
+static void expectAbiRule(const Vector<abi::Variant>& abis, abi::Variant variant, const char* a, const char* b) {
+    Vector<const char*> matches;
+    matches.add(a);
+    matches.add(b);
+    expectAbiRule(abis, variant, matches);
+}
+
 } // namespace split
diff --git a/tools/split-select/SplitDescription.cpp b/tools/split-select/SplitDescription.cpp
index 8037ef0..99bc23d 100644
--- a/tools/split-select/SplitDescription.cpp
+++ b/tools/split-select/SplitDescription.cpp
@@ -27,7 +27,7 @@
 namespace split {
 
 SplitDescription::SplitDescription()
-: abi(abi::Variant::none) {
+: abi(abi::Variant_none) {
 }
 
 int SplitDescription::compare(const SplitDescription& rhs) const {
@@ -38,11 +38,11 @@
 }
 
 bool SplitDescription::isBetterThan(const SplitDescription& o, const SplitDescription& target) const {
-    if (abi != abi::Variant::none || o.abi != abi::Variant::none) {
+    if (abi != abi::Variant_none || o.abi != abi::Variant_none) {
         abi::Family family = abi::getFamily(abi);
         abi::Family oFamily = abi::getFamily(o.abi);
         if (family != oFamily) {
-            return family != abi::Family::none;
+            return family != abi::Family_none;
         }
 
         if (int(target.abi) - int(abi) < int(target.abi) - int(o.abi)) {
@@ -53,7 +53,7 @@
 }
 
 bool SplitDescription::match(const SplitDescription& o) const {
-    if (abi != abi::Variant::none) {
+    if (abi != abi::Variant_none) {
         abi::Family family = abi::getFamily(abi);
         abi::Family oFamily = abi::getFamily(o.abi);
         if (family != oFamily) {
@@ -69,7 +69,7 @@
 
 String8 SplitDescription::toString() const {
     String8 extension;
-    if (abi != abi::Variant::none) {
+    if (abi != abi::Variant_none) {
         if (extension.isEmpty()) {
             extension.append(":");
         } else {
@@ -85,40 +85,40 @@
 ssize_t parseAbi(const Vector<String8>& parts, const ssize_t index,
         SplitDescription* outSplit) {
     const ssize_t N = parts.size();
-    abi::Variant abi = abi::Variant::none;
+    abi::Variant abi = abi::Variant_none;
     ssize_t endIndex = index;
     if (parts[endIndex] == "arm64") {
         endIndex++;
         if (endIndex < N) {
             if (parts[endIndex] == "v8a") {
                 endIndex++;
-                abi = abi::Variant::arm64_v8a;
+                abi = abi::Variant_arm64_v8a;
             }
         }
     } else if (parts[endIndex] == "armeabi") {
         endIndex++;
-        abi = abi::Variant::armeabi;
+        abi = abi::Variant_armeabi;
         if (endIndex < N) {
             if (parts[endIndex] == "v7a") {
                 endIndex++;
-                abi = abi::Variant::armeabi_v7a;
+                abi = abi::Variant_armeabi_v7a;
             }
         }
     } else if (parts[endIndex] == "x86") {
         endIndex++;
-        abi = abi::Variant::x86;
+        abi = abi::Variant_x86;
     } else if (parts[endIndex] == "x86_64") {
         endIndex++;
-        abi = abi::Variant::x86_64;
+        abi = abi::Variant_x86_64;
     } else if (parts[endIndex] == "mips") {
         endIndex++;
-        abi = abi::Variant::mips;
+        abi = abi::Variant_mips;
     } else if (parts[endIndex] == "mips64") {
         endIndex++;
-        abi = abi::Variant::mips64;
+        abi = abi::Variant_mips64;
     }
 
-    if (abi == abi::Variant::none && endIndex != index) {
+    if (abi == abi::Variant_none && endIndex != index) {
         return -1;
     }
 
diff --git a/tools/split-select/SplitDescription.h b/tools/split-select/SplitDescription.h
index 5fcafc8..b13c9ee 100644
--- a/tools/split-select/SplitDescription.h
+++ b/tools/split-select/SplitDescription.h
@@ -27,7 +27,6 @@
 
 struct SplitDescription {
     SplitDescription();
-    SplitDescription(const SplitDescription&) = default;
 
     ConfigDescription config;
     abi::Variant abi;