Merge "Implement new volume UI design."
diff --git a/api/current.txt b/api/current.txt
index 6f565d7..d6e66ee 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -8972,6 +8972,7 @@
 
   public class TypedArray {
     method public boolean getBoolean(int, boolean);
+    method public int getChangingConfigurations();
     method public int getColor(int, int);
     method public android.content.res.ColorStateList getColorStateList(int);
     method public float getDimension(int, float);
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 28498ec..2914a61 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -5202,6 +5202,22 @@
     }
 
     /**
+     * Indication of whether this is the highest level activity in this task. Can be used to
+     * determine whether an activity launched by this activity was placed in the same task or
+     * another task.
+     *
+     * @return true if this is the topmost, non-finishing activity in its task.
+     * @hide
+     */
+    public boolean isTopOfTask() {
+        try {
+            return ActivityManagerNative.getDefault().isTopOfTask(mToken);
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+
+    /**
      * Convert a translucent themed Activity {@link android.R.attr#windowIsTranslucent} to a
      * fullscreen opaque Activity.
      * <p>
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 1b2b08f..ce36fd8 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1546,6 +1546,15 @@
             return true;
         }
 
+        case IS_TOP_OF_TASK_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            IBinder token = data.readStrongBinder();
+            final boolean isTopOfTask = isTopOfTask(token);
+            reply.writeNoException();
+            reply.writeInt(isTopOfTask ? 1 : 0);
+            return true;
+        }
+
         case CONVERT_FROM_TRANSLUCENT_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             IBinder token = data.readStrongBinder();
@@ -2129,7 +2138,7 @@
             return true;
         }
 
-        case START_LOCK_TASK_BY_CURRENT: {
+        case START_LOCK_TASK_BY_CURRENT_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             startLockTaskModeOnCurrent();
             reply.writeNoException();
@@ -2143,7 +2152,7 @@
             return true;
         }
 
-        case STOP_LOCK_TASK_BY_CURRENT: {
+        case STOP_LOCK_TASK_BY_CURRENT_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             stopLockTaskModeOnCurrent();
             reply.writeNoException();
@@ -4182,6 +4191,19 @@
         return res;
     }
 
+    public boolean isTopOfTask(IBinder token) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        data.writeStrongBinder(token);
+        mRemote.transact(IS_TOP_OF_TASK_TRANSACTION, data, reply, 0);
+        reply.readException();
+        boolean res = reply.readInt() == 1;
+        data.recycle();
+        reply.recycle();
+        return res;
+    }
+
     public boolean isTopActivityImmersive()
             throws RemoteException {
         Parcel data = Parcel.obtain();
@@ -4930,7 +4952,7 @@
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
-        mRemote.transact(START_LOCK_TASK_BY_CURRENT, data, reply, 0);
+        mRemote.transact(START_LOCK_TASK_BY_CURRENT_TRANSACTION, data, reply, 0);
         reply.readException();
         data.recycle();
         reply.recycle();
@@ -4952,7 +4974,7 @@
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
-        mRemote.transact(STOP_LOCK_TASK_BY_CURRENT, data, reply, 0);
+        mRemote.transact(STOP_LOCK_TASK_BY_CURRENT_TRANSACTION, data, reply, 0);
         reply.readException();
         data.recycle();
         reply.recycle();
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 931903b..6e4192b 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -302,10 +302,10 @@
     
     public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
             throws RemoteException;
-    
+
     public void overridePendingTransition(IBinder token, String packageName,
             int enterAnim, int exitAnim) throws RemoteException;
-    
+
     public boolean isUserAMonkey() throws RemoteException;
 
     public void setUserIsMonkey(boolean monkey) throws RemoteException;
@@ -320,12 +320,13 @@
     public void setImmersive(IBinder token, boolean immersive) throws RemoteException;
     public boolean isImmersive(IBinder token) throws RemoteException;
     public boolean isTopActivityImmersive() throws RemoteException;
-    
+    public boolean isTopOfTask(IBinder token) throws RemoteException;
+
     public void crashApplication(int uid, int initialPid, String packageName,
             String message) throws RemoteException;
 
     public String getProviderMimeType(Uri uri, int userId) throws RemoteException;
-    
+
     public IBinder newUriPermissionOwner(String name) throws RemoteException;
     public void grantUriPermissionFromOwner(IBinder owner, int fromUid, String targetPkg,
             Uri uri, int mode, int userId) throws RemoteException;
@@ -748,7 +749,8 @@
     int START_VOICE_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+218;
     int GET_ACTIVITY_OPTIONS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+219;
     int GET_APP_TASKS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+220;
-    int START_LOCK_TASK_BY_CURRENT = IBinder.FIRST_CALL_TRANSACTION+221;
-    int STOP_LOCK_TASK_BY_CURRENT = IBinder.FIRST_CALL_TRANSACTION+222;
+    int START_LOCK_TASK_BY_CURRENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+221;
+    int STOP_LOCK_TASK_BY_CURRENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+222;
     int FINISH_VOICE_TASK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+223;
+    int IS_TOP_OF_TASK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+224;
 }
diff --git a/core/java/android/app/TimePickerDialog.java b/core/java/android/app/TimePickerDialog.java
index 8cf8c25..abd042b 100644
--- a/core/java/android/app/TimePickerDialog.java
+++ b/core/java/android/app/TimePickerDialog.java
@@ -16,9 +16,11 @@
 
 package android.app;
 
+import android.app.UiModeManager;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.DialogInterface.OnClickListener;
+import android.content.res.Configuration;
 import android.os.Bundle;
 import android.util.TypedValue;
 import android.view.LayoutInflater;
@@ -110,11 +112,14 @@
                 (LayoutInflater) themeContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
         View view = inflater.inflate(R.layout.time_picker_dialog, null);
         setView(view);
-        setButtonPanelLayoutHint(LAYOUT_HINT_SIDE);
         mTimePicker = (TimePicker) view.findViewById(R.id.timePicker);
 
         // Initialize state
-        mTimePicker.setLegacyMode(false /* will show new UI */);
+        UiModeManager uiModeManager =
+                (UiModeManager) mContext.getSystemService(Context.UI_MODE_SERVICE);
+        if (uiModeManager.getCurrentModeType() != Configuration.UI_MODE_TYPE_TELEVISION) {
+            mTimePicker.setLegacyMode(false /* will show new UI */);
+        }
         mTimePicker.setShowDoneButton(true);
         mTimePicker.setDismissCallback(new TimePicker.TimePickerDismissCallback() {
             @Override
diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java
index d2146ac..645f7df 100644
--- a/core/java/android/content/res/TypedArray.java
+++ b/core/java/android/content/res/TypedArray.java
@@ -927,6 +927,30 @@
         return attrs;
     }
 
+    /**
+     * Return a mask of the configuration parameters for which the values in
+     * this typed array may change.
+     *
+     * @return Returns a mask of the changing configuration parameters, as
+     *         defined by {@link android.content.pm.ActivityInfo}.
+     * @see android.content.pm.ActivityInfo
+     */
+    public int getChangingConfigurations() {
+        int changingConfig = 0;
+
+        final int[] data = mData;
+        final int N = length();
+        for (int i = 0; i < N; i++) {
+            final int index = i * AssetManager.STYLE_NUM_ENTRIES;
+            final int type = data[index + AssetManager.STYLE_TYPE];
+            if (type == TypedValue.TYPE_NULL) {
+                continue;
+            }
+            changingConfig |= data[index + AssetManager.STYLE_CHANGING_CONFIGURATIONS];
+        }
+        return changingConfig;
+    }
+
     private boolean getValueAt(int index, TypedValue outValue) {
         final int[] data = mData;
         final int type = data[index+AssetManager.STYLE_TYPE];
diff --git a/core/java/android/widget/EdgeEffect.java b/core/java/android/widget/EdgeEffect.java
index 90fec23..3758d86 100644
--- a/core/java/android/widget/EdgeEffect.java
+++ b/core/java/android/widget/EdgeEffect.java
@@ -330,7 +330,7 @@
 
         canvas.clipRect(mBounds);
         canvas.translate(translateX, 0);
-        canvas.drawArc(mArcRect, 45, 90, true, mPaint);
+        canvas.drawArc(mArcRect, 45, 90, false, mPaint);
         canvas.restoreToCount(count);
 
         boolean oneLastFrame = false;
diff --git a/core/java/android/widget/LegacyTimePickerDelegate.java b/core/java/android/widget/LegacyTimePickerDelegate.java
index 1634d5f..97f46ea 100644
--- a/core/java/android/widget/LegacyTimePickerDelegate.java
+++ b/core/java/android/widget/LegacyTimePickerDelegate.java
@@ -75,6 +75,11 @@
     // accommodates these two cases to be backwards compatible.
     private final Button mAmPmButton;
 
+    // May be null if layout has no done button
+    private final View mDoneButton;
+    private boolean mShowDoneButton;
+    private TimePicker.TimePickerDismissCallback mDismissCallback;
+
     private final String[] mAmPmStrings;
 
     private boolean mIsEnabled = DEFAULT_ENABLED_STATE;
@@ -218,6 +223,19 @@
             }
         }
 
+        mDoneButton = delegator.findViewById(R.id.done_button);
+        if (mDoneButton != null) {
+            mDoneButton.setOnClickListener(new View.OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    if (mDismissCallback != null) {
+                        mDismissCallback.dismiss(mDelegator, false, getCurrentHour(),
+                                                 getCurrentMinute());
+                    }
+                }
+            });
+        }
+
         getHourFormatData();
 
         // update controls to initial state
@@ -242,6 +260,9 @@
         if (mDelegator.getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
             mDelegator.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
         }
+
+        mShowDoneButton = false;
+        updateDoneButton();
     }
 
     private void getHourFormatData() {
@@ -408,12 +429,23 @@
 
     @Override
     public void setShowDoneButton(boolean showDoneButton) {
-        // Nothing to do
+        mShowDoneButton = showDoneButton;
+        updateDoneButton();
+    }
+
+    private boolean isShowDoneButton() {
+        return mShowDoneButton;
+    }
+
+    private void updateDoneButton() {
+        if (mDoneButton != null) {
+            mDoneButton.setVisibility(mShowDoneButton ? View.VISIBLE : View.GONE);
+        }
     }
 
     @Override
     public void setDismissCallback(TimePicker.TimePickerDismissCallback callback) {
-        // Nothing to do
+        mDismissCallback = callback;
     }
 
     @Override
@@ -428,7 +460,8 @@
 
     @Override
     public Parcelable onSaveInstanceState(Parcelable superState) {
-        return new SavedState(superState, getCurrentHour(), getCurrentMinute());
+        return new SavedState(superState, getCurrentHour(), getCurrentMinute(),
+                isShowDoneButton());
     }
 
     @Override
@@ -436,6 +469,7 @@
         SavedState ss = (SavedState) state;
         setCurrentHour(ss.getHour());
         setCurrentMinute(ss.getMinute());
+        setShowDoneButton(ss.isShowDoneButton());
     }
 
     @Override
@@ -596,16 +630,20 @@
 
         private final int mMinute;
 
-        private SavedState(Parcelable superState, int hour, int minute) {
+        private final boolean mShowDoneButton;
+
+        private SavedState(Parcelable superState, int hour, int minute, boolean showDoneButton) {
             super(superState);
             mHour = hour;
             mMinute = minute;
+            mShowDoneButton = showDoneButton;
         }
 
         private SavedState(Parcel in) {
             super(in);
             mHour = in.readInt();
             mMinute = in.readInt();
+            mShowDoneButton = (in.readInt() == 1);
         }
 
         public int getHour() {
@@ -616,11 +654,16 @@
             return mMinute;
         }
 
+        public boolean isShowDoneButton() {
+            return mShowDoneButton;
+        }
+
         @Override
         public void writeToParcel(Parcel dest, int flags) {
             super.writeToParcel(dest, flags);
             dest.writeInt(mHour);
             dest.writeInt(mMinute);
+            dest.writeInt(mShowDoneButton ? 1 : 0);
         }
 
         @SuppressWarnings({"unused", "hiding"})
diff --git a/core/res/res/layout/time_picker_legacy_leanback.xml b/core/res/res/layout/time_picker_legacy_leanback.xml
new file mode 100644
index 0000000..397f733
--- /dev/null
+++ b/core/res/res/layout/time_picker_legacy_leanback.xml
@@ -0,0 +1,92 @@
+<?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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/timePickerLayout"
+    android:orientation="horizontal"
+    android:layout_gravity="center_horizontal"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:paddingStart="8dip"
+    android:paddingEnd="8dip">
+
+    <LinearLayout android:orientation="horizontal"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:paddingStart="8dip"
+        android:paddingEnd="8dip"
+        android:layoutDirection="ltr">
+
+        <!-- hour -->
+        <NumberPicker
+            android:id="@+id/hour"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="16dip"
+            android:layout_marginBottom="16dip"
+            android:focusable="true"
+            android:focusableInTouchMode="true"
+            />
+
+        <!-- divider -->
+        <TextView
+            android:id="@+id/divider"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginStart="6dip"
+            android:layout_marginEnd="6dip"
+            android:layout_gravity="center_vertical"
+            android:importantForAccessibility="no"
+            />
+
+        <!-- minute -->
+        <NumberPicker
+            android:id="@+id/minute"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="16dip"
+            android:layout_marginBottom="16dip"
+            android:focusable="true"
+            android:focusableInTouchMode="true"
+            />
+
+    </LinearLayout>
+
+    <!-- AM / PM -->
+    <NumberPicker
+        android:id="@+id/amPm"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="16dip"
+        android:layout_marginBottom="16dip"
+        android:layout_marginStart="8dip"
+        android:layout_marginEnd="8dip"
+        android:focusable="true"
+        android:focusableInTouchMode="true"
+        />
+
+    <!-- Width fixed here because TextView doesn't set MEASURED_STATE_TOO_SMALL -->
+    <Button
+        android:id="@+id/done_button"
+        android:layout_width="100dp"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_vertical"
+        android:text="@string/done_label"
+        android:textSize="@dimen/timepicker_done_label_size"
+        style="?android:attr/buttonBarButtonStyle" />
+
+</LinearLayout>
diff --git a/core/res/res/values/styles_leanback.xml b/core/res/res/values/styles_leanback.xml
index 72d0379..ff9d73f 100644
--- a/core/res/res/values/styles_leanback.xml
+++ b/core/res/res/values/styles_leanback.xml
@@ -22,4 +22,9 @@
     <style name="AlertDialog.Leanback.Light">
     </style>
 
+    <style name="Widget.Leanback.TimePicker" parent="Widget.Material.TimePicker">
+        <item name="legacyLayout">@layout/time_picker_legacy_leanback</item>
+    </style>
+
+
 </resources>
diff --git a/core/res/res/values/themes_leanback.xml b/core/res/res/values/themes_leanback.xml
index a571b98..15ae14c 100644
--- a/core/res/res/values/themes_leanback.xml
+++ b/core/res/res/values/themes_leanback.xml
@@ -33,6 +33,7 @@
       <item name="textColorPrimary">@color/primary_text_leanback_dark</item>
       <item name="textColorSecondary">@color/secondary_text_leanback_dark</item>
       <item name="alertDialogStyle">@style/AlertDialog.Leanback</item>
+      <item name="timePickerStyle">@style/Widget.Leanback.TimePicker</item>
     </style>
 
     <style name="Theme.Leanback.Light.Dialog.TimePicker" parent="Theme.Material.Light.Dialog.BaseTimePicker">
@@ -40,6 +41,7 @@
       <item name="textColorPrimary">@color/primary_text_leanback_light</item>
       <item name="textColorSecondary">@color/secondary_text_leanback_light</item>
       <item name="alertDialogStyle">@style/AlertDialog.Leanback.Light</item>
+      <item name="timePickerStyle">@style/Widget.Leanback.TimePicker</item>
     </style>
 
     <style name="Theme.Leanback.Light.Dialog" parent="Theme.Material.Light.Dialog">
diff --git a/data/fonts/Android.mk b/data/fonts/Android.mk
index 6437e07..86a45c5 100644
--- a/data/fonts/Android.mk
+++ b/data/fonts/Android.mk
@@ -56,7 +56,6 @@
 
 droidsans_fallback_src := DroidSansFallbackFull.ttf
 
-ifneq ($(EXTENDED_FONT_FOOTPRINT),true)
 include $(CLEAR_VARS)
 LOCAL_MODULE := MTLmr3m.ttf
 LOCAL_SRC_FILES := $(LOCAL_MODULE)
@@ -65,7 +64,6 @@
 LOCAL_MODULE_PATH := $(TARGET_OUT)/fonts
 include $(BUILD_PREBUILT)
 extra_font_files += MTLmr3m.ttf
-endif  # !EXTENDED_FONT_FOOTPRINT
 
 endif  # SMALLER_FONT_FOOTPRINT
 
diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java
index e080375..83a8ed5 100644
--- a/graphics/java/android/graphics/drawable/BitmapDrawable.java
+++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java
@@ -31,7 +31,6 @@
 import android.graphics.PixelFormat;
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuff.Mode;
-import android.graphics.drawable.ColorDrawable.ColorState;
 import android.graphics.PorterDuffColorFilter;
 import android.graphics.Rect;
 import android.graphics.Shader;
@@ -712,9 +711,11 @@
         final Resources r = a.getResources();
         final BitmapState state = mBitmapState;
 
+        // Account for any configuration changes.
+        state.mChangingConfigurations |= a.getChangingConfigurations();
+
         // Extract the theme attributes, if any.
-        final int[] themeAttrs = a.extractThemeAttrs();
-        state.mThemeAttrs = themeAttrs;
+        state.mThemeAttrs = a.extractThemeAttrs();
 
         final int srcResId = a.getResourceId(R.styleable.BitmapDrawable_src, 0);
         if (srcResId != 0) {
diff --git a/graphics/java/android/graphics/drawable/ColorDrawable.java b/graphics/java/android/graphics/drawable/ColorDrawable.java
index 3716182..ca2f7a3 100644
--- a/graphics/java/android/graphics/drawable/ColorDrawable.java
+++ b/graphics/java/android/graphics/drawable/ColorDrawable.java
@@ -45,7 +45,6 @@
 
     @ViewDebug.ExportedProperty(deepExport = true, prefix = "state_")
     private ColorState mColorState;
-    private ColorStateList mTint;
     private PorterDuffColorFilter mTintFilter;
 
     private boolean mMutated;
@@ -215,60 +214,42 @@
         super.inflate(r, parser, attrs, theme);
 
         final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.ColorDrawable);
-        inflateStateFromTypedArray(a);
+        updateStateFromTypedArray(a);
         a.recycle();
     }
 
     /**
-     * Initializes the constant state from the values in the typed array.
-     */
-    private void inflateStateFromTypedArray(TypedArray a) {
-        final ColorState state = mColorState;
-
-        // Extract the theme attributes, if any.
-        final int[] themeAttrs = a.extractThemeAttrs();
-        state.mThemeAttrs = themeAttrs;
-
-        if (themeAttrs == null || themeAttrs[R.styleable.ColorDrawable_color] == 0) {
-            final int color = a.getColor(R.styleable.ColorDrawable_color, 0);
-            state.mBaseColor = color;
-            state.mUseColor = color;
-        }
-    }
-
-    @Override
-    public void applyTheme(Theme t) {
-        super.applyTheme(t);
-
-        final ColorState state = mColorState;
-        if (state == null) {
-            throw new RuntimeException("Can't apply theme to <color> with no constant state");
-        }
-
-        final int[] themeAttrs = state.mThemeAttrs;
-        if (themeAttrs != null) {
-            final TypedArray a = t.resolveAttributes(themeAttrs, R.styleable.ColorDrawable);
-            updateStateFromTypedArray(a);
-            a.recycle();
-        }
-    }
-
-    /**
      * Updates the constant state from the values in the typed array.
      */
     private void updateStateFromTypedArray(TypedArray a) {
         final ColorState state = mColorState;
 
-        if (a.hasValue(R.styleable.ColorDrawable_color)) {
-            final int color = a.getColor(R.styleable.ColorDrawable_color, 0);
-            state.mBaseColor = color;
-            state.mUseColor = color;
+        // Account for any configuration changes.
+        state.mChangingConfigurations |= a.getChangingConfigurations();
+
+        // Extract the theme attributes, if any.
+        state.mThemeAttrs = a.extractThemeAttrs();
+
+        state.mBaseColor = a.getColor(R.styleable.ColorDrawable_color, state.mBaseColor);
+        state.mUseColor = state.mBaseColor;
+    }
+
+    @Override
+    public void applyTheme(Theme t) {
+        super.applyTheme(t);
+
+        final ColorState state = mColorState;
+        if (state == null || state.mThemeAttrs == null) {
+            return;
         }
+
+        final TypedArray a = t.resolveAttributes(state.mThemeAttrs, R.styleable.ColorDrawable);
+        updateStateFromTypedArray(a);
+        a.recycle();
     }
 
     @Override
     public ConstantState getConstantState() {
-        mColorState.mChangingConfigurations = getChangingConfigurations();
         return mColorState;
     }
 
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index c2759ec..b050a02 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -238,9 +238,9 @@
      * may change, requiring that it be re-created.
      *
      * @param configs A mask of the changing configuration parameters, as
-     * defined by {@link android.content.res.Configuration}.
+     * defined by {@link android.content.pm.ActivityInfo}.
      *
-     * @see android.content.res.Configuration
+     * @see android.content.pm.ActivityInfo
      */
     public void setChangingConfigurations(int configs) {
         mChangingConfigurations = configs;
@@ -255,9 +255,9 @@
      * drawables they hold.
      *
      * @return Returns a mask of the changing configuration parameters, as
-     * defined by {@link android.content.res.Configuration}.
+     * defined by {@link android.content.pm.ActivityInfo}.
      *
-     * @see android.content.res.Configuration
+     * @see android.content.pm.ActivityInfo
      */
     public int getChangingConfigurations() {
         return mChangingConfigurations;
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index 0ccce93..6e9b776 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -1011,6 +1011,9 @@
     private void updateStateFromTypedArray(TypedArray a) {
         final GradientState state = mGradientState;
 
+        // Account for any configuration changes.
+        state.mChangingConfigurations |= a.getChangingConfigurations();
+
         // Extract the theme attributes, if any.
         state.mThemeAttrs = a.extractThemeAttrs();
 
@@ -1152,6 +1155,9 @@
     private void updateGradientDrawablePadding(TypedArray a) {
         final GradientState st = mGradientState;
 
+        // Account for any configuration changes.
+        st.mChangingConfigurations |= a.getChangingConfigurations();
+
         // Extract the theme attributes, if any.
         st.mAttrPadding = a.extractThemeAttrs();
 
@@ -1170,6 +1176,9 @@
     private void updateDrawableCorners(TypedArray a) {
         final GradientState st = mGradientState;
 
+        // Account for any configuration changes.
+        st.mChangingConfigurations |= a.getChangingConfigurations();
+
         // Extract the theme attributes, if any.
         st.mAttrCorners = a.extractThemeAttrs();
 
@@ -1201,6 +1210,10 @@
     private void updateGradientDrawableStroke(TypedArray a) {
         final GradientState st = mGradientState;
 
+        // Account for any configuration changes.
+        st.mChangingConfigurations |= a.getChangingConfigurations();
+
+        // Extract the theme attributes, if any.
         st.mAttrStroke = a.extractThemeAttrs();
 
         // We have an explicit stroke defined, so the default stroke width
@@ -1227,7 +1240,13 @@
     }
 
     private void updateGradientDrawableSolid(TypedArray a) {
-        mGradientState.mAttrSolid = a.extractThemeAttrs();
+        final GradientState st = mGradientState;
+
+        // Account for any configuration changes.
+        st.mChangingConfigurations |= a.getChangingConfigurations();
+
+        // Extract the theme attributes, if any.
+        st.mAttrSolid = a.extractThemeAttrs();
 
         final ColorStateList colorStateList = a.getColorStateList(
                 R.styleable.GradientDrawableSolid_color);
@@ -1240,6 +1259,9 @@
             throws XmlPullParserException {
         final GradientState st = mGradientState;
 
+        // Account for any configuration changes.
+        st.mChangingConfigurations |= a.getChangingConfigurations();
+
         // Extract the theme attributes, if any.
         st.mAttrGradient = a.extractThemeAttrs();
 
@@ -1351,6 +1373,9 @@
     private void updateGradientDrawableSize(TypedArray a) {
         final GradientState st = mGradientState;
 
+        // Account for any configuration changes.
+        st.mChangingConfigurations |= a.getChangingConfigurations();
+
         // Extract the theme attributes, if any.
         st.mAttrSize = a.extractThemeAttrs();
 
diff --git a/graphics/java/android/graphics/drawable/InsetDrawable.java b/graphics/java/android/graphics/drawable/InsetDrawable.java
index e91ffb1..d214a47 100644
--- a/graphics/java/android/graphics/drawable/InsetDrawable.java
+++ b/graphics/java/android/graphics/drawable/InsetDrawable.java
@@ -16,6 +16,8 @@
 
 package android.graphics.drawable;
 
+import com.android.internal.R;
+
 import android.annotation.NonNull;
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -48,9 +50,11 @@
  * @attr ref android.R.styleable#InsetDrawable_insetBottom
  */
 public class InsetDrawable extends Drawable implements Drawable.Callback {
-    // Most of this is copied from ScaleDrawable.
-    private InsetState mInsetState;
+    private static final String LOG_TAG = "InsetDrawable";
+
     private final Rect mTmpRect = new Rect();
+
+    private InsetState mInsetState;
     private boolean mMutated;
 
     /*package*/ InsetDrawable() {
@@ -79,59 +83,81 @@
     @Override
     public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme)
             throws XmlPullParserException, IOException {
-        int type;
-
-        TypedArray a = r.obtainAttributes(attrs,
-                com.android.internal.R.styleable.InsetDrawable);
-
-        super.inflateWithAttributes(r, parser, a,
-                com.android.internal.R.styleable.InsetDrawable_visible);
-
-        int drawableRes = a.getResourceId(com.android.internal.R.styleable.
-                                    InsetDrawable_drawable, 0);
-
-        int inLeft = a.getDimensionPixelOffset(com.android.internal.R.styleable.
-                                    InsetDrawable_insetLeft, 0);
-        int inTop = a.getDimensionPixelOffset(com.android.internal.R.styleable.
-                                    InsetDrawable_insetTop, 0);
-        int inRight = a.getDimensionPixelOffset(com.android.internal.R.styleable.
-                                    InsetDrawable_insetRight, 0);
-        int inBottom = a.getDimensionPixelOffset(com.android.internal.R.styleable.
-                                    InsetDrawable_insetBottom, 0);
-
+        final TypedArray a = r.obtainAttributes(attrs, R.styleable.InsetDrawable);
+        super.inflateWithAttributes(r, parser, a, R.styleable.InsetDrawable_visible);
+        updateStateFromTypedArray(a);
         a.recycle();
 
-        Drawable dr;
-        if (drawableRes != 0) {
-            dr = r.getDrawable(drawableRes);
-        } else {
+        // Load inner XML elements.
+        if (mInsetState.mDrawable == null) {
+            int type;
             while ((type=parser.next()) == XmlPullParser.TEXT) {
             }
             if (type != XmlPullParser.START_TAG) {
                 throw new XmlPullParserException(
                         parser.getPositionDescription()
-                        + ": <inset> tag requires a 'drawable' attribute or "
-                        + "child tag defining a drawable");
+                                + ": <inset> tag requires a 'drawable' attribute or "
+                                + "child tag defining a drawable");
             }
-            dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
-        }
-
-        if (dr == null) {
-            Log.w("drawable", "No drawable specified for <inset>");
-        }
-
-        mInsetState.mDrawable = dr;
-        mInsetState.mInsetLeft = inLeft;
-        mInsetState.mInsetRight = inRight;
-        mInsetState.mInsetTop = inTop;
-        mInsetState.mInsetBottom = inBottom;
-
-        if (dr != null) {
+            final Drawable dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
+            mInsetState.mDrawable = dr;
             dr.setCallback(this);
         }
+
+        // Verify state.
+        if (mInsetState.mDrawable == null) {
+            Log.w(LOG_TAG, "No drawable specified for <inset>");
+        }
     }
 
-    // overrides from Drawable.Callback
+    private void updateStateFromTypedArray(TypedArray a) throws XmlPullParserException {
+        final InsetState state = mInsetState;
+
+        // Account for any configuration changes.
+        state.mChangingConfigurations |= a.getChangingConfigurations();
+
+        // Extract the theme attributes, if any.
+        state.mThemeAttrs = a.extractThemeAttrs();
+
+        final Drawable dr = a.getDrawable(R.styleable.InsetDrawable_drawable);
+        if (dr != null) {
+            state.mDrawable = dr;
+            dr.setCallback(this);
+        }
+
+        state.mInsetLeft = a.getDimensionPixelOffset(
+                R.styleable.InsetDrawable_insetLeft, state.mInsetLeft);
+        state.mInsetTop = a.getDimensionPixelOffset(
+                R.styleable.InsetDrawable_insetTop, state.mInsetTop);
+        state.mInsetRight = a.getDimensionPixelOffset(
+                R.styleable.InsetDrawable_insetRight, state.mInsetRight);
+        state.mInsetBottom = a.getDimensionPixelOffset(
+                R.styleable.InsetDrawable_insetBottom, state.mInsetBottom);
+    }
+
+    @Override
+    public void applyTheme(Theme t) {
+        super.applyTheme(t);
+
+        final InsetState state = mInsetState;
+        if (state == null || state.mThemeAttrs == null) {
+            return;
+        }
+
+        final TypedArray a = t.resolveAttributes(state.mThemeAttrs, R.styleable.InsetDrawable);
+        try {
+            updateStateFromTypedArray(a);
+        } catch (XmlPullParserException e) {
+            throw new RuntimeException(e);
+        } finally {
+            a.recycle();
+        }
+    }
+
+    @Override
+    public boolean canApplyTheme() {
+        return mInsetState != null && mInsetState.mThemeAttrs != null;
+    }
 
     @Override
     public void invalidateDrawable(Drawable who) {
@@ -157,8 +183,6 @@
         }
     }
 
-    // overrides from Drawable
-
     @Override
     public void draw(Canvas canvas) {
         mInsetState.mDrawable.draw(canvas);
@@ -316,9 +340,11 @@
     }
 
     final static class InsetState extends ConstantState {
-        Drawable mDrawable;
+        int[] mThemeAttrs;
         int mChangingConfigurations;
 
+        Drawable mDrawable;
+
         int mInsetLeft;
         int mInsetTop;
         int mInsetRight;
@@ -329,6 +355,8 @@
 
         InsetState(InsetState orig, InsetDrawable owner, Resources res) {
             if (orig != null) {
+                mThemeAttrs = orig.mThemeAttrs;
+                mChangingConfigurations = orig.mChangingConfigurations;
                 if (res != null) {
                     mDrawable = orig.mDrawable.getConstantState().newDrawable(res);
                 } else {
diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java
index 8ebb6f2..0707d66 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -155,9 +155,11 @@
     private void updateStateFromTypedArray(TypedArray a) {
         final LayerState state = mLayerState;
 
+        // Account for any configuration changes.
+        state.mChangingConfigurations |= a.getChangingConfigurations();
+
         // Extract the theme attributes, if any.
-        final int[] themeAttrs = a.extractThemeAttrs();
-        state.mThemeAttrs = themeAttrs;
+        state.mThemeAttrs = a.extractThemeAttrs();
 
         mOpacityOverride = a.getInt(R.styleable.LayerDrawable_opacity, mOpacityOverride);
 
@@ -172,7 +174,8 @@
      */
     private void inflateLayers(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme)
             throws XmlPullParserException, IOException {
-        TypedArray a;
+        final LayerState state = mLayerState;
+
         final int innerDepth = parser.getDepth() + 1;
         int type;
         int depth;
@@ -186,28 +189,12 @@
                 continue;
             }
 
-            a = obtainAttributes(r, theme, attrs, R.styleable.LayerDrawableItem);
-
-            final int[] themeAttrs = a.extractThemeAttrs();
-            final int left = a.getDimensionPixelOffset(
-                    R.styleable.LayerDrawableItem_left, 0);
-            final int top = a.getDimensionPixelOffset(
-                    R.styleable.LayerDrawableItem_top, 0);
-            final int right = a.getDimensionPixelOffset(
-                    R.styleable.LayerDrawableItem_right, 0);
-            final int bottom = a.getDimensionPixelOffset(
-                    R.styleable.LayerDrawableItem_bottom, 0);
-            final int drawableRes = a.getResourceId(
-                    R.styleable.LayerDrawableItem_drawable, 0);
-            final int id = a.getResourceId(
-                    R.styleable.LayerDrawableItem_id, View.NO_ID);
-
+            final ChildDrawable layer = new ChildDrawable();
+            final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.LayerDrawableItem);
+            updateLayerFromTypedArray(layer, a);
             a.recycle();
 
-            final Drawable dr;
-            if (drawableRes != 0) {
-                dr = r.getDrawable(drawableRes, theme);
-            } else {
+            if (layer.mDrawable == null) {
                 while ((type = parser.next()) == XmlPullParser.TEXT) {
                 }
                 if (type != XmlPullParser.START_TAG) {
@@ -215,10 +202,39 @@
                             + ": <item> tag requires a 'drawable' attribute or "
                             + "child tag defining a drawable");
                 }
-                dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
+                layer.mDrawable = Drawable.createFromXmlInner(r, parser, attrs, theme);
             }
 
-            addLayer(dr, themeAttrs, id, left, top, right, bottom);
+            if (layer.mDrawable != null) {
+                state.mChildrenChangingConfigurations |=
+                        layer.mDrawable.getChangingConfigurations();
+                layer.mDrawable.setCallback(this);
+            }
+        }
+    }
+
+    private void updateLayerFromTypedArray(ChildDrawable layer, TypedArray a) {
+        final LayerState state = mLayerState;
+
+        // Account for any configuration changes.
+        state.mChildrenChangingConfigurations |= a.getChangingConfigurations();
+
+        // Extract the theme attributes, if any.
+        layer.mThemeAttrs = a.extractThemeAttrs();
+
+        layer.mInsetL = a.getDimensionPixelOffset(
+                R.styleable.LayerDrawableItem_left, layer.mInsetL);
+        layer.mInsetT = a.getDimensionPixelOffset(
+                R.styleable.LayerDrawableItem_top, layer.mInsetT);
+        layer.mInsetR = a.getDimensionPixelOffset(
+                R.styleable.LayerDrawableItem_right, layer.mInsetR);
+        layer.mInsetB = a.getDimensionPixelOffset(
+                R.styleable.LayerDrawableItem_bottom, layer.mInsetB);
+        layer.mId = a.getResourceId(R.styleable.LayerDrawableItem_id, layer.mId);
+
+        final Drawable dr = a.getDrawable(R.styleable.LayerDrawableItem_drawable);
+        if (dr != null) {
+            layer.mDrawable = dr;
         }
     }
 
@@ -231,19 +247,23 @@
             return;
         }
 
-        final int[] themeAttrs = state.mThemeAttrs;
-        if (themeAttrs != null) {
-            final TypedArray a = t.resolveAttributes(themeAttrs, R.styleable.LayerDrawable);
+        if (state.mThemeAttrs != null) {
+            final TypedArray a = t.resolveAttributes(state.mThemeAttrs, R.styleable.LayerDrawable);
             updateStateFromTypedArray(a);
             a.recycle();
         }
 
-        // TODO: Update layer positions from cached typed arrays.
-
         final ChildDrawable[] array = mLayerState.mChildren;
         final int N = mLayerState.mNum;
         for (int i = 0; i < N; i++) {
             final ChildDrawable layer = array[i];
+            if (layer.mThemeAttrs != null) {
+                final TypedArray a = t.resolveAttributes(layer.mThemeAttrs,
+                        R.styleable.LayerDrawableItem);
+                updateLayerFromTypedArray(layer, a);
+                a.recycle();
+            }
+
             final Drawable d = layer.mDrawable;
             if (d.canApplyTheme()) {
                 d.applyTheme(t);
@@ -297,19 +317,7 @@
         return false;
     }
 
-    /**
-     * Add a new layer to this drawable. The new layer is identified by an id.
-     *
-     * @param layer The drawable to add as a layer.
-     * @param themeAttrs Theme attributes extracted from the layer.
-     * @param id The id of the new layer.
-     * @param left The left padding of the new layer.
-     * @param top The top padding of the new layer.
-     * @param right The right padding of the new layer.
-     * @param bottom The bottom padding of the new layer.
-     */
-    void addLayer(Drawable layer, int[] themeAttrs, int id, int left, int top, int right,
-            int bottom) {
+    void addLayer(ChildDrawable layer) {
         final LayerState st = mLayerState;
         final int N = st.mChildren != null ? st.mChildren.length : 0;
         final int i = st.mNum;
@@ -322,10 +330,25 @@
             st.mChildren = nu;
         }
 
-        mLayerState.mChildrenChangingConfigurations |= layer.getChangingConfigurations();
+        st.mChildren[i] = layer;
+        st.mNum++;
+        st.invalidateCache();
+    }
 
+    /**
+     * Add a new layer to this drawable. The new layer is identified by an id.
+     *
+     * @param layer The drawable to add as a layer.
+     * @param themeAttrs Theme attributes extracted from the layer.
+     * @param id The id of the new layer.
+     * @param left The left padding of the new layer.
+     * @param top The top padding of the new layer.
+     * @param right The right padding of the new layer.
+     * @param bottom The bottom padding of the new layer.
+     */
+    ChildDrawable addLayer(Drawable layer, int[] themeAttrs, int id, int left, int top, int right,
+            int bottom) {
         final ChildDrawable childDrawable = new ChildDrawable();
-        st.mChildren[i] = childDrawable;
         childDrawable.mId = id;
         childDrawable.mThemeAttrs = themeAttrs;
         childDrawable.mDrawable = layer;
@@ -334,10 +357,13 @@
         childDrawable.mInsetT = top;
         childDrawable.mInsetR = right;
         childDrawable.mInsetB = bottom;
-        st.mNum++;
-        st.invalidateCache();
 
+        addLayer(childDrawable);
+
+        mLayerState.mChildrenChangingConfigurations |= layer.getChangingConfigurations();
         layer.setCallback(this);
+
+        return childDrawable;
     }
 
     /**
@@ -904,7 +930,7 @@
         public Drawable mDrawable;
         public int[] mThemeAttrs;
         public int mInsetL, mInsetT, mInsetR, mInsetB;
-        public int mId;
+        public int mId = View.NO_ID;
 
         ChildDrawable() {
             // Default empty constructor.
diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
index 6642bdd..24bbf7c 100644
--- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java
+++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
@@ -382,9 +382,11 @@
         final Resources r = a.getResources();
         final NinePatchState state = mNinePatchState;
 
+        // Account for any configuration changes.
+        state.mChangingConfigurations |= a.getChangingConfigurations();
+
         // Extract the theme attributes, if any.
-        final int[] themeAttrs = a.extractThemeAttrs();
-        state.mThemeAttrs = themeAttrs;
+        state.mThemeAttrs = a.extractThemeAttrs();
 
         state.mDither = a.getBoolean(R.styleable.NinePatchDrawable_dither, state.mDither);
 
diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java
index dfe14f2..87f5989 100644
--- a/graphics/java/android/graphics/drawable/RippleDrawable.java
+++ b/graphics/java/android/graphics/drawable/RippleDrawable.java
@@ -358,6 +358,9 @@
     private void updateStateFromTypedArray(TypedArray a) throws XmlPullParserException {
         final RippleState state = mState;
 
+        // Account for any configuration changes.
+        state.mChangingConfigurations |= a.getChangingConfigurations();
+
         // Extract the theme attributes, if any.
         state.mTouchThemeAttrs = a.extractThemeAttrs();
 
diff --git a/graphics/java/android/graphics/drawable/ShapeDrawable.java b/graphics/java/android/graphics/drawable/ShapeDrawable.java
index 86765dd..9802529 100644
--- a/graphics/java/android/graphics/drawable/ShapeDrawable.java
+++ b/graphics/java/android/graphics/drawable/ShapeDrawable.java
@@ -422,6 +422,9 @@
         final ShapeState state = mShapeState;
         final Paint paint = state.mPaint;
 
+        // Account for any configuration changes.
+        state.mChangingConfigurations |= a.getChangingConfigurations();
+
         // Extract the theme attributes, if any.
         state.mThemeAttrs = a.extractThemeAttrs();
 
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index b37204d..150f210 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -44,7 +44,6 @@
 
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Stack;
 
 /**
@@ -308,6 +307,9 @@
     private void updateStateFromTypedArray(TypedArray a) {
         final VectorDrawableState state = mVectorState;
 
+        // Account for any configuration changes.
+        state.mChangingConfigurations |= a.getChangingConfigurations();
+
         // Extract the theme attributes, if any.
         state.mThemeAttrs = a.extractThemeAttrs();
 
@@ -322,8 +324,9 @@
         }
     }
 
-    private VPathRenderer inflateInternal(Resources res, XmlPullParser parser, AttributeSet attrs, Theme theme)
-            throws XmlPullParserException, IOException {
+    private VPathRenderer inflateInternal(Resources res, XmlPullParser parser, AttributeSet attrs,
+            Theme theme) throws XmlPullParserException, IOException {
+        final VectorDrawableState state = mVectorState;
         final VPathRenderer pathRenderer = new VPathRenderer();
 
         boolean noSizeTag = true;
@@ -349,12 +352,15 @@
                         mVGTargetsMap.put(path.getPathName(), path);
                     }
                     noPathTag = false;
+                    state.mChangingConfigurations |= path.mChangingConfigurations;
                 } else if (SHAPE_SIZE.equals(tagName)) {
                     pathRenderer.parseSize(res, attrs);
                     noSizeTag = false;
+                    state.mChangingConfigurations |= pathRenderer.mChangingConfigurations;
                 } else if (SHAPE_VIEWPORT.equals(tagName)) {
                     pathRenderer.parseViewport(res, attrs);
                     noViewportTag = false;
+                    state.mChangingConfigurations |= pathRenderer.mChangingConfigurations;
                 } else if (SHAPE_GROUP.equals(tagName)) {
                     VGroup newChildGroup = new VGroup();
                     newChildGroup.inflate(res, attrs, theme);
@@ -363,6 +369,7 @@
                     if (newChildGroup.getGroupName() != null) {
                         mVGTargetsMap.put(newChildGroup.getGroupName(), newChildGroup);
                     }
+                    state.mChangingConfigurations |= newChildGroup.mChangingConfigurations;
                 }
             } else if (eventType == XmlPullParser.END_TAG) {
                 final String tagName = parser.getName();
@@ -483,6 +490,8 @@
         private ColorFilter mColorFilter;
         private PathMeasure mPathMeasure;
 
+        private int mChangingConfigurations;
+
         private float mBaseWidth = 0;
         private float mBaseHeight = 0;
         private float mViewportWidth = 0;
@@ -509,6 +518,7 @@
             mBaseHeight = copy.mBaseHeight;
             mViewportWidth = copy.mViewportHeight;
             mViewportHeight = copy.mViewportHeight;
+            mChangingConfigurations = copy.mChangingConfigurations;
         }
 
         public boolean canApplyTheme() {
@@ -609,7 +619,8 @@
 
             mFinalPathMatrix.set(vGroup.mStackedMatrix);
             mFinalPathMatrix.postScale(scale, scale, mViewportWidth / 2f, mViewportHeight / 2f);
-            mFinalPathMatrix.postTranslate(w / 2f - mViewportWidth / 2f, h / 2f - mViewportHeight / 2f);
+            mFinalPathMatrix.postTranslate(
+                    w / 2f - mViewportWidth / 2f, h / 2f - mViewportHeight / 2f);
 
             ArrayList<VPath> paths = vGroup.getPaths();
             for (int i = 0; i < paths.size(); i++) {
@@ -687,8 +698,14 @@
         private void parseViewport(Resources r, AttributeSet attrs)
                 throws XmlPullParserException {
             final TypedArray a = r.obtainAttributes(attrs, R.styleable.VectorDrawableViewport);
-            mViewportWidth = a.getFloat(R.styleable.VectorDrawableViewport_viewportWidth, mViewportWidth);
-            mViewportHeight = a.getFloat(R.styleable.VectorDrawableViewport_viewportHeight, mViewportHeight);
+
+            // Account for any configuration changes.
+            mChangingConfigurations |= a.getChangingConfigurations();
+
+            mViewportWidth = a.getFloat(
+                    R.styleable.VectorDrawableViewport_viewportWidth, mViewportWidth);
+            mViewportHeight = a.getFloat(
+                    R.styleable.VectorDrawableViewport_viewportHeight, mViewportHeight);
 
             if (mViewportWidth <= 0) {
                 throw new XmlPullParserException(a.getPositionDescription() +
@@ -704,6 +721,10 @@
         private void parseSize(Resources r, AttributeSet attrs)
                 throws XmlPullParserException  {
             final TypedArray a = r.obtainAttributes(attrs, R.styleable.VectorDrawableSize);
+
+            // Account for any configuration changes.
+            mChangingConfigurations |= a.getChangingConfigurations();
+
             mBaseWidth = a.getDimension(R.styleable.VectorDrawableSize_width, mBaseWidth);
             mBaseHeight = a.getDimension(R.styleable.VectorDrawableSize_height, mBaseHeight);
 
@@ -739,6 +760,7 @@
         // parents' local matrices with the current one.
         private final Matrix mStackedMatrix = new Matrix();
 
+        private int mChangingConfigurations;
         private int[] mThemeAttrs;
 
         private String mGroupName = null;
@@ -847,13 +869,19 @@
             return mThemeAttrs != null;
         }
 
-        public void applyTheme(Theme t) {
-            if (mThemeAttrs == null) {
-                return;
-            }
+        public void inflate(Resources res, AttributeSet attrs, Theme theme) {
+            final TypedArray a = obtainAttributes(res, theme, attrs,
+                    R.styleable.VectorDrawableGroup);
+            updateStateFromTypedArray(a);
+            a.recycle();
+        }
 
-            final TypedArray a = t.resolveAttributes(
-                    mThemeAttrs, R.styleable.VectorDrawablePath);
+        private void updateStateFromTypedArray(TypedArray a) {
+            // Account for any configuration changes.
+            mChangingConfigurations |= a.getChangingConfigurations();
+
+            // Extract the theme attributes, if any.
+            mThemeAttrs = a.extractThemeAttrs();
 
             mRotate = a.getFloat(R.styleable.VectorDrawableGroup_rotation, mRotate);
             mPivotX = a.getFloat(R.styleable.VectorDrawableGroup_pivotX, mPivotX);
@@ -863,58 +891,22 @@
             mTranslateX = a.getFloat(R.styleable.VectorDrawableGroup_translateX, mTranslateX);
             mTranslateY = a.getFloat(R.styleable.VectorDrawableGroup_translateY, mTranslateY);
             mGroupAlpha = a.getFloat(R.styleable.VectorDrawableGroup_alpha, mGroupAlpha);
-            updateLocalMatrix();
-            if (a.hasValue(R.styleable.VectorDrawableGroup_name)) {
-                mGroupName = a.getString(R.styleable.VectorDrawableGroup_name);
+
+            final String groupName = a.getString(R.styleable.VectorDrawableGroup_name);
+            if (groupName != null) {
+                mGroupName = groupName;
             }
-            a.recycle();
+
+            updateLocalMatrix();
         }
 
-        public void inflate(Resources res, AttributeSet attrs, Theme theme) {
-            final TypedArray a = obtainAttributes(res, theme, attrs, R.styleable.VectorDrawableGroup);
-            final int[] themeAttrs = a.extractThemeAttrs();
-
-            mThemeAttrs = themeAttrs;
-            // NOTE: The set of attributes loaded here MUST match the
-            // set of attributes loaded in applyTheme.
-
-            if (themeAttrs == null || themeAttrs[R.styleable.VectorDrawableGroup_rotation] == 0) {
-                mRotate = a.getFloat(R.styleable.VectorDrawableGroup_rotation, mRotate);
+        public void applyTheme(Theme t) {
+            if (mThemeAttrs == null) {
+                return;
             }
 
-            if (themeAttrs == null || themeAttrs[R.styleable.VectorDrawableGroup_pivotX] == 0) {
-                mPivotX = a.getFloat(R.styleable.VectorDrawableGroup_pivotX, mPivotX);
-            }
-
-            if (themeAttrs == null || themeAttrs[R.styleable.VectorDrawableGroup_pivotY] == 0) {
-                mPivotY = a.getFloat(R.styleable.VectorDrawableGroup_pivotY, mPivotY);
-            }
-
-            if (themeAttrs == null || themeAttrs[R.styleable.VectorDrawableGroup_scaleX] == 0) {
-                mScaleX = a.getFloat(R.styleable.VectorDrawableGroup_scaleX, mScaleX);
-            }
-
-            if (themeAttrs == null || themeAttrs[R.styleable.VectorDrawableGroup_scaleY] == 0) {
-                mScaleY = a.getFloat(R.styleable.VectorDrawableGroup_scaleY, mScaleY);
-            }
-
-            if (themeAttrs == null || themeAttrs[R.styleable.VectorDrawableGroup_translateX] == 0) {
-                mTranslateX = a.getFloat(R.styleable.VectorDrawableGroup_translateX, mTranslateX);
-            }
-
-            if (themeAttrs == null || themeAttrs[R.styleable.VectorDrawableGroup_translateY] == 0) {
-                mTranslateY = a.getFloat(R.styleable.VectorDrawableGroup_translateY, mTranslateY);
-            }
-
-            if (themeAttrs == null || themeAttrs[R.styleable.VectorDrawableGroup_name] == 0) {
-                mGroupName = a.getString(R.styleable.VectorDrawableGroup_name);
-            }
-
-            if (themeAttrs == null || themeAttrs[R.styleable.VectorDrawableGroup_alpha] == 0) {
-                mGroupAlpha = a.getFloat(R.styleable.VectorDrawableGroup_alpha, mGroupAlpha);
-            }
-
-            updateLocalMatrix();
+            final TypedArray a = t.resolveAttributes(mThemeAttrs, R.styleable.VectorDrawablePath);
+            updateStateFromTypedArray(a);
             a.recycle();
         }
 
@@ -939,6 +931,7 @@
     }
 
     private static class VPath {
+        private int mChangingConfigurations;
         private int[] mThemeAttrs;
 
         int mStrokeColor = 0;
@@ -1096,113 +1089,29 @@
             mTrimPathOffset = trimPathOffset;
         }
 
-        public void inflate(Resources r, AttributeSet attrs, Theme theme) {
-            final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.VectorDrawablePath);
-            final int[] themeAttrs = a.extractThemeAttrs();
-            mThemeAttrs = themeAttrs;
-
-            // NOTE: The set of attributes loaded here MUST match the
-            // set of attributes loaded in applyTheme.
-            if (themeAttrs == null || themeAttrs[R.styleable.VectorDrawablePath_clipToPath] == 0) {
-                mClip = a.getBoolean(R.styleable.VectorDrawablePath_clipToPath, mClip);
-            }
-
-            if (themeAttrs == null || themeAttrs[R.styleable.VectorDrawablePath_name] == 0) {
-                mPathName = a.getString(R.styleable.VectorDrawablePath_name);
-            }
-
-            if (themeAttrs == null || themeAttrs[R.styleable.VectorDrawablePath_pathData] == 0) {
-                mNode = PathParser.createNodesFromPathData(a.getString(
-                        R.styleable.VectorDrawablePath_pathData));
-            }
-
-            if (themeAttrs == null || themeAttrs[R.styleable.VectorDrawablePath_fill] == 0) {
-                mFillColor = a.getColor(R.styleable.VectorDrawablePath_fill, mFillColor);
-            }
-
-            if (themeAttrs == null || themeAttrs[R.styleable.VectorDrawablePath_fillOpacity] == 0) {
-                mFillOpacity = a.getFloat(R.styleable.VectorDrawablePath_fillOpacity, mFillOpacity);
-            }
-
-            if (themeAttrs == null
-                    || themeAttrs[R.styleable.VectorDrawablePath_strokeLineCap] == 0) {
-                mStrokeLineCap = getStrokeLineCap(
-                        a.getInt(R.styleable.VectorDrawablePath_strokeLineCap, -1), mStrokeLineCap);
-            }
-
-            if (themeAttrs == null
-                    || themeAttrs[R.styleable.VectorDrawablePath_strokeLineJoin] == 0) {
-                mStrokeLineJoin = getStrokeLineJoin(
-                        a.getInt(R.styleable.VectorDrawablePath_strokeLineJoin, -1), mStrokeLineJoin);
-            }
-
-            if (themeAttrs == null
-                    || themeAttrs[R.styleable.VectorDrawablePath_strokeMiterLimit] == 0) {
-                mStrokeMiterlimit = a.getFloat(
-                        R.styleable.VectorDrawablePath_strokeMiterLimit, mStrokeMiterlimit);
-            }
-
-            if (themeAttrs == null || themeAttrs[R.styleable.VectorDrawablePath_stroke] == 0) {
-                mStrokeColor = a.getColor(R.styleable.VectorDrawablePath_stroke, mStrokeColor);
-            }
-
-            if (themeAttrs == null
-                    || themeAttrs[R.styleable.VectorDrawablePath_strokeOpacity] == 0) {
-                mStrokeOpacity = a.getFloat(
-                        R.styleable.VectorDrawablePath_strokeOpacity, mStrokeOpacity);
-            }
-
-            if (themeAttrs == null || themeAttrs[R.styleable.VectorDrawablePath_strokeWidth] == 0) {
-                mStrokeWidth = a.getFloat(R.styleable.VectorDrawablePath_strokeWidth, mStrokeWidth);
-            }
-
-            if (themeAttrs == null || themeAttrs[R.styleable.VectorDrawablePath_trimPathEnd] == 0) {
-                mTrimPathEnd = a.getFloat(R.styleable.VectorDrawablePath_trimPathEnd, mTrimPathEnd);
-            }
-
-            if (themeAttrs == null
-                    || themeAttrs[R.styleable.VectorDrawablePath_trimPathOffset] == 0) {
-                mTrimPathOffset = a.getFloat(
-                        R.styleable.VectorDrawablePath_trimPathOffset, mTrimPathOffset);
-            }
-
-            if (themeAttrs == null
-                    || themeAttrs[R.styleable.VectorDrawablePath_trimPathStart] == 0) {
-                mTrimPathStart = a.getFloat(
-                        R.styleable.VectorDrawablePath_trimPathStart, mTrimPathStart);
-            }
-
-            updateColorAlphas();
-
-            a.recycle();
-        }
-
         public boolean canApplyTheme() {
             return mThemeAttrs != null;
         }
 
-        public void applyTheme(Theme t) {
-            if (mThemeAttrs == null) {
-                return;
-            }
+        public void inflate(Resources r, AttributeSet attrs, Theme theme) {
+            final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.VectorDrawablePath);
+            updateStateFromTypedArray(a);
+            a.recycle();
+        }
 
-            final TypedArray a = t.resolveAttributes(
-                    mThemeAttrs, R.styleable.VectorDrawablePath);
+        private void updateStateFromTypedArray(TypedArray a) {
+            // Account for any configuration changes.
+            mChangingConfigurations |= a.getChangingConfigurations();
+
+            // Extract the theme attributes, if any.
+            mThemeAttrs = a.extractThemeAttrs();
 
             mClip = a.getBoolean(R.styleable.VectorDrawablePath_clipToPath, mClip);
-
-            if (a.hasValue(R.styleable.VectorDrawablePath_name)) {
-                mPathName = a.getString(R.styleable.VectorDrawablePath_name);
-            }
-
-            if (a.hasValue(R.styleable.VectorDrawablePath_pathData)) {
-                mNode = PathParser.createNodesFromPathData(a.getString(
-                        R.styleable.VectorDrawablePath_pathData));
-            }
-
+            mPathName = a.getString(R.styleable.VectorDrawablePath_name);
+            mNode = PathParser.createNodesFromPathData(a.getString(
+                    R.styleable.VectorDrawablePath_pathData));
             mFillColor = a.getColor(R.styleable.VectorDrawablePath_fill, mFillColor);
             mFillOpacity = a.getFloat(R.styleable.VectorDrawablePath_fillOpacity, mFillOpacity);
-
             mStrokeLineCap = getStrokeLineCap(a.getInt(
                     R.styleable.VectorDrawablePath_strokeLineCap, -1), mStrokeLineCap);
             mStrokeLineJoin = getStrokeLineJoin(a.getInt(
@@ -1213,7 +1122,6 @@
             mStrokeOpacity = a.getFloat(
                     R.styleable.VectorDrawablePath_strokeOpacity, mStrokeOpacity);
             mStrokeWidth = a.getFloat(R.styleable.VectorDrawablePath_strokeWidth, mStrokeWidth);
-
             mTrimPathEnd = a.getFloat(R.styleable.VectorDrawablePath_trimPathEnd, mTrimPathEnd);
             mTrimPathOffset = a.getFloat(
                     R.styleable.VectorDrawablePath_trimPathOffset, mTrimPathOffset);
@@ -1221,6 +1129,15 @@
                     R.styleable.VectorDrawablePath_trimPathStart, mTrimPathStart);
 
             updateColorAlphas();
+        }
+
+        public void applyTheme(Theme t) {
+            if (mThemeAttrs == null) {
+                return;
+            }
+
+            final TypedArray a = t.resolveAttributes(mThemeAttrs, R.styleable.VectorDrawablePath);
+            updateStateFromTypedArray(a);
             a.recycle();
         }
 
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 42afd67..7a2fe32 100755
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -9437,6 +9437,17 @@
         }
     }
 
+    @Override
+    public boolean isTopOfTask(IBinder token) {
+        synchronized (this) {
+            ActivityRecord r = ActivityRecord.isInStackLocked(token);
+            if (r == null) {
+                throw new IllegalArgumentException();
+            }
+            return r.task.getTopActivity() == r;
+        }
+    }
+
     public final void enterSafeMode() {
         synchronized(this) {
             // It only makes sense to do this before the system is ready
@@ -16537,11 +16548,9 @@
                     }
                     cleanUpApplicationRecordLocked(app, false, true, -1);
                     mRemovedProcesses.remove(i);
-                    
+
                     if (app.persistent) {
-                        if (app.persistent) {
-                            addAppLocked(app.info, false, null /* ABI override */);
-                        }
+                        addAppLocked(app.info, false, null /* ABI override */);
                     }
                 }
             }