Merge "MediaBrowser: Handle null results properly in onLoadChildren" into mnc-ub-dev
diff --git a/.gitignore b/.gitignore
index c8c3ed8..a72b3dc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,3 +6,5 @@
 project.properties
 **/bin
 **/gen
+*.iml
+**/out
diff --git a/build.gradle b/build.gradle
index e366b16..3b23406 100644
--- a/build.gradle
+++ b/build.gradle
@@ -34,6 +34,7 @@
 }
 
 ext.supportRepoOut = new File(buildDir, 'support_repo')
+ext.testApkDistOut = new File(buildDir, 'test_apks')
 
 // Main task called by the build server.
 task(createArchive) << {
diff --git a/design/api/current.txt b/design/api/current.txt
index 216100540..7d85b1b 100644
--- a/design/api/current.txt
+++ b/design/api/current.txt
@@ -375,7 +375,7 @@
     method public void setTabMode(int);
     method public void setTabTextColors(android.content.res.ColorStateList);
     method public void setTabTextColors(int, int);
-    method public void setTabsFromPagerAdapter(android.support.v4.view.PagerAdapter);
+    method public deprecated void setTabsFromPagerAdapter(android.support.v4.view.PagerAdapter);
     method public void setupWithViewPager(android.support.v4.view.ViewPager);
     field public static final int GRAVITY_CENTER = 1; // 0x1
     field public static final int GRAVITY_FILL = 0; // 0x0
diff --git a/design/src/android/support/design/widget/DrawableUtils.java b/design/src/android/support/design/widget/DrawableUtils.java
new file mode 100644
index 0000000..1c46e6b2
--- /dev/null
+++ b/design/src/android/support/design/widget/DrawableUtils.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.support.design.widget;
+
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.DrawableContainer;
+import android.os.Build;
+import android.util.Log;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+/**
+ * Caution. Gross hacks ahead.
+ */
+class DrawableUtils {
+
+    private static final String LOG_TAG = "DrawableUtils";
+
+    private static Method sSetConstantStateMethod;
+    private static boolean sSetConstantStateMethodFetched;
+
+    private static Field sDrawableContainerStateField;
+    private static boolean sDrawableContainerStateFieldFetched;
+
+    private DrawableUtils() {}
+
+    static boolean setContainerConstantState(DrawableContainer drawable,
+            Drawable.ConstantState constantState) {
+        if (Build.VERSION.SDK_INT >= 9) {
+            // We can use getDeclaredMethod() on v9+
+            return setContainerConstantStateV9(drawable, constantState);
+        } else {
+            // Else we'll just have to set the field directly
+            return setContainerConstantStateV7(drawable, constantState);
+        }
+    }
+
+    private static boolean setContainerConstantStateV9(DrawableContainer drawable,
+            Drawable.ConstantState constantState) {
+        if (!sSetConstantStateMethodFetched) {
+            try {
+                sSetConstantStateMethod = DrawableContainer.class.getDeclaredMethod(
+                        "setConstantState", DrawableContainer.DrawableContainerState.class);
+                sSetConstantStateMethod.setAccessible(true);
+            } catch (NoSuchMethodException e) {
+                Log.e(LOG_TAG, "Could not fetch setConstantState(). Oh well.");
+            }
+            sSetConstantStateMethodFetched = true;
+        }
+        if (sSetConstantStateMethod != null) {
+            try {
+                sSetConstantStateMethod.invoke(drawable, constantState);
+                return true;
+            } catch (Exception e) {
+                Log.e(LOG_TAG, "Could not invoke setConstantState(). Oh well.");
+            }
+        }
+        return false;
+    }
+
+    private static boolean setContainerConstantStateV7(DrawableContainer drawable,
+            Drawable.ConstantState constantState) {
+        if (!sDrawableContainerStateFieldFetched) {
+            try {
+                sDrawableContainerStateField = DrawableContainer.class
+                        .getDeclaredField("mDrawableContainerStateField");
+                sDrawableContainerStateField.setAccessible(true);
+            } catch (NoSuchFieldException e) {
+                Log.e(LOG_TAG, "Could not fetch mDrawableContainerStateField. Oh well.");
+            }
+            sDrawableContainerStateFieldFetched = true;
+        }
+        if (sDrawableContainerStateField != null) {
+            try {
+                sDrawableContainerStateField.set(drawable, constantState);
+                return true;
+            } catch (Exception e) {
+                Log.e(LOG_TAG, "Could not set mDrawableContainerStateField. Oh well.");
+            }
+        }
+        return false;
+    }
+
+}
diff --git a/design/src/android/support/design/widget/TabLayout.java b/design/src/android/support/design/widget/TabLayout.java
index 5640692..fe1a105 100755
--- a/design/src/android/support/design/widget/TabLayout.java
+++ b/design/src/android/support/design/widget/TabLayout.java
@@ -21,6 +21,7 @@
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
+import android.database.DataSetObserver;
 import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.graphics.drawable.Drawable;
@@ -33,6 +34,7 @@
 import android.support.annotation.Nullable;
 import android.support.annotation.StringRes;
 import android.support.design.R;
+import android.support.v4.util.Pools;
 import android.support.v4.view.GravityCompat;
 import android.support.v4.view.PagerAdapter;
 import android.support.v4.view.ViewCompat;
@@ -63,6 +65,10 @@
 import java.util.ArrayList;
 import java.util.Iterator;
 
+import static android.support.v4.view.ViewPager.SCROLL_STATE_DRAGGING;
+import static android.support.v4.view.ViewPager.SCROLL_STATE_IDLE;
+import static android.support.v4.view.ViewPager.SCROLL_STATE_SETTLING;
+
 /**
  * TabLayout provides a horizontal layout to display tabs.
  *
@@ -81,15 +87,8 @@
  * notified when any tab's selection state has been changed.
  * <p>
  * If you're using a {@link android.support.v4.view.ViewPager} together
- * with this layout, you can use {@link #setTabsFromPagerAdapter(PagerAdapter)} which will populate
- * the tabs using the given {@link PagerAdapter}'s page titles. You should also use a
- * {@link TabLayoutOnPageChangeListener} to forward the scroll and selection changes to this
- * layout like so:
- * <pre>
- * ViewPager viewPager = ...;
- * TabLayout tabLayout = ...;
- * viewPager.addOnPageChangeListener(new TabLayoutOnPageChangeListener(tabLayout));
- * </pre>
+ * with this layout, you can use {@link #setupWithViewPager(ViewPager)} to link the two together.
+ * This layout will be automatically populated from the {@link PagerAdapter}'s page titles.</p>
  *
  * @see <a href="http://www.google.com/design/spec/components/tabs.html">Tabs</a>
  */
@@ -105,6 +104,8 @@
 
     private static final int ANIMATION_DURATION = 300;
 
+    private static final Pools.Pool<Tab> sTabPool = new Pools.SynchronizedPool<>(16);
+
     /**
      * Scrollable tabs display a subset of tabs at any given moment, and can contain longer tab
      * labels and a larger number of tabs. They are best used for browsing contexts in touch
@@ -216,6 +217,14 @@
 
     private ValueAnimatorCompat mScrollAnimator;
 
+    private ViewPager mViewPager;
+    private PagerAdapter mPagerAdapter;
+    private DataSetObserver mPagerAdapterObserver;
+    private TabLayoutOnPageChangeListener mPageChangeListener;
+
+    // Pool we use as a simple RecyclerBin
+    private final Pools.Pool<TabView> mTabViewPool = new Pools.SimplePool<>(12);
+
     public TabLayout(Context context) {
         this(context, null);
     }
@@ -436,7 +445,8 @@
      */
     @NonNull
     public Tab newTab() {
-        return new Tab(this);
+        final Tab poolTab = sTabPool.acquire();
+        return poolTab != null ? poolTab : new Tab(this);
     }
 
     /**
@@ -489,9 +499,10 @@
         final int selectedTabPosition = mSelectedTab != null ? mSelectedTab.getPosition() : 0;
         removeTabViewAt(position);
 
-        Tab removedTab = mTabs.remove(position);
+        final Tab removedTab = mTabs.remove(position);
         if (removedTab != null) {
-            removedTab.setPosition(Tab.INVALID_POSITION);
+            removedTab.reset();
+            sTabPool.release(removedTab);
         }
 
         final int newTabCount = mTabs.size();
@@ -509,12 +520,15 @@
      */
     public void removeAllTabs() {
         // Remove all the views
-        mTabStrip.removeAllViews();
+        for (int i = mTabStrip.getChildCount() - 1; i >= 0; i--) {
+            removeTabViewAt(i);
+        }
 
-        for (Iterator<Tab> i = mTabs.iterator(); i.hasNext(); ) {
-            Tab tab = i.next();
-            tab.setPosition(Tab.INVALID_POSITION);
+        for (final Iterator<Tab> i = mTabs.iterator(); i.hasNext();) {
+            final Tab tab = i.next();
             i.remove();
+            tab.reset();
+            sTabPool.release(tab);
         }
 
         mSelectedTab = null;
@@ -600,57 +614,102 @@
     /**
      * The one-stop shop for setting up this {@link TabLayout} with a {@link ViewPager}.
      *
-     * <p>This method will:
-     * <ul>
-     *     <li>Add a {@link ViewPager.OnPageChangeListener} that will forward events to
-     *     this TabLayout.</li>
-     *     <li>Populate the TabLayout's tabs from the ViewPager's {@link PagerAdapter}.</li>
-     *     <li>Set our {@link TabLayout.OnTabSelectedListener} which will forward
-     *     selected events to the ViewPager</li>
-     * </ul>
-     * </p>
+     * <p>This method will link the given ViewPager and this TabLayout together so that any
+     * changes in one are automatically reflected in the other. This includes adapter changes,
+     * scroll state changes, and clicks. The tabs displayed in this layout will be populated
+     * from the ViewPager adapter's page titles.</p>
      *
-     * @see #setTabsFromPagerAdapter(PagerAdapter)
-     * @see TabLayoutOnPageChangeListener
-     * @see ViewPagerOnTabSelectedListener
+     * <p>After this method is called, you will not need this method again unless you want
+     * to change the linked ViewPager.</p>
+     *
+     * <p>If the given ViewPager is non-null, it needs to already have a
+     * {@link PagerAdapter} set.</p>
+     *
+     * @param viewPager The ViewPager to link, or {@code null} to clear any previous link.
      */
-    public void setupWithViewPager(@NonNull ViewPager viewPager) {
-        final PagerAdapter adapter = viewPager.getAdapter();
-        if (adapter == null) {
-            throw new IllegalArgumentException("ViewPager does not have a PagerAdapter set");
+    public void setupWithViewPager(@Nullable final ViewPager viewPager) {
+        if (mViewPager != null && mPageChangeListener != null) {
+            // If we've already been setup with a ViewPager, remove us from it
+            mViewPager.removeOnPageChangeListener(mPageChangeListener);
         }
 
-        // First we'll add Tabs, using the adapter's page titles
-        setTabsFromPagerAdapter(adapter);
-
-        // Now we'll add our page change listener to the ViewPager
-        viewPager.addOnPageChangeListener(new TabLayoutOnPageChangeListener(this));
-
-        // Now we'll add a tab selected listener to set ViewPager's current item
-        setOnTabSelectedListener(new ViewPagerOnTabSelectedListener(viewPager));
-
-        // Make sure we reflect the currently set ViewPager item
-        if (adapter.getCount() > 0) {
-            final int curItem = viewPager.getCurrentItem();
-            if (getSelectedTabPosition() != curItem) {
-                selectTab(getTabAt(curItem));
+        if (viewPager != null) {
+            final PagerAdapter adapter = viewPager.getAdapter();
+            if (adapter == null) {
+                throw new IllegalArgumentException("ViewPager does not have a PagerAdapter set");
             }
+
+            mViewPager = viewPager;
+
+            // Add our custom OnPageChangeListener to the ViewPager
+            if (mPageChangeListener == null) {
+                mPageChangeListener = new TabLayoutOnPageChangeListener(this);
+            }
+            mPageChangeListener.reset();
+            viewPager.addOnPageChangeListener(mPageChangeListener);
+
+            // Now we'll add a tab selected listener to set ViewPager's current item
+            setOnTabSelectedListener(new ViewPagerOnTabSelectedListener(viewPager));
+
+            // Now we'll populate ourselves from the pager adapter
+            setPagerAdapter(adapter, true);
+        } else {
+            // We've been given a null ViewPager so we need to clear out the internal state,
+            // listeners and observers
+            mViewPager = null;
+            setOnTabSelectedListener(null);
+            setPagerAdapter(null, true);
         }
     }
 
     /**
-     * Populate our tab content from the given {@link PagerAdapter}.
-     * <p>
-     * Any existing tabs will be removed first. Each tab will have it's text set to the value
-     * returned from {@link PagerAdapter#getPageTitle(int)}
-     * </p>
-     *
-     * @param adapter the adapter to populate from
+     * @deprecated Use {@link #setupWithViewPager(ViewPager)} to link a TabLayout with a ViewPager
+     *             together. When that method is used, the TabLayout will be automatically updated
+     *             when the {@link PagerAdapter} is changed.
      */
-    public void setTabsFromPagerAdapter(@NonNull PagerAdapter adapter) {
+    @Deprecated
+    public void setTabsFromPagerAdapter(@Nullable final PagerAdapter adapter) {
+        setPagerAdapter(adapter, false);
+    }
+
+    private void setPagerAdapter(@Nullable final PagerAdapter adapter, final boolean addObserver) {
+        if (mPagerAdapter != null && mPagerAdapterObserver != null) {
+            // If we already have a PagerAdapter, unregister our observer
+            mPagerAdapter.unregisterDataSetObserver(mPagerAdapterObserver);
+        }
+
+        mPagerAdapter = adapter;
+
+        if (addObserver && adapter != null) {
+            // Register our observer on the new adapter
+            if (mPagerAdapterObserver == null) {
+                mPagerAdapterObserver = new PagerAdapterObserver();
+            }
+            adapter.registerDataSetObserver(mPagerAdapterObserver);
+        }
+
+        // Finally make sure we reflect the new adapter
+        populateFromPagerAdapter();
+    }
+
+    private void populateFromPagerAdapter() {
         removeAllTabs();
-        for (int i = 0, count = adapter.getCount(); i < count; i++) {
-            addTab(newTab().setText(adapter.getPageTitle(i)));
+
+        if (mPagerAdapter != null) {
+            final int adapterCount = mPagerAdapter.getCount();
+            for (int i = 0; i < adapterCount; i++) {
+                addTab(newTab().setText(mPagerAdapter.getPageTitle(i)), false);
+            }
+
+            // Make sure we reflect the currently set ViewPager item
+            if (mViewPager != null && adapterCount > 0) {
+                final int curItem = mViewPager.getCurrentItem();
+                if (curItem != getSelectedTabPosition() && curItem < getTabCount()) {
+                    selectTab(getTabAt(curItem));
+                }
+            }
+        } else {
+            removeAllTabs();
         }
     }
 
@@ -660,8 +719,12 @@
         }
     }
 
-    private TabView createTabView(Tab tab) {
-        final TabView tabView = new TabView(getContext(), tab);
+    private TabView createTabView(@NonNull final Tab tab) {
+        TabView tabView = mTabViewPool != null ? mTabViewPool.acquire() : null;
+        if (tabView == null) {
+            tabView = new TabView(getContext());
+        }
+        tabView.setTab(tab);
         tabView.setFocusable(true);
         tabView.setMinimumWidth(getTabMinWidth());
 
@@ -794,7 +857,12 @@
     }
 
     private void removeTabViewAt(int position) {
+        final TabView view = (TabView) mTabStrip.getChildAt(position);
         mTabStrip.removeViewAt(position);
+        if (view != null) {
+            view.reset();
+            mTabViewPool.release(view);
+        }
         requestLayout();
     }
 
@@ -1173,10 +1241,19 @@
         public CharSequence getContentDescription() {
             return mContentDesc;
         }
+
+        private void reset() {
+            mTag = null;
+            mIcon = null;
+            mText = null;
+            mContentDesc = null;
+            mPosition = INVALID_POSITION;
+            mCustomView = null;
+        }
     }
 
     class TabView extends LinearLayout implements OnLongClickListener {
-        private final Tab mTab;
+        private Tab mTab;
         private TextView mTextView;
         private ImageView mIconView;
 
@@ -1186,9 +1263,8 @@
 
         private int mDefaultMaxLines = 2;
 
-        public TabView(Context context, Tab tab) {
+        public TabView(Context context) {
             super(context);
-            mTab = tab;
             if (mTabBackgroundResId != 0) {
                 setBackgroundDrawable(
                         AppCompatDrawableManager.get().getDrawable(context, mTabBackgroundResId));
@@ -1197,7 +1273,6 @@
                     mTabPaddingEnd, mTabPaddingBottom);
             setGravity(Gravity.CENTER);
             setOrientation(VERTICAL);
-            update();
         }
 
         @Override
@@ -1297,9 +1372,21 @@
             }
         }
 
+        private void setTab(@Nullable final Tab tab) {
+            if (tab != mTab) {
+                mTab = tab;
+                update();
+            }
+        }
+
+        private void reset() {
+            setTab(null);
+            setSelected(false);
+        }
+
         final void update() {
             final Tab tab = mTab;
-            final View custom = tab.getCustomView();
+            final View custom = tab != null ? tab.getCustomView() : null;
             if (custom != null) {
                 final ViewParent customParent = custom.getParent();
                 if (customParent != this) {
@@ -1351,18 +1438,20 @@
                 if (mTabTextColors != null) {
                     mTextView.setTextColor(mTabTextColors);
                 }
-                updateTextAndIcon(tab, mTextView, mIconView);
+                updateTextAndIcon(mTextView, mIconView);
             } else {
                 // Else, we'll see if there is a TextView or ImageView present and update them
                 if (mCustomTextView != null || mCustomIconView != null) {
-                    updateTextAndIcon(tab, mCustomTextView, mCustomIconView);
+                    updateTextAndIcon(mCustomTextView, mCustomIconView);
                 }
             }
         }
 
-        private void updateTextAndIcon(Tab tab, TextView textView, ImageView iconView) {
-            final Drawable icon = tab.getIcon();
-            final CharSequence text = tab.getText();
+        private void updateTextAndIcon(@Nullable final TextView textView,
+                @Nullable final ImageView iconView) {
+            final Drawable icon = mTab != null ? mTab.getIcon() : null;
+            final CharSequence text = mTab != null ? mTab.getText() : null;
+            final CharSequence contentDesc = mTab != null ? mTab.getContentDescription() : null;
 
             if (iconView != null) {
                 if (icon != null) {
@@ -1373,20 +1462,20 @@
                     iconView.setVisibility(GONE);
                     iconView.setImageDrawable(null);
                 }
-                iconView.setContentDescription(tab.getContentDescription());
+                iconView.setContentDescription(contentDesc);
             }
 
             final boolean hasText = !TextUtils.isEmpty(text);
             if (textView != null) {
                 if (hasText) {
                     textView.setText(text);
-                    textView.setContentDescription(tab.getContentDescription());
                     textView.setVisibility(VISIBLE);
                     setVisibility(VISIBLE);
                 } else {
                     textView.setVisibility(GONE);
                     textView.setText(null);
                 }
+                textView.setContentDescription(contentDesc);
             }
 
             if (iconView != null) {
@@ -1402,7 +1491,7 @@
                 }
             }
 
-            if (!hasText && !TextUtils.isEmpty(tab.getContentDescription())) {
+            if (!hasText && !TextUtils.isEmpty(contentDesc)) {
                 setOnLongClickListener(this);
             } else {
                 setOnLongClickListener(null);
@@ -1751,16 +1840,15 @@
                 int positionOffsetPixels) {
             final TabLayout tabLayout = mTabLayoutRef.get();
             if (tabLayout != null) {
-                // Update the scroll position, only update the text selection if we're being
-                // dragged (or we're settling after a drag)
-                final boolean updateText = (mScrollState == ViewPager.SCROLL_STATE_DRAGGING)
-                        || (mScrollState == ViewPager.SCROLL_STATE_SETTLING
-                        && mPreviousScrollState == ViewPager.SCROLL_STATE_DRAGGING);
+                // Only update the text selection if we're not settling, or we are settling after
+                // being dragged
+                final boolean updateText = mScrollState != SCROLL_STATE_SETTLING ||
+                        mPreviousScrollState == SCROLL_STATE_DRAGGING;
                 // Update the indicator if we're not settling after being idle. This is caused
                 // from a setCurrentItem() call and will be handled by an animation from
                 // onPageSelected() instead.
-                final boolean updateIndicator = !(mScrollState == ViewPager.SCROLL_STATE_SETTLING
-                        && mPreviousScrollState == ViewPager.SCROLL_STATE_IDLE);
+                final boolean updateIndicator = !(mScrollState == SCROLL_STATE_SETTLING
+                        && mPreviousScrollState == SCROLL_STATE_IDLE);
                 tabLayout.setScrollPosition(position, positionOffset, updateText, updateIndicator);
             }
         }
@@ -1771,12 +1859,16 @@
             if (tabLayout != null && tabLayout.getSelectedTabPosition() != position) {
                 // Select the tab, only updating the indicator if we're not being dragged/settled
                 // (since onPageScrolled will handle that).
-                final boolean updateIndicator = mScrollState == ViewPager.SCROLL_STATE_IDLE
-                        || (mScrollState == ViewPager.SCROLL_STATE_SETTLING
-                        && mPreviousScrollState == ViewPager.SCROLL_STATE_IDLE);
+                final boolean updateIndicator = mScrollState == SCROLL_STATE_IDLE
+                        || (mScrollState == SCROLL_STATE_SETTLING
+                        && mPreviousScrollState == SCROLL_STATE_IDLE);
                 tabLayout.selectTab(tabLayout.getTabAt(position), updateIndicator);
             }
         }
+
+        private void reset() {
+            mPreviousScrollState = mScrollState = SCROLL_STATE_IDLE;
+        }
     }
 
     /**
@@ -1806,4 +1898,16 @@
         }
     }
 
+    private class PagerAdapterObserver extends DataSetObserver {
+        @Override
+        public void onChanged() {
+            populateFromPagerAdapter();
+        }
+
+        @Override
+        public void onInvalidated() {
+            populateFromPagerAdapter();
+        }
+    }
+
 }
diff --git a/design/src/android/support/design/widget/TextInputLayout.java b/design/src/android/support/design/widget/TextInputLayout.java
index 162643e..318ca6d 100644
--- a/design/src/android/support/design/widget/TextInputLayout.java
+++ b/design/src/android/support/design/widget/TextInputLayout.java
@@ -22,7 +22,10 @@
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.Paint;
+import android.graphics.PorterDuff;
 import android.graphics.Typeface;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.DrawableContainer;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.support.annotation.StyleRes;
@@ -68,6 +71,7 @@
     private Paint mTmpPaint;
 
     private LinearLayout mIndicatorArea;
+    private int mIndicatorsAdded;
 
     private boolean mErrorEnabled;
     private TextView mErrorView;
@@ -89,6 +93,8 @@
     private boolean mHintAnimationEnabled;
     private ValueAnimatorCompat mAnimator;
 
+    private boolean mHasReconstructedEditTextBackground;
+
     public TextInputLayout(Context context) {
         this(context, null);
     }
@@ -416,6 +422,7 @@
         }
         mIndicatorArea.setVisibility(View.VISIBLE);
         mIndicatorArea.addView(indicator, index);
+        mIndicatorsAdded++;
     }
 
     private void adjustIndicatorPadding() {
@@ -427,7 +434,7 @@
     private void removeIndicator(TextView indicator) {
         if (mIndicatorArea != null) {
             mIndicatorArea.removeView(indicator);
-            if (mIndicatorArea.getChildCount() == 0) {
+            if (--mIndicatorsAdded == 0) {
                 mIndicatorArea.setVisibility(View.GONE);
             }
         }
@@ -624,17 +631,60 @@
     }
 
     private void updateEditTextBackground() {
+        ensureBackgroundDrawableStateWorkaround();
+
+        final Drawable editTextBackground = mEditText.getBackground();
+        if (editTextBackground == null) {
+            return;
+        }
+
         if (mErrorShown && mErrorView != null) {
-            // Set the EditText's background tint to the error color
-            ViewCompat.setBackgroundTintList(mEditText,
-                    ColorStateList.valueOf(mErrorView.getCurrentTextColor()));
+            // Set a color filter of the error color
+            editTextBackground.setColorFilter(
+                    AppCompatDrawableManager.getPorterDuffColorFilter(
+                            mErrorView.getCurrentTextColor(), PorterDuff.Mode.SRC_IN));
         } else if (mCounterOverflowed && mCounterView != null) {
-            ViewCompat.setBackgroundTintList(mEditText,
-                    ColorStateList.valueOf(mCounterView.getCurrentTextColor()));
+            // Set a color filter of the counter color
+            editTextBackground.setColorFilter(
+                    AppCompatDrawableManager.getPorterDuffColorFilter(
+                            mCounterView.getCurrentTextColor(), PorterDuff.Mode.SRC_IN));
         } else {
-            ViewCompat.setBackgroundTintList(mEditText,
-                    AppCompatDrawableManager.get()
-                            .getTintList(getContext(), R.drawable.abc_edit_text_material));
+            // Else reset the color filter and refresh the drawable state so that the
+            // normal tint is used
+            editTextBackground.clearColorFilter();
+            mEditText.refreshDrawableState();
+        }
+    }
+
+    private void ensureBackgroundDrawableStateWorkaround() {
+        final Drawable bg = mEditText.getBackground();
+        if (bg == null) {
+            return;
+        }
+
+        if (!mHasReconstructedEditTextBackground) {
+            // This is gross. There is an issue in the platform which affects container Drawables
+            // where the first drawable retrieved from resources will propogate any changes
+            // (like color filter) to all instances from the cache. We'll try to workaround it...
+
+            final Drawable newBg = bg.getConstantState().newDrawable();
+
+            if (bg instanceof DrawableContainer) {
+                // If we have a Drawable container, we can try and set it's constant state via
+                // reflection from the new Drawable
+                mHasReconstructedEditTextBackground =
+                        DrawableUtils.setContainerConstantState(
+                                (DrawableContainer) bg, newBg.getConstantState());
+            }
+
+            if (!mHasReconstructedEditTextBackground) {
+                // If we reach here then we just need to set a brand new instance of the Drawable
+                // as the background. This has the unfortunate side-effect of wiping out any
+                // user set padding, but I'd hope that use of custom padding on an EditText
+                // is limited.
+                mEditText.setBackgroundDrawable(newBg);
+                mHasReconstructedEditTextBackground = true;
+            }
         }
     }
 
diff --git a/design/src/android/support/design/widget/ViewOffsetHelper.java b/design/src/android/support/design/widget/ViewOffsetHelper.java
index a76ca9a..1254f17 100644
--- a/design/src/android/support/design/widget/ViewOffsetHelper.java
+++ b/design/src/android/support/design/widget/ViewOffsetHelper.java
@@ -66,9 +66,9 @@
     }
 
     private static void tickleInvalidationFlag(View view) {
-        final float x = ViewCompat.getTranslationX(view);
-        ViewCompat.setTranslationY(view, x + 1);
-        ViewCompat.setTranslationY(view, x);
+        final float y = ViewCompat.getTranslationY(view);
+        ViewCompat.setTranslationY(view, y + 1);
+        ViewCompat.setTranslationY(view, y);
     }
 
     /**
diff --git a/graphics/drawable/Android.mk b/graphics/drawable/Android.mk
index 63e93b7..06d8d6f 100644
--- a/graphics/drawable/Android.mk
+++ b/graphics/drawable/Android.mk
@@ -17,8 +17,8 @@
 #static vector drawable library
 include $(CLEAR_VARS)
 LOCAL_MODULE := android-support-v7-vectordrawable
-LOCAL_SDK_VERSION := 7
-LOCAL_SRC_FILES := $(call all-java-files-under, static)
+LOCAL_SDK_VERSION := current
+LOCAL_SRC_FILES := $(call all-java-files-under, static util)
 
 LOCAL_JAVA_LIBRARIES := android-support-v4
 
@@ -29,8 +29,8 @@
 #Animated vector drawable library
 include $(CLEAR_VARS)
 LOCAL_MODULE := android-support-v11-animatedvectordrawable
-LOCAL_SDK_VERSION := 11
-LOCAL_SRC_FILES := $(call all-java-files-under, animated)
+LOCAL_SDK_VERSION := current
+LOCAL_SRC_FILES := $(call all-java-files-under, animated util)
 
 LOCAL_JAVA_LIBRARIES := android-support-v4
 
@@ -38,4 +38,5 @@
 
 LOCAL_STATIC_JAVA_LIBRARIES := android-support-v7-vectordrawable
 
+LOCAL_AAPT_FLAGS := --no-version-vectors
 include $(BUILD_STATIC_JAVA_LIBRARY)
\ No newline at end of file
diff --git a/graphics/drawable/animated/src/android/support/graphics/drawable/AnimatedVectorDrawableCompat.java b/graphics/drawable/animated/src/android/support/graphics/drawable/AnimatedVectorDrawableCompat.java
index 78ef62d..eff9670 100644
--- a/graphics/drawable/animated/src/android/support/graphics/drawable/AnimatedVectorDrawableCompat.java
+++ b/graphics/drawable/animated/src/android/support/graphics/drawable/AnimatedVectorDrawableCompat.java
@@ -16,7 +16,6 @@
 
 import android.animation.Animator;
 import android.animation.AnimatorInflater;
-import android.animation.ObjectAnimator;
 import android.content.Context;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
@@ -45,12 +44,12 @@
 /**
  * This class uses {@link android.animation.ObjectAnimator} and
  * {@link android.animation.AnimatorSet} to animate the properties of a
- * {@link android.graphics.drawable.VectorDrawableCompat} to create an animated drawable.
+ * {@link android.support.graphics.drawable.VectorDrawableCompat} to create an animated drawable.
  * <p>
  * AnimatedVectorDrawableCompat are normally defined as 3 separate XML files.
  * </p>
  * <p>
- * First is the XML file for {@link android.graphics.drawable.VectorDrawableCompat}. Note that we
+ * First is the XML file for {@link android.support.graphics.drawable.VectorDrawableCompat}. Note that we
  * allow the animation to happen on the group's attributes and path's attributes, which requires they
  * are uniquely named in this XML file. Groups and paths without animations do not need names.
  * </p>
@@ -306,9 +305,9 @@
                 }
                 if (ANIMATED_VECTOR.equals(tagName)) {
                     final TypedArray a =
-                            obtainAttributes(res, theme, attrs, R.styleable.AnimatedVectorDrawable);
+                            obtainAttributes(res, theme, attrs, AndroidResources.styleable_AnimatedVectorDrawable);
 
-                    int drawableRes = a.getResourceId(R.styleable.AnimatedVectorDrawable_drawable,
+                    int drawableRes = a.getResourceId(AndroidResources.styleable_AnimatedVectorDrawable_drawable,
                             0);
                     if (DBG_ANIMATION_VECTOR_DRAWABLE) {
                         Log.v(LOGTAG, "drawableRes is " + drawableRes);
@@ -327,11 +326,11 @@
                     a.recycle();
                 } else if (TARGET.equals(tagName)) {
                     final TypedArray a =
-                            res.obtainAttributes(attrs, R.styleable.AnimatedVectorDrawableTarget);
+                            res.obtainAttributes(attrs, AndroidResources.styleable_AnimatedVectorDrawableTarget);
                     final String target = a.getString(
-                            R.styleable.AnimatedVectorDrawableTarget_name);
+                            AndroidResources.styleable_AnimatedVectorDrawableTarget_name);
 
-                    int id = a.getResourceId(R.styleable.AnimatedVectorDrawableTarget_animation, 0);
+                    int id = a.getResourceId(AndroidResources.styleable_AnimatedVectorDrawableTarget_animation, 0);
                     if (id != 0) {
                         Animator objectAnimator = AnimatorInflater.loadAnimator(mContext, id);
                         setupAnimatorsForTarget(target, objectAnimator);
diff --git a/graphics/drawable/static/src/android/support/graphics/drawable/PathParser.java b/graphics/drawable/static/src/android/support/graphics/drawable/PathParser.java
index a92c3e5..8503fae 100644
--- a/graphics/drawable/static/src/android/support/graphics/drawable/PathParser.java
+++ b/graphics/drawable/static/src/android/support/graphics/drawable/PathParser.java
@@ -131,8 +131,8 @@
         }
 
         for (int i = 0; i < nodesFrom.length; i ++) {
-            if (nodesFrom[i].mType != nodesTo[i].mType
-                    || nodesFrom[i].mParams.length != nodesTo[i].mParams.length) {
+            if (nodesFrom[i].type != nodesTo[i].type
+                    || nodesFrom[i].params.length != nodesTo[i].params.length) {
                 return false;
             }
         }
@@ -148,9 +148,9 @@
      */
     public static void updateNodes(PathDataNode[] target, PathDataNode[] source) {
         for (int i = 0; i < source.length; i ++) {
-            target[i].mType = source[i].mType;
-            for (int j = 0; j < source[i].mParams.length; j ++) {
-                target[i].mParams[j] = source[i].mParams[j];
+            target[i].type = source[i].type;
+            for (int j = 0; j < source[i].params.length; j ++) {
+                target[i].params[j] = source[i].params[j];
             }
         }
     }
@@ -288,17 +288,18 @@
      * An array of PathDataNode can represent the whole "d" attribute.
      */
     public static class PathDataNode {
-        private char mType;
-        private float[] mParams;
+        /*package*/
+        char type;
+        float[] params;
 
         private PathDataNode(char type, float[] params) {
-            mType = type;
-            mParams = params;
+            this.type = type;
+            this.params = params;
         }
 
         private PathDataNode(PathDataNode n) {
-            mType = n.mType;
-            mParams = copyOfRange(n.mParams, 0, n.mParams.length);
+            type = n.type;
+            params = copyOfRange(n.params, 0, n.params.length);
         }
 
         /**
@@ -311,8 +312,8 @@
             float[] current = new float[6];
             char previousCommand = 'm';
             for (int i = 0; i < node.length; i++) {
-                addCommand(path, current, previousCommand, node[i].mType, node[i].mParams);
-                previousCommand = node[i].mType;
+                addCommand(path, current, previousCommand, node[i].type, node[i].params);
+                previousCommand = node[i].type;
             }
         }
 
@@ -327,9 +328,9 @@
          */
         public void interpolatePathDataNode(PathDataNode nodeFrom,
                 PathDataNode nodeTo, float fraction) {
-            for (int i = 0; i < nodeFrom.mParams.length; i++) {
-                mParams[i] = nodeFrom.mParams[i] * (1 - fraction)
-                        + nodeTo.mParams[i] * fraction;
+            for (int i = 0; i < nodeFrom.params.length; i++) {
+                params[i] = nodeFrom.params[i] * (1 - fraction)
+                        + nodeTo.params[i] * fraction;
             }
         }
 
diff --git a/graphics/drawable/static/src/android/support/graphics/drawable/VectorDrawableCompat.java b/graphics/drawable/static/src/android/support/graphics/drawable/VectorDrawableCompat.java
index d33c204..c0e5b40 100644
--- a/graphics/drawable/static/src/android/support/graphics/drawable/VectorDrawableCompat.java
+++ b/graphics/drawable/static/src/android/support/graphics/drawable/VectorDrawableCompat.java
@@ -196,7 +196,7 @@
     private static final int LINEJOIN_ROUND = 1;
     private static final int LINEJOIN_BEVEL = 2;
 
-    private static final boolean DBG_VECTOR_DRAWABLE = true;
+    private static final boolean DBG_VECTOR_DRAWABLE = false;
 
     private VectorDrawableState mVectorState;
 
@@ -420,7 +420,6 @@
 
             final VectorDrawableCompat drawable = new VectorDrawableCompat();
             drawable.inflate(res, parser, attrs, theme);
-
             return drawable;
         } catch (XmlPullParserException e) {
             Log.e(LOGTAG, "parser error", e);
@@ -462,8 +461,9 @@
         final VPathRenderer pathRenderer = new VPathRenderer();
         state.mVPathRenderer = pathRenderer;
 
-        final TypedArray a = obtainAttributes(res, theme, attrs, R.styleable.VectorDrawable);
-        updateStateFromTypedArray(a);
+        final TypedArray a = obtainAttributes(res, theme, attrs, AndroidResources.styleable_VectorDrawableTypeArray);
+
+        updateStateFromTypedArray(a, parser);
         a.recycle();
         state.mChangingConfigurations = getChangingConfigurations();
         state.mCacheDirty = true;
@@ -472,30 +472,47 @@
         mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode);
     }
 
-    private void updateStateFromTypedArray(TypedArray a) throws XmlPullParserException {
+
+    /**
+     * Parses a {@link android.graphics.PorterDuff.Mode} from a tintMode
+     * attribute's enum value.
+     */
+    private static PorterDuff.Mode parseTintMode(int value, Mode defaultMode) {
+        switch (value) {
+            case 3: return Mode.SRC_OVER;
+            case 5: return Mode.SRC_IN;
+            case 9: return Mode.SRC_ATOP;
+            case 14: return Mode.MULTIPLY;
+            case 15: return Mode.SCREEN;
+            case 16: return Mode.ADD;
+            default: return defaultMode;
+        }
+    }
+
+    private void updateStateFromTypedArray(TypedArray a, XmlPullParser parser) throws XmlPullParserException {
         final VectorDrawableState state = mVectorState;
         final VPathRenderer pathRenderer = state.mVPathRenderer;
 
         // Account for any configuration changes.
         // state.mChangingConfigurations |= Utils.getChangingConfigurations(a);
 
-        final int tintMode = a.getInt(R.styleable.VectorDrawable_tintMode, -1);
-        // if (tintMode != -1) {
-        // state.mTintMode = Utils.parseTintMode(tintMode, DEFAULT_TINT_MODE);
-        // }
+        final int mode = TypedArrayUtils.getNamedInt(a, parser, "tintMode",
+                AndroidResources.styleable_VectorDrawable_Mode, -1);
+        state.mTintMode = parseTintMode(mode, Mode.SRC_IN);
 
-        final ColorStateList tint = a.getColorStateList(R.styleable.VectorDrawable_tint);
+        final ColorStateList tint = a.getColorStateList(AndroidResources.styleable_VectorDrawable_tint);
         if (tint != null) {
             state.mTint = tint;
         }
 
-        state.mAutoMirrored = a.getBoolean(
-                R.styleable.VectorDrawable_autoMirrored, state.mAutoMirrored);
+        state.mAutoMirrored = TypedArrayUtils.getNamedBoolean(a, parser, "autoMirrored",
+                    AndroidResources.styleable_VectorDrawable_autoMirrored, state.mAutoMirrored);
 
-        pathRenderer.mViewportWidth = a.getFloat(
-                R.styleable.VectorDrawable_viewportWidth, pathRenderer.mViewportWidth);
-        pathRenderer.mViewportHeight = a.getFloat(
-                R.styleable.VectorDrawable_viewportHeight, pathRenderer.mViewportHeight);
+        pathRenderer.mViewportWidth = TypedArrayUtils.getNamedFloat(a, parser, "viewportWidth",
+                AndroidResources.styleable_VectorDrawable_viewportWidth, pathRenderer.mViewportWidth);
+
+        pathRenderer.mViewportHeight = TypedArrayUtils.getNamedFloat(a, parser, "viewportHeight",
+                AndroidResources.styleable_VectorDrawable_viewportHeight, pathRenderer.mViewportHeight);
 
         if (pathRenderer.mViewportWidth <= 0) {
             throw new XmlPullParserException(a.getPositionDescription() +
@@ -506,10 +523,9 @@
         }
 
         pathRenderer.mBaseWidth = a.getDimension(
-                R.styleable.VectorDrawable_width, pathRenderer.mBaseWidth);
+                AndroidResources.styleable_VectorDrawable_width, pathRenderer.mBaseWidth);
         pathRenderer.mBaseHeight = a.getDimension(
-                R.styleable.VectorDrawable_height, pathRenderer.mBaseHeight);
-
+                AndroidResources.styleable_VectorDrawable_height, pathRenderer.mBaseHeight);
         if (pathRenderer.mBaseWidth <= 0) {
             throw new XmlPullParserException(a.getPositionDescription() +
                     "<vector> tag requires width > 0");
@@ -518,11 +534,12 @@
                     "<vector> tag requires height > 0");
         }
 
-        final float alphaInFloat = a.getFloat(R.styleable.VectorDrawable_alpha,
-                pathRenderer.getAlpha());
+        // shown up from API 11.
+        final float alphaInFloat = TypedArrayUtils.getNamedFloat(a, parser, "alpha",
+                    AndroidResources.styleable_VectorDrawable_alpha, pathRenderer.getAlpha());
         pathRenderer.setAlpha(alphaInFloat);
 
-        final String name = a.getString(R.styleable.VectorDrawable_name);
+        final String name = a.getString(AndroidResources.styleable_VectorDrawable_name);
         if (name != null) {
             pathRenderer.mRootName = name;
             pathRenderer.mVGTargetsMap.put(name, pathRenderer);
@@ -545,10 +562,9 @@
             if (eventType == XmlPullParser.START_TAG) {
                 final String tagName = parser.getName();
                 final VGroup currentGroup = groupStack.peek();
-                Log.v(LOGTAG, tagName);
                 if (SHAPE_PATH.equals(tagName)) {
                     final VFullPath path = new VFullPath();
-                    path.inflate(res, attrs, theme);
+                    path.inflate(res, attrs, theme, parser);
                     currentGroup.mChildren.add(path);
                     if (path.getPathName() != null) {
                         pathRenderer.mVGTargetsMap.put(path.getPathName(), path);
@@ -557,7 +573,7 @@
                     state.mChangingConfigurations |= path.mChangingConfigurations;
                 } else if (SHAPE_CLIP_PATH.equals(tagName)) {
                     final VClipPath path = new VClipPath();
-                    path.inflate(res, attrs, theme);
+                    path.inflate(res, attrs, theme, parser);
                     currentGroup.mChildren.add(path);
                     if (path.getPathName() != null) {
                         pathRenderer.mVGTargetsMap.put(path.getPathName(), path);
@@ -565,7 +581,7 @@
                     state.mChangingConfigurations |= path.mChangingConfigurations;
                 } else if (SHAPE_GROUP.equals(tagName)) {
                     VGroup newChildGroup = new VGroup();
-                    newChildGroup.inflate(res, attrs, theme);
+                    newChildGroup.inflate(res, attrs, theme, parser);
                     currentGroup.mChildren.add(newChildGroup);
                     groupStack.push(newChildGroup);
                     if (newChildGroup.getGroupName() != null) {
@@ -614,6 +630,8 @@
             Object child = currentGroup.mChildren.get(i);
             if (child instanceof VGroup) {
                 printGroupTree((VGroup) child, level + 1);
+            } else {
+                ((VPath) child).printVPath(level + 1);
             }
         }
     }
@@ -1017,29 +1035,41 @@
             return mLocalMatrix;
         }
 
-        public void inflate(Resources res, AttributeSet attrs, Theme theme) {
+        public void inflate(Resources res, AttributeSet attrs, Theme theme, XmlPullParser parser) {
             final TypedArray a = obtainAttributes(res, theme, attrs,
-                    R.styleable.VectorDrawableGroup);
-            updateStateFromTypedArray(a);
+                    AndroidResources.styleable_VectorDrawableGroup);
+            updateStateFromTypedArray(a, parser);
             a.recycle();
         }
 
-        private void updateStateFromTypedArray(TypedArray a) {
+        private void updateStateFromTypedArray(TypedArray a, XmlPullParser parser) {
             // Account for any configuration changes.
             // mChangingConfigurations |= Utils.getChangingConfigurations(a);
 
             // Extract the theme attributes, if any.
             mThemeAttrs = null; // TODO TINT THEME Not supported yet a.extractThemeAttrs();
 
-            mRotate = a.getFloat(R.styleable.VectorDrawableGroup_rotation, mRotate);
-            mPivotX = a.getFloat(R.styleable.VectorDrawableGroup_pivotX, mPivotX);
-            mPivotY = a.getFloat(R.styleable.VectorDrawableGroup_pivotY, mPivotY);
-            mScaleX = a.getFloat(R.styleable.VectorDrawableGroup_scaleX, mScaleX);
-            mScaleY = a.getFloat(R.styleable.VectorDrawableGroup_scaleY, mScaleY);
-            mTranslateX = a.getFloat(R.styleable.VectorDrawableGroup_translateX, mTranslateX);
-            mTranslateY = a.getFloat(R.styleable.VectorDrawableGroup_translateY, mTranslateY);
+            // This is added in API 11
+            mRotate = TypedArrayUtils.getNamedFloat(a, parser, "rotation",
+                    AndroidResources.styleable_VectorDrawableGroup_rotation, mRotate);
 
-            final String groupName = a.getString(R.styleable.VectorDrawableGroup_name);
+            mPivotX = a.getFloat(AndroidResources.styleable_VectorDrawableGroup_pivotX, mPivotX);
+            mPivotY = a.getFloat(AndroidResources.styleable_VectorDrawableGroup_pivotY, mPivotY);
+
+            // This is added in API 11
+            mScaleX = TypedArrayUtils.getNamedFloat(a, parser, "scaleX",
+                    AndroidResources.styleable_VectorDrawableGroup_scaleX, mScaleX);
+
+            // This is added in API 11
+            mScaleY = TypedArrayUtils.getNamedFloat(a, parser, "scaleY",
+                    AndroidResources.styleable_VectorDrawableGroup_scaleY, mScaleY);
+
+            mTranslateX = TypedArrayUtils.getNamedFloat(a, parser, "translateX",
+                    AndroidResources.styleable_VectorDrawableGroup_translateX, mTranslateX);
+            mTranslateY = TypedArrayUtils.getNamedFloat(a, parser, "translateY",
+                    AndroidResources.styleable_VectorDrawableGroup_translateY, mTranslateY);
+
+            final String groupName = a.getString(AndroidResources.styleable_VectorDrawableGroup_name);
             if (groupName != null) {
                 mGroupName = groupName;
             }
@@ -1162,6 +1192,28 @@
             // Empty constructor.
         }
 
+        public void printVPath(int level) {
+            String indent = "";
+            for (int i = 0; i < level; i++) {
+                indent += "    ";
+            }
+            Log.v(LOGTAG, indent + "current path is :" + mPathName +
+                    " pathData is " + NodesToString(mNodes));
+
+        }
+
+        public String NodesToString(PathParser.PathDataNode[] nodes) {
+            String result = " ";
+            for (int i = 0; i < nodes.length; i++) {
+                result += nodes[i].type + ":";
+                float[] params = nodes[i].params;
+                for (int j = 0; j < params.length; j++) {
+                    result += params[j] + ",";
+                }
+            }
+            return result;
+        }
+
         public VPath(VPath copy) {
             mPathName = copy.mPathName;
             mChangingConfigurations = copy.mChangingConfigurations;
@@ -1219,10 +1271,14 @@
             super(copy);
         }
 
-        public void inflate(Resources r, AttributeSet attrs, Theme theme) {
+        public void inflate(Resources r, AttributeSet attrs, Theme theme, XmlPullParser parser) {
             // TODO TINT THEME Not supported yet
+            final boolean hasPathData = TypedArrayUtils.hasAttribute(parser, "pathData");
+            if (!hasPathData) {
+                return;
+            }
             final TypedArray a = obtainAttributes(r, theme, attrs,
-                    R.styleable.VectorDrawableClipPath);
+                    AndroidResources.styleable_VectorDrawableClipPath);
             updateStateFromTypedArray(a);
             a.recycle();
         }
@@ -1231,12 +1287,12 @@
             // Account for any configuration changes.
             // mChangingConfigurations |= Utils.getChangingConfigurations(a);;
 
-            final String pathName = a.getString(R.styleable.VectorDrawableClipPath_name);
+            final String pathName = a.getString(AndroidResources.styleable_VectorDrawableClipPath_name);
             if (pathName != null) {
                 mPathName = pathName;
             }
 
-            final String pathData = a.getString(R.styleable.VectorDrawableClipPath_pathData);
+            final String pathData = a.getString(AndroidResources.styleable_VectorDrawableClipPath_pathData);
             if (pathData != null) {
                 mNodes = PathParser.createNodesFromPathData(pathData);
             }
@@ -1325,52 +1381,64 @@
             return mThemeAttrs != null;
         }
 
-        public void inflate(Resources r, AttributeSet attrs, Theme theme) {
+        public void inflate(Resources r, AttributeSet attrs, Theme theme, XmlPullParser parser) {
             final TypedArray a = obtainAttributes(r, theme, attrs,
-                    R.styleable.VectorDrawablePath);
-            updateStateFromTypedArray(a);
+                    AndroidResources.styleable_VectorDrawablePath);
+            updateStateFromTypedArray(a, parser);
             a.recycle();
         }
 
-        private void updateStateFromTypedArray(TypedArray a) {
+        private void updateStateFromTypedArray(TypedArray a, XmlPullParser parser) {
             // Account for any configuration changes.
             // mChangingConfigurations |= Utils.getChangingConfigurations(a);
 
             // Extract the theme attributes, if any.
             mThemeAttrs = null; // TODO TINT THEME Not supported yet a.extractThemeAttrs();
 
-            final String pathName = a.getString(R.styleable.VectorDrawablePath_name);
+            // In order to work around the conflicting id issue, we need to double check the existence
+            // of the attribute.
+            // B/c if the attribute existed in the compiled XML, then calling TypedArray will be safe
+            // since the framework will look up in the XML first.
+            // Note that each getAttributeValue take roughly 0.03ms, it is a price we have to pay here.
+            final boolean hasPathData = TypedArrayUtils.hasAttribute(parser, "pathData");
+            if (!hasPathData) {
+                //If there is no pathData in the <path> tag, then this is an empty path, nothing need to be drawn.
+                return;
+            }
+
+            final String pathName = a.getString(AndroidResources.styleable_VectorDrawablePath_name);
             if (pathName != null) {
                 mPathName = pathName;
             }
-
-            final String pathData = a.getString(R.styleable.VectorDrawablePath_pathData);
+            final String pathData = a.getString(AndroidResources.styleable_VectorDrawablePath_pathData);
             if (pathData != null) {
                 mNodes = PathParser.createNodesFromPathData(pathData);
             }
 
-            mFillColor = a.getColor(R.styleable.VectorDrawablePath_fillColor,
-                    mFillColor);
-            mFillAlpha = a.getFloat(R.styleable.VectorDrawablePath_fillAlpha,
-                    mFillAlpha);
-            mStrokeLineCap = getStrokeLineCap(a.getInt(
-                    R.styleable.VectorDrawablePath_strokeLineCap, -1), mStrokeLineCap);
-            mStrokeLineJoin = getStrokeLineJoin(a.getInt(
-                    R.styleable.VectorDrawablePath_strokeLineJoin, -1), mStrokeLineJoin);
-            mStrokeMiterlimit = a.getFloat(
-                    R.styleable.VectorDrawablePath_strokeMiterLimit, mStrokeMiterlimit);
-            mStrokeColor = a.getColor(R.styleable.VectorDrawablePath_strokeColor,
-                    mStrokeColor);
-            mStrokeAlpha = a.getFloat(R.styleable.VectorDrawablePath_strokeAlpha,
-                    mStrokeAlpha);
-            mStrokeWidth = a.getFloat(R.styleable.VectorDrawablePath_strokeWidth,
-                    mStrokeWidth);
-            mTrimPathEnd = a.getFloat(R.styleable.VectorDrawablePath_trimPathEnd,
-                    mTrimPathEnd);
-            mTrimPathOffset = a.getFloat(
-                    R.styleable.VectorDrawablePath_trimPathOffset, mTrimPathOffset);
-            mTrimPathStart = a.getFloat(
-                    R.styleable.VectorDrawablePath_trimPathStart, mTrimPathStart);
+            mFillColor = TypedArrayUtils.getNamedColor(a, parser, "fillColor",
+                    AndroidResources.styleable_VectorDrawablePath_fillColor, mFillColor);
+            mFillAlpha = TypedArrayUtils.getNamedFloat(a, parser, "alpha",
+                    AndroidResources.styleable_VectorDrawablePath_fillAlpha, mFillAlpha);
+            final int lineCap = TypedArrayUtils.getNamedInt(a, parser, "strokeLineCap",
+                    AndroidResources.styleable_VectorDrawablePath_strokeLineCap, -1);
+            mStrokeLineCap = getStrokeLineCap(lineCap, mStrokeLineCap);
+            final int lineJoin = TypedArrayUtils.getNamedInt(a, parser, "strokeLineJoin",
+                    AndroidResources.styleable_VectorDrawablePath_strokeLineJoin, -1);
+            mStrokeLineJoin = getStrokeLineJoin(lineJoin, mStrokeLineJoin);
+            mStrokeMiterlimit = TypedArrayUtils.getNamedFloat(a, parser, "strokeMiterLimit",
+                    AndroidResources.styleable_VectorDrawablePath_strokeMiterLimit, mStrokeMiterlimit);
+            mStrokeColor = TypedArrayUtils.getNamedColor(a, parser, "strokeColor",
+                    AndroidResources.styleable_VectorDrawablePath_strokeColor, mStrokeColor);
+            mStrokeAlpha = TypedArrayUtils.getNamedFloat(a, parser, "strokeAlpha",
+                    AndroidResources.styleable_VectorDrawablePath_strokeAlpha, mStrokeAlpha);
+            mStrokeWidth = TypedArrayUtils.getNamedFloat(a, parser, "strokeWidth",
+                    AndroidResources.styleable_VectorDrawablePath_strokeWidth, mStrokeWidth);
+            mTrimPathEnd = TypedArrayUtils.getNamedFloat(a, parser, "trimPathEnd",
+                    AndroidResources.styleable_VectorDrawablePath_trimPathEnd, mTrimPathEnd);
+            mTrimPathOffset = TypedArrayUtils.getNamedFloat(a, parser, "trimPathOffset",
+                    AndroidResources.styleable_VectorDrawablePath_trimPathOffset, mTrimPathOffset);
+            mTrimPathStart = TypedArrayUtils.getNamedFloat(a, parser, "trimPathStart",
+                    AndroidResources.styleable_VectorDrawablePath_trimPathStart, mTrimPathStart);
         }
 
         @Override
@@ -1381,7 +1449,7 @@
 
             /*
              * TODO TINT THEME Not supported yet final TypedArray a =
-             * t.resolveAttributes(mThemeAttrs, R.styleable.VectorDrawablePath);
+             * t.resolveAttributes(mThemeAttrs, styleable_VectorDrawablePath);
              * updateStateFromTypedArray(a); a.recycle();
              */
         }
diff --git a/graphics/drawable/testanimated/Android.mk b/graphics/drawable/testanimated/Android.mk
index c888d9e..004cddb 100644
--- a/graphics/drawable/testanimated/Android.mk
+++ b/graphics/drawable/testanimated/Android.mk
@@ -18,7 +18,7 @@
 
 LOCAL_MODULE_TAGS := tests
 
-LOCAL_SDK_VERSION := 11
+LOCAL_SDK_VERSION := current
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
@@ -30,6 +30,8 @@
 
 LOCAL_STATIC_JAVA_LIBRARIES := android-support-v11-animatedvectordrawable android-support-v4
 
-LOCAL_AAPT_FLAGS += --auto-add-overlay --extra-packages android.support.graphics.drawable
+LOCAL_AAPT_FLAGS += --auto-add-overlay \
+        --extra-packages android.support.graphics.drawable \
+        --no-version-vectors
 
 include $(BUILD_PACKAGE)
diff --git a/graphics/drawable/testanimated/res/drawable/animation_vector_drawable_grouping_1.xml b/graphics/drawable/testanimated/res/drawable/animation_vector_drawable_grouping_1.xml
index 7c3b1de..dac981b 100644
--- a/graphics/drawable/testanimated/res/drawable/animation_vector_drawable_grouping_1.xml
+++ b/graphics/drawable/testanimated/res/drawable/animation_vector_drawable_grouping_1.xml
@@ -14,14 +14,13 @@
      limitations under the License.
 -->
 <animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:auto="http://schemas.android.com/apk/res-auto"
-    auto:drawable="@drawable/vector_drawable_grouping_1" >
+    android:drawable="@drawable/vector_drawable_grouping_1" >
 
     <target
-        auto:name="sun"
-        auto:animation="@anim/animation_grouping_1_01" />
+        android:name="sun"
+        android:animation="@anim/animation_grouping_1_01" />
     <target
-        auto:name="earth"
-        auto:animation="@anim/animation_grouping_1_01" />
+        android:name="earth"
+        android:animation="@anim/animation_grouping_1_01" />
 
 </animated-vector>
\ No newline at end of file
diff --git a/graphics/drawable/testanimated/res/drawable/animation_vector_progress_bar.xml b/graphics/drawable/testanimated/res/drawable/animation_vector_progress_bar.xml
index e37d2a1..2944dc2 100644
--- a/graphics/drawable/testanimated/res/drawable/animation_vector_progress_bar.xml
+++ b/graphics/drawable/testanimated/res/drawable/animation_vector_progress_bar.xml
@@ -14,13 +14,12 @@
      limitations under the License.
 -->
 <animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:auto="http://schemas.android.com/apk/res-auto"
-    auto:drawable="@drawable/vector_drawable_progress_bar" >
+    android:drawable="@drawable/vector_drawable_progress_bar" >
 
     <target
-        auto:name="pie1"
-        auto:animation="@anim/trim_path_animation_progress_bar" />
+        android:name="pie1"
+        android:animation="@anim/trim_path_animation_progress_bar" />
     <target
-        auto:name="root_bar"
-        auto:animation="@anim/alpha_animation_progress_bar" />
+        android:name="root_bar"
+        android:animation="@anim/alpha_animation_progress_bar" />
 </animated-vector>
\ No newline at end of file
diff --git a/graphics/drawable/testanimated/res/drawable/vector_drawable_grouping_1.xml b/graphics/drawable/testanimated/res/drawable/vector_drawable_grouping_1.xml
index eceda71..06f098e 100644
--- a/graphics/drawable/testanimated/res/drawable/vector_drawable_grouping_1.xml
+++ b/graphics/drawable/testanimated/res/drawable/vector_drawable_grouping_1.xml
@@ -14,37 +14,36 @@
      limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:auto="http://schemas.android.com/apk/res-auto"
-        auto:height="64dp"
-        auto:width="64dp"
-        auto:viewportHeight="256"
-        auto:viewportWidth="256" >
+        android:height="64dp"
+        android:width="64dp"
+        android:viewportHeight="256"
+        android:viewportWidth="256" >
 
     <group
-        auto:name="shape_layer_1"
-        auto:translateX="128"
-        auto:translateY="128" >
-        <group auto:name="sun" >
+        android:name="shape_layer_1"
+        android:translateX="128"
+        android:translateY="128" >
+        <group android:name="sun" >
             <path
-                auto:name="ellipse_path_1"
-                auto:fillColor="#ffff8000"
-                auto:pathData="m -25 0 a 25,25 0 1,0 50,0 a 25,25 0 1,0 -50,0" />
+                android:name="ellipse_path_1"
+                android:fillColor="#ffff8000"
+                android:pathData="m -25 0 a 25,25 0 1,0 50,0 a 25,25 0 1,0 -50,0" />
 
             <group
-                auto:name="earth"
-                auto:translateX="75" >
+                android:name="earth"
+                android:translateX="75" >
                 <path
-                    auto:name="ellipse_path_1_1"
-                    auto:fillColor="#ff5656ea"
-                    auto:pathData="m -10 0 a 10,10 0 1,0 20,0 a 10,10 0 1,0 -20,0" />
+                    android:name="ellipse_path_1_1"
+                    android:fillColor="#ff5656ea"
+                    android:pathData="m -10 0 a 10,10 0 1,0 20,0 a 10,10 0 1,0 -20,0" />
 
                 <group
-                    auto:name="moon"
-                    auto:translateX="25" >
+                    android:name="moon"
+                    android:translateX="25" >
                     <path
-                        auto:name="ellipse_path_1_2"
-                        auto:fillColor="#ffadadad"
-                        auto:pathData="m -5 0 a 5,5 0 1,0 10,0 a 5,5 0 1,0 -10,0" />
+                        android:name="ellipse_path_1_2"
+                        android:fillColor="#ffadadad"
+                        android:pathData="m -5 0 a 5,5 0 1,0 10,0 a 5,5 0 1,0 -10,0" />
                 </group>
             </group>
         </group>
diff --git a/graphics/drawable/testanimated/res/drawable/vector_drawable_progress_bar.xml b/graphics/drawable/testanimated/res/drawable/vector_drawable_progress_bar.xml
index 0b8884b..535265e 100644
--- a/graphics/drawable/testanimated/res/drawable/vector_drawable_progress_bar.xml
+++ b/graphics/drawable/testanimated/res/drawable/vector_drawable_progress_bar.xml
@@ -14,36 +14,35 @@
      limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:auto="http://schemas.android.com/apk/res-auto"
-        auto:height="64dp"
-        auto:width="64dp"
-        auto:viewportHeight="64"
-        auto:viewportWidth="64"
-        auto:name="root_bar" >
+        android:height="64dp"
+        android:width="64dp"
+        android:viewportHeight="64"
+        android:viewportWidth="64"
+        android:name="root_bar" >
 
     <group
-        auto:name="root"
-        auto:pivotX="0.0"
-        auto:pivotY="0.0"
-        auto:rotation="0"
-        auto:translateX="32.0"
-        auto:translateY="32.0" >
+        android:name="root"
+        android:pivotX="0.0"
+        android:pivotY="0.0"
+        android:rotation="0"
+        android:translateX="32.0"
+        android:translateY="32.0" >
         <group
-            auto:name="rotationGroup"
-            auto:pivotX="0.0"
-            auto:pivotY="0.0"
-            auto:rotation="0" >
+            android:name="rotationGroup"
+            android:pivotX="0.0"
+            android:pivotY="0.0"
+            android:rotation="0" >
             <path
-                auto:name="pie1"
-                auto:fillColor="#00000000"
-                auto:pathData="M0, 0 m 0, -9.5 a 9.5,9.5 0 1,1 0,19 a 9.5,9.5 0 1,1 0,-19"
-                auto:strokeColor="#FF00FFFF"
-                auto:strokeLineCap="round"
-                auto:strokeLineJoin="miter"
-                auto:strokeWidth="2"
-                auto:trimPathEnd="0.1"
-                auto:trimPathOffset="0"
-                auto:trimPathStart="0" />
+                android:name="pie1"
+                android:fillColor="#00000000"
+                android:pathData="M0, 0 m 0, -9.5 a 9.5,9.5 0 1,1 0,19 a 9.5,9.5 0 1,1 0,-19"
+                android:strokeColor="#FF00FFFF"
+                android:strokeLineCap="round"
+                android:strokeLineJoin="miter"
+                android:strokeWidth="2"
+                android:trimPathEnd="0.1"
+                android:trimPathOffset="0"
+                android:trimPathStart="0" />
         </group>
     </group>
 
diff --git a/graphics/drawable/teststatic/Android.mk b/graphics/drawable/teststatic/Android.mk
index d8a0fd7..4c4a7ba 100644
--- a/graphics/drawable/teststatic/Android.mk
+++ b/graphics/drawable/teststatic/Android.mk
@@ -18,7 +18,7 @@
 
 LOCAL_MODULE_TAGS := tests
 
-LOCAL_SDK_VERSION := 7
+LOCAL_SDK_VERSION := current
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
@@ -32,7 +32,8 @@
 
 LOCAL_AAPT_FLAGS := \
         --auto-add-overlay \
-        --extra-packages android.support.graphics.drawable
+        --extra-packages android.support.graphics.drawable \
+        --no-version-vectors
 
 include $(BUILD_PACKAGE)
 
diff --git a/graphics/drawable/teststatic/AndroidManifest.xml b/graphics/drawable/teststatic/AndroidManifest.xml
index 19586fb..39ac8ba 100644
--- a/graphics/drawable/teststatic/AndroidManifest.xml
+++ b/graphics/drawable/teststatic/AndroidManifest.xml
@@ -17,7 +17,7 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="android.support.test.vectordrawable" >
 
-    <uses-sdk android:minSdkVersion="7" />
+    <uses-sdk android:minSdkVersion="7"/>
 
     <application android:icon="@drawable/app_sample_code" android:label="VectorDrawableCompatTest" >
         <activity android:name="android.support.test.vectordrawable.TestActivity" />
@@ -29,4 +29,4 @@
         </intent-filter>
     </application>
 
-</manifest>
\ No newline at end of file
+</manifest>
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable01.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable01.xml
index 12357ef..286b487 100644
--- a/graphics/drawable/teststatic/res/drawable/vector_drawable01.xml
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable01.xml
@@ -1,4 +1,3 @@
-<?xml version="1.0" encoding="utf-8"?>
 <!--
  Copyright (C) 2015 The Android Open Source Project
 
@@ -15,20 +14,16 @@
      limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:auto="http://schemas.android.com/apk/res-auto"
-    auto:height="48dp"
-    auto:viewportHeight="480"
-    auto:viewportWidth="480"
-    auto:width="48dp" >
+        android:height="48dp"
+        android:width="48dp"
+        android:viewportHeight="480"
+        android:viewportWidth="480" >
 
     <group>
         <path
-            auto:name="box1"
-            auto:fillColor="?android:attr/textColorPrimary"
-            auto:pathData="m20,200l100,90l180-180l-35-35l-145,145l-60-60l-40,40z"
-            auto:strokeColor="?android:attr/colorBackground"
-            auto:strokeLineCap="round"
-            auto:strokeLineJoin="round" />
+            android:name="box1"
+            android:pathData="m20,200l100,90l180-180l-35-35l-145,145l-60-60l-40,40z"
+            android:strokeLineCap="round"
+            android:strokeLineJoin="round" />
     </group>
-
-</vector>
\ No newline at end of file
+</vector>
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable02.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable02.xml
index cb6b9df..7567887 100644
--- a/graphics/drawable/teststatic/res/drawable/vector_drawable02.xml
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable02.xml
@@ -1,5 +1,4 @@
-<!--
- Copyright (C) 2015 The Android Open Source Project
+<!-- Copyright (C) 2015 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -14,24 +13,20 @@
      limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:auto="http://schemas.android.com/apk/res-auto"
-    auto:height="64dp"
-    auto:viewportHeight="320"
-    auto:viewportWidth="320"
-    auto:width="64dp" >
-
+        android:width="64dp"
+        android:height="64dp" android:viewportWidth="320"
+          android:viewportHeight="320">
     <group
-        auto:pivotX="70"
-        auto:pivotY="120"
-        auto:rotation="180" >
+        android:rotation="180"
+        android:pivotX="70"
+        android:pivotY="120">
         <path
-            auto:name="house"
-            auto:fillColor="#ff440000"
-            auto:pathData="M 130,225 L 130,115 L 130,115 L 70,15 L 10,115 L 10,115 L 10,225 z"
-            auto:strokeColor="#FF00FF00"
-            auto:strokeWidth="10"
-            auto:trimPathEnd=".9"
-            auto:trimPathStart=".1" />
+            android:name="house"
+            android:pathData="M 130,225 L 130,115 L 130,115 L 70,15 L 10,115 L 10,115 L 10,225 z"
+            android:fillColor="#ff440000"
+            android:strokeColor="#FF00FF00"
+            android:strokeWidth="10"
+            android:trimPathStart=".1"
+            android:trimPathEnd=".9"/>
     </group>
-
-</vector>
\ No newline at end of file
+</vector>
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable03.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable03.xml
index 37d0086..454468a 100644
--- a/graphics/drawable/teststatic/res/drawable/vector_drawable03.xml
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable03.xml
@@ -14,51 +14,57 @@
      limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:auto="http://schemas.android.com/apk/res-auto"
-    auto:height="64dp"
-    auto:viewportHeight="12.25"
-    auto:viewportWidth="7.30625"
-    auto:width="64dp" >
+    android:height="64dp"
+    android:viewportHeight="12.25"
+    android:viewportWidth="7.30625"
+    android:width="64dp" >
 
     <group
-        auto:pivotX="3.65"
-        auto:pivotY="6.125"
-        auto:rotation="-30" >
+        android:pivotX="3.65"
+        android:pivotY="6.125"
+        android:rotation="-30" >
         <clip-path
-            auto:name="clip1"
-            auto:pathData="
+            android:name="clip1"
+            android:pathData="
                 M 0, 6.125
                 l 7.3, 0
                 l 0, 12.25
                 l-7.3, 0
                 z" />
-    </group>
-    <group>
-        <path
-            auto:name="one"
-            auto:fillColor="#ff88ff"
-            auto:pathData="M 1.215625,9.5l 1.9375,0.0 0.0-6.671875-2.109375,0.421875 0.0-1.078125
+
+        <group
+            android:pivotX="3.65"
+            android:pivotY="6.125"
+            android:rotation="30" >
+            <path
+                android:name="one"
+                android:fillColor="#ff88ff"
+                android:pathData="M 1.215625,9.5l 1.9375,0.0 0.0-6.671875-2.109375,0.421875 0.0-1.078125
                 l 2.09375-0.421875 1.1874998,0.0 0.0,7.75 1.9375,0.0 0.0,1.0
                 l-5.046875,0.0 0.0-1.0Z" />
+        </group>
     </group>
     <group
-        auto:pivotX="3.65"
-        auto:pivotY="6.125"
-        auto:rotation="-30" >
+        android:pivotX="3.65"
+        android:pivotY="6.125"
+        android:rotation="-30" >
         <clip-path
-            auto:name="clip2"
-            auto:pathData="
+            android:name="clip2"
+            android:pathData="
                 M 0, 0
                 l 7.3, 0
                 l 0, 6.125
                 l-7.3, 0
                 z" />
-    </group>
-    <group>
-        <path
-            auto:name="two"
-            auto:fillColor="#ff88ff"
-            auto:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0-5.5625,0.0 0.0-1.0q 0.671875-0.6875 1.828125-1.859375
+
+        <group
+            android:pivotX="3.65"
+            android:pivotY="6.125"
+            android:rotation="30" >
+            <path
+                android:name="two"
+                android:fillColor="#ff88ff"
+                android:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0-5.5625,0.0 0.0-1.0q 0.671875-0.6875 1.828125-1.859375
                         q 1.1718752-1.1875 1.4687502-1.53125 0.578125-0.625 0.796875-1.0625
                         q 0.234375-0.453125 0.234375-0.875 0.0-0.703125-0.5-1.140625
                         q-0.484375-0.4375-1.2656252-0.4375-0.5625,0.0-1.1875,0.1875
@@ -67,6 +73,7 @@
                         q 0.8125,0.671875 0.8125,1.8125 0.0,0.53125-0.203125,1.015625
                         q-0.203125,0.484375-0.734375,1.140625-0.15625,0.171875-0.9375,0.984375
                         q-0.78125024,0.8125-2.2187502,2.265625Z" />
+        </group>
     </group>
 
 </vector>
\ No newline at end of file
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable04.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable04.xml
index 4e2086f..e6658a6 100644
--- a/graphics/drawable/teststatic/res/drawable/vector_drawable04.xml
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable04.xml
@@ -13,38 +13,41 @@
      limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:auto="http://schemas.android.com/apk/res-auto"
-            auto:width="64dp"
-            auto:height="64dp"
-            auto:viewportWidth="7.30625"
-            auto:viewportHeight="12.25"
-            auto:autoMirrored="true">
+    android:autoMirrored="true"
+    android:height="64dp"
+    android:viewportHeight="12.25"
+    android:viewportWidth="7.30625"
+    android:width="64dp" >
 
     <group>
         <clip-path
-                auto:name="clip1"
-                auto:pathData="
+            android:name="clip1"
+            android:pathData="
                 M 3.65, 6.125
                 m-.001, 0
                 a .001,.001 0 1,0 .002,0
-                a .001,.001 0 1,0-.002,0z"/>
-        <path
-                auto:name="one"
-                auto:pathData="M 1.215625,9.5l 1.9375,0.0 0.0-6.671875-2.109375,0.421875 0.0-1.078125
-                l 2.09375-0.421875 1.1874998,0.0 0.0,7.75 1.9375,0.0 0.0,1.0
-                l-5.046875,0.0 0.0-1.0Z"
-                auto:fillColor="#ff88ff"/>
+                a .001,.001 0 1,0-.002,0z" />
 
+        <path
+            android:name="one"
+            android:fillColor="#ff88ff"
+            android:pathData="M 1.215625,9.5l 1.9375,0.0 0.0-6.671875-2.109375,0.421875 0.0-1.078125
+                l 2.09375-0.421875 1.1874998,0.0 0.0,7.75 1.9375,0.0 0.0,1.0
+                l-5.046875,0.0 0.0-1.0Z" />
+    </group>
+    <group>
         <clip-path
-                auto:name="clip2"
-                auto:pathData="
+            android:name="clip2"
+            android:pathData="
                 M 3.65, 6.125
                 m-6, 0
                 a 6,6 0 1,0 12,0
-                a 6,6 0 1,0-12,0z"/>
+                a 6,6 0 1,0-12,0z" />
+
         <path
-                auto:name="two"
-                auto:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0-5.5625,0.0 0.0-1.0q 0.671875-0.6875 1.828125-1.859375
+            android:name="two"
+            android:fillColor="#ff88ff"
+            android:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0-5.5625,0.0 0.0-1.0q 0.671875-0.6875 1.828125-1.859375
                         q 1.1718752-1.1875 1.4687502-1.53125 0.578125-0.625 0.796875-1.0625
                         q 0.234375-0.453125 0.234375-0.875 0.0-0.703125-0.5-1.140625
                         q-0.484375-0.4375-1.2656252-0.4375-0.5625,0.0-1.1875,0.1875
@@ -52,7 +55,7 @@
                         q 0.625-0.15625 1.140625-0.15625 1.3593752,0.0 2.1718752,0.6875
                         q 0.8125,0.671875 0.8125,1.8125 0.0,0.53125-0.203125,1.015625
                         q-0.203125,0.484375-0.734375,1.140625-0.15625,0.171875-0.9375,0.984375
-                        q-0.78125024,0.8125-2.2187502,2.265625Z"
-                auto:fillColor="#ff88ff"/>
+                        q-0.78125024,0.8125-2.2187502,2.265625Z" />
     </group>
-</vector>
+
+</vector>
\ No newline at end of file
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable05.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable05.xml
index 48801e3..d1723dc 100644
--- a/graphics/drawable/teststatic/res/drawable/vector_drawable05.xml
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable05.xml
@@ -14,24 +14,23 @@
      limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:auto="http://schemas.android.com/apk/res-auto"
-        auto:height="64dp"
-        auto:width="64dp"
-        auto:viewportHeight="12.25"
-        auto:viewportWidth="7.30625" >
+        android:height="64dp"
+        android:width="64dp"
+        android:viewportHeight="12.25"
+        android:viewportWidth="7.30625" >
 
     <group>
         <path
-            auto:name="one"
-            auto:fillColor="#ffff00"
-            auto:pathData="M 1.215625,9.5l 1.9375,0.0 0.0-6.671875-2.109375,0.421875 0.0-1.078125
+            android:name="one"
+            android:fillColor="#ffff00"
+            android:pathData="M 1.215625,9.5l 1.9375,0.0 0.0-6.671875-2.109375,0.421875 0.0-1.078125
                 l 2.09375-0.421875 1.1874998,0.0 0.0,7.75 1.9375,0.0 0.0,1.0
                 l-5.046875,0.0 0.0-1.0Z" />
         <path
-            auto:name="two"
-            auto:fillColor="#ffff00"
-            auto:fillAlpha="0"
-            auto:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0-5.5625,0.0 0.0-1.0q 0.671875-0.6875 1.828125-1.859375
+            android:name="two"
+            android:fillColor="#ffff00"
+            android:fillAlpha="0"
+            android:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0-5.5625,0.0 0.0-1.0q 0.671875-0.6875 1.828125-1.859375
                         q 1.1718752-1.1875 1.4687502-1.53125 0.578125-0.625 0.796875-1.0625
                         q 0.234375-0.453125 0.234375-0.875 0.0-0.703125-0.5-1.140625
                         q-0.484375-0.4375-1.2656252-0.4375-0.5625,0.0-1.1875,0.1875
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable06.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable06.xml
index 24173e2..4b530fd 100644
--- a/graphics/drawable/teststatic/res/drawable/vector_drawable06.xml
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable06.xml
@@ -13,37 +13,36 @@
      limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:auto="http://schemas.android.com/apk/res-auto"
-            auto:width="64dp"
-            auto:height="64dp"
-            auto:viewportWidth="700"
-            auto:viewportHeight="700">
+            android:width="64dp"
+            android:height="64dp"
+            android:viewportWidth="700"
+            android:viewportHeight="700">
 
     <group>
-        <path auto:pathData="M 569.374 461.472L 569.374 160.658L 160.658 160.658L 160.658 461.472L 569.374 461.472z"
-              auto:name="path2451"
-              auto:fillColor="#00000000"
-              auto:strokeColor="#FF000000"
-              auto:strokeWidth="30.65500000000000"/>
-        <path auto:pathData="M 365.015 311.066"
-              auto:name="path2453"
-              auto:fillColor="#00000000"
-              auto:strokeColor="#FF000000"
-              auto:strokeWidth="30.655000000000001"/>
-        <path auto:pathData="M 164.46 164.49L 340.78 343.158C 353.849 356.328 377.63 356.172 390.423 343.278L 566.622 165.928"
-              auto:name="path2455"
-              auto:strokeColor="#FF000000"
-              auto:fillColor="#FFFFFFFF"
-              auto:strokeWidth="30.655000000000001"/>
-        <path auto:pathData="M 170.515 451.566L 305.61 313.46"
-              auto:name="path2457"
-              auto:fillColor="#00000000"
-              auto:strokeColor="#000000"
-              auto:strokeWidth="30.655000000000001"/>
-        <path auto:pathData="M 557.968 449.974L 426.515 315.375"
-              auto:name="path2459"
-              auto:fillColor="#00000000"
-              auto:strokeColor="#000000"
-              auto:strokeWidth="30.655000000000001"/>
+        <path android:pathData="M 569.374 461.472L 569.374 160.658L 160.658 160.658L 160.658 461.472L 569.374 461.472z"
+              android:name="path2451"
+              android:fillColor="#00000000"
+              android:strokeColor="#FF000000"
+              android:strokeWidth="30.65500000000000"/>
+        <path android:pathData="M 365.015 311.066"
+              android:name="path2453"
+              android:fillColor="#00000000"
+              android:strokeColor="#FF000000"
+              android:strokeWidth="30.655000000000001"/>
+        <path android:pathData="M 164.46 164.49L 340.78 343.158C 353.849 356.328 377.63 356.172 390.423 343.278L 566.622 165.928"
+              android:name="path2455"
+              android:strokeColor="#FF000000"
+              android:fillColor="#FFFFFFFF"
+              android:strokeWidth="30.655000000000001"/>
+        <path android:pathData="M 170.515 451.566L 305.61 313.46"
+              android:name="path2457"
+              android:fillColor="#00000000"
+              android:strokeColor="#000000"
+              android:strokeWidth="30.655000000000001"/>
+        <path android:pathData="M 557.968 449.974L 426.515 315.375"
+              android:name="path2459"
+              android:fillColor="#00000000"
+              android:strokeColor="#000000"
+              android:strokeWidth="30.655000000000001"/>
     </group>
 </vector>
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable07.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable07.xml
index 90435d3..bbf2451 100644
--- a/graphics/drawable/teststatic/res/drawable/vector_drawable07.xml
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable07.xml
@@ -13,18 +13,17 @@
      limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:auto="http://schemas.android.com/apk/res-auto"
-            auto:width="64dp"
-            auto:height="64dp" auto:viewportWidth="140"
-          auto:viewportHeight="110">
+            android:width="64dp"
+            android:height="64dp" android:viewportWidth="140"
+          android:viewportHeight="110">
 
     <group>
         <path
-                auto:name="back"
-                auto:pathData="M 20,55 l 35.3-35.3 7.07,7.07-35.3,35.3 z
+                android:name="back"
+                android:pathData="M 20,55 l 35.3-35.3 7.07,7.07-35.3,35.3 z
               M 27,50 l 97,0 0,10-97,0 z
               M 20,55 l 7.07-7.07 35.3,35.3-7.07,7.07 z"
-                auto:fillColor="#ffffffff"
+                android:fillColor="#ffffffff"
                 />
     </group>
 </vector>
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable08.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable08.xml
index 251d694..e5b59df 100644
--- a/graphics/drawable/teststatic/res/drawable/vector_drawable08.xml
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable08.xml
@@ -13,18 +13,17 @@
      limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:auto="http://schemas.android.com/apk/res-auto"
-            auto:width="64dp"
-            auto:height="64dp" auto:viewportWidth="600"
-          auto:viewportHeight="600">
+            android:width="64dp"
+            android:height="64dp" android:viewportWidth="600"
+          android:viewportHeight="600">
 
     <group>
         <path
-                auto:name="pie1"
-                auto:pathData="M535.441,412.339A280.868,280.868 0 1,1 536.186,161.733L284.493,286.29Z"
-                auto:fillColor="#ffffcc00"
-                auto:strokeColor="#FF00FF00"
-                auto:strokeWidth="1"/>
+                android:name="pie1"
+                android:pathData="M535.441,412.339A280.868,280.868 0 1,1 536.186,161.733L284.493,286.29Z"
+                android:fillColor="#ffffcc00"
+                android:strokeColor="#FF00FF00"
+                android:strokeWidth="1"/>
     </group>
 
 </vector>
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable09.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable09.xml
index eccb0d0..ce2441d 100644
--- a/graphics/drawable/teststatic/res/drawable/vector_drawable09.xml
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable09.xml
@@ -14,20 +14,19 @@
      limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:auto="http://schemas.android.com/apk/res-auto"
-        auto:height="64dp"
-        auto:width="64dp"
-        auto:viewportHeight="200"
-        auto:viewportWidth="200" >
+        android:height="64dp"
+        android:width="64dp"
+        android:viewportHeight="200"
+        android:viewportWidth="200" >
 
     <group
-        auto:pivotX="100"
-        auto:pivotY="100"
-        auto:rotation="90">
+        android:pivotX="100"
+        android:pivotY="100"
+        android:rotation="90">
         <path
-            auto:name="house"
-            auto:fillColor="#ffffffff"
-            auto:pathData="M 100,20 l 0,0 0,140-80,0 z M 100,20 l 0,0 80,140-80,0 z"/>
+            android:name="house"
+            android:fillColor="#ffffffff"
+            android:pathData="M 100,20 l 0,0 0,140-80,0 z M 100,20 l 0,0 80,140-80,0 z"/>
     </group>
 
 </vector>
\ No newline at end of file
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable10.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable10.xml
index b26d30d..935d4a5 100644
--- a/graphics/drawable/teststatic/res/drawable/vector_drawable10.xml
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable10.xml
@@ -15,29 +15,28 @@
      limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:auto="http://schemas.android.com/apk/res-auto"
-        auto:height="64dp"
-        auto:width="64dp"
-        auto:viewportWidth="200"
-        auto:viewportHeight="200">
+        android:height="64dp"
+        android:width="64dp"
+        android:viewportWidth="200"
+        android:viewportHeight="200">
 
     <group>
         <path
-            auto:name="bar3"
-            auto:fillColor="#FFFFFFFF"
-            auto:pathData="M49.001,60c-5.466,0-9.899,4.478-9.899,10s4.434,10,9.899,10c5.468,0,9.899-4.478,9.899-10S54.469,60,49.001,60z" />
+            android:name="bar3"
+            android:fillColor="#FFFFFFFF"
+            android:pathData="M49.001,60c-5.466,0-9.899,4.478-9.899,10s4.434,10,9.899,10c5.468,0,9.899-4.478,9.899-10S54.469,60,49.001,60z" />
         <path
-            auto:name="bar2"
-            auto:fillColor="#FFFFFFFF"
-            auto:pathData="M28.001,48.787l7,7.07c7.731-7.811,20.269-7.81,28.001,0l6.999-7.07C58.403,37.071,39.599,37.071,28.001,48.787z" />
+            android:name="bar2"
+            android:fillColor="#FFFFFFFF"
+            android:pathData="M28.001,48.787l7,7.07c7.731-7.811,20.269-7.81,28.001,0l6.999-7.07C58.403,37.071,39.599,37.071,28.001,48.787z" />
         <path
-            auto:name="bar1"
-            auto:fillColor="#FF555555"
-            auto:pathData="M14.001,34.645   L21,41.716c15.464-15.621,40.536-15.621,56,0l7.001-7.071C64.672,15.119,33.33,15.119,14.001,34.645z" />
+            android:name="bar1"
+            android:fillColor="#FF555555"
+            android:pathData="M14.001,34.645   L21,41.716c15.464-15.621,40.536-15.621,56,0l7.001-7.071C64.672,15.119,33.33,15.119,14.001,34.645z" />
         <path
-            auto:name="bar0"
-            auto:fillColor="#FF555555"
-            auto:pathData="M0,20.502l6.999,7.071   c23.196-23.431,60.806-23.431,84.002,0L98,20.503C70.938-6.834,27.063-6.834,0,20.502z" />
+            android:name="bar0"
+            android:fillColor="#FF555555"
+            android:pathData="M0,20.502l6.999,7.071   c23.196-23.431,60.806-23.431,84.002,0L98,20.503C70.938-6.834,27.063-6.834,0,20.502z" />
     </group>
 
 </vector>
\ No newline at end of file
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable11.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable11.xml
index eb440f5..05f481b 100644
--- a/graphics/drawable/teststatic/res/drawable/vector_drawable11.xml
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable11.xml
@@ -14,23 +14,22 @@
      limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:auto="http://schemas.android.com/apk/res-auto"
-        auto:height="64dp"
-        auto:width="64dp"
-        auto:viewportHeight="80"
-        auto:viewportWidth="40" >
+        android:height="64dp"
+        android:width="64dp"
+        android:viewportHeight="80"
+        android:viewportWidth="40" >
 
     <group>
         <path
-            auto:name="battery"
-            auto:fillColor="#3388ff"
-            auto:pathData="M 20.28125,2.0000002 C 17.352748,2.0000002 15,4.3527485 15,7.2812502 L 15,8.0000002 L 13.15625,8.0000002 C 9.7507553,8.0000002 7,10.750759 7,14.15625 L 7,39.84375 C 7,43.24924 9.7507558,46 13.15625,46 L 33.84375,46 C 37.249245,46 39.999999,43.24924 40,39.84375 L 40,14.15625 C 40,10.75076 37.249243,8.0000002 33.84375,8.0000002 L 32,8.0000002 L 32,7.2812502 C 32,4.3527485 29.647252,2.0000002 26.71875,2.0000002 L 20.28125,2.0000002 z"
-            auto:strokeColor="#ff8833"
-            auto:strokeWidth="1" />
+            android:name="battery"
+            android:fillColor="#3388ff"
+            android:pathData="M 20.28125,2.0000002 C 17.352748,2.0000002 15,4.3527485 15,7.2812502 L 15,8.0000002 L 13.15625,8.0000002 C 9.7507553,8.0000002 7,10.750759 7,14.15625 L 7,39.84375 C 7,43.24924 9.7507558,46 13.15625,46 L 33.84375,46 C 37.249245,46 39.999999,43.24924 40,39.84375 L 40,14.15625 C 40,10.75076 37.249243,8.0000002 33.84375,8.0000002 L 32,8.0000002 L 32,7.2812502 C 32,4.3527485 29.647252,2.0000002 26.71875,2.0000002 L 20.28125,2.0000002 z"
+            android:strokeColor="#ff8833"
+            android:strokeWidth="1" />
         <path
-            auto:name="spark"
-            auto:fillColor="#FFFF0000"
-            auto:pathData="M 30,18.031528 L 25.579581,23.421071 L 29.370621,26.765348 L 20.096792,37 L 21.156922,28.014053 L 17,24.902844 L 20.880632,18 L 30,18.031528 z" />
+            android:name="spark"
+            android:fillColor="#FFFF0000"
+            android:pathData="M 30,18.031528 L 25.579581,23.421071 L 29.370621,26.765348 L 20.096792,37 L 21.156922,28.014053 L 17,24.902844 L 20.880632,18 L 30,18.031528 z" />
     </group>
 
 </vector>
\ No newline at end of file
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable12.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable12.xml
index 94a23e8..94338a7 100644
--- a/graphics/drawable/teststatic/res/drawable/vector_drawable12.xml
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable12.xml
@@ -14,79 +14,78 @@
      limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:auto="http://schemas.android.com/apk/res-auto"
-        auto:name="rootGroup"
-        auto:height="64dp"
-        auto:width="64dp"
-        auto:viewportHeight="600"
-        auto:viewportWidth="600"
-        auto:alpha="0.5" >
+        android:name="rootGroup"
+        android:height="64dp"
+        android:width="64dp"
+        android:viewportHeight="600"
+        android:viewportWidth="600"
+        android:alpha="0.5" >
 
     <group
-        auto:name="rotationGroup"
-        auto:pivotX="300.0"
-        auto:pivotY="300.0"
-        auto:rotation="45.0" >
+        android:name="rotationGroup"
+        android:pivotX="300.0"
+        android:pivotY="300.0"
+        android:rotation="45.0" >
         <path
-            auto:name="pie1"
-            auto:fillColor="#00000000"
-            auto:pathData="M300,70 a230,230 0 1,0 1,0 z"
-            auto:strokeColor="#FF777777"
-            auto:strokeWidth="70"
-            auto:trimPathEnd=".75"
-            auto:trimPathOffset="0"
-            auto:trimPathStart="0" />
+            android:name="pie1"
+            android:fillColor="#00000000"
+            android:pathData="M300,70 a230,230 0 1,0 1,0 z"
+            android:strokeColor="#FF777777"
+            android:strokeWidth="70"
+            android:trimPathEnd=".75"
+            android:trimPathOffset="0"
+            android:trimPathStart="0" />
         <path
-            auto:name="v"
-            auto:fillColor="#000000"
-            auto:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z" />
+            android:name="v"
+            android:fillColor="#000000"
+            android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z" />
 
         <group
-            auto:name="translateToCenterGroup"
-            auto:rotation="0.0"
-            auto:translateX="200.0"
-            auto:translateY="200.0" >
+            android:name="translateToCenterGroup"
+            android:rotation="0.0"
+            android:translateX="200.0"
+            android:translateY="200.0" >
             <group
-                auto:name="rotationGroup2"
-                auto:pivotX="0.0"
-                auto:pivotY="0.0"
-                auto:rotation="-45.0" >
+                android:name="rotationGroup2"
+                android:pivotX="0.0"
+                android:pivotY="0.0"
+                android:rotation="-45.0" >
                 <path
-                    auto:name="twoLines1"
-                    auto:pathData="@string/twoLinePathData"
-                    auto:strokeColor="#FFFF0000"
-                    auto:strokeWidth="20" />
+                    android:name="twoLines1"
+                    android:pathData="@string/twoLinePathData"
+                    android:strokeColor="#FFFF0000"
+                    android:strokeWidth="20" />
 
                 <group
-                    auto:name="translateGroupHalf"
-                    auto:translateX="65.0"
-                    auto:translateY="80.0" >
+                    android:name="translateGroupHalf"
+                    android:translateX="65.0"
+                    android:translateY="80.0" >
                     <group
-                        auto:name="rotationGroup3"
-                        auto:pivotX="-65.0"
-                        auto:pivotY="-80.0"
-                        auto:rotation="-45.0" >
+                        android:name="rotationGroup3"
+                        android:pivotX="-65.0"
+                        android:pivotY="-80.0"
+                        android:rotation="-45.0" >
                         <path
-                            auto:name="twoLines2"
-                            auto:fillColor="#FF00FF00"
-                            auto:pathData="@string/twoLinePathData"
-                            auto:strokeColor="#FF00FF00"
-                            auto:strokeWidth="20" />
+                            android:name="twoLines2"
+                            android:fillColor="#FF00FF00"
+                            android:pathData="@string/twoLinePathData"
+                            android:strokeColor="#FF00FF00"
+                            android:strokeWidth="20" />
 
                         <group
-                            auto:name="translateGroup"
-                            auto:translateX="65.0"
-                            auto:translateY="80.0" >
+                            android:name="translateGroup"
+                            android:translateX="65.0"
+                            android:translateY="80.0" >
                             <group
-                                auto:name="rotationGroupBlue"
-                                auto:pivotX="-65.0"
-                                auto:pivotY="-80.0"
-                                auto:rotation="-45.0" >
+                                android:name="rotationGroupBlue"
+                                android:pivotX="-65.0"
+                                android:pivotY="-80.0"
+                                android:rotation="-45.0" >
                                 <path
-                                    auto:name="twoLines3"
-                                    auto:pathData="@string/twoLinePathData"
-                                    auto:strokeColor="#FF0000FF"
-                                    auto:strokeWidth="20" />
+                                    android:name="twoLines3"
+                                    android:pathData="@string/twoLinePathData"
+                                    android:strokeColor="#FF0000FF"
+                                    android:strokeWidth="20" />
                             </group>
                         </group>
                     </group>
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable13.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable13.xml
index 43fc7ea..097e028 100644
--- a/graphics/drawable/teststatic/res/drawable/vector_drawable13.xml
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable13.xml
@@ -14,25 +14,24 @@
      limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:auto="http://schemas.android.com/apk/res-auto"
-        auto:height="64dp"
-        auto:width="64dp"
-        auto:viewportHeight="400"
-        auto:viewportWidth="600" >
+        android:height="64dp"
+        android:width="64dp"
+        android:viewportHeight="400"
+        android:viewportWidth="600" >
 
     <group>
         <path
-            auto:name="pie1"
-            auto:fillColor="#ffffffff"
-            auto:pathData="M300,200 h-150 a150,150 0 1,0 150,-150 z"
-            auto:strokeColor="#FF00FF00"
-            auto:strokeWidth="1" />
+            android:name="pie1"
+            android:fillColor="#ffffffff"
+            android:pathData="M300,200 h-150 a150,150 0 1,0 150,-150 z"
+            android:strokeColor="#FF00FF00"
+            android:strokeWidth="1" />
         <path
-            auto:name="half"
-            auto:fillColor="#FFFF0000"
-            auto:pathData="M275,175 v-150 a150,150 0 0,0 -150,150 z"
-            auto:strokeColor="#FF0000FF"
-            auto:strokeWidth="5" />
+            android:name="half"
+            android:fillColor="#FFFF0000"
+            android:pathData="M275,175 v-150 a150,150 0 0,0 -150,150 z"
+            android:strokeColor="#FF0000FF"
+            android:strokeWidth="5" />
     </group>
 
 </vector>
\ No newline at end of file
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable14.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable14.xml
index 5b4fdd1..102ae7a 100644
--- a/graphics/drawable/teststatic/res/drawable/vector_drawable14.xml
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable14.xml
@@ -14,26 +14,25 @@
      limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:auto="http://schemas.android.com/apk/res-auto"
-        auto:height="64dp"
-        auto:width="64dp"
-        auto:viewportHeight="500"
-        auto:viewportWidth="800" >
+        android:height="64dp"
+        android:width="64dp"
+        android:viewportHeight="500"
+        android:viewportWidth="800" >
 
     <group
-        auto:pivotX="90"
-        auto:pivotY="100"
-        auto:rotation="20">
+        android:pivotX="90"
+        android:pivotY="100"
+        android:rotation="20">
         <path
-            auto:name="pie2"
-            auto:pathData="M200,350 l 50,-25
+            android:name="pie2"
+            android:pathData="M200,350 l 50,-25
            a25,12 -30 0,1 100,-50 l 50,-25
            a25,25 -30 0,1 100,-50 l 50,-25
            a25,37 -30 0,1 100,-50 l 50,-25
            a25,50 -30 0,1 100,-50 l 50,-25"
-            auto:fillColor="#00000000"
-            auto:strokeColor="#FF00FF00"
-            auto:strokeWidth="10" />
+            android:fillColor="#00000000"
+            android:strokeColor="#FF00FF00"
+            android:strokeWidth="10" />
     </group>
 
 </vector>
\ No newline at end of file
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable15.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable15.xml
index f4ef87f..bdfcf81 100644
--- a/graphics/drawable/teststatic/res/drawable/vector_drawable15.xml
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable15.xml
@@ -14,22 +14,21 @@
      limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:auto="http://schemas.android.com/apk/res-auto"
-        auto:height="64dp"
-        auto:width="64dp"
-        auto:viewportHeight="400"
-        auto:viewportWidth="500" >
+        android:height="64dp"
+        android:width="64dp"
+        android:viewportHeight="400"
+        android:viewportWidth="500" >
 
     <group
-        auto:pivotX="250"
-        auto:pivotY="200"
-        auto:rotation="180">
+        android:pivotX="250"
+        android:pivotY="200"
+        android:rotation="180">
         <path
-            auto:name="house"
-            auto:fillColor="#ff440000"
-            auto:pathData="M100,200 C100,100 250,100 250,200 S400,300 400,200"
-            auto:strokeColor="#FFFF0000"
-            auto:strokeWidth="10" />
+            android:name="house"
+            android:fillColor="#ff440000"
+            android:pathData="M100,200 C100,100 250,100 250,200 S400,300 400,200"
+            android:strokeColor="#FFFF0000"
+            android:strokeWidth="10" />
     </group>
 
 </vector>
\ No newline at end of file
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable16.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable16.xml
index 0c64bca..ed1efa0 100644
--- a/graphics/drawable/teststatic/res/drawable/vector_drawable16.xml
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable16.xml
@@ -14,35 +14,34 @@
      limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:auto="http://schemas.android.com/apk/res-auto"
-        auto:height="64dp"
-        auto:width="64dp"
-        auto:viewportHeight="200"
-        auto:viewportWidth="200" >
+        android:height="64dp"
+        android:width="64dp"
+        android:viewportHeight="200"
+        android:viewportWidth="200" >
 
     <group>
         <path
-            auto:name="background1"
-            auto:pathData="M 0,0 l 100,0 l 0, 100 l -100, 0 z"
-            auto:fillColor="#FF000000"/>
+            android:name="background1"
+            android:pathData="M 0,0 l 100,0 l 0, 100 l -100, 0 z"
+            android:fillColor="#FF000000"/>
         <path
-            auto:name="background2"
-            auto:pathData="M 100,100 l 100,0 l 0, 100 l -100, 0 z"
-            auto:fillColor="#FF000000"/>
+            android:name="background2"
+            android:pathData="M 100,100 l 100,0 l 0, 100 l -100, 0 z"
+            android:fillColor="#FF000000"/>
     </group>
     <group
-        auto:pivotX="100"
-        auto:pivotY="100"
-        auto:rotation="90"
-        auto:scaleX="0.75"
-        auto:scaleY="0.5"
-        auto:translateX="0.0"
-        auto:translateY="100.0">
+        android:pivotX="100"
+        android:pivotY="100"
+        android:rotation="90"
+        android:scaleX="0.75"
+        android:scaleY="0.5"
+        android:translateX="0.0"
+        android:translateY="100.0">
         <path
-            auto:name="twoLines"
-            auto:pathData="M 100,10 v 90 M 10,100 h 90"
-            auto:strokeColor="#FF00FF00"
-            auto:strokeWidth="10" />
+            android:name="twoLines"
+            android:pathData="M 100,10 v 90 M 10,100 h 90"
+            android:strokeColor="#FF00FF00"
+            android:strokeWidth="10" />
     </group>
 
 </vector>
\ No newline at end of file
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable17.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable17.xml
index 28cf09a..ba15f41 100644
--- a/graphics/drawable/teststatic/res/drawable/vector_drawable17.xml
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable17.xml
@@ -13,18 +13,17 @@
      limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:auto="http://schemas.android.com/apk/res-auto"
-            auto:width="64dp"
-            auto:height="64dp" auto:viewportWidth="1200"
-          auto:viewportHeight="600">
+            android:width="64dp"
+            android:height="64dp" android:viewportWidth="1200"
+          android:viewportHeight="600">
 
     <group>
         <path
-                auto:name="house"
-                auto:pathData="M200,300 Q400,50 600,300 T1000,300"
-                auto:fillColor="#00000000"
-                auto:strokeColor="#FFFF0000"
-                auto:strokeWidth="10"/>
+                android:name="house"
+                android:pathData="M200,300 Q400,50 600,300 T1000,300"
+                android:fillColor="#00000000"
+                android:strokeColor="#FFFF0000"
+                android:strokeWidth="10"/>
     </group>
 
 </vector>
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable18.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable18.xml
index d66d4ff..ee2122a 100644
--- a/graphics/drawable/teststatic/res/drawable/vector_drawable18.xml
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable18.xml
@@ -14,19 +14,18 @@
      limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:auto="http://schemas.android.com/apk/res-auto"
-        auto:height="64dp"
-        auto:width="64dp"
-        auto:viewportHeight="400"
-        auto:viewportWidth="500" >
+        android:height="64dp"
+        android:width="64dp"
+        android:viewportHeight="400"
+        android:viewportWidth="500" >
 
     <group>
         <path
-            auto:name="house"
-            auto:pathData="M100,200 C100,100 250,100 250,200 S400,300 400,200"
-            auto:fillColor="#00000000"
-            auto:strokeColor="#FFFFFF00"
-            auto:strokeWidth="10" />
+            android:name="house"
+            android:pathData="M100,200 C100,100 250,100 250,200 S400,300 400,200"
+            android:fillColor="#00000000"
+            android:strokeColor="#FFFFFF00"
+            android:strokeWidth="10" />
     </group>
 
 </vector>
\ No newline at end of file
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable19.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable19.xml
index 3a6559d..b98e1de 100644
--- a/graphics/drawable/teststatic/res/drawable/vector_drawable19.xml
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable19.xml
@@ -14,21 +14,20 @@
      limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:auto="http://schemas.android.com/apk/res-auto"
-        auto:height="64dp"
-        auto:width="64dp"
-        auto:viewportHeight="800"
-        auto:viewportWidth="1000" >
+        android:height="64dp"
+        android:width="64dp"
+        android:viewportHeight="800"
+        android:viewportWidth="1000" >
 
     <group>
         <path
-            auto:name="house"
-            auto:pathData="M10,300 Q400,550 600,300 T1000,300"
-            auto:pivotX="90"
-            auto:pivotY="100"
-            auto:fillColor="#00000000"
-            auto:strokeColor="#FFFF0000"
-            auto:strokeWidth="60" />
+            android:name="house"
+            android:pathData="M10,300 Q400,550 600,300 T1000,300"
+            android:pivotX="90"
+            android:pivotY="100"
+            android:fillColor="#00000000"
+            android:strokeColor="#FFFF0000"
+            android:strokeWidth="60" />
     </group>
 
 </vector>
\ No newline at end of file
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable20.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable20.xml
index d6fd704..1c86818 100644
--- a/graphics/drawable/teststatic/res/drawable/vector_drawable20.xml
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable20.xml
@@ -14,22 +14,21 @@
      limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:auto="http://schemas.android.com/apk/res-auto"
-        auto:height="64dp"
-        auto:width="64dp"
-        auto:viewportHeight="480"
-        auto:viewportWidth="480" >
+        android:height="64dp"
+        android:width="64dp"
+        android:viewportHeight="480"
+        android:viewportWidth="480" >
 
     <group>
         <path
-            auto:name="edit"
-            auto:fillColor="#FF00FFFF"
-            auto:pathData="M406.667,180c0,0 -100 -100 -113.334 -113.333
+            android:name="edit"
+            android:fillColor="#FF00FFFF"
+            android:pathData="M406.667,180c0,0 -100 -100 -113.334 -113.333
     c-13.333 -13.334 -33.333,0 -33.333,0l-160,160c0,0 -40,153.333 -40,173.333c0,13.333,13.333,13.333,13.333,13.333l173.334 -40
     c0,0,146.666 -146.666,160 -160C420,200,406.667,180,406.667,180z M226.399,356.823L131.95,378.62l-38.516 -38.522
     c7.848 -34.675,20.152 -82.52,23.538 -95.593l3.027,2.162l106.667,106.666L226.399,356.823z"
-            auto:strokeColor="#FF000000"
-            auto:strokeWidth="10" />
+            android:strokeColor="#FF000000"
+            android:strokeWidth="10" />
     </group>
 
 </vector>
\ No newline at end of file
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable21.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable21.xml
index 9136b73..247f6bc 100644
--- a/graphics/drawable/teststatic/res/drawable/vector_drawable21.xml
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable21.xml
@@ -14,35 +14,34 @@
      limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:auto="http://schemas.android.com/apk/res-auto"
-        auto:height="64dp"
-        auto:width="64dp"
-        auto:viewportHeight="200"
-        auto:viewportWidth="200" >
+        android:height="64dp"
+        android:width="64dp"
+        android:viewportHeight="200"
+        android:viewportWidth="200" >
 
     <group>
         <path
-            auto:name="background1"
-            auto:pathData="M 0,0 l 100,0 l 0, 100 l -100, 0 z"
-            auto:fillColor="#FF000000"/>
+            android:name="background1"
+            android:pathData="M 0,0 l 100,0 l 0, 100 l -100, 0 z"
+            android:fillColor="#FF000000"/>
         <path
-            auto:name="background2"
-            auto:pathData="M 100,100 l 100,0 l 0, 100 l -100, 0 z"
-            auto:fillColor="#FF000000"/>
+            android:name="background2"
+            android:pathData="M 100,100 l 100,0 l 0, 100 l -100, 0 z"
+            android:fillColor="#FF000000"/>
     </group>
     <group
-        auto:pivotX="0"
-        auto:pivotY="0"
-        auto:rotation="90"
-        auto:scaleX="0.75"
-        auto:scaleY="0.5"
-        auto:translateX="100.0"
-        auto:translateY="100.0">
+        android:pivotX="0"
+        android:pivotY="0"
+        android:rotation="90"
+        android:scaleX="0.75"
+        android:scaleY="0.5"
+        android:translateX="100.0"
+        android:translateY="100.0">
         <path
-            auto:name="twoLines"
-            auto:pathData="M 100,10 v 90 M 10,100 h 90"
-            auto:strokeColor="#FF00FF00"
-            auto:strokeWidth="10" />
+            android:name="twoLines"
+            android:pathData="M 100,10 v 90 M 10,100 h 90"
+            android:strokeColor="#FF00FF00"
+            android:strokeWidth="10" />
     </group>
 
 </vector>
\ No newline at end of file
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable22.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable22.xml
index 2b33a89..39d891f 100644
--- a/graphics/drawable/teststatic/res/drawable/vector_drawable22.xml
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable22.xml
@@ -14,53 +14,52 @@
      limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:auto="http://schemas.android.com/apk/res-auto"
-        auto:height="64dp"
-        auto:width="64dp"
-        auto:viewportHeight="400"
-        auto:viewportWidth="400" >
+        android:height="64dp"
+        android:width="64dp"
+        android:viewportHeight="400"
+        android:viewportWidth="400" >
 
-    <group auto:name="backgroundGroup" >
+    <group android:name="backgroundGroup" >
         <path
-            auto:name="background1"
-            auto:fillColor="#80000000"
-            auto:pathData="M 0,0 l 200,0 l 0, 200 l -200, 0 z" />
+            android:name="background1"
+            android:fillColor="#80000000"
+            android:pathData="M 0,0 l 200,0 l 0, 200 l -200, 0 z" />
         <path
-            auto:name="background2"
-            auto:fillColor="#80000000"
-            auto:pathData="M 200,200 l 200,0 l 0, 200 l -200, 0 z" />
+            android:name="background2"
+            android:fillColor="#80000000"
+            android:pathData="M 200,200 l 200,0 l 0, 200 l -200, 0 z" />
     </group>
     <group
-        auto:name="translateToCenterGroup"
-        auto:translateX="50.0"
-        auto:translateY="90.0" >
+        android:name="translateToCenterGroup"
+        android:translateX="50.0"
+        android:translateY="90.0" >
         <path
-            auto:name="twoLines"
-            auto:pathData="M 0,0 v 100 M 0,0 h 100"
-            auto:strokeColor="#FFFF0000"
-            auto:strokeWidth="20" />
+            android:name="twoLines"
+            android:pathData="M 0,0 v 100 M 0,0 h 100"
+            android:strokeColor="#FFFF0000"
+            android:strokeWidth="20" />
 
         <group
-            auto:name="rotationGroup"
-            auto:pivotX="0.0"
-            auto:pivotY="0.0"
-            auto:rotation="-45.0" >
+            android:name="rotationGroup"
+            android:pivotX="0.0"
+            android:pivotY="0.0"
+            android:rotation="-45.0" >
             <path
-                auto:name="twoLines1"
-                auto:pathData="M 0,0 v 100 M 0,0 h 100"
-                auto:strokeColor="#FF00FF00"
-                auto:strokeWidth="20" />
+                android:name="twoLines1"
+                android:pathData="M 0,0 v 100 M 0,0 h 100"
+                android:strokeColor="#FF00FF00"
+                android:strokeWidth="20" />
 
             <group
-                auto:name="translateGroup"
-                auto:translateX="130.0"
-                auto:translateY="160.0" >
-                <group auto:name="scaleGroup" >
+                android:name="translateGroup"
+                android:translateX="130.0"
+                android:translateY="160.0" >
+                <group android:name="scaleGroup" >
                     <path
-                        auto:name="twoLines2"
-                        auto:pathData="M 0,0 v 100 M 0,0 h 100"
-                        auto:strokeColor="#FF0000FF"
-                        auto:strokeWidth="20" />
+                        android:name="twoLines2"
+                        android:pathData="M 0,0 v 100 M 0,0 h 100"
+                        android:strokeColor="#FF0000FF"
+                        android:strokeWidth="20" />
                 </group>
             </group>
         </group>
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable23.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable23.xml
index d5759f9..4a1c062 100644
--- a/graphics/drawable/teststatic/res/drawable/vector_drawable23.xml
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable23.xml
@@ -14,67 +14,66 @@
      limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:auto="http://schemas.android.com/apk/res-auto"
-        auto:height="64dp"
-        auto:width="64dp"
-        auto:viewportHeight="400"
-        auto:viewportWidth="400" >
+        android:height="64dp"
+        android:width="64dp"
+        android:viewportHeight="400"
+        android:viewportWidth="400" >
 
-    <group auto:name="backgroundGroup" >
+    <group android:name="backgroundGroup" >
         <path
-            auto:name="background1"
-            auto:fillColor="#80000000"
-            auto:pathData="M 0,0 l 200,0 l 0, 200 l -200, 0 z" />
+            android:name="background1"
+            android:fillColor="#80000000"
+            android:pathData="M 0,0 l 200,0 l 0, 200 l -200, 0 z" />
         <path
-            auto:name="background2"
-            auto:fillColor="#80000000"
-            auto:pathData="M 200,200 l 200,0 l 0, 200 l -200, 0 z" />
+            android:name="background2"
+            android:fillColor="#80000000"
+            android:pathData="M 200,200 l 200,0 l 0, 200 l -200, 0 z" />
     </group>
     <group
-        auto:name="translateToCenterGroup"
-        auto:translateX="50.0"
-        auto:translateY="90.0" >
+        android:name="translateToCenterGroup"
+        android:translateX="50.0"
+        android:translateY="90.0" >
         <path
-            auto:name="twoLines"
-            auto:pathData="@string/twoLinePathData"
-            auto:strokeColor="#FFFF0000"
-            auto:strokeWidth="20" />
+            android:name="twoLines"
+            android:pathData="@string/twoLinePathData"
+            android:strokeColor="#FFFF0000"
+            android:strokeWidth="20" />
 
         <group
-            auto:name="rotationGroup"
-            auto:pivotX="0.0"
-            auto:pivotY="0.0"
-            auto:rotation="-45.0" >
+            android:name="rotationGroup"
+            android:pivotX="0.0"
+            android:pivotY="0.0"
+            android:rotation="-45.0" >
             <path
-                auto:name="twoLines1"
-                auto:pathData="@string/twoLinePathData"
-                auto:strokeColor="#FF00FF00"
-                auto:strokeWidth="20" />
+                android:name="twoLines1"
+                android:pathData="@string/twoLinePathData"
+                android:strokeColor="#FF00FF00"
+                android:strokeWidth="20" />
 
             <group
-                auto:name="translateGroup"
-                auto:translateX="130.0"
-                auto:translateY="160.0" >
-                <group auto:name="scaleGroup" >
+                android:name="translateGroup"
+                android:translateX="130.0"
+                android:translateY="160.0" >
+                <group android:name="scaleGroup" >
                     <path
-                        auto:name="twoLines3"
-                        auto:pathData="@string/twoLinePathData"
-                        auto:strokeColor="#FF0000FF"
-                        auto:strokeWidth="20" />
+                        android:name="twoLines3"
+                        android:pathData="@string/twoLinePathData"
+                        android:strokeColor="#FF0000FF"
+                        android:strokeWidth="20" />
                 </group>
             </group>
 
             <group
-                auto:name="translateGroupHalf"
-                auto:translateX="65.0"
-                auto:translateY="80.0" >
-                <group auto:name="scaleGroup" >
+                android:name="translateGroupHalf"
+                android:translateX="65.0"
+                android:translateY="80.0" >
+                <group android:name="scaleGroup" >
                     <path
-                        auto:name="twoLines2"
-                        auto:pathData="@string/twoLinePathData"
-                        auto:fillColor="#FFFFFFFF"
-                        auto:strokeColor="#FFFFFFFF"
-                        auto:strokeWidth="20" />
+                        android:name="twoLines2"
+                        android:pathData="@string/twoLinePathData"
+                        android:fillColor="?android:attr/colorForeground"
+                        android:strokeColor="?android:attr/colorForeground"
+                        android:strokeWidth="20" />
                 </group>
             </group>
         </group>
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable24.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable24.xml
index b054692..a7a8bd3 100644
--- a/graphics/drawable/teststatic/res/drawable/vector_drawable24.xml
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable24.xml
@@ -14,67 +14,66 @@
      limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:auto="http://schemas.android.com/apk/res-auto"
-        auto:height="64dp"
-        auto:width="64dp"
-        auto:viewportHeight="400"
-        auto:viewportWidth="400" >
+        android:height="64dp"
+        android:width="64dp"
+        android:viewportHeight="400"
+        android:viewportWidth="400" >
 
-    <group auto:name="backgroundGroup">
+    <group android:name="backgroundGroup">
         <path
-            auto:name="background1"
-            auto:fillColor="#FF000000"
-            auto:pathData="M 0,0 l 200,0 l 0, 200 l -200, 0 z" />
+            android:name="background1"
+            android:fillColor="#FF000000"
+            android:pathData="M 0,0 l 200,0 l 0, 200 l -200, 0 z" />
         <path
-            auto:name="background2"
-            auto:fillColor="#FF000000"
-            auto:pathData="M 200,200 l 200,0 l 0, 200 l -200, 0 z" />
+            android:name="background2"
+            android:fillColor="#FF000000"
+            android:pathData="M 200,200 l 200,0 l 0, 200 l -200, 0 z" />
     </group>
     <group
-        auto:name="translateToCenterGroup"
-        auto:translateX="50.0"
-        auto:translateY="90.0" >
+        android:name="translateToCenterGroup"
+        android:translateX="50.0"
+        android:translateY="90.0" >
         <path
-            auto:name="twoLines"
-            auto:pathData="@string/twoLinePathData"
-            auto:strokeColor="#FFFF0000"
-            auto:strokeWidth="20" />
+            android:name="twoLines"
+            android:pathData="@string/twoLinePathData"
+            android:strokeColor="#FFFF0000"
+            android:strokeWidth="20" />
 
         <group
-            auto:name="rotationGroup"
-            auto:pivotX="0.0"
-            auto:pivotY="0.0"
-            auto:rotation="-45.0">
+            android:name="rotationGroup"
+            android:pivotX="0.0"
+            android:pivotY="0.0"
+            android:rotation="-45.0">
             <path
-                auto:name="twoLines1"
-                auto:pathData="@string/twoLinePathData"
-                auto:strokeColor="#FF00FF00"
-                auto:strokeWidth="20" />
+                android:name="twoLines1"
+                android:pathData="@string/twoLinePathData"
+                android:strokeColor="#FF00FF00"
+                android:strokeWidth="20" />
 
             <group
-                auto:name="translateGroup"
-                auto:translateX="130.0"
-                auto:translateY="160.0">
-                <group auto:name="scaleGroup" >
+                android:name="translateGroup"
+                android:translateX="130.0"
+                android:translateY="160.0">
+                <group android:name="scaleGroup" >
                     <path
-                        auto:name="twoLines3"
-                        auto:pathData="@string/twoLinePathData"
-                        auto:strokeColor="#FF0000FF"
-                        auto:strokeWidth="20" />
+                        android:name="twoLines3"
+                        android:pathData="@string/twoLinePathData"
+                        android:strokeColor="#FF0000FF"
+                        android:strokeWidth="20" />
                 </group>
             </group>
 
             <group
-                auto:name="translateGroupHalf"
-                auto:translateX="65.0"
-                auto:translateY="80.0">
-                <group auto:name="scaleGroup" >
+                android:name="translateGroupHalf"
+                android:translateX="65.0"
+                android:translateY="80.0">
+                <group android:name="scaleGroup" >
                     <path
-                        auto:name="twoLines2"
-                        auto:pathData="@string/twoLinePathData"
-                        auto:fillColor="#FFFFFFFF"
-                        auto:strokeColor="#FFFFFFFF"
-                        auto:strokeWidth="20" />
+                        android:name="twoLines2"
+                        android:pathData="@string/twoLinePathData"
+                        android:fillColor="?android:attr/colorForeground"
+                        android:strokeColor="?android:attr/colorForeground"
+                        android:strokeWidth="20" />
                 </group>
             </group>
         </group>
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable25.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable25.xml
index 7a94ed6..7c9e771 100644
--- a/graphics/drawable/teststatic/res/drawable/vector_drawable25.xml
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable25.xml
@@ -14,70 +14,69 @@
      limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:auto="http://schemas.android.com/apk/res-auto"
-        auto:height="64dp"
-        auto:width="64dp"
-        auto:viewportHeight="400"
-        auto:viewportWidth="400" >
+        android:height="64dp"
+        android:width="64dp"
+        android:viewportHeight="400"
+        android:viewportWidth="400" >
 
     <group
-        auto:name="FirstLevelGroup"
-        auto:translateX="100.0"
-        auto:translateY="0.0" >
+        android:name="FirstLevelGroup"
+        android:translateX="100.0"
+        android:translateY="0.0" >
         <group
-            auto:name="SecondLevelGroup1"
-            auto:translateX="-100.0"
-            auto:translateY="50.0" >
+            android:name="SecondLevelGroup1"
+            android:translateX="-100.0"
+            android:translateY="50.0" >
             <path
-                auto:fillColor="#FF00FF00"
-                auto:pathData="@string/rectangle200" />
+                android:fillColor="#FF00FF00"
+                android:pathData="@string/rectangle200" />
 
             <group
-                auto:name="ThridLevelGroup1"
-                auto:translateX="-100.0"
-                auto:translateY="50.0" >
+                android:name="ThridLevelGroup1"
+                android:translateX="-100.0"
+                android:translateY="50.0" >
                 <path
-                    auto:fillColor="#FF0000FF"
-                    auto:pathData="@string/rectangle200" />
+                    android:fillColor="#FF0000FF"
+                    android:pathData="@string/rectangle200" />
             </group>
             <group
-                auto:name="ThridLevelGroup2"
-                auto:translateX="100.0"
-                auto:translateY="50.0" >
+                android:name="ThridLevelGroup2"
+                android:translateX="100.0"
+                android:translateY="50.0" >
                 <path
-                    auto:fillColor="#FF000000"
-                    auto:pathData="@string/rectangle200" />
+                    android:fillColor="#FF000000"
+                    android:pathData="@string/rectangle200" />
             </group>
         </group>
         <group
-            auto:name="SecondLevelGroup2"
-            auto:translateX="100.0"
-            auto:translateY="50.0" >
+            android:name="SecondLevelGroup2"
+            android:translateX="100.0"
+            android:translateY="50.0" >
             <path
-                auto:fillColor="#FF0000FF"
-                auto:pathData="@string/rectangle200" />
+                android:fillColor="#FF0000FF"
+                android:pathData="@string/rectangle200" />
 
             <group
-                auto:name="ThridLevelGroup3"
-                auto:translateX="-100.0"
-                auto:translateY="50.0" >
+                android:name="ThridLevelGroup3"
+                android:translateX="-100.0"
+                android:translateY="50.0" >
                 <path
-                    auto:fillColor="#FFFF0000"
-                    auto:pathData="@string/rectangle200" />
+                    android:fillColor="#FFFF0000"
+                    android:pathData="@string/rectangle200" />
             </group>
             <group
-                auto:name="ThridLevelGroup4"
-                auto:translateX="100.0"
-                auto:translateY="50.0" >
+                android:name="ThridLevelGroup4"
+                android:translateX="100.0"
+                android:translateY="50.0" >
                 <path
-                    auto:fillColor="#FF00FF00"
-                    auto:pathData="@string/rectangle200" />
+                    android:fillColor="#FF00FF00"
+                    android:pathData="@string/rectangle200" />
             </group>
         </group>
 
         <path
-            auto:fillColor="#FFFF0000"
-            auto:pathData="@string/rectangle200" />
+            android:fillColor="#FFFF0000"
+            android:pathData="@string/rectangle200" />
     </group>
 
 </vector>
\ No newline at end of file
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable26.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable26.xml
index b2dd4a3..eda06d8 100644
--- a/graphics/drawable/teststatic/res/drawable/vector_drawable26.xml
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable26.xml
@@ -14,33 +14,32 @@
      limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:auto="http://schemas.android.com/apk/res-auto"
-    auto:height="64dp"
-    auto:viewportHeight="200"
-    auto:viewportWidth="200"
-    auto:width="64dp" >
+    android:height="64dp"
+    android:viewportHeight="200"
+    android:viewportWidth="200"
+    android:width="64dp" >
 
     <group>
         <path
-            auto:name="background1"
-            auto:fillColor="#FF000000"
-            auto:pathData="M 0,0 l 100,0 l 0, 100 l -100, 0 z" />
+            android:name="background1"
+            android:fillColor="#FF000000"
+            android:pathData="M 0,0 l 100,0 l 0, 100 l -100, 0 z" />
         <path
-            auto:name="background2"
-            auto:fillColor="#FF000000"
-            auto:pathData="M 100,100 l 100,0 l 0, 100 l -100, 0 z" />
+            android:name="background2"
+            android:fillColor="#FF000000"
+            android:pathData="M 100,100 l 100,0 l 0, 100 l -100, 0 z" />
     </group>
     <group
-        auto:translateX="50"
-        auto:translateY="50" >
+        android:translateX="50"
+        android:translateY="50" >
         <path
-            auto:name="twoLines"
-            auto:pathData="M 100,20 l 0 80 l -30 -80"
-            auto:strokeColor="#FF00FF00"
-            auto:strokeLineCap="butt"
-            auto:strokeLineJoin="miter"
-            auto:strokeMiterLimit="5"
-            auto:strokeWidth="20" />
+            android:name="twoLines"
+            android:pathData="M 100,20 l 0 80 l -30 -80"
+            android:strokeColor="#FF00FF00"
+            android:strokeLineCap="butt"
+            android:strokeLineJoin="miter"
+            android:strokeMiterLimit="5"
+            android:strokeWidth="20" />
     </group>
 
 </vector>
\ No newline at end of file
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable27.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable27.xml
index b8f88ce..cd46dd9 100644
--- a/graphics/drawable/teststatic/res/drawable/vector_drawable27.xml
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable27.xml
@@ -14,33 +14,32 @@
      limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:auto="http://schemas.android.com/apk/res-auto"
-    auto:height="64dp"
-    auto:viewportHeight="200"
-    auto:viewportWidth="200"
-    auto:width="64dp" >
+    android:height="64dp"
+    android:viewportHeight="200"
+    android:viewportWidth="200"
+    android:width="64dp" >
 
     <group>
         <path
-            auto:name="background1"
-            auto:fillColor="#FF000000"
-            auto:pathData="M 0,0 l 100,0 l 0, 100 l -100, 0 z" />
+            android:name="background1"
+            android:fillColor="#FF000000"
+            android:pathData="M 0,0 l 100,0 l 0, 100 l -100, 0 z" />
         <path
-            auto:name="background2"
-            auto:fillColor="#FF000000"
-            auto:pathData="M 100,100 l 100,0 l 0, 100 l -100, 0 z" />
+            android:name="background2"
+            android:fillColor="#FF000000"
+            android:pathData="M 100,100 l 100,0 l 0, 100 l -100, 0 z" />
     </group>
     <group
-        auto:translateX="50"
-        auto:translateY="50" >
+        android:translateX="50"
+        android:translateY="50" >
         <path
-            auto:name="twoLines"
-            auto:pathData="M 100,20 l 0 80 l -30 -80"
-            auto:strokeColor="#FF00FF00"
-            auto:strokeLineCap="round"
-            auto:strokeLineJoin="round"
-            auto:strokeMiterLimit="10"
-            auto:strokeWidth="20" />
+            android:name="twoLines"
+            android:pathData="M 100,20 l 0 80 l -30 -80"
+            android:strokeColor="#FF00FF00"
+            android:strokeLineCap="round"
+            android:strokeLineJoin="round"
+            android:strokeMiterLimit="10"
+            android:strokeWidth="20" />
     </group>
 
 </vector>
\ No newline at end of file
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable28.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable28.xml
index 30c7fce..812af6b 100644
--- a/graphics/drawable/teststatic/res/drawable/vector_drawable28.xml
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable28.xml
@@ -14,34 +14,33 @@
      limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:auto="http://schemas.android.com/apk/res-auto"
-    auto:height="64dp"
-    auto:viewportHeight="200"
-    auto:viewportWidth="200"
-    auto:width="64dp"
-    auto:autoMirrored="true" >
+    android:height="64dp"
+    android:viewportHeight="200"
+    android:viewportWidth="200"
+    android:width="64dp"
+    android:autoMirrored="true" >
 
     <group>
         <path
-            auto:name="background1"
-            auto:fillColor="#FF000000"
-            auto:pathData="M 0,0 l 100,0 l 0, 100 l -100, 0 z" />
+            android:name="background1"
+            android:fillColor="#FF000000"
+            android:pathData="M 0,0 l 100,0 l 0, 100 l -100, 0 z" />
         <path
-            auto:name="background2"
-            auto:fillColor="#FF000000"
-            auto:pathData="M 100,100 l 100,0 l 0, 100 l -100, 0 z" />
+            android:name="background2"
+            android:fillColor="#FF000000"
+            android:pathData="M 100,100 l 100,0 l 0, 100 l -100, 0 z" />
     </group>
     <group
-        auto:translateX="50"
-        auto:translateY="50" >
+        android:translateX="50"
+        android:translateY="50" >
         <path
-            auto:name="twoLines"
-            auto:pathData="M 100,20 l 0 80 l -30 -80"
-            auto:strokeColor="#FF00FF00"
-            auto:strokeLineCap="square"
-            auto:strokeLineJoin="bevel"
-            auto:strokeMiterLimit="10"
-            auto:strokeWidth="20" />
+            android:name="twoLines"
+            android:pathData="M 100,20 l 0 80 l -30 -80"
+            android:strokeColor="#FF00FF00"
+            android:strokeLineCap="square"
+            android:strokeLineJoin="bevel"
+            android:strokeMiterLimit="10"
+            android:strokeWidth="20" />
     </group>
 
 </vector>
\ No newline at end of file
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable29.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable29.xml
index 2ac1d42..b24d31c 100644
--- a/graphics/drawable/teststatic/res/drawable/vector_drawable29.xml
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable29.xml
@@ -14,16 +14,15 @@
      limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:auto="http://schemas.android.com/apk/res-auto"
-        auto:height="48dp"
-        auto:width="48dp"
-        auto:viewportHeight="1"
-        auto:viewportWidth="1" >
+        android:height="48dp"
+        android:width="48dp"
+        android:viewportHeight="1"
+        android:viewportWidth="1" >
 
     <group>
         <path
-            auto:name="box1"
-            auto:pathData="l0.0.0.5.0.0.5-0.5.0.0-.5z"
-            auto:fillColor="#ff00ff00"/>
+            android:name="box1"
+            android:pathData="l0.0.0.5.0.0.5-0.5.0.0-.5z"
+            android:fillColor="#ff00ff00"/>
     </group>
 </vector>
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable30.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable30.xml
index 6abb455..24f7372 100644
--- a/graphics/drawable/teststatic/res/drawable/vector_drawable30.xml
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable30.xml
@@ -14,16 +14,15 @@
      limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:auto="http://schemas.android.com/apk/res-auto"
-        auto:height="48dp"
-        auto:width="48dp"
-        auto:viewportHeight="48"
-        auto:viewportWidth="48" >
+        android:height="48dp"
+        android:width="48dp"
+        android:viewportHeight="48"
+        android:viewportWidth="48" >
 
     <group>
         <path
-            auto:name="plus1"
-            auto:pathData="M20 16h-4v8h-8v4h8v8h4v-8h8v-4h-8zm9-3.84v3.64l5-1v21.2h4v-26z"
-            auto:fillColor="#ff00ff00"/>
+            android:name="plus1"
+            android:pathData="M20 16h-4v8h-8v4h8v8h4v-8h8v-4h-8zm9-3.84v3.64l5-1v21.2h4v-26z"
+            android:fillColor="#ff00ff00"/>
     </group>
 </vector>
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable_scale0.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable_scale0.xml
new file mode 100644
index 0000000..828f0d9
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable_scale0.xml
@@ -0,0 +1,57 @@
+<!--
+ Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:height="64dp"
+    android:viewportHeight="200"
+    android:viewportWidth="200"
+    android:width="64dp" >
+
+    <group>
+        <path
+            android:name="background1"
+            android:fillColor="@color/color0"
+            android:pathData="M 0,0 l 100,0 l 0, 100 l -100, 0 z" />
+        <path
+            android:name="background2"
+            android:fillColor="@color/color2"
+            android:pathData="M 100,100 l 100,0 l 0, 100 l -100, 0 z" />
+    </group>
+    <group
+        android:pivotX="0"
+        android:pivotY="0"
+        android:rotation="90" >
+        <group
+            android:scaleX="1.5"
+            android:scaleY="1" >
+            <group
+                android:pivotX="0"
+                android:pivotY="0"
+                android:rotation="-90" >
+                <group
+                    android:scaleX="1.5"
+                    android:scaleY="1" >
+                    <path
+                        android:name="twoLines"
+                        android:fillColor="#FFFF0000"
+                        android:pathData="@string/triangle100"
+                        android:strokeColor="#FF00FF00"
+                        android:strokeWidth="10" />
+                </group>
+            </group>
+        </group>
+    </group>
+
+</vector>
\ No newline at end of file
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable_scale1.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable_scale1.xml
new file mode 100644
index 0000000..530c73b
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable_scale1.xml
@@ -0,0 +1,52 @@
+<!--
+ Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:height="64dp"
+    android:viewportHeight="200"
+    android:viewportWidth="200"
+    android:width="64dp" >
+
+    <group>
+        <path
+            android:name="background1"
+            android:fillColor="#FF000000"
+            android:pathData="M 0,0 l 100,0 l 0, 100 l -100, 0 z" />
+        <path
+            android:name="background2"
+            android:fillColor="#FF000000"
+            android:pathData="M 100,100 l 100,0 l 0, 100 l -100, 0 z" />
+    </group>
+    <group
+        android:scaleX="-1"
+        android:scaleY="-1" >
+        <group
+            android:scaleX="-1"
+            android:scaleY="-1" >
+            <group
+                android:pivotX="100"
+                android:pivotY="100"
+                android:rotation="45" >
+                <path
+                    android:name="twoLines"
+                    android:fillColor="#FFFF0000"
+                    android:pathData="M 100, 0 l 0, 100, -100, 0 z"
+                    android:strokeColor="#FF00FF00"
+                    android:strokeWidth="10" />
+            </group>
+        </group>
+    </group>
+
+</vector>
\ No newline at end of file
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable_scale2.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable_scale2.xml
new file mode 100644
index 0000000..200eb61
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable_scale2.xml
@@ -0,0 +1,48 @@
+<!--
+ Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:height="64dp"
+    android:viewportHeight="200"
+    android:viewportWidth="200"
+    android:width="64dp" >
+
+    <group>
+        <path
+            android:name="background1"
+            android:fillColor="#FF000000"
+            android:pathData="M 0,0 l 100,0 l 0, 100 l -100, 0 z" />
+        <path
+            android:name="background2"
+            android:fillColor="#FF000000"
+            android:pathData="M 100,100 l 100,0 l 0, 100 l -100, 0 z" />
+    </group>
+    <group
+        android:scaleX="2"
+        android:scaleY="0.5" >
+        <group
+            android:pivotX="100"
+            android:pivotY="100"
+            android:rotation="45" >
+            <path
+                android:name="twoLines"
+                android:fillColor="#FFFF0000"
+                android:pathData="M 100, 0 l 0, 100, -100, 0 z"
+                android:strokeColor="#FF00FF00"
+                android:strokeWidth="10" />
+        </group>
+    </group>
+
+</vector>
\ No newline at end of file
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable_scale3.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable_scale3.xml
new file mode 100644
index 0000000..a40fc9c2
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable_scale3.xml
@@ -0,0 +1,62 @@
+<!--
+ Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:height="64dp"
+    android:viewportHeight="200"
+    android:viewportWidth="200"
+    android:width="64dp" >
+
+    <group>
+        <path
+            android:name="background1"
+            android:fillColor="#FF000000"
+            android:pathData="M 0,0 l 100,0 l 0, 100 l -100, 0 z" />
+        <path
+            android:name="background2"
+            android:fillColor="#FF000000"
+            android:pathData="M 100,100 l 100,0 l 0, 100 l -100, 0 z" />
+    </group>
+    <group
+        android:pivotX="0"
+        android:pivotY="0"
+        android:rotation="45" >
+        <group
+            android:pivotX="0"
+            android:pivotY="0"
+            android:rotation="90" >
+            <group
+                android:scaleX="1.5"
+                android:scaleY="1" >
+                <group
+                    android:pivotX="0"
+                    android:pivotY="0"
+                    android:rotation="-90" >
+                    <group
+                        android:scaleX="1.5"
+                        android:scaleY="1" >
+                        <path
+                            android:name="twoLines"
+                            android:fillColor="#FFFF0000"
+                            android:pathData="M 100, 0 l 0, 100, -100, 0 z"
+                            android:strokeColor="#FF00FF00"
+                            android:strokeWidth="10" />
+                    </group>
+                </group>
+            </group>
+        </group>
+    </group>
+
+</vector>
\ No newline at end of file
diff --git a/graphics/drawable/teststatic/res/drawable/vector_test01.xml b/graphics/drawable/teststatic/res/drawable/vector_test01.xml
new file mode 100644
index 0000000..8b891d6
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_test01.xml
@@ -0,0 +1,31 @@
+<!--
+ Copyright (C) 2015 The Android Open Source Project
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at"+
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:height="128dp"
+        android:width="128dp"
+        android:viewportHeight="512"
+        android:viewportWidth="512" >
+
+    <group>
+        <path
+            android:name="002b"
+            android:pathData="M100,200c0,-100 150,-100 150,0s150,100 150,0t-200,299"
+            android:strokeColor="#FF0000FF"
+            android:strokeWidth="4"
+            android:fillColor="#00000000" />
+    </group>
+
+</vector>
\ No newline at end of file
diff --git a/graphics/drawable/teststatic/res/drawable/vector_test02.xml b/graphics/drawable/teststatic/res/drawable/vector_test02.xml
new file mode 100644
index 0000000..e0af323
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_test02.xml
@@ -0,0 +1,31 @@
+<!--
+ Copyright (C) 2015 The Android Open Source Project
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at"+
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:height="128dp"
+        android:width="128dp"
+        android:viewportHeight="512"
+        android:viewportWidth="512" >
+
+    <group>
+        <path
+            android:name="002b"
+            android:pathData="M100,200c0,-100 150,-100 150,0s150,100 150,0T-200,299"
+            android:strokeColor="#FF0000FF"
+            android:strokeWidth="4"
+            android:fillColor="#00000000" />
+    </group>
+
+</vector>
\ No newline at end of file
diff --git a/v17/leanback/res/animator/lb_guidedactions_item_checked.xml b/graphics/drawable/teststatic/res/values/colors.xml
similarity index 60%
rename from v17/leanback/res/animator/lb_guidedactions_item_checked.xml
rename to graphics/drawable/teststatic/res/values/colors.xml
index 463b9f7..6eb3036 100644
--- a/v17/leanback/res/animator/lb_guidedactions_item_checked.xml
+++ b/graphics/drawable/teststatic/res/values/colors.xml
@@ -1,6 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2015 The Android Open Source Project
+<!-- Copyright (C) 2015 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -14,9 +12,9 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
-    android:duration="@integer/lb_guidedactions_item_animation_duration"
-    android:propertyName="alpha"
-    android:valueFrom="0.0"
-    android:valueTo="1.0"
-    android:valueType="floatType" />
+<resources>
+    <color name="color0">#a6e4ea</color>
+    <color name="color1">#ff3838</color>
+    <color name="color2">#ffff51</color>
+    <color name="color3">#0ed300</color>
+</resources>
diff --git a/graphics/drawable/teststatic/res/values/strings.xml b/graphics/drawable/teststatic/res/values/strings.xml
index c5451c88..065e7d9 100644
--- a/graphics/drawable/teststatic/res/values/strings.xml
+++ b/graphics/drawable/teststatic/res/values/strings.xml
@@ -25,4 +25,5 @@
     <string name="round_box">"m2.10001,-6c-1.9551,0 -0.5,0.02499 -2.10001,0.02499c-1.575,0 0.0031,-0.02499 -1.95,-0.02499c-2.543,0 -4,2.2816 -4,4.85001c0,3.52929 0.25,6.25 5.95,6.25c5.7,0 6,-2.72071 6,-6.25c0,-2.56841 -1.35699,-4.85001 -3.89999,-4.85001"</string>
     <string name="heart">    "m4.5,-7c-1.95509,0 -3.83009,1.26759 -4.5,3c-0.66991,-1.73241 -2.54691,-3 -4.5,-3c-2.543,0 -4.5,1.93159 -4.5,4.5c0,3.5293 3.793,6.2578 9,11.5c5.207,-5.2422 9,-7.9707 9,-11.5c0,-2.56841 -1.957,-4.5 -4.5,-4.5"</string>
     <string name="rectangle200">"M 0,0 l 200,0 l 0, 200 l -200, 0 z"</string>
-</resources>
\ No newline at end of file
+    <string name="triangle100">"M 100, 0 l 0, 100, -100, 0 z"</string>
+</resources>
diff --git a/graphics/drawable/teststatic/src/android/support/test/vectordrawable/TestActivity.java b/graphics/drawable/teststatic/src/android/support/test/vectordrawable/TestActivity.java
index 8bb766e5..c92ff47 100644
--- a/graphics/drawable/teststatic/src/android/support/test/vectordrawable/TestActivity.java
+++ b/graphics/drawable/teststatic/src/android/support/test/vectordrawable/TestActivity.java
@@ -34,6 +34,10 @@
 
     private static final String LOGCAT = "VectorDrawable1";
     protected int[] icon = {
+            R.drawable.vector_drawable_scale0,
+            R.drawable.vector_drawable_scale1,
+            R.drawable.vector_drawable_scale2,
+            R.drawable.vector_drawable_scale3,
             R.drawable.vector_drawable01,
             R.drawable.vector_drawable02,
             R.drawable.vector_drawable03,
@@ -64,6 +68,8 @@
             R.drawable.vector_drawable28,
             R.drawable.vector_drawable29,
             R.drawable.vector_drawable30,
+            R.drawable.vector_test01,
+            R.drawable.vector_test02
     };
 
     private static final int EXTRA_TESTS = 2;
@@ -85,8 +91,10 @@
         time =  android.os.SystemClock.currentThreadTimeMillis()-time;
 
         // Testing Tint on one particular case.
-        d[3].setTint(0x8000FF00);
-        d[3].setTintMode(Mode.MULTIPLY);
+        if (d.length > 3) {
+            d[3].setTint(0x8000FF00);
+            d[3].setTintMode(Mode.MULTIPLY);
+        }
 
         // Testing Constant State like operation by creating the first 2 icons
         // from the 3rd one's constant state.
diff --git a/graphics/drawable/util/src/android/support/graphics/drawable/AndroidResources.java b/graphics/drawable/util/src/android/support/graphics/drawable/AndroidResources.java
new file mode 100644
index 0000000..e6b2e14
--- /dev/null
+++ b/graphics/drawable/util/src/android/support/graphics/drawable/AndroidResources.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package android.support.graphics.drawable;
+
+public class AndroidResources {
+
+    // Resources ID generated in the latest R.java for framework.
+    static final int[] styleable_VectorDrawableTypeArray = {
+            android.R.attr.name, android.R.attr.tint, android.R.attr.height,
+            android.R.attr.width, android.R.attr.alpha, android.R.attr.autoMirrored,
+            android.R.attr.mode, android.R.attr.viewportWidth, android.R.attr.viewportHeight
+    };
+    static final int styleable_VectorDrawable_alpha = 4;
+    static final int styleable_VectorDrawable_autoMirrored = 5;
+    static final int styleable_VectorDrawable_height = 2;
+    static final int styleable_VectorDrawable_name = 0;
+    static final int styleable_VectorDrawable_tint = 1;
+    static final int styleable_VectorDrawable_Mode = 6;
+    static final int styleable_VectorDrawable_viewportHeight = 8;
+    static final int styleable_VectorDrawable_viewportWidth = 7;
+    static final int styleable_VectorDrawable_width = 3;
+    static final int[] styleable_VectorDrawableGroup = {
+            android.R.attr.name, android.R.attr.pivotX, android.R.attr.pivotY,
+            android.R.attr.scaleX, android.R.attr.scaleY, android.R.attr.rotation,
+            android.R.attr.translateX, android.R.attr.translateY
+    };
+    static final int styleable_VectorDrawableGroup_name = 0;
+    static final int styleable_VectorDrawableGroup_pivotX = 1;
+    static final int styleable_VectorDrawableGroup_pivotY = 2;
+    static final int styleable_VectorDrawableGroup_rotation = 5;
+    static final int styleable_VectorDrawableGroup_scaleX = 3;
+    static final int styleable_VectorDrawableGroup_scaleY = 4;
+    static final int styleable_VectorDrawableGroup_translateX = 6;
+    static final int styleable_VectorDrawableGroup_translateY = 7;
+    static final int[] styleable_VectorDrawablePath = {
+            android.R.attr.name, android.R.attr.fillColor, android.R.attr.pathData,
+            android.R.attr.strokeColor, android.R.attr.strokeWidth, android.R.attr.trimPathStart,
+            android.R.attr.trimPathEnd, android.R.attr.trimPathOffset, android.R.attr.strokeLineCap,
+            android.R.attr.strokeLineJoin, android.R.attr.strokeMiterLimit,
+            android.R.attr.strokeAlpha, android.R.attr.fillAlpha
+    };
+    static final int styleable_VectorDrawablePath_fillAlpha = 12;
+    static final int styleable_VectorDrawablePath_fillColor = 1;
+    static final int styleable_VectorDrawablePath_name = 0;
+    static final int styleable_VectorDrawablePath_pathData = 2;
+    static final int styleable_VectorDrawablePath_strokeAlpha = 11;
+    static final int styleable_VectorDrawablePath_strokeColor = 3;
+    static final int styleable_VectorDrawablePath_strokeLineCap = 8;
+    static final int styleable_VectorDrawablePath_strokeLineJoin = 9;
+    static final int styleable_VectorDrawablePath_strokeMiterLimit = 10;
+    static final int styleable_VectorDrawablePath_strokeWidth = 4;
+    static final int styleable_VectorDrawablePath_trimPathEnd = 6;
+    static final int styleable_VectorDrawablePath_trimPathOffset = 7;
+    static final int styleable_VectorDrawablePath_trimPathStart = 5;
+    static final int[] styleable_VectorDrawableClipPath = {
+            android.R.attr.name, android.R.attr.pathData
+    };
+    static final int styleable_VectorDrawableClipPath_name = 0;
+    static final int styleable_VectorDrawableClipPath_pathData = 1;
+
+    static final int[] styleable_AnimatedVectorDrawable = {
+            android.R.attr.drawable
+    };
+    static final int styleable_AnimatedVectorDrawable_drawable = 0;
+    static final int[] styleable_AnimatedVectorDrawableTarget = {
+            android.R.attr.name, android.R.attr.animation
+    };
+    static final int styleable_AnimatedVectorDrawableTarget_animation = 1;
+    static final int styleable_AnimatedVectorDrawableTarget_name = 0;
+}
diff --git a/graphics/drawable/util/src/android/support/graphics/drawable/TypedArrayUtils.java b/graphics/drawable/util/src/android/support/graphics/drawable/TypedArrayUtils.java
new file mode 100644
index 0000000..161eae6
--- /dev/null
+++ b/graphics/drawable/util/src/android/support/graphics/drawable/TypedArrayUtils.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package android.support.graphics.drawable;
+
+import android.content.res.TypedArray;
+import org.xmlpull.v1.XmlPullParser;
+
+
+public class TypedArrayUtils {
+    private static final String NAMESPACE = "http://schemas.android.com/apk/res/android";
+
+    public static boolean hasAttribute(XmlPullParser parser, String attrName) {
+        return parser.getAttributeValue(NAMESPACE, attrName) != null;
+    }
+
+    public static float getNamedFloat(TypedArray a, XmlPullParser parser, String attrName,
+                                      int resId, float defaultValue) {
+        final boolean hasAttr = hasAttribute(parser, attrName);
+        if (!hasAttr) {
+            return defaultValue;
+        } else {
+            return a.getFloat(resId, defaultValue);
+        }
+    }
+
+    public static boolean getNamedBoolean(TypedArray a, XmlPullParser parser, String attrName,
+                                      int resId, boolean defaultValue) {
+        final boolean hasAttr = hasAttribute(parser, attrName);
+        if (!hasAttr) {
+            return defaultValue;
+        } else {
+            return a.getBoolean(resId, defaultValue);
+        }
+    }
+
+    public static int getNamedInt(TypedArray a, XmlPullParser parser, String attrName,
+                                          int resId, int defaultValue) {
+        final boolean hasAttr = hasAttribute(parser, attrName);
+        if (!hasAttr) {
+            return defaultValue;
+        } else {
+            return a.getInt(resId, defaultValue);
+        }
+    }
+
+    public static int getNamedColor(TypedArray a, XmlPullParser parser, String attrName,
+                                        int resId, int defaultValue) {
+        final boolean hasAttr = hasAttribute(parser, attrName);
+        if (!hasAttr) {
+            return defaultValue;
+        } else {
+            return a.getColor(resId, defaultValue);
+        }
+    }
+}
diff --git a/v17/leanback/.classpath b/v17/leanback/.classpath
index 7bc01d9..f568681 100644
--- a/v17/leanback/.classpath
+++ b/v17/leanback/.classpath
@@ -1,9 +1,14 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-	<classpathentry kind="src" path="src"/>
-	<classpathentry kind="src" path="gen"/>
 	<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
 	<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
 	<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="src" path="api21"/>
+	<classpathentry kind="src" path="api23"/>
+	<classpathentry kind="src" path="jbmr2"/>
+	<classpathentry kind="src" path="common"/>
+	<classpathentry kind="src" path="kitkat"/>
+	<classpathentry kind="src" path="gen"/>
 	<classpathentry kind="output" path="bin/classes"/>
 </classpath>
diff --git a/v17/leanback/api/current.txt b/v17/leanback/api/current.txt
index 550e838..a4decd8 100644
--- a/v17/leanback/api/current.txt
+++ b/v17/leanback/api/current.txt
@@ -216,7 +216,6 @@
     method public java.util.List<android.support.v17.leanback.widget.GuidedAction> getActions();
     method public android.view.View getButtonActionItemView(int);
     method public java.util.List<android.support.v17.leanback.widget.GuidedAction> getButtonActions();
-    method protected int getContainerIdForBackground();
     method public static android.support.v17.leanback.app.GuidedStepFragment getCurrentGuidedStepFragment(android.app.FragmentManager);
     method public android.support.v17.leanback.widget.GuidanceStylist getGuidanceStylist();
     method public android.support.v17.leanback.widget.GuidedActionsStylist getGuidedActionsStylist();
@@ -232,6 +231,7 @@
     method protected void onAddSharedElementTransition(android.app.FragmentTransaction, android.support.v17.leanback.app.GuidedStepFragment);
     method public void onCreateActions(java.util.List<android.support.v17.leanback.widget.GuidedAction>, android.os.Bundle);
     method public android.support.v17.leanback.widget.GuidedActionsStylist onCreateActionsStylist();
+    method public android.view.View onCreateBackgroundView(android.view.LayoutInflater, android.view.ViewGroup, android.os.Bundle);
     method public void onCreateButtonActions(java.util.List<android.support.v17.leanback.widget.GuidedAction>, android.os.Bundle);
     method public android.support.v17.leanback.widget.GuidedActionsStylist onCreateButtonActionsStylist();
     method public android.support.v17.leanback.widget.GuidanceStylist.Guidance onCreateGuidance(android.os.Bundle);
@@ -240,7 +240,6 @@
     method public void onGuidedActionEdited(android.support.v17.leanback.widget.GuidedAction);
     method public long onGuidedActionEditedAndProceed(android.support.v17.leanback.widget.GuidedAction);
     method public void onGuidedActionFocused(android.support.v17.leanback.widget.GuidedAction);
-    method protected android.app.Fragment onProvideBackgroundFragment();
     method protected void onProvideFragmentTransitions();
     method public int onProvideTheme();
     method public void popBackStackToGuidedStepFragment(java.lang.Class, int);
@@ -251,13 +250,8 @@
     method public void setUiStyle(int);
     field public static final java.lang.String EXTRA_UI_STYLE = "uiStyle";
     field public static final int UI_STYLE_ACTIVITY_ROOT = 2; // 0x2
-    field public static final int UI_STYLE_DEFAULT = 0; // 0x0
     field public static final int UI_STYLE_ENTRANCE = 1; // 0x1
-  }
-
-  public static class GuidedStepFragment.GuidedStepBackgroundFragment extends android.app.Fragment {
-    ctor public GuidedStepFragment.GuidedStepBackgroundFragment();
-    method protected void onProvideFragmentTransitions();
+    field public static final int UI_STYLE_REPLACE = 0; // 0x0
   }
 
   public class GuidedStepSupportFragment extends android.support.v4.app.Fragment {
@@ -276,7 +270,6 @@
     method public java.util.List<android.support.v17.leanback.widget.GuidedAction> getActions();
     method public android.view.View getButtonActionItemView(int);
     method public java.util.List<android.support.v17.leanback.widget.GuidedAction> getButtonActions();
-    method protected int getContainerIdForBackground();
     method public static android.support.v17.leanback.app.GuidedStepSupportFragment getCurrentGuidedStepSupportFragment(android.support.v4.app.FragmentManager);
     method public android.support.v17.leanback.widget.GuidanceStylist getGuidanceStylist();
     method public android.support.v17.leanback.widget.GuidedActionsStylist getGuidedActionsStylist();
@@ -292,6 +285,7 @@
     method protected void onAddSharedElementTransition(android.support.v4.app.FragmentTransaction, android.support.v17.leanback.app.GuidedStepSupportFragment);
     method public void onCreateActions(java.util.List<android.support.v17.leanback.widget.GuidedAction>, android.os.Bundle);
     method public android.support.v17.leanback.widget.GuidedActionsStylist onCreateActionsStylist();
+    method public android.view.View onCreateBackgroundView(android.view.LayoutInflater, android.view.ViewGroup, android.os.Bundle);
     method public void onCreateButtonActions(java.util.List<android.support.v17.leanback.widget.GuidedAction>, android.os.Bundle);
     method public android.support.v17.leanback.widget.GuidedActionsStylist onCreateButtonActionsStylist();
     method public android.support.v17.leanback.widget.GuidanceStylist.Guidance onCreateGuidance(android.os.Bundle);
@@ -300,7 +294,6 @@
     method public void onGuidedActionEdited(android.support.v17.leanback.widget.GuidedAction);
     method public long onGuidedActionEditedAndProceed(android.support.v17.leanback.widget.GuidedAction);
     method public void onGuidedActionFocused(android.support.v17.leanback.widget.GuidedAction);
-    method protected android.support.v4.app.Fragment onProvideBackgroundSupportFragment();
     method protected void onProvideFragmentTransitions();
     method public int onProvideTheme();
     method public void popBackStackToGuidedStepSupportFragment(java.lang.Class, int);
@@ -311,13 +304,8 @@
     method public void setUiStyle(int);
     field public static final java.lang.String EXTRA_UI_STYLE = "uiStyle";
     field public static final int UI_STYLE_ACTIVITY_ROOT = 2; // 0x2
-    field public static final int UI_STYLE_DEFAULT = 0; // 0x0
     field public static final int UI_STYLE_ENTRANCE = 1; // 0x1
-  }
-
-  public static class GuidedStepSupportFragment.GuidedStepBackgroundSupportFragment extends android.support.v4.app.Fragment {
-    ctor public GuidedStepSupportFragment.GuidedStepBackgroundSupportFragment();
-    method protected void onProvideFragmentTransitions();
+    field public static final int UI_STYLE_REPLACE = 0; // 0x0
   }
 
   public class HeadersFragment extends android.support.v17.leanback.app.BaseRowFragment {
@@ -1040,6 +1028,7 @@
     field public static final long ACTION_ID_NO = -9L; // 0xfffffffffffffff7L
     field public static final long ACTION_ID_OK = -4L; // 0xfffffffffffffffcL
     field public static final long ACTION_ID_YES = -8L; // 0xfffffffffffffff8L
+    field public static final int CHECKBOX_CHECK_SET_ID = -1; // 0xffffffff
     field public static final int DEFAULT_CHECK_SET_ID = 1; // 0x1
     field public static final int NO_CHECK_SET = 0; // 0x0
   }
@@ -1093,6 +1082,8 @@
     method public void onAnimateItemFocused(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, boolean);
     method public void onAnimateItemPressed(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, boolean);
     method public void onAnimateItemPressedCancelled(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder);
+    method public void onBindCheckMarkView(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, android.support.v17.leanback.widget.GuidedAction);
+    method public void onBindChevronView(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, android.support.v17.leanback.widget.GuidedAction);
     method public void onBindViewHolder(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, android.support.v17.leanback.widget.GuidedAction);
     method public android.view.View onCreateView(android.view.LayoutInflater, android.view.ViewGroup);
     method public android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder onCreateViewHolder(android.view.ViewGroup);
@@ -1106,6 +1097,7 @@
     method public int onProvideLayoutId();
     method public void setAsButtonActions();
     method public void setEditingMode(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, android.support.v17.leanback.widget.GuidedAction, boolean);
+    method protected void setupImeOptions(android.support.v17.leanback.widget.GuidedActionsStylist.ViewHolder, android.support.v17.leanback.widget.GuidedAction);
     field public static final int VIEW_TYPE_DEFAULT = 0; // 0x0
   }
 
diff --git a/v17/leanback/project.properties b/v17/leanback/project.properties
index 91d2b02..b2ef7dc 100644
--- a/v17/leanback/project.properties
+++ b/v17/leanback/project.properties
@@ -11,5 +11,5 @@
 #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
 
 # Project target.
-target=android-19
+target=android-23
 android.library=true
diff --git a/v17/leanback/res/animator/lb_guidedactions_item_unchecked.xml b/v17/leanback/res/animator/lb_guidedactions_item_unchecked.xml
deleted file mode 100644
index 86525c8..0000000
--- a/v17/leanback/res/animator/lb_guidedactions_item_unchecked.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
-    android:duration="@integer/lb_guidedactions_item_animation_duration"
-    android:propertyName="alpha"
-    android:valueFrom="1.0"
-    android:valueTo="0.0"
-    android:valueType="floatType" />
diff --git a/v17/leanback/res/drawable/lb_guidedactions_item_checkmark.xml b/v17/leanback/res/drawable/lb_guidedactions_item_checkmark.xml
deleted file mode 100644
index ec7903b..0000000
--- a/v17/leanback/res/drawable/lb_guidedactions_item_checkmark.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
-    android:shape="oval" >
-
-    <size
-        android:height="@dimen/lb_guidedactions_item_checkmark_diameter"
-        android:width="@dimen/lb_guidedactions_item_checkmark_diameter" />
-
-    <solid android:color="@color/lb_tv_white" />
-
-</shape>
diff --git a/v17/leanback/res/layout/lb_guidedactions_item.xml b/v17/leanback/res/layout/lb_guidedactions_item.xml
index 8f5fcb7..831c355 100644
--- a/v17/leanback/res/layout/lb_guidedactions_item.xml
+++ b/v17/leanback/res/layout/lb_guidedactions_item.xml
@@ -20,7 +20,7 @@
     xmlns:tools="http://schemas.android.com/tools"
     style="?attr/guidedActionItemContainerStyle" >
 
-    <ImageView
+    <android.support.v17.leanback.widget.CheckableImageView
         android:id="@+id/guidedactions_item_checkmark"
         style="?attr/guidedActionItemCheckmarkStyle"
         tools:ignore="ContentDescription" />
diff --git a/v17/leanback/res/layout/lb_guidedstep_background.xml b/v17/leanback/res/layout/lb_guidedstep_background.xml
index 66b68c4..08ea47d 100644
--- a/v17/leanback/res/layout/lb_guidedstep_background.xml
+++ b/v17/leanback/res/layout/lb_guidedstep_background.xml
@@ -17,6 +17,7 @@
 <android.support.v17.leanback.widget.NonOverlappingView
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/guidedstep_background"
+    android:transitionName="guidedstep_background"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:background="?attr/guidedStepBackground" />
diff --git a/v17/leanback/res/layout/lb_guidedstep_fragment.xml b/v17/leanback/res/layout/lb_guidedstep_fragment.xml
index 31e2fee..ca6efc4 100644
--- a/v17/leanback/res/layout/lb_guidedstep_fragment.xml
+++ b/v17/leanback/res/layout/lb_guidedstep_fragment.xml
@@ -15,51 +15,57 @@
      limitations under the License.
 -->
 <!-- Layout for the frame of a 2 pane actions fragment. -->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/content_frame"
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/guidedstep_root"
     android:orientation="horizontal"
     android:layout_width="match_parent"
     android:layout_height="match_parent" >
-
-    <android.support.v17.leanback.widget.NonOverlappingFrameLayout
-        android:id="@+id/content_fragment"
-        android:layout_toStartOf="@+id/action_fragment"
-        android:layout_width="0dp"
-        android:layout_weight="1"
-        android:layout_height="match_parent"
-        android:layout_alignParentStart="true" />
-
-    <android.support.v17.leanback.widget.NonOverlappingFrameLayout
-        android:id="@+id/action_fragment_root"
-        android:transitionName="action_fragment_root"
-        android:transitionGroup="false"
+    <LinearLayout
+        android:id="@+id/content_frame"
         android:orientation="horizontal"
-        android:clipToPadding="false"
-        android:clipChildren="false"
-        android:paddingStart="@dimen/lb_guidedactions_section_shadow_width"
-        android:layout_width="0dp"
-        android:layout_weight="?attr/guidedActionContentWidthWeight"
-        android:layout_height="match_parent"
-        android:layout_alignParentEnd="true">
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" >
 
-        <android.support.v17.leanback.widget.NonOverlappingView
-            android:id="@+id/action_fragment_background"
-            android:transitionName="action_fragment_background"
-            android:orientation="horizontal"
-            android:outlineProvider="paddedBounds"
-            android:layout_width="match_parent"
+        <android.support.v17.leanback.widget.NonOverlappingFrameLayout
+            android:id="@+id/content_fragment"
+            android:layout_toStartOf="@+id/action_fragment"
+            android:layout_width="0dp"
+            android:layout_weight="1"
             android:layout_height="match_parent"
-            android:background="?attr/guidedActionsBackground"
-            android:elevation="?attr/guidedActionsElevation" />
+            android:layout_alignParentStart="true" />
 
-        <android.support.v17.leanback.widget.NonOverlappingLinearLayout
-            android:id="@+id/action_fragment"
-            android:transitionName="action_fragment"
+        <android.support.v17.leanback.widget.NonOverlappingFrameLayout
+            android:id="@+id/action_fragment_root"
+            android:transitionName="action_fragment_root"
             android:transitionGroup="false"
             android:orientation="horizontal"
-            android:layout_width="match_parent"
+            android:clipToPadding="false"
+            android:clipChildren="false"
+            android:paddingStart="@dimen/lb_guidedactions_section_shadow_width"
+            android:layout_width="0dp"
+            android:layout_weight="?attr/guidedActionContentWidthWeight"
             android:layout_height="match_parent"
-            android:elevation="@dimen/lb_guidedactions_elevation" />
-    </android.support.v17.leanback.widget.NonOverlappingFrameLayout>
+            android:layout_alignParentEnd="true">
 
-</LinearLayout>
\ No newline at end of file
+            <android.support.v17.leanback.widget.NonOverlappingView
+                android:id="@+id/action_fragment_background"
+                android:transitionName="action_fragment_background"
+                android:orientation="horizontal"
+                android:outlineProvider="paddedBounds"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:background="?attr/guidedActionsBackground"
+                android:elevation="?attr/guidedActionsElevation" />
+
+            <android.support.v17.leanback.widget.NonOverlappingLinearLayout
+                android:id="@+id/action_fragment"
+                android:transitionName="action_fragment"
+                android:transitionGroup="false"
+                android:orientation="horizontal"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:elevation="@dimen/lb_guidedactions_elevation" />
+        </android.support.v17.leanback.widget.NonOverlappingFrameLayout>
+
+    </LinearLayout>
+</FrameLayout>
\ No newline at end of file
diff --git a/v17/leanback/res/transition-v21/lb_guidedstep_activity_enter.xml b/v17/leanback/res/transition-v21/lb_guidedstep_activity_enter.xml
index 7c4dfc3..ef14957 100644
--- a/v17/leanback/res/transition-v21/lb_guidedstep_activity_enter.xml
+++ b/v17/leanback/res/transition-v21/lb_guidedstep_activity_enter.xml
@@ -16,6 +16,13 @@
 -->
 
 <transitionSet xmlns:android="http://schemas.android.com/apk/res/android" >
+  <fade
+      android:interpolator="@android:interpolator/fast_out_linear_in"
+      android:duration="350">
+        <targets>
+            <target android:targetId="@id/guidedstep_background" />
+        </targets>
+  </fade>
   <slide
       android:interpolator="@android:interpolator/fast_out_linear_in"
       android:duration="350"
diff --git a/v17/leanback/res/values/attrs.xml b/v17/leanback/res/values/attrs.xml
index 9ce1094..cae72e5 100644
--- a/v17/leanback/res/values/attrs.xml
+++ b/v17/leanback/res/values/attrs.xml
@@ -398,14 +398,6 @@
         <attr name="guidedActionItemChevronStyle" format="reference" />
 
         <!-- Theme attribute for the animation used in a GuidedActionsPresenter when an action
-             is checked. Default is {@link
-             android.support.v17.leanback.R.animator#lb_guidedactions_item_checked}. -->
-        <attr name="guidedActionCheckedAnimation" format="reference" />
-        <!-- Theme attribute for the animation used in a GuidedActionsPresenter when an action
-             is unchecked. Default is {@link
-             android.support.v17.leanback.R.animator#lb_guidedactions_item_unchecked}. -->
-        <attr name="guidedActionUncheckedAnimation" format="reference" />
-        <!-- Theme attribute for the animation used in a GuidedActionsPresenter when an action
              is pressed. Default is {@link
              android.support.v17.leanback.R.animator#lb_guidedactions_item_pressed}. -->
         <attr name="guidedActionPressedAnimation" format="reference" />
diff --git a/v17/leanback/res/values/dimens.xml b/v17/leanback/res/values/dimens.xml
index f5f42f2..053c7e0 100644
--- a/v17/leanback/res/values/dimens.xml
+++ b/v17/leanback/res/values/dimens.xml
@@ -248,10 +248,10 @@
     <dimen name="lb_guidedactions_item_text_width">248dp</dimen>
     <dimen name="lb_guidedactions_item_text_width_no_icon">284dp</dimen>
     <dimen name="lb_guidedactions_item_min_height">64dp</dimen>
-    <dimen name="lb_guidedactions_item_start_padding">20dp</dimen>
+    <dimen name="lb_guidedactions_item_start_padding">28dp</dimen>
     <dimen name="lb_guidedactions_item_end_padding">28dp</dimen>
     <dimen name="lb_guidedactions_item_delimiter_padding">4dp</dimen>
-    <dimen name="lb_guidedactions_item_checkmark_diameter">8dp</dimen>
+    <dimen name="lb_guidedactions_item_checkmark_diameter">16dp</dimen>
     <dimen name="lb_guidedactions_item_icon_width">32dp</dimen>
     <dimen name="lb_guidedactions_item_icon_height">32dp</dimen>
     <dimen name="lb_guidedactions_item_title_font_size">18sp</dimen>
diff --git a/v17/leanback/res/values/styles.xml b/v17/leanback/res/values/styles.xml
index 0e5b0b6..094732d 100644
--- a/v17/leanback/res/values/styles.xml
+++ b/v17/leanback/res/values/styles.xml
@@ -456,9 +456,8 @@
         <item name="android:layout_height">@dimen/lb_guidedactions_item_checkmark_diameter</item>
         <item name="android:layout_gravity">center</item>
         <item name="android:layout_marginEnd">@dimen/lb_guidedactions_item_delimiter_padding</item>
-        <item name="android:scaleType">center</item>
-        <item name="android:src">@drawable/lb_guidedactions_item_checkmark</item>
-        <item name="android:visibility">invisible</item>
+        <item name="android:scaleType">centerInside</item>
+        <item name="android:visibility">gone</item>
     </style>
 
     <!-- Style for an action's icon in a GuidedActionsStylist's default item layout. -->
diff --git a/v17/leanback/res/values/themes.xml b/v17/leanback/res/values/themes.xml
index d00bc36..056ed1f 100644
--- a/v17/leanback/res/values/themes.xml
+++ b/v17/leanback/res/values/themes.xml
@@ -15,7 +15,7 @@
      limitations under the License.
 -->
 
-<resources>
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
 
     <!-- LeanbackBase may be overridden for specific api levels -->
     <style name="Theme.LeanbackBase" parent="android:Theme.Holo.NoActionBar">
@@ -118,7 +118,8 @@
 
         <item name="android:windowEnterTransition">@transition/lb_guidedstep_activity_enter</item>
 
-        <item name="guidedStepBackground">?android:attr/windowBackground</item>
+        <item name="guidedStepBackground">?android:attr/colorBackground</item>
+        <item name="android:windowBackground">@null</item>
 
         <item name="guidedStepImeAppearingAnimation">@animator/lb_guidedstep_slide_up</item>
         <item name="guidedStepImeDisappearingAnimation">@animator/lb_guidedstep_slide_down</item>
@@ -145,8 +146,6 @@
         <item name="guidedActionItemDescriptionStyle">@style/Widget.Leanback.GuidedActionItemDescriptionStyle</item>
         <item name="guidedActionItemChevronStyle">@style/Widget.Leanback.GuidedActionItemChevronStyle</item>
 
-        <item name="guidedActionCheckedAnimation">@animator/lb_guidedactions_item_checked</item>
-        <item name="guidedActionUncheckedAnimation">@animator/lb_guidedactions_item_unchecked</item>
         <item name="guidedActionPressedAnimation">@animator/lb_guidedactions_item_pressed</item>
         <item name="guidedActionUnpressedAnimation">@animator/lb_guidedactions_item_unpressed</item>
         <item name="guidedActionEnabledChevronAlpha">@string/lb_guidedactions_item_enabled_chevron_alpha</item>
diff --git a/v17/leanback/src/android/support/v17/leanback/app/GuidedActionAdapter.java b/v17/leanback/src/android/support/v17/leanback/app/GuidedActionAdapter.java
index 639ee7f..142e971 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/GuidedActionAdapter.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/GuidedActionAdapter.java
@@ -98,9 +98,9 @@
     /**
      * View holder containing a {@link GuidedAction}.
      */
-    private static class ActionViewHolder extends ViewHolder {
+    static class ActionViewHolder extends ViewHolder {
 
-        private final GuidedActionsStylist.ViewHolder mStylistViewHolder;
+        final GuidedActionsStylist.ViewHolder mStylistViewHolder;
         private GuidedAction mAction;
 
         /**
@@ -128,45 +128,48 @@
         }
     }
 
-    private RecyclerView mRecyclerView;
     private final ActionOnKeyListener mActionOnKeyListener;
     private final ActionOnFocusListener mActionOnFocusListener;
     private final ActionEditListener mActionEditListener;
     private final List<GuidedAction> mActions;
     private ClickListener mClickListener;
-    private GuidedActionsStylist mStylist;
+    private final GuidedActionsStylist mStylist;
     private final View.OnClickListener mOnClickListener = new View.OnClickListener() {
         @Override
         public void onClick(View v) {
-            if (v != null && v.getWindowToken() != null && mClickListener != null) {
-                ActionViewHolder avh = (ActionViewHolder)mRecyclerView.getChildViewHolder(v);
+            if (v != null && v.getWindowToken() != null && getRecyclerView() != null) {
+                ActionViewHolder avh = (ActionViewHolder)getRecyclerView().getChildViewHolder(v);
                 GuidedAction action = avh.getAction();
-                if (action.isEnabled() && !action.infoOnly()) {
-                    mClickListener.onGuidedActionClicked(action);
+                if (action.isEditable() || action.isDescriptionEditable()) {
+                    if (DEBUG_EDIT) Log.v(TAG_EDIT, "openIme by click");
+                    mGroup.openIme(GuidedActionAdapter.this, avh);
+                } else {
+                    handleCheckedActions(avh);
+                    if (action.isEnabled() && !action.infoOnly()) {
+                        performOnActionClick(avh);
+                    }
                 }
             }
         }
     };
-    private boolean mImeOpened;
+    GuidedActionAdapterGroup mGroup;
 
     /**
      * Constructs a GuidedActionAdapter with the given list of guided actions, the given click and
      * focus listeners, and the given presenter.
      * @param actions The list of guided actions this adapter will manage.
-     * @param clickListener The click listener for items in this adapter.
      * @param focusListener The focus listener for items in this adapter.
      * @param presenter The presenter that will manage the display of items in this adapter.
      */
     public GuidedActionAdapter(List<GuidedAction> actions, ClickListener clickListener,
-            FocusListener focusListener, EditListener editListener,
-            GuidedActionsStylist presenter) {
+            FocusListener focusListener, GuidedActionsStylist presenter) {
         super();
         mActions = new ArrayList<GuidedAction>(actions);
         mClickListener = clickListener;
         mStylist = presenter;
         mActionOnKeyListener = new ActionOnKeyListener();
         mActionOnFocusListener = new ActionOnFocusListener(focusListener);
-        mActionEditListener = new ActionEditListener(editListener);
+        mActionEditListener = new ActionEditListener();
     }
 
     /**
@@ -198,6 +201,22 @@
     }
 
     /**
+     * Return index of action in array
+     * @param action Action to search index.
+     * @return Index of Action in array.
+     */
+    public int indexOf(GuidedAction action) {
+        return mActions.indexOf(action);
+    }
+
+    /**
+     * @return GuidedActionsStylist used to build the actions list UI.
+     */
+    public GuidedActionsStylist getGuidedActionsStylist() {
+        return mStylist;
+    }
+
+    /**
      * Sets the click listener for items managed by this adapter.
      * @param clickListener The click listener for this adapter.
      */
@@ -225,24 +244,12 @@
      * {@inheritDoc}
      */
     @Override
-    public void onAttachedToRecyclerView(RecyclerView recyclerView) {
-        mRecyclerView = recyclerView;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
     public int getItemViewType(int position) {
         return mStylist.getItemViewType(mActions.get(position));
     }
 
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void onDetachedFromRecyclerView(RecyclerView recyclerView) {
-        mRecyclerView = null;
+    private RecyclerView getRecyclerView() {
+        return mStylist.getActionsGridView();
     }
 
     /**
@@ -285,15 +292,6 @@
         GuidedAction action = mActions.get(position);
         avh.setAction(action);
         mStylist.onBindViewHolder(avh.mStylistViewHolder, action);
-
-        setupNextImeOptions(avh.mStylistViewHolder.getEditableTitleView());
-        setupNextImeOptions(avh.mStylistViewHolder.getEditableDescriptionView());
-    }
-
-    private void setupNextImeOptions(EditText edit) {
-        if (edit != null) {
-            edit.setImeOptions(EditorInfo.IME_ACTION_NEXT);
-        }
     }
 
     /**
@@ -304,31 +302,6 @@
         return mActions.size();
     }
 
-    private int getNextActionIndex(GuidedAction action, long nextActionId) {
-        if (nextActionId == GuidedAction.ACTION_ID_NEXT) {
-            int i, size = mActions.size();
-            for (i = 0; i < size; i++) {
-                GuidedAction a = mActions.get(i);
-                if (mActions.get(i) == action) {
-                    break;
-                }
-            }
-            do {
-                i++;
-            } while (i < size && !mActions.get(i).isFocusable());
-            return (i == size) ? -1 : i;
-        } else {
-            int i, size = mActions.size();
-            for (i = 0; i < size; i++) {
-                GuidedAction a = mActions.get(i);
-                if (mActions.get(i).getId() == nextActionId) {
-                    break;
-                }
-            }
-            return (i == size) ? -1 : i;
-        }
-    }
-
     private class ActionOnFocusListener implements View.OnFocusChangeListener {
 
         private FocusListener mFocusListener;
@@ -343,8 +316,8 @@
         }
 
         public void unFocus() {
-            if (mSelectedView != null) {
-                ViewHolder vh = mRecyclerView.getChildViewHolder(mSelectedView);
+            if (mSelectedView != null && getRecyclerView() != null) {
+                ViewHolder vh = getRecyclerView().getChildViewHolder(mSelectedView);
                 if (vh != null) {
                     ActionViewHolder avh = (ActionViewHolder)vh;
                     mStylist.onAnimateItemFocused(avh.mStylistViewHolder, false);
@@ -357,7 +330,10 @@
 
         @Override
         public void onFocusChange(View v, boolean hasFocus) {
-            ActionViewHolder avh = (ActionViewHolder)mRecyclerView.getChildViewHolder(v);
+            if (getRecyclerView() == null) {
+                return;
+            }
+            ActionViewHolder avh = (ActionViewHolder) getRecyclerView().getChildViewHolder(v);
             if (hasFocus) {
                 mSelectedView = v;
                 if (mFocusListener != null) {
@@ -375,10 +351,61 @@
         }
     }
 
-    public void openIme(ActionViewHolder avh) {
-        mStylist.setEditingMode(avh.mStylistViewHolder,
-                avh.getAction(), true);
-        mActionEditListener.openIme(avh);
+    public ActionViewHolder findSubChildViewHolder(View v) {
+        // Needed because RecyclerView.getChildViewHolder does not traverse the hierarchy
+        if (getRecyclerView() == null) {
+            return null;
+        }
+        ActionViewHolder result = null;
+        ViewParent parent = v.getParent();
+        while (parent != getRecyclerView() && parent != null && v != null) {
+            v = (View)parent;
+            parent = parent.getParent();
+        }
+        if (parent != null && v != null) {
+            result = (ActionViewHolder)getRecyclerView().getChildViewHolder(v);
+        }
+        return result;
+    }
+
+    public void handleCheckedActions(ActionViewHolder avh) {
+        GuidedAction action = avh.getAction();
+        int actionCheckSetId = action.getCheckSetId();
+        if (getRecyclerView() != null && actionCheckSetId != GuidedAction.NO_CHECK_SET) {
+            // Find any actions that are checked and are in the same group
+            // as the selected action. Fade their checkmarks out.
+            if (actionCheckSetId != GuidedAction.CHECKBOX_CHECK_SET_ID) {
+                for (int i = 0, size = mActions.size(); i < size; i++) {
+                    GuidedAction a = mActions.get(i);
+                    if (a != action && a.getCheckSetId() == actionCheckSetId && a.isChecked()) {
+                        a.setChecked(false);
+                        ViewHolder vh = getRecyclerView().findViewHolderForPosition(i);
+                        if (vh != null) {
+                            GuidedActionsStylist.ViewHolder subViewHolder =
+                                    ((ActionViewHolder)vh).mStylistViewHolder;
+                            mStylist.onAnimateItemChecked(subViewHolder, false);
+                        }
+                    }
+                }
+            }
+
+            // If we we'ren't already checked, fade our checkmark in.
+            if (!action.isChecked()) {
+                action.setChecked(true);
+                mStylist.onAnimateItemChecked(avh.mStylistViewHolder, true);
+            } else {
+                if (actionCheckSetId == GuidedAction.CHECKBOX_CHECK_SET_ID) {
+                    action.setChecked(false);
+                    mStylist.onAnimateItemChecked(avh.mStylistViewHolder, false);
+                }
+            }
+        }
+    }
+
+    public void performOnActionClick(ActionViewHolder avh) {
+        if (mClickListener != null) {
+            mClickListener.onGuidedActionClicked(avh.getAction());
+        }
     }
 
     private class ActionOnKeyListener implements View.OnKeyListener {
@@ -398,7 +425,7 @@
          */
         @Override
         public boolean onKey(View v, int keyCode, KeyEvent event) {
-            if (v == null || event == null) {
+            if (v == null || event == null || getRecyclerView() == null) {
                 return false;
             }
             boolean handled = false;
@@ -409,7 +436,8 @@
                 case KeyEvent.KEYCODE_BUTTON_Y:
                 case KeyEvent.KEYCODE_ENTER:
 
-                    ActionViewHolder avh = (ActionViewHolder)mRecyclerView.getChildViewHolder(v);
+                    ActionViewHolder avh = (ActionViewHolder) getRecyclerView()
+                            .getChildViewHolder(v);
                     GuidedAction action = avh.getAction();
 
                     if (!action.isEnabled() || action.infoOnly()) {
@@ -431,7 +459,6 @@
                                 mStylist.onAnimateItemPressed(avh.mStylistViewHolder,
                                         mKeyPressed);
                             }
-                            handled = true;
                             break;
                         case KeyEvent.ACTION_UP:
                             if (DEBUG) {
@@ -443,14 +470,6 @@
                                 mKeyPressed = false;
                                 mStylist.onAnimateItemPressed(avh.mStylistViewHolder, mKeyPressed);
                             }
-                            if (action.isEditable() || action.isDescriptionEditable()) {
-                                if (DEBUG_EDIT) Log.v(TAG_EDIT, "openIme click");
-                                openIme(avh);
-                            } else {
-                                handleCheckedActions(avh, action);
-                                mClickListener.onGuidedActionClicked(action);
-                            }
-                            handled = true;
                             break;
                         default:
                             break;
@@ -462,175 +481,40 @@
             return handled;
         }
 
-        private void handleCheckedActions(ActionViewHolder avh, GuidedAction action) {
-            int actionCheckSetId = action.getCheckSetId();
-            if (actionCheckSetId != GuidedAction.NO_CHECK_SET) {
-                // Find any actions that are checked and are in the same group
-                // as the selected action. Fade their checkmarks out.
-                for (int i = 0, size = mActions.size(); i < size; i++) {
-                    GuidedAction a = mActions.get(i);
-                    if (a != action && a.getCheckSetId() == actionCheckSetId && a.isChecked()) {
-                        a.setChecked(false);
-                        ViewHolder vh = mRecyclerView.findViewHolderForPosition(i);
-                        if (vh != null) {
-                            GuidedActionsStylist.ViewHolder subViewHolder =
-                                    ((ActionViewHolder)vh).mStylistViewHolder;
-                            mStylist.onAnimateItemChecked(subViewHolder, false);
-                        }
-                    }
-                }
-
-                // If we we'ren't already checked, fade our checkmark in.
-                if (!action.isChecked()) {
-                    action.setChecked(true);
-                    mStylist.onAnimateItemChecked(avh.mStylistViewHolder, true);
-                }
-            }
-        }
     }
 
     private class ActionEditListener implements OnEditorActionListener,
             ImeKeyMonitor.ImeKeyListener {
 
-        private EditListener mEditListener;
-
-        public ActionEditListener(EditListener listener) {
-            mEditListener = listener;
-        }
-
         @Override
         public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
             if (DEBUG_EDIT) Log.v(TAG_EDIT, "IME action: " + actionId);
             boolean handled = false;
             if (actionId == EditorInfo.IME_ACTION_NEXT ||
                 actionId == EditorInfo.IME_ACTION_DONE) {
-                fillAndGoNext(v);
+                mGroup.fillAndGoNext(GuidedActionAdapter.this, v);
                 handled = true;
             } else if (actionId == EditorInfo.IME_ACTION_NONE) {
                 if (DEBUG_EDIT) Log.v(TAG_EDIT, "closeIme escape north");
                 // Escape north handling: stay on current item, but close editor
                 handled = true;
-                fillAndStay(v);
+                mGroup.fillAndStay(GuidedActionAdapter.this, v);
             }
             return handled;
         }
 
-        private void fillAndStay(TextView v) {
-            ActionViewHolder avh = findSubChildViewHolder(v);
-            updateTextIntoAction(avh, v);
-            finishEditing(avh);
-            closeIme(v);
-            avh.mStylistViewHolder.view.requestFocus();
-        }
-
-        private void fillAndGoNext(TextView v) {
-            boolean handled = false;
-            ActionViewHolder avh = findSubChildViewHolder(v);
-            updateTextIntoAction(avh, v);
-            mClickListener.onGuidedActionClicked(avh.getAction());
-            long nextActionId = finishEditing(avh);
-            if (nextActionId != GuidedAction.ACTION_ID_CURRENT
-                    && nextActionId != avh.getAction().getId()) {
-                int next = getNextActionIndex(avh.getAction(), nextActionId);
-                if (next != -1) {
-                    ActionViewHolder vh = (ActionViewHolder) mRecyclerView
-                            .findViewHolderForPosition(next);
-                    if (vh != null) {
-                        handled = true;
-                        if (vh.getAction().isEditable() ||
-                                vh.getAction().isDescriptionEditable()) {
-                            if (DEBUG_EDIT) Log.v(TAG_EDIT, "openIme of next Action");
-                            mStylist.setEditingMode(vh.mStylistViewHolder,
-                                    vh.getAction(), true);
-                            // open Ime on next action.
-                            openIme(vh);
-                        } else {
-                            if (DEBUG_EDIT) Log.v(TAG_EDIT, "closeIme and focus to next Action");
-                            // close IME and focus to next (not editable) action
-                            closeIme(v);
-                            vh.mStylistViewHolder.view.requestFocus();
-                        }
-                    }
-                }
-            }
-            if (!handled) {
-                if (DEBUG_EDIT) Log.v(TAG_EDIT, "closeIme no next action");
-                handled = true;
-                closeIme(v);
-                avh.mStylistViewHolder.view.requestFocus();
-            }
-        }
-
-        private void updateTextIntoAction(ActionViewHolder avh, TextView v) {
-            GuidedAction action = avh.getAction();
-            if (v == avh.mStylistViewHolder.getDescriptionView()) {
-                if (action.getEditDescription() != null) {
-                    action.setEditDescription(v.getText());
-                } else {
-                    action.setDescription(v.getText());
-                }
-            } else if (v == avh.mStylistViewHolder.getTitleView()) {
-                if (action.getEditTitle() != null) {
-                    action.setEditTitle(v.getText());
-                } else {
-                    action.setTitle(v.getText());
-                }
-            }
-        }
-
         @Override
         public boolean onKeyPreIme(EditText editText, int keyCode, KeyEvent event) {
             if (DEBUG_EDIT) Log.v(TAG_EDIT, "IME key: " + keyCode);
             if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
-                fillAndStay(editText);
+                mGroup.fillAndStay(GuidedActionAdapter.this, editText);
             } else if (keyCode == KeyEvent.KEYCODE_ENTER && event.getAction() ==
                     KeyEvent.ACTION_UP) {
-                fillAndGoNext(editText);
+                mGroup.fillAndGoNext(GuidedActionAdapter.this, editText);
             }
             return false;
         }
 
-        public void openIme(ActionViewHolder avh) {
-            View v = avh.mStylistViewHolder.getEditingView();
-            InputMethodManager mgr = (InputMethodManager)
-                    v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
-            v.requestFocus();
-            mgr.showSoftInput(v, 0);
-            if (!mImeOpened) {
-                mImeOpened = true;
-                mEditListener.onImeOpen();
-            }
-        }
-
-        public long finishEditing(ActionViewHolder avh) {
-            long nextActionId = mEditListener.onGuidedActionEdited(avh.getAction());
-            mStylist.setEditingMode(avh.mStylistViewHolder, avh.getAction(), false);
-            return nextActionId;
-        }
-
-        public void closeIme(View v) {
-            if (mImeOpened) {
-                mImeOpened = false;
-                InputMethodManager mgr = (InputMethodManager)
-                        v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
-                mgr.hideSoftInputFromWindow(v.getWindowToken(), 0);
-                mEditListener.onImeClose();
-            }
-        }
-
-        private ActionViewHolder findSubChildViewHolder(View v) {
-            // Needed because RecyclerView.getChildViewHolder does not traverse the hierarchy
-            ActionViewHolder result = null;
-            ViewParent parent = v.getParent();
-            while (parent != mRecyclerView && parent != null && v != null) {
-                v = (View)parent;
-                parent = parent.getParent();
-            }
-            if (parent != null && v != null) {
-                result = (ActionViewHolder)mRecyclerView.getChildViewHolder(v);
-            }
-            return result;
-        }
     }
 
 }
diff --git a/v17/leanback/src/android/support/v17/leanback/app/GuidedActionAdapterGroup.java b/v17/leanback/src/android/support/v17/leanback/app/GuidedActionAdapterGroup.java
new file mode 100644
index 0000000..8f8951c
--- /dev/null
+++ b/v17/leanback/src/android/support/v17/leanback/app/GuidedActionAdapterGroup.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package android.support.v17.leanback.app;
+
+import android.content.Context;
+import android.support.v17.leanback.app.GuidedActionAdapter.ActionViewHolder;
+import android.support.v17.leanback.app.GuidedActionAdapter.ClickListener;
+import android.support.v17.leanback.app.GuidedActionAdapter.EditListener;
+import android.support.v17.leanback.widget.GuidedAction;
+import android.support.v17.leanback.widget.ImeKeyMonitor;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.ViewParent;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.EditText;
+import android.widget.TextView;
+import android.widget.TextView.OnEditorActionListener;
+
+import java.util.ArrayList;
+
+/**
+ * Internal implementation manages a group of GuidedActionAdapters, control the next action after
+ * editing finished, maintain the Ime open/close status.
+ */
+class GuidedActionAdapterGroup {
+
+    private static final String TAG_EDIT = "EditableAction";
+    private static final boolean DEBUG_EDIT = false;
+
+    ArrayList<GuidedActionAdapter> mAdapters = new ArrayList<GuidedActionAdapter>();
+    private boolean mImeOpened;
+    private EditListener mEditListener;
+
+    GuidedActionAdapterGroup() {
+    }
+
+    public void addAdpter(GuidedActionAdapter adapter) {
+        mAdapters.add(adapter);
+        adapter.mGroup = this;
+    }
+
+    public void setEditListener(EditListener listener) {
+        mEditListener = listener;
+    }
+
+    boolean focusToNextAction(GuidedActionAdapter adapter, GuidedAction action, long nextActionId) {
+        // for ACTION_ID_NEXT, we first find out the matching index in Actions list.
+        int index = 0;
+        if (nextActionId == GuidedAction.ACTION_ID_NEXT) {
+            index = adapter.indexOf(action);
+            if (index < 0) {
+                return false;
+            }
+            // start from next, if reach end, will go next Adapter below
+            index++;
+        }
+
+        int adapterIndex = mAdapters.indexOf(adapter);
+        do {
+            int size = adapter.getCount();
+            if (nextActionId == GuidedAction.ACTION_ID_NEXT) {
+                while (index < size && !adapter.getItem(index).isFocusable()) {
+                    index++;
+                }
+            } else {
+                while (index < size && adapter.getItem(index).getId() != nextActionId) {
+                    index++;
+                }
+            }
+            if (index < size) {
+                ActionViewHolder vh = (ActionViewHolder) adapter.getGuidedActionsStylist()
+                        .getActionsGridView().findViewHolderForPosition(index);
+                if (vh != null) {
+                    if (vh.getAction().isEditable() || vh.getAction().isDescriptionEditable()) {
+                        if (DEBUG_EDIT) Log.v(TAG_EDIT, "openIme of next Action");
+                        // open Ime on next action.
+                        openIme(adapter, vh);
+                    } else {
+                        if (DEBUG_EDIT) Log.v(TAG_EDIT, "closeIme and focus to next Action");
+                        // close IME and focus to next (not editable) action
+                        closeIme(vh.mStylistViewHolder.view);
+                        vh.mStylistViewHolder.view.requestFocus();
+                    }
+                    return true;
+                }
+                return false;
+            }
+            // search from index 0 of next Adapter
+            adapterIndex++;
+            if (adapterIndex >= mAdapters.size()) {
+                break;
+            }
+            adapter = mAdapters.get(adapterIndex);
+            index = 0;
+        } while (true);
+        return false;
+    }
+
+    public void openIme(GuidedActionAdapter adapter, ActionViewHolder avh) {
+        adapter.getGuidedActionsStylist().setEditingMode(avh.mStylistViewHolder, avh.getAction(),
+                true);
+        View v = avh.mStylistViewHolder.getEditingView();
+        if (v == null) {
+            return;
+        }
+        InputMethodManager mgr = (InputMethodManager)
+                v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+        v.requestFocus();
+        mgr.showSoftInput(v, 0);
+        if (!mImeOpened) {
+            mImeOpened = true;
+            mEditListener.onImeOpen();
+        }
+    }
+
+    public void closeIme(View v) {
+        if (mImeOpened) {
+            mImeOpened = false;
+            InputMethodManager mgr = (InputMethodManager)
+                    v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+            mgr.hideSoftInputFromWindow(v.getWindowToken(), 0);
+            mEditListener.onImeClose();
+        }
+    }
+
+    private long finishEditing(GuidedActionAdapter adapter, ActionViewHolder avh) {
+        long nextActionId = mEditListener.onGuidedActionEdited(avh.getAction());
+        adapter.getGuidedActionsStylist().setEditingMode(avh.mStylistViewHolder, avh.getAction(),
+                false);
+        return nextActionId;
+    }
+
+    public void fillAndStay(GuidedActionAdapter adapter, TextView v) {
+        ActionViewHolder avh = adapter.findSubChildViewHolder(v);
+        updateTextIntoAction(avh, v);
+        finishEditing(adapter, avh);
+        closeIme(v);
+        avh.mStylistViewHolder.view.requestFocus();
+    }
+
+    public void fillAndGoNext(GuidedActionAdapter adapter, TextView v) {
+        boolean handled = false;
+        ActionViewHolder avh = adapter.findSubChildViewHolder(v);
+        updateTextIntoAction(avh, v);
+        adapter.performOnActionClick(avh);
+        long nextActionId = finishEditing(adapter, avh);
+        if (nextActionId != GuidedAction.ACTION_ID_CURRENT
+                && nextActionId != avh.getAction().getId()) {
+            handled = focusToNextAction(adapter, avh.getAction(), nextActionId);
+        }
+        if (!handled) {
+            if (DEBUG_EDIT) Log.v(TAG_EDIT, "closeIme no next action");
+            handled = true;
+            closeIme(v);
+            avh.mStylistViewHolder.view.requestFocus();
+        }
+    }
+
+    private void updateTextIntoAction(ActionViewHolder avh, TextView v) {
+        GuidedAction action = avh.getAction();
+        if (v == avh.mStylistViewHolder.getDescriptionView()) {
+            if (action.getEditDescription() != null) {
+                action.setEditDescription(v.getText());
+            } else {
+                action.setDescription(v.getText());
+            }
+        } else if (v == avh.mStylistViewHolder.getTitleView()) {
+            if (action.getEditTitle() != null) {
+                action.setEditTitle(v.getText());
+            } else {
+                action.setTitle(v.getText());
+            }
+        }
+    }
+
+}
diff --git a/v17/leanback/src/android/support/v17/leanback/app/GuidedStepFragment.java b/v17/leanback/src/android/support/v17/leanback/app/GuidedStepFragment.java
index 15f88d6..cb6859d 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/GuidedStepFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/GuidedStepFragment.java
@@ -74,6 +74,11 @@
  * <li>{@link #add(FragmentManager, GuidedStepFragment)} or {@link #add(FragmentManager,
  * GuidedStepFragment, int)}, to add GuidedStepFragment on top of existing Fragments or
  * replacing existing GuidedStepFragment when moving forward to next step.</li>
+ * <li>{@link #finishGuidedStepFragments()} can either finish the activity or pop all
+ * GuidedStepFragment from stack.
+ * <li>If app chooses not to use the helper function, it is the app's responsibility to call
+ * {@link #setUiStyle(int)} to select fragment transition and remember the stack entry where it
+ * need pops to.
  * </ul>
  * <h3>Theming and Stylists</h3>
  * <p>
@@ -139,15 +144,13 @@
     private static final String TAG_LEAN_BACK_ACTIONS_FRAGMENT = "leanBackGuidedStepFragment";
     private static final String EXTRA_ACTION_SELECTED_INDEX = "selectedIndex";
 
-    private static final String ENTRY_NAME_DEFAULT = "GuidedStepDefault";
+    private static final String ENTRY_NAME_REPLACE = "GuidedStepDefault";
 
     private static final String ENTRY_NAME_ENTRANCE = "GuidedStepEntrance";
 
-    private static final boolean IS_FRAMEWORK_FRAGMENT = true;
-
     /**
      * Fragment argument name for UI style.  The argument value is persisted in fragment state.
-     * The value is initially {@link #UI_STYLE_DEFAULT} and might be changed in one of the three
+     * The value is initially {@link #UI_STYLE_ENTRANCE} and might be changed in one of the three
      * helper functions:
      * <ul>
      * <li>{@link #addAsRoot(Activity, GuidedStepFragment, int)}</li>
@@ -157,7 +160,7 @@
      * <p>
      * Argument value can be either:
      * <ul>
-     * <li>{@link #UI_STYLE_DEFAULT}</li>
+     * <li>{@link #UI_STYLE_REPLACE}</li>
      * <li>{@link #UI_STYLE_ENTRANCE}</li>
      * <li>{@link #UI_STYLE_ACTIVITY_ROOT}</li>
      * </ul>
@@ -165,42 +168,37 @@
     public static final String EXTRA_UI_STYLE = "uiStyle";
 
     /**
-     * Default value for argument {@link #EXTRA_UI_STYLE}.  The default value is assigned
-     * in GuidedStepFragment constructor.  This is the case that we use GuidedStepFragment to
-     * replace another existing GuidedStepFragment when moving forward to next step. Default
-     * behavior of this style is:
+     * This is the case that we use GuidedStepFragment to replace another existing
+     * GuidedStepFragment when moving forward to next step. Default behavior of this style is:
      * <ul>
-     * <li> Enter transition slides in from END(right), exit transition slide out to START(left).
+     * <li>Enter transition slides in from END(right), exit transition same as
+     * {@link #UI_STYLE_ENTRANCE}.
      * </li>
-     * <li> No background, see {@link #onProvideBackgroundFragment()}.</li>
      * </ul>
      */
-    public static final int UI_STYLE_DEFAULT = 0;
+    public static final int UI_STYLE_REPLACE = 0;
 
     /**
-     * One possible value of argument {@link #EXTRA_UI_STYLE}.  This is the case that we show
-     * GuidedStepFragment on top of other content.  The default behavior of this style:
+     * Default value for argument {@link #EXTRA_UI_STYLE}. The default value is assigned in
+     * GuidedStepFragment constructor. This is the case that we show GuidedStepFragment on top of
+     * other content. The default behavior of this style:
      * <ul>
-     * <li>Enter transition slides in from two sides, exit transition is inherited from
-     * {@link #UI_STYLE_DEFAULT}.  Note: Changing exit transition by UI style is not working because
-     * fragment transition asks for exit transition before UI style is restored in Fragment
+     * <li>Enter transition slides in from two sides, exit transition slide out to START(left).
+     * Background will be faded in. Note: Changing exit transition by UI style is not working
+     * because fragment transition asks for exit transition before UI style is restored in Fragment
      * .onCreate().</li>
-     * <li> {@link #onProvideBackgroundFragment()} will create {@link GuidedStepBackgroundFragment}
-     * to covering underneath content. The activity must provide a container to host background
-     * fragment and override {@link #getContainerIdForBackground()}</li>
      * </ul>
      */
     public static final int UI_STYLE_ENTRANCE = 1;
 
     /**
-     * One possible value of argument {@link #EXTRA_UI_STYLE}.  This is the case that we show first
-     * GuidedStepFragment in a separate activity.  The default behavior of this style:
+     * One possible value of argument {@link #EXTRA_UI_STYLE}. This is the case that we show first
+     * GuidedStepFragment in a separate activity. The default behavior of this style:
      * <ul>
-     * <li> Enter transition is assigned null (will rely on activity transition), exit transition is
-     * same as {@link #UI_STYLE_DEFAULT}.  Note: Changing exit transition by UI style is not working
+     * <li>Enter transition is assigned null (will rely on activity transition), exit transition is
+     * same as {@link #UI_STYLE_ENTRANCE}. Note: Changing exit transition by UI style is not working
      * because fragment transition asks for exit transition before UI style is restored in
      * Fragment.onCreate().</li>
-     * <li> No background, see {@link #onProvideBackgroundFragment()}.
      * </ul>
      */
     public static final int UI_STYLE_ACTIVITY_ROOT = 2;
@@ -215,6 +213,7 @@
     private GuidedActionsStylist mButtonActionsStylist;
     private GuidedActionAdapter mAdapter;
     private GuidedActionAdapter mButtonAdapter;
+    private GuidedActionAdapterGroup mAdapterGroup;
     private List<GuidedAction> mActions = new ArrayList<GuidedAction>();
     private List<GuidedAction> mButtonActions = new ArrayList<GuidedAction>();
     private int mSelectedIndex = -1;
@@ -341,7 +340,7 @@
      * GuidedStepFragments in the stack, and configuring the fragment-to-fragment custom
      * transitions.  A backstack entry is added, so the fragment will be dismissed when BACK key
      * is pressed.
-     * <li>If current fragment on stack is GuidedStepFragment: assign {@link #UI_STYLE_DEFAULT}
+     * <li>If current fragment on stack is GuidedStepFragment: assign {@link #UI_STYLE_REPLACE}
      * <li>If current fragment on stack is not GuidedStepFragment: assign {@link #UI_STYLE_ENTRANCE}
      * <p>
      * Note: currently fragments added using this method must be created programmatically rather
@@ -359,7 +358,7 @@
      * GuidedStepFragments in the stack, and configuring the fragment-to-fragment custom
      * transitions.  A backstack entry is added, so the fragment will be dismissed when BACK key
      * is pressed.
-     * <li>If current fragment on stack is GuidedStepFragment: assign {@link #UI_STYLE_DEFAULT} and
+     * <li>If current fragment on stack is GuidedStepFragment: assign {@link #UI_STYLE_REPLACE} and
      * {@link #onAddSharedElementTransition(FragmentTransaction, GuidedStepFragment)} will be called
      * to perform shared element transition between GuidedStepFragments.
      * <li>If current fragment on stack is not GuidedStepFragment: assign {@link #UI_STYLE_ENTRANCE}
@@ -374,32 +373,24 @@
     public static int add(FragmentManager fragmentManager, GuidedStepFragment fragment, int id) {
         GuidedStepFragment current = getCurrentGuidedStepFragment(fragmentManager);
         boolean inGuidedStep = current != null;
-        if (IS_FRAMEWORK_FRAGMENT && Build.VERSION.SDK_INT >= 21 && Build.VERSION.SDK_INT < 23
-                && !inGuidedStep && fragment.getContainerIdForBackground() != View.NO_ID) {
-            // workaround b/22631964 for framework fragment
-            fragmentManager.beginTransaction()
-                .replace(id, new DummyFragment(), TAG_LEAN_BACK_ACTIONS_FRAGMENT)
-                .replace(fragment.getContainerIdForBackground(), new DummyFragment())
-                .commit();
-        }
         FragmentTransaction ft = fragmentManager.beginTransaction();
 
-        fragment.setUiStyle(inGuidedStep ? UI_STYLE_DEFAULT : UI_STYLE_ENTRANCE);
+        fragment.setUiStyle(inGuidedStep ? UI_STYLE_REPLACE : UI_STYLE_ENTRANCE);
         ft.addToBackStack(fragment.generateStackEntryName());
         if (current != null) {
             fragment.onAddSharedElementTransition(ft, current);
         }
-        initialBackground(fragment, id, ft);
         return ft.replace(id, fragment, TAG_LEAN_BACK_ACTIONS_FRAGMENT).commit();
     }
 
     /**
-     * Called when this fragment is added to FragmentTransaction with {@link #UI_STYLE_DEFAULT} (aka
-     * when the GuidedStepFragment replacing an existing GuidedStepFragment).
-     * Default implementation establishes connections between background views to morph background
-     * bounds change from disappearing GuidedStepFragment into this GuidedStepFragment.  The default
+     * Called when this fragment is added to FragmentTransaction with {@link #UI_STYLE_REPLACE} (aka
+     * when the GuidedStepFragment replacing an existing GuidedStepFragment). Default implementation
+     * establishes connections between action background views to morph action background bounds
+     * change from disappearing GuidedStepFragment into this GuidedStepFragment. The default
      * implementation heavily relies on {@link GuidedActionsStylist}'s layout, app may override this
      * method when modifying the default layout of {@link GuidedActionsStylist}.
+     *
      * @see GuidedActionsStylist
      * @see #onProvideFragmentTransitions()
      * @param ft The FragmentTransaction to add shared element.
@@ -441,7 +432,7 @@
     /**
      * Generates BackStackEntry name for GuidedStepFragment class or empty String if no entry is
      * associated.  Note {@link #UI_STYLE_ACTIVITY_ROOT} is not allowed and returns empty String.
-     * @param uiStyle {@link #UI_STYLE_DEFAULT} or {@link #UI_STYLE_ENTRANCE}
+     * @param uiStyle {@link #UI_STYLE_REPLACE} or {@link #UI_STYLE_ENTRANCE}
      * @return BackStackEntry name for the GuidedStepFragment or empty String if no entry is
      * associated.
      */
@@ -450,8 +441,8 @@
             return "";
         }
         switch (uiStyle) {
-        case UI_STYLE_DEFAULT:
-            return ENTRY_NAME_DEFAULT + guidedStepFragmentClass.getName();
+        case UI_STYLE_REPLACE:
+            return ENTRY_NAME_REPLACE + guidedStepFragmentClass.getName();
         case UI_STYLE_ENTRANCE:
             return ENTRY_NAME_ENTRANCE + guidedStepFragmentClass.getName();
         case UI_STYLE_ACTIVITY_ROOT:
@@ -472,14 +463,14 @@
     }
 
     /**
-     * Returns true if the backstack represents GuidedStepFragment with {@link #UI_STYLE_DEFAULT};
+     * Returns true if the backstack represents GuidedStepFragment with {@link #UI_STYLE_REPLACE};
      * false otherwise.
      * @param backStackEntryName Name of BackStackEntry.
-     * @return True if the backstack represents GuidedStepFragment with {@link #UI_STYLE_DEFAULT};
+     * @return True if the backstack represents GuidedStepFragment with {@link #UI_STYLE_REPLACE};
      * false otherwise.
      */
     public static boolean isUiStyleDefault(String backStackEntryName) {
-        return backStackEntryName != null && backStackEntryName.startsWith(ENTRY_NAME_DEFAULT);
+        return backStackEntryName != null && backStackEntryName.startsWith(ENTRY_NAME_REPLACE);
     }
 
     /**
@@ -488,8 +479,8 @@
      * @return Class name of GuidedStepFragment.
      */
     public static String getGuidedStepFragmentClassName(String backStackEntryName) {
-        if (backStackEntryName.startsWith(ENTRY_NAME_DEFAULT)) {
-            return backStackEntryName.substring(ENTRY_NAME_DEFAULT.length());
+        if (backStackEntryName.startsWith(ENTRY_NAME_REPLACE)) {
+            return backStackEntryName.substring(ENTRY_NAME_REPLACE.length());
         } else if (backStackEntryName.startsWith(ENTRY_NAME_ENTRANCE)) {
             return backStackEntryName.substring(ENTRY_NAME_ENTRANCE.length());
         } else {
@@ -516,19 +507,9 @@
         FragmentManager fragmentManager = activity.getFragmentManager();
         FragmentTransaction ft = fragmentManager.beginTransaction();
         fragment.setUiStyle(UI_STYLE_ACTIVITY_ROOT);
-        initialBackground(fragment, id, ft);
         return ft.replace(id, fragment, TAG_LEAN_BACK_ACTIONS_FRAGMENT).commit();
     }
 
-    static void initialBackground(GuidedStepFragment fragment, int id, FragmentTransaction ft) {
-        if (fragment.getContainerIdForBackground() != View.NO_ID) {
-            Fragment backgroundFragment = fragment.onProvideBackgroundFragment();
-            if (backgroundFragment != null) {
-                ft.replace(fragment.getContainerIdForBackground(), backgroundFragment);
-            }
-        }
-    }
-
     /**
      * Returns the current GuidedStepFragment on the fragment transaction stack.
      * @return The current GuidedStepFragment, if any, on the fragment transaction stack.
@@ -542,20 +523,6 @@
     }
 
     /**
-     * @hide
-     */
-    public static class DummyFragment extends Fragment {
-
-        @Override
-        public View onCreateView(LayoutInflater inflater, ViewGroup container,
-                Bundle savedInstanceState) {
-            final View v = new View(inflater.getContext());
-            v.setVisibility(View.GONE);
-            return v;
-        }
-    }
-
-    /**
      * Returns the GuidanceStylist that displays guidance information for the user.
      * @return The GuidanceStylist for this fragment.
      */
@@ -753,12 +720,12 @@
      * Called by Constructor to provide fragment transitions.  The default implementation assigns
      * transitions based on {@link #getUiStyle()}:
      * <ul>
-     * <li> {@link #UI_STYLE_DEFAULT} Slide from/to end(right) for enter transition, slide from/to
+     * <li> {@link #UI_STYLE_REPLACE} Slide from/to end(right) for enter transition, slide from/to
      * start(left) for exit transition, shared element enter transition is set to ChangeBounds.
      * <li> {@link #UI_STYLE_ENTRANCE} Enter transition is set to slide from both sides, exit
-     * transition is same as {@link #UI_STYLE_DEFAULT}, no shared element enter transition.
+     * transition is same as {@link #UI_STYLE_REPLACE}, no shared element enter transition.
      * <li> {@link #UI_STYLE_ACTIVITY_ROOT} Enter transition is set to null and app should rely on
-     * activity transition, exit transition is same as {@link #UI_STYLE_DEFAULT}, no shared element
+     * activity transition, exit transition is same as {@link #UI_STYLE_REPLACE}, no shared element
      * enter transition.
      * </ul>
      * <p>
@@ -773,7 +740,8 @@
      */
     protected void onProvideFragmentTransitions() {
         if (Build.VERSION.SDK_INT >= 21) {
-            if (getUiStyle() == UI_STYLE_DEFAULT) {
+            final int uiStyle = getUiStyle();
+            if (uiStyle == UI_STYLE_REPLACE) {
                 Object enterTransition = TransitionHelper.createFadeAndShortSlide(Gravity.END);
                 TransitionHelper.exclude(enterTransition, R.id.action_fragment_background, true);
                 TransitionHelper.exclude(enterTransition, R.id.guided_button_actions_background,
@@ -781,7 +749,32 @@
                 TransitionHelper.exclude(enterTransition, R.id.guided_button_actions_background2,
                         true);
                 TransitionHelper.exclude(enterTransition, R.id.guidedactions_selector, true);
+                TransitionHelper.exclude(enterTransition, R.id.guidedstep_background, true);
                 TransitionHelper.setEnterTransition(this, enterTransition);
+
+                // exit transition is unchanged, same as default UI_STYLE_ENTRANCE
+
+                Object changeBounds = TransitionHelper.createChangeBounds(false);
+                TransitionHelper.setSharedElementEnterTransition(this, changeBounds);
+            } else if (uiStyle == UI_STYLE_ENTRANCE) {
+                Object fade = TransitionHelper.createFadeTransition(TransitionHelper.FADE_IN |
+                        TransitionHelper.FADE_OUT);
+                TransitionHelper.include(fade, R.id.guidedstep_background);
+                Object slide = TransitionHelper.createFadeAndShortSlide(Gravity.END |
+                        Gravity.START);
+                TransitionHelper.include(slide, R.id.content_fragment);
+                TransitionHelper.include(slide, R.id.action_fragment_background);
+                TransitionHelper.include(slide, R.id.guided_button_actions_background);
+                TransitionHelper.include(slide, R.id.guidedactions_selector);
+                TransitionHelper.include(slide, R.id.guidedactions_list);
+                TransitionHelper.include(slide, R.id.guided_button_actions_background2);
+                TransitionHelper.include(slide, R.id.guidedactions_selector2);
+                TransitionHelper.include(slide, R.id.guidedactions_list2);
+                Object enterTransition = TransitionHelper.createTransitionSet(false);
+                TransitionHelper.addTransition(enterTransition, fade);
+                TransitionHelper.addTransition(enterTransition, slide);
+                TransitionHelper.setEnterTransition(this, enterTransition);
+
                 Object exitTransition = TransitionHelper.createFadeAndShortSlide(Gravity.START);
                 TransitionHelper.exclude(exitTransition, R.id.action_fragment_background, true);
                 TransitionHelper.exclude(exitTransition, R.id.guided_button_actions_background,
@@ -790,118 +783,47 @@
                 TransitionHelper.exclude(exitTransition, R.id.guided_button_actions_background2,
                         true);
                 TransitionHelper.exclude(exitTransition, R.id.guidedactions_selector2, true);
+                TransitionHelper.exclude(exitTransition, R.id.guidedstep_background, true);
                 TransitionHelper.setExitTransition(this, exitTransition);
-
-                Object changeBounds = TransitionHelper.createChangeBounds(false);
-                TransitionHelper.setSharedElementEnterTransition(this, changeBounds);
-            } else if (getUiStyle() == UI_STYLE_ENTRANCE) {
-                Object enterTransition = TransitionHelper.createFadeAndShortSlide(Gravity.END |
-                        Gravity.START);
-                TransitionHelper.include(enterTransition, R.id.content_fragment);
-                TransitionHelper.include(enterTransition, R.id.action_fragment_background);
-                TransitionHelper.include(enterTransition, R.id.guided_button_actions_background);
-                TransitionHelper.include(enterTransition, R.id.guidedactions_selector);
-                TransitionHelper.include(enterTransition, R.id.guidedactions_list);
-                TransitionHelper.include(enterTransition, R.id.guided_button_actions_background2);
-                TransitionHelper.include(enterTransition, R.id.guidedactions_selector2);
-                TransitionHelper.include(enterTransition, R.id.guidedactions_list2);
-                TransitionHelper.setEnterTransition(this, enterTransition);
-                // exit transition is unchanged, same as UI_STYLE_DEFAULT
                 // No shared element transition
                 TransitionHelper.setSharedElementEnterTransition(this, null);
-            } else if (getUiStyle() == UI_STYLE_ACTIVITY_ROOT) {
+            } else if (uiStyle == UI_STYLE_ACTIVITY_ROOT) {
                 // for Activity root, we dont need enter transition, use activity transition
                 TransitionHelper.setEnterTransition(this, null);
-                // exit transition is unchanged, same as UI_STYLE_DEFAULT
+                // exit transition is unchanged, same as UI_STYLE_ENTRANCE
                 // No shared element transition
                 TransitionHelper.setSharedElementEnterTransition(this, null);
+            } else {
+                return;
             }
         }
     }
 
     /**
-     * Default implementation of background for covering content below GuidedStepFragment.
-     * It uses current theme attribute guidedStepBackground which by default is read from
-     * android:windowBackground.
+     * Called by onCreateView to inflate background view.  Default implementation loads view
+     * from {@link R.layout#lb_guidedstep_background} which holds a reference to
+     * guidedStepBackground.
+     * @param inflater LayoutInflater to load background view.
+     * @param container Parent view of background view.
+     * @param savedInstanceState
+     * @return Created background view or null if no background.
      */
-    public static class GuidedStepBackgroundFragment extends Fragment {
-        public GuidedStepBackgroundFragment() {
-            onProvideFragmentTransitions();
-        }
-
-        /**
-         * Sets fragment transitions for GuidedStepBackgroundFragment.  Can be overridden.
-         */
-        protected void onProvideFragmentTransitions() {
-            if (Build.VERSION.SDK_INT >= 21) {
-                Object enterTransition = TransitionHelper.createFadeTransition(
-                        TransitionHelper.FADE_IN|TransitionHelper.FADE_OUT);
-                TransitionHelper.setEnterTransition(this, enterTransition);
-            }
-        }
-
-        @Override
-        public View onCreateView(LayoutInflater inflater, ViewGroup container,
-                Bundle savedInstanceState) {
-            Activity activity = getActivity();
-            Context themedContext = null;
-            if (!isGuidedStepTheme(activity)) {
-                // Look up the guidedStepTheme in the activity's currently specified theme.  If it
-                // exists, replace the theme with its value.
-                int resId = R.attr.guidedStepTheme;
-                TypedValue typedValue = new TypedValue();
-                boolean found = activity.getTheme().resolveAttribute(resId, typedValue, true);
-                if (DEBUG) Log.v(TAG, "Found guided step theme reference? " + found);
-                if (found) {
-                    ContextThemeWrapper themeWrapper =
-                            new ContextThemeWrapper(activity, typedValue.resourceId);
-                    if (isGuidedStepTheme(themeWrapper)) {
-                        themedContext = themeWrapper;
-                    }
-                }
-                if (!found) {
-                    Log.e(TAG, "GuidedStepFragment does not have an appropriate theme set.");
-                }
-            }
-
-            if (themedContext != null) {
-                inflater = inflater.cloneInContext(themedContext);
-            }
-
-            return inflater.inflate(R.layout.lb_guidedstep_background, container, false);
-        }
+    public View onCreateBackgroundView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        return inflater.inflate(R.layout.lb_guidedstep_background, container, false);
     }
 
     /**
-     * Creates a background fragment for {@link #UI_STYLE_ENTRANCE}, returns null for other cases.
-     * Subclass may override the default behavior, e.g. provide different backgrounds
-     * for {@link #UI_STYLE_DEFAULT}.  Background fragment will be inserted in {@link
-     * #getContainerIdForBackground()}.
+     * Set UI style to fragment arguments. Default value is {@link #UI_STYLE_ENTRANCE} when fragment
+     * is first initialized. UI style is used to choose different fragment transition animations and
+     * determine if this is the first GuidedStepFragment on backstack. In most cases app does not
+     * directly call this method, app calls helper function
+     * {@link #add(FragmentManager, GuidedStepFragment, int)}. However if the app creates Fragment
+     * transaction and controls backstack by itself, it would need call setUiStyle() to select the
+     * fragment transition to use.
      *
-     * @return fragment that will be inserted below GuidedStepFragment.
-     */
-    protected Fragment onProvideBackgroundFragment() {
-        if (getUiStyle() == UI_STYLE_ENTRANCE) {
-            return new GuidedStepBackgroundFragment();
-        }
-        return null;
-    }
-
-    /**
-     * Returns container id for inserting {@link #onProvideBackgroundFragment()}.  The id should be
-     * different than container id for inserting GuidedStepFragment.
-     * Default value is {@link View#NO_ID}.  Subclass must override to host background fragment.
-     * @return container id for inserting {@link #onProvideBackgroundFragment()}
-     */
-    protected int getContainerIdForBackground() {
-        return View.NO_ID;
-    }
-
-
-    /**
-     * Set UI style to fragment arguments,  UI style cannot be changed after initialization.
-     * @param style {@link #UI_STYLE_ACTIVITY_ROOT} {@link #UI_STYLE_DEFAULT} or
-     * {@link #UI_STYLE_ENTRANCE}.
+     * @param style {@link #UI_STYLE_ACTIVITY_ROOT} {@link #UI_STYLE_REPLACE} or
+     *        {@link #UI_STYLE_ENTRANCE}.
      */
     public void setUiStyle(int style) {
         int oldStyle = getUiStyle();
@@ -922,15 +844,18 @@
     }
 
     /**
-     * Read UI style from fragment arguments.
+     * Read UI style from fragment arguments.  Default value is {@link #UI_STYLE_ENTRANCE} when
+     * fragment is first initialized.  UI style is used to choose different fragment transition
+     * animations and determine if this is the first GuidedStepFragment on backstack.
      *
-     * @return {@link #UI_STYLE_ACTIVITY_ROOT} {@link #UI_STYLE_DEFAULT} or
+     * @return {@link #UI_STYLE_ACTIVITY_ROOT} {@link #UI_STYLE_REPLACE} or
      * {@link #UI_STYLE_ENTRANCE}.
+     * @see #onProvideFragmentTransitions()
      */
     public int getUiStyle() {
         Bundle b = getArguments();
-        if (b == null) return UI_STYLE_DEFAULT;
-        return b.getInt(EXTRA_UI_STYLE, UI_STYLE_DEFAULT);
+        if (b == null) return UI_STYLE_ENTRANCE;
+        return b.getInt(EXTRA_UI_STYLE, UI_STYLE_ENTRANCE);
     }
 
     /**
@@ -964,6 +889,9 @@
         mGuidanceStylist.onDestroyView();
         mActionsStylist.onDestroyView();
         mButtonActionsStylist.onDestroyView();
+        mAdapter = null;
+        mButtonAdapter = null;
+        mAdapterGroup = null;
         super.onDestroyView();
     }
 
@@ -978,9 +906,10 @@
         resolveTheme();
         inflater = getThemeInflater(inflater);
 
-        View v = inflater.inflate(R.layout.lb_guidedstep_fragment, container, false);
-        ViewGroup guidanceContainer = (ViewGroup) v.findViewById(R.id.content_fragment);
-        ViewGroup actionContainer = (ViewGroup) v.findViewById(R.id.action_fragment);
+        ViewGroup root = (ViewGroup) inflater.inflate(R.layout.lb_guidedstep_fragment,
+                container, false);
+        ViewGroup guidanceContainer = (ViewGroup) root.findViewById(R.id.content_fragment);
+        ViewGroup actionContainer = (ViewGroup) root.findViewById(R.id.action_fragment);
 
         Guidance guidance = onCreateGuidance(savedInstanceState);
         View guidanceView = mGuidanceStylist.onCreateView(inflater, guidanceContainer, guidance);
@@ -1011,10 +940,12 @@
                 }
         };
 
-        mAdapter = new GuidedActionAdapter(mActions, this, this, editListener,
-                mActionsStylist);
-        mButtonAdapter = new GuidedActionAdapter(mButtonActions, this, this, editListener,
-                mButtonActionsStylist);
+        mAdapter = new GuidedActionAdapter(mActions, this, this, mActionsStylist);
+        mButtonAdapter = new GuidedActionAdapter(mButtonActions, this, this, mButtonActionsStylist);
+        mAdapterGroup = new GuidedActionAdapterGroup();
+        mAdapterGroup.addAdpter(mAdapter);
+        mAdapterGroup.addAdpter(mButtonAdapter);
+        mAdapterGroup.setEditListener(editListener);
 
         mActionsStylist.getActionsGridView().setAdapter(mAdapter);
         mButtonActionsStylist.getActionsGridView().setAdapter(mButtonAdapter);
@@ -1032,7 +963,7 @@
             TypedValue typedValue = new TypedValue();
             if (ctx.getTheme().resolveAttribute(R.attr.guidedActionContentWidthWeightTwoPanels,
                     typedValue, true)) {
-                View actionsRoot = v.findViewById(R.id.action_fragment_root);
+                View actionsRoot = root.findViewById(R.id.action_fragment_root);
                 float weight = typedValue.getFloat();
                 LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) actionsRoot
                         .getLayoutParams();
@@ -1047,7 +978,11 @@
 
         setSelectedButtonActionPosition(0);
 
-        return v;
+        View backgroundView = onCreateBackgroundView(inflater, root, savedInstanceState);
+        if (backgroundView != null) {
+            root.addView(backgroundView, 0);
+        }
+        return root;
     }
 
     @Override
@@ -1079,6 +1014,8 @@
      * Convenient method to close GuidedStepFragments on top of other content or finish Activity if
      * GuidedStepFragments were started in a separate activity.  Pops all stack entries including
      * {@link #UI_STYLE_ENTRANCE}; if {@link #UI_STYLE_ENTRANCE} is not found, finish the activity.
+     * Note that this method must be paired with {@link #add(FragmentManager, GuidedStepFragment,
+     * int)} which sets up the stack entry name for finding which fragment we need to pop back to.
      */
     public void finishGuidedStepFragments() {
         final FragmentManager fragmentManager = getFragmentManager();
diff --git a/v17/leanback/src/android/support/v17/leanback/app/GuidedStepSupportFragment.java b/v17/leanback/src/android/support/v17/leanback/app/GuidedStepSupportFragment.java
index 864e04f..fae8c50 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/GuidedStepSupportFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/GuidedStepSupportFragment.java
@@ -76,6 +76,11 @@
  * <li>{@link #add(FragmentManager, GuidedStepSupportFragment)} or {@link #add(FragmentManager,
  * GuidedStepSupportFragment, int)}, to add GuidedStepSupportFragment on top of existing Fragments or
  * replacing existing GuidedStepSupportFragment when moving forward to next step.</li>
+ * <li>{@link #finishGuidedStepSupportFragments()} can either finish the activity or pop all
+ * GuidedStepSupportFragment from stack.
+ * <li>If app chooses not to use the helper function, it is the app's responsibility to call
+ * {@link #setUiStyle(int)} to select fragment transition and remember the stack entry where it
+ * need pops to.
  * </ul>
  * <h3>Theming and Stylists</h3>
  * <p>
@@ -141,15 +146,13 @@
     private static final String TAG_LEAN_BACK_ACTIONS_FRAGMENT = "leanBackGuidedStepSupportFragment";
     private static final String EXTRA_ACTION_SELECTED_INDEX = "selectedIndex";
 
-    private static final String ENTRY_NAME_DEFAULT = "GuidedStepDefault";
+    private static final String ENTRY_NAME_REPLACE = "GuidedStepDefault";
 
     private static final String ENTRY_NAME_ENTRANCE = "GuidedStepEntrance";
 
-    private static final boolean IS_FRAMEWORK_FRAGMENT = false;
-
     /**
      * Fragment argument name for UI style.  The argument value is persisted in fragment state.
-     * The value is initially {@link #UI_STYLE_DEFAULT} and might be changed in one of the three
+     * The value is initially {@link #UI_STYLE_ENTRANCE} and might be changed in one of the three
      * helper functions:
      * <ul>
      * <li>{@link #addAsRoot(FragmentActivity, GuidedStepSupportFragment, int)}</li>
@@ -159,7 +162,7 @@
      * <p>
      * Argument value can be either:
      * <ul>
-     * <li>{@link #UI_STYLE_DEFAULT}</li>
+     * <li>{@link #UI_STYLE_REPLACE}</li>
      * <li>{@link #UI_STYLE_ENTRANCE}</li>
      * <li>{@link #UI_STYLE_ACTIVITY_ROOT}</li>
      * </ul>
@@ -167,42 +170,37 @@
     public static final String EXTRA_UI_STYLE = "uiStyle";
 
     /**
-     * Default value for argument {@link #EXTRA_UI_STYLE}.  The default value is assigned
-     * in GuidedStepSupportFragment constructor.  This is the case that we use GuidedStepSupportFragment to
-     * replace another existing GuidedStepSupportFragment when moving forward to next step. Default
-     * behavior of this style is:
+     * This is the case that we use GuidedStepSupportFragment to replace another existing
+     * GuidedStepSupportFragment when moving forward to next step. Default behavior of this style is:
      * <ul>
-     * <li> Enter transition slides in from END(right), exit transition slide out to START(left).
+     * <li>Enter transition slides in from END(right), exit transition same as
+     * {@link #UI_STYLE_ENTRANCE}.
      * </li>
-     * <li> No background, see {@link #onProvideBackgroundSupportFragment()}.</li>
      * </ul>
      */
-    public static final int UI_STYLE_DEFAULT = 0;
+    public static final int UI_STYLE_REPLACE = 0;
 
     /**
-     * One possible value of argument {@link #EXTRA_UI_STYLE}.  This is the case that we show
-     * GuidedStepSupportFragment on top of other content.  The default behavior of this style:
+     * Default value for argument {@link #EXTRA_UI_STYLE}. The default value is assigned in
+     * GuidedStepSupportFragment constructor. This is the case that we show GuidedStepSupportFragment on top of
+     * other content. The default behavior of this style:
      * <ul>
-     * <li>Enter transition slides in from two sides, exit transition is inherited from
-     * {@link #UI_STYLE_DEFAULT}.  Note: Changing exit transition by UI style is not working because
-     * fragment transition asks for exit transition before UI style is restored in Fragment
+     * <li>Enter transition slides in from two sides, exit transition slide out to START(left).
+     * Background will be faded in. Note: Changing exit transition by UI style is not working
+     * because fragment transition asks for exit transition before UI style is restored in Fragment
      * .onCreate().</li>
-     * <li> {@link #onProvideBackgroundSupportFragment()} will create {@link GuidedStepBackgroundSupportFragment}
-     * to covering underneath content. The activity must provide a container to host background
-     * fragment and override {@link #getContainerIdForBackground()}</li>
      * </ul>
      */
     public static final int UI_STYLE_ENTRANCE = 1;
 
     /**
-     * One possible value of argument {@link #EXTRA_UI_STYLE}.  This is the case that we show first
-     * GuidedStepSupportFragment in a separate activity.  The default behavior of this style:
+     * One possible value of argument {@link #EXTRA_UI_STYLE}. This is the case that we show first
+     * GuidedStepSupportFragment in a separate activity. The default behavior of this style:
      * <ul>
-     * <li> Enter transition is assigned null (will rely on activity transition), exit transition is
-     * same as {@link #UI_STYLE_DEFAULT}.  Note: Changing exit transition by UI style is not working
+     * <li>Enter transition is assigned null (will rely on activity transition), exit transition is
+     * same as {@link #UI_STYLE_ENTRANCE}. Note: Changing exit transition by UI style is not working
      * because fragment transition asks for exit transition before UI style is restored in
      * Fragment.onCreate().</li>
-     * <li> No background, see {@link #onProvideBackgroundSupportFragment()}.
      * </ul>
      */
     public static final int UI_STYLE_ACTIVITY_ROOT = 2;
@@ -217,6 +215,7 @@
     private GuidedActionsStylist mButtonActionsStylist;
     private GuidedActionAdapter mAdapter;
     private GuidedActionAdapter mButtonAdapter;
+    private GuidedActionAdapterGroup mAdapterGroup;
     private List<GuidedAction> mActions = new ArrayList<GuidedAction>();
     private List<GuidedAction> mButtonActions = new ArrayList<GuidedAction>();
     private int mSelectedIndex = -1;
@@ -343,7 +342,7 @@
      * GuidedStepSupportFragments in the stack, and configuring the fragment-to-fragment custom
      * transitions.  A backstack entry is added, so the fragment will be dismissed when BACK key
      * is pressed.
-     * <li>If current fragment on stack is GuidedStepSupportFragment: assign {@link #UI_STYLE_DEFAULT}
+     * <li>If current fragment on stack is GuidedStepSupportFragment: assign {@link #UI_STYLE_REPLACE}
      * <li>If current fragment on stack is not GuidedStepSupportFragment: assign {@link #UI_STYLE_ENTRANCE}
      * <p>
      * Note: currently fragments added using this method must be created programmatically rather
@@ -361,7 +360,7 @@
      * GuidedStepSupportFragments in the stack, and configuring the fragment-to-fragment custom
      * transitions.  A backstack entry is added, so the fragment will be dismissed when BACK key
      * is pressed.
-     * <li>If current fragment on stack is GuidedStepSupportFragment: assign {@link #UI_STYLE_DEFAULT} and
+     * <li>If current fragment on stack is GuidedStepSupportFragment: assign {@link #UI_STYLE_REPLACE} and
      * {@link #onAddSharedElementTransition(FragmentTransaction, GuidedStepSupportFragment)} will be called
      * to perform shared element transition between GuidedStepSupportFragments.
      * <li>If current fragment on stack is not GuidedStepSupportFragment: assign {@link #UI_STYLE_ENTRANCE}
@@ -376,32 +375,24 @@
     public static int add(FragmentManager fragmentManager, GuidedStepSupportFragment fragment, int id) {
         GuidedStepSupportFragment current = getCurrentGuidedStepSupportFragment(fragmentManager);
         boolean inGuidedStep = current != null;
-        if (IS_FRAMEWORK_FRAGMENT && Build.VERSION.SDK_INT >= 21 && Build.VERSION.SDK_INT < 23
-                && !inGuidedStep && fragment.getContainerIdForBackground() != View.NO_ID) {
-            // workaround b/22631964 for framework fragment
-            fragmentManager.beginTransaction()
-                .replace(id, new DummyFragment(), TAG_LEAN_BACK_ACTIONS_FRAGMENT)
-                .replace(fragment.getContainerIdForBackground(), new DummyFragment())
-                .commit();
-        }
         FragmentTransaction ft = fragmentManager.beginTransaction();
 
-        fragment.setUiStyle(inGuidedStep ? UI_STYLE_DEFAULT : UI_STYLE_ENTRANCE);
+        fragment.setUiStyle(inGuidedStep ? UI_STYLE_REPLACE : UI_STYLE_ENTRANCE);
         ft.addToBackStack(fragment.generateStackEntryName());
         if (current != null) {
             fragment.onAddSharedElementTransition(ft, current);
         }
-        initialBackground(fragment, id, ft);
         return ft.replace(id, fragment, TAG_LEAN_BACK_ACTIONS_FRAGMENT).commit();
     }
 
     /**
-     * Called when this fragment is added to FragmentTransaction with {@link #UI_STYLE_DEFAULT} (aka
-     * when the GuidedStepSupportFragment replacing an existing GuidedStepSupportFragment).
-     * Default implementation establishes connections between background views to morph background
-     * bounds change from disappearing GuidedStepSupportFragment into this GuidedStepSupportFragment.  The default
+     * Called when this fragment is added to FragmentTransaction with {@link #UI_STYLE_REPLACE} (aka
+     * when the GuidedStepSupportFragment replacing an existing GuidedStepSupportFragment). Default implementation
+     * establishes connections between action background views to morph action background bounds
+     * change from disappearing GuidedStepSupportFragment into this GuidedStepSupportFragment. The default
      * implementation heavily relies on {@link GuidedActionsStylist}'s layout, app may override this
      * method when modifying the default layout of {@link GuidedActionsStylist}.
+     *
      * @see GuidedActionsStylist
      * @see #onProvideFragmentTransitions()
      * @param ft The FragmentTransaction to add shared element.
@@ -443,7 +434,7 @@
     /**
      * Generates BackStackEntry name for GuidedStepSupportFragment class or empty String if no entry is
      * associated.  Note {@link #UI_STYLE_ACTIVITY_ROOT} is not allowed and returns empty String.
-     * @param uiStyle {@link #UI_STYLE_DEFAULT} or {@link #UI_STYLE_ENTRANCE}
+     * @param uiStyle {@link #UI_STYLE_REPLACE} or {@link #UI_STYLE_ENTRANCE}
      * @return BackStackEntry name for the GuidedStepSupportFragment or empty String if no entry is
      * associated.
      */
@@ -452,8 +443,8 @@
             return "";
         }
         switch (uiStyle) {
-        case UI_STYLE_DEFAULT:
-            return ENTRY_NAME_DEFAULT + guidedStepFragmentClass.getName();
+        case UI_STYLE_REPLACE:
+            return ENTRY_NAME_REPLACE + guidedStepFragmentClass.getName();
         case UI_STYLE_ENTRANCE:
             return ENTRY_NAME_ENTRANCE + guidedStepFragmentClass.getName();
         case UI_STYLE_ACTIVITY_ROOT:
@@ -474,14 +465,14 @@
     }
 
     /**
-     * Returns true if the backstack represents GuidedStepSupportFragment with {@link #UI_STYLE_DEFAULT};
+     * Returns true if the backstack represents GuidedStepSupportFragment with {@link #UI_STYLE_REPLACE};
      * false otherwise.
      * @param backStackEntryName Name of BackStackEntry.
-     * @return True if the backstack represents GuidedStepSupportFragment with {@link #UI_STYLE_DEFAULT};
+     * @return True if the backstack represents GuidedStepSupportFragment with {@link #UI_STYLE_REPLACE};
      * false otherwise.
      */
     public static boolean isUiStyleDefault(String backStackEntryName) {
-        return backStackEntryName != null && backStackEntryName.startsWith(ENTRY_NAME_DEFAULT);
+        return backStackEntryName != null && backStackEntryName.startsWith(ENTRY_NAME_REPLACE);
     }
 
     /**
@@ -490,8 +481,8 @@
      * @return Class name of GuidedStepSupportFragment.
      */
     public static String getGuidedStepSupportFragmentClassName(String backStackEntryName) {
-        if (backStackEntryName.startsWith(ENTRY_NAME_DEFAULT)) {
-            return backStackEntryName.substring(ENTRY_NAME_DEFAULT.length());
+        if (backStackEntryName.startsWith(ENTRY_NAME_REPLACE)) {
+            return backStackEntryName.substring(ENTRY_NAME_REPLACE.length());
         } else if (backStackEntryName.startsWith(ENTRY_NAME_ENTRANCE)) {
             return backStackEntryName.substring(ENTRY_NAME_ENTRANCE.length());
         } else {
@@ -518,19 +509,9 @@
         FragmentManager fragmentManager = activity.getSupportFragmentManager();
         FragmentTransaction ft = fragmentManager.beginTransaction();
         fragment.setUiStyle(UI_STYLE_ACTIVITY_ROOT);
-        initialBackground(fragment, id, ft);
         return ft.replace(id, fragment, TAG_LEAN_BACK_ACTIONS_FRAGMENT).commit();
     }
 
-    static void initialBackground(GuidedStepSupportFragment fragment, int id, FragmentTransaction ft) {
-        if (fragment.getContainerIdForBackground() != View.NO_ID) {
-            Fragment backgroundFragment = fragment.onProvideBackgroundSupportFragment();
-            if (backgroundFragment != null) {
-                ft.replace(fragment.getContainerIdForBackground(), backgroundFragment);
-            }
-        }
-    }
-
     /**
      * Returns the current GuidedStepSupportFragment on the fragment transaction stack.
      * @return The current GuidedStepSupportFragment, if any, on the fragment transaction stack.
@@ -544,20 +525,6 @@
     }
 
     /**
-     * @hide
-     */
-    public static class DummyFragment extends Fragment {
-
-        @Override
-        public View onCreateView(LayoutInflater inflater, ViewGroup container,
-                Bundle savedInstanceState) {
-            final View v = new View(inflater.getContext());
-            v.setVisibility(View.GONE);
-            return v;
-        }
-    }
-
-    /**
      * Returns the GuidanceStylist that displays guidance information for the user.
      * @return The GuidanceStylist for this fragment.
      */
@@ -755,12 +722,12 @@
      * Called by Constructor to provide fragment transitions.  The default implementation assigns
      * transitions based on {@link #getUiStyle()}:
      * <ul>
-     * <li> {@link #UI_STYLE_DEFAULT} Slide from/to end(right) for enter transition, slide from/to
+     * <li> {@link #UI_STYLE_REPLACE} Slide from/to end(right) for enter transition, slide from/to
      * start(left) for exit transition, shared element enter transition is set to ChangeBounds.
      * <li> {@link #UI_STYLE_ENTRANCE} Enter transition is set to slide from both sides, exit
-     * transition is same as {@link #UI_STYLE_DEFAULT}, no shared element enter transition.
+     * transition is same as {@link #UI_STYLE_REPLACE}, no shared element enter transition.
      * <li> {@link #UI_STYLE_ACTIVITY_ROOT} Enter transition is set to null and app should rely on
-     * activity transition, exit transition is same as {@link #UI_STYLE_DEFAULT}, no shared element
+     * activity transition, exit transition is same as {@link #UI_STYLE_REPLACE}, no shared element
      * enter transition.
      * </ul>
      * <p>
@@ -775,7 +742,8 @@
      */
     protected void onProvideFragmentTransitions() {
         if (Build.VERSION.SDK_INT >= 21) {
-            if (getUiStyle() == UI_STYLE_DEFAULT) {
+            final int uiStyle = getUiStyle();
+            if (uiStyle == UI_STYLE_REPLACE) {
                 Object enterTransition = TransitionHelper.createFadeAndShortSlide(Gravity.END);
                 TransitionHelper.exclude(enterTransition, R.id.action_fragment_background, true);
                 TransitionHelper.exclude(enterTransition, R.id.guided_button_actions_background,
@@ -783,7 +751,32 @@
                 TransitionHelper.exclude(enterTransition, R.id.guided_button_actions_background2,
                         true);
                 TransitionHelper.exclude(enterTransition, R.id.guidedactions_selector, true);
+                TransitionHelper.exclude(enterTransition, R.id.guidedstep_background, true);
                 TransitionHelper.setEnterTransition(this, enterTransition);
+
+                // exit transition is unchanged, same as default UI_STYLE_ENTRANCE
+
+                Object changeBounds = TransitionHelper.createChangeBounds(false);
+                TransitionHelper.setSharedElementEnterTransition(this, changeBounds);
+            } else if (uiStyle == UI_STYLE_ENTRANCE) {
+                Object fade = TransitionHelper.createFadeTransition(TransitionHelper.FADE_IN |
+                        TransitionHelper.FADE_OUT);
+                TransitionHelper.include(fade, R.id.guidedstep_background);
+                Object slide = TransitionHelper.createFadeAndShortSlide(Gravity.END |
+                        Gravity.START);
+                TransitionHelper.include(slide, R.id.content_fragment);
+                TransitionHelper.include(slide, R.id.action_fragment_background);
+                TransitionHelper.include(slide, R.id.guided_button_actions_background);
+                TransitionHelper.include(slide, R.id.guidedactions_selector);
+                TransitionHelper.include(slide, R.id.guidedactions_list);
+                TransitionHelper.include(slide, R.id.guided_button_actions_background2);
+                TransitionHelper.include(slide, R.id.guidedactions_selector2);
+                TransitionHelper.include(slide, R.id.guidedactions_list2);
+                Object enterTransition = TransitionHelper.createTransitionSet(false);
+                TransitionHelper.addTransition(enterTransition, fade);
+                TransitionHelper.addTransition(enterTransition, slide);
+                TransitionHelper.setEnterTransition(this, enterTransition);
+
                 Object exitTransition = TransitionHelper.createFadeAndShortSlide(Gravity.START);
                 TransitionHelper.exclude(exitTransition, R.id.action_fragment_background, true);
                 TransitionHelper.exclude(exitTransition, R.id.guided_button_actions_background,
@@ -792,118 +785,47 @@
                 TransitionHelper.exclude(exitTransition, R.id.guided_button_actions_background2,
                         true);
                 TransitionHelper.exclude(exitTransition, R.id.guidedactions_selector2, true);
+                TransitionHelper.exclude(exitTransition, R.id.guidedstep_background, true);
                 TransitionHelper.setExitTransition(this, exitTransition);
-
-                Object changeBounds = TransitionHelper.createChangeBounds(false);
-                TransitionHelper.setSharedElementEnterTransition(this, changeBounds);
-            } else if (getUiStyle() == UI_STYLE_ENTRANCE) {
-                Object enterTransition = TransitionHelper.createFadeAndShortSlide(Gravity.END |
-                        Gravity.START);
-                TransitionHelper.include(enterTransition, R.id.content_fragment);
-                TransitionHelper.include(enterTransition, R.id.action_fragment_background);
-                TransitionHelper.include(enterTransition, R.id.guided_button_actions_background);
-                TransitionHelper.include(enterTransition, R.id.guidedactions_selector);
-                TransitionHelper.include(enterTransition, R.id.guidedactions_list);
-                TransitionHelper.include(enterTransition, R.id.guided_button_actions_background2);
-                TransitionHelper.include(enterTransition, R.id.guidedactions_selector2);
-                TransitionHelper.include(enterTransition, R.id.guidedactions_list2);
-                TransitionHelper.setEnterTransition(this, enterTransition);
-                // exit transition is unchanged, same as UI_STYLE_DEFAULT
                 // No shared element transition
                 TransitionHelper.setSharedElementEnterTransition(this, null);
-            } else if (getUiStyle() == UI_STYLE_ACTIVITY_ROOT) {
+            } else if (uiStyle == UI_STYLE_ACTIVITY_ROOT) {
                 // for Activity root, we dont need enter transition, use activity transition
                 TransitionHelper.setEnterTransition(this, null);
-                // exit transition is unchanged, same as UI_STYLE_DEFAULT
+                // exit transition is unchanged, same as UI_STYLE_ENTRANCE
                 // No shared element transition
                 TransitionHelper.setSharedElementEnterTransition(this, null);
+            } else {
+                return;
             }
         }
     }
 
     /**
-     * Default implementation of background for covering content below GuidedStepSupportFragment.
-     * It uses current theme attribute guidedStepBackground which by default is read from
-     * android:windowBackground.
+     * Called by onCreateView to inflate background view.  Default implementation loads view
+     * from {@link R.layout#lb_guidedstep_background} which holds a reference to
+     * guidedStepBackground.
+     * @param inflater LayoutInflater to load background view.
+     * @param container Parent view of background view.
+     * @param savedInstanceState
+     * @return Created background view or null if no background.
      */
-    public static class GuidedStepBackgroundSupportFragment extends Fragment {
-        public GuidedStepBackgroundSupportFragment() {
-            onProvideFragmentTransitions();
-        }
-
-        /**
-         * Sets fragment transitions for GuidedStepBackgroundSupportFragment.  Can be overridden.
-         */
-        protected void onProvideFragmentTransitions() {
-            if (Build.VERSION.SDK_INT >= 21) {
-                Object enterTransition = TransitionHelper.createFadeTransition(
-                        TransitionHelper.FADE_IN|TransitionHelper.FADE_OUT);
-                TransitionHelper.setEnterTransition(this, enterTransition);
-            }
-        }
-
-        @Override
-        public View onCreateView(LayoutInflater inflater, ViewGroup container,
-                Bundle savedInstanceState) {
-            FragmentActivity activity = getActivity();
-            Context themedContext = null;
-            if (!isGuidedStepTheme(activity)) {
-                // Look up the guidedStepTheme in the activity's currently specified theme.  If it
-                // exists, replace the theme with its value.
-                int resId = R.attr.guidedStepTheme;
-                TypedValue typedValue = new TypedValue();
-                boolean found = activity.getTheme().resolveAttribute(resId, typedValue, true);
-                if (DEBUG) Log.v(TAG, "Found guided step theme reference? " + found);
-                if (found) {
-                    ContextThemeWrapper themeWrapper =
-                            new ContextThemeWrapper(activity, typedValue.resourceId);
-                    if (isGuidedStepTheme(themeWrapper)) {
-                        themedContext = themeWrapper;
-                    }
-                }
-                if (!found) {
-                    Log.e(TAG, "GuidedStepSupportFragment does not have an appropriate theme set.");
-                }
-            }
-
-            if (themedContext != null) {
-                inflater = inflater.cloneInContext(themedContext);
-            }
-
-            return inflater.inflate(R.layout.lb_guidedstep_background, container, false);
-        }
+    public View onCreateBackgroundView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        return inflater.inflate(R.layout.lb_guidedstep_background, container, false);
     }
 
     /**
-     * Creates a background fragment for {@link #UI_STYLE_ENTRANCE}, returns null for other cases.
-     * Subclass may override the default behavior, e.g. provide different backgrounds
-     * for {@link #UI_STYLE_DEFAULT}.  Background fragment will be inserted in {@link
-     * #getContainerIdForBackground()}.
+     * Set UI style to fragment arguments. Default value is {@link #UI_STYLE_ENTRANCE} when fragment
+     * is first initialized. UI style is used to choose different fragment transition animations and
+     * determine if this is the first GuidedStepSupportFragment on backstack. In most cases app does not
+     * directly call this method, app calls helper function
+     * {@link #add(FragmentManager, GuidedStepSupportFragment, int)}. However if the app creates Fragment
+     * transaction and controls backstack by itself, it would need call setUiStyle() to select the
+     * fragment transition to use.
      *
-     * @return fragment that will be inserted below GuidedStepSupportFragment.
-     */
-    protected Fragment onProvideBackgroundSupportFragment() {
-        if (getUiStyle() == UI_STYLE_ENTRANCE) {
-            return new GuidedStepBackgroundSupportFragment();
-        }
-        return null;
-    }
-
-    /**
-     * Returns container id for inserting {@link #onProvideBackgroundSupportFragment()}.  The id should be
-     * different than container id for inserting GuidedStepSupportFragment.
-     * Default value is {@link View#NO_ID}.  Subclass must override to host background fragment.
-     * @return container id for inserting {@link #onProvideBackgroundSupportFragment()}
-     */
-    protected int getContainerIdForBackground() {
-        return View.NO_ID;
-    }
-
-
-    /**
-     * Set UI style to fragment arguments,  UI style cannot be changed after initialization.
-     * @param style {@link #UI_STYLE_ACTIVITY_ROOT} {@link #UI_STYLE_DEFAULT} or
-     * {@link #UI_STYLE_ENTRANCE}.
+     * @param style {@link #UI_STYLE_ACTIVITY_ROOT} {@link #UI_STYLE_REPLACE} or
+     *        {@link #UI_STYLE_ENTRANCE}.
      */
     public void setUiStyle(int style) {
         int oldStyle = getUiStyle();
@@ -924,15 +846,18 @@
     }
 
     /**
-     * Read UI style from fragment arguments.
+     * Read UI style from fragment arguments.  Default value is {@link #UI_STYLE_ENTRANCE} when
+     * fragment is first initialized.  UI style is used to choose different fragment transition
+     * animations and determine if this is the first GuidedStepSupportFragment on backstack.
      *
-     * @return {@link #UI_STYLE_ACTIVITY_ROOT} {@link #UI_STYLE_DEFAULT} or
+     * @return {@link #UI_STYLE_ACTIVITY_ROOT} {@link #UI_STYLE_REPLACE} or
      * {@link #UI_STYLE_ENTRANCE}.
+     * @see #onProvideFragmentTransitions()
      */
     public int getUiStyle() {
         Bundle b = getArguments();
-        if (b == null) return UI_STYLE_DEFAULT;
-        return b.getInt(EXTRA_UI_STYLE, UI_STYLE_DEFAULT);
+        if (b == null) return UI_STYLE_ENTRANCE;
+        return b.getInt(EXTRA_UI_STYLE, UI_STYLE_ENTRANCE);
     }
 
     /**
@@ -966,6 +891,9 @@
         mGuidanceStylist.onDestroyView();
         mActionsStylist.onDestroyView();
         mButtonActionsStylist.onDestroyView();
+        mAdapter = null;
+        mButtonAdapter = null;
+        mAdapterGroup = null;
         super.onDestroyView();
     }
 
@@ -980,9 +908,10 @@
         resolveTheme();
         inflater = getThemeInflater(inflater);
 
-        View v = inflater.inflate(R.layout.lb_guidedstep_fragment, container, false);
-        ViewGroup guidanceContainer = (ViewGroup) v.findViewById(R.id.content_fragment);
-        ViewGroup actionContainer = (ViewGroup) v.findViewById(R.id.action_fragment);
+        ViewGroup root = (ViewGroup) inflater.inflate(R.layout.lb_guidedstep_fragment,
+                container, false);
+        ViewGroup guidanceContainer = (ViewGroup) root.findViewById(R.id.content_fragment);
+        ViewGroup actionContainer = (ViewGroup) root.findViewById(R.id.action_fragment);
 
         Guidance guidance = onCreateGuidance(savedInstanceState);
         View guidanceView = mGuidanceStylist.onCreateView(inflater, guidanceContainer, guidance);
@@ -1013,10 +942,12 @@
                 }
         };
 
-        mAdapter = new GuidedActionAdapter(mActions, this, this, editListener,
-                mActionsStylist);
-        mButtonAdapter = new GuidedActionAdapter(mButtonActions, this, this, editListener,
-                mButtonActionsStylist);
+        mAdapter = new GuidedActionAdapter(mActions, this, this, mActionsStylist);
+        mButtonAdapter = new GuidedActionAdapter(mButtonActions, this, this, mButtonActionsStylist);
+        mAdapterGroup = new GuidedActionAdapterGroup();
+        mAdapterGroup.addAdpter(mAdapter);
+        mAdapterGroup.addAdpter(mButtonAdapter);
+        mAdapterGroup.setEditListener(editListener);
 
         mActionsStylist.getActionsGridView().setAdapter(mAdapter);
         mButtonActionsStylist.getActionsGridView().setAdapter(mButtonAdapter);
@@ -1034,7 +965,7 @@
             TypedValue typedValue = new TypedValue();
             if (ctx.getTheme().resolveAttribute(R.attr.guidedActionContentWidthWeightTwoPanels,
                     typedValue, true)) {
-                View actionsRoot = v.findViewById(R.id.action_fragment_root);
+                View actionsRoot = root.findViewById(R.id.action_fragment_root);
                 float weight = typedValue.getFloat();
                 LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) actionsRoot
                         .getLayoutParams();
@@ -1049,7 +980,11 @@
 
         setSelectedButtonActionPosition(0);
 
-        return v;
+        View backgroundView = onCreateBackgroundView(inflater, root, savedInstanceState);
+        if (backgroundView != null) {
+            root.addView(backgroundView, 0);
+        }
+        return root;
     }
 
     @Override
@@ -1081,6 +1016,8 @@
      * Convenient method to close GuidedStepSupportFragments on top of other content or finish Activity if
      * GuidedStepSupportFragments were started in a separate activity.  Pops all stack entries including
      * {@link #UI_STYLE_ENTRANCE}; if {@link #UI_STYLE_ENTRANCE} is not found, finish the activity.
+     * Note that this method must be paired with {@link #add(FragmentManager, GuidedStepSupportFragment,
+     * int)} which sets up the stack entry name for finding which fragment we need to pop back to.
      */
     public void finishGuidedStepSupportFragments() {
         final FragmentManager fragmentManager = getFragmentManager();
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/CheckableImageView.java b/v17/leanback/src/android/support/v17/leanback/widget/CheckableImageView.java
new file mode 100644
index 0000000..627bbd4
--- /dev/null
+++ b/v17/leanback/src/android/support/v17/leanback/widget/CheckableImageView.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package android.support.v17.leanback.widget;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.Checkable;
+import android.widget.ImageView;
+
+/**
+ * ImageView that supports Checkable states.
+ */
+class CheckableImageView extends ImageView implements Checkable {
+
+    private boolean mChecked;
+
+    private static final int[] CHECKED_STATE_SET = { android.R.attr.state_checked };
+
+    public CheckableImageView(Context context) {
+        this(context, null);
+    }
+
+    public CheckableImageView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public CheckableImageView(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+    }
+
+    @Override
+    public int[] onCreateDrawableState(final int extraSpace) {
+        final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
+        if (isChecked()) {
+            mergeDrawableStates(drawableState, CHECKED_STATE_SET);
+        }
+        return drawableState;
+    }
+
+    @Override
+    public void toggle() {
+        setChecked(!mChecked);
+    }
+
+    @Override
+    public boolean isChecked() {
+        return mChecked;
+    }
+
+    @Override
+    public void setChecked(final boolean checked) {
+        if (mChecked != checked) {
+            mChecked = checked;
+            refreshDrawableState();
+        }
+    }
+
+}
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/GridLayoutManager.java b/v17/leanback/src/android/support/v17/leanback/widget/GridLayoutManager.java
index e7fa99f0..20d54e2 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/GridLayoutManager.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/GridLayoutManager.java
@@ -1773,6 +1773,11 @@
         mFocusPositionOffset = 0;
         saveContext(recycler, state);
 
+        View savedFocusView = findViewByPosition(mFocusPosition);
+        int savedFocusPos = mFocusPosition;
+        int savedSubFocusPos = mSubFocusPosition;
+        boolean hadFocus = mBaseGridView.hasFocus();
+
         // Track the old focus view so we can adjust our system scroll position
         // so that any scroll animations happening now will remain valid.
         // We must use same delta in Pre Layout (if prelayout exists) and second layout.
@@ -1781,17 +1786,14 @@
         if (mFocusPosition != NO_POSITION && scrollToFocus
                 && mBaseGridView.getScrollState() != RecyclerView.SCROLL_STATE_IDLE) {
             // FIXME: we should get the remaining scroll animation offset from RecyclerView
-            View focusView = findViewByPosition(mFocusPosition);
-            if (focusView != null) {
-                if (getScrollPosition(focusView, focusView.findFocus(), sTwoInts)) {
+            if (savedFocusView != null) {
+                if (getScrollPosition(savedFocusView, savedFocusView.findFocus(), sTwoInts)) {
                     delta = sTwoInts[0];
                     deltaSecondary = sTwoInts[1];
                 }
             }
         }
 
-        boolean hadFocus = mBaseGridView.hasFocus();
-        int savedFocusPos = mFocusPosition;
         if (mInFastRelayout = layoutInit()) {
             fastRelayout();
             // appends items till focus position.
@@ -1859,7 +1861,8 @@
         }
 
         // For fastRelayout, only dispatch event when focus position changes.
-        if (mInFastRelayout && mFocusPosition != savedFocusPos) {
+        if (mInFastRelayout && (mFocusPosition != savedFocusPos || mSubFocusPosition !=
+                savedFocusPos || findViewByPosition(mFocusPosition) != savedFocusView)) {
             dispatchChildSelected();
         } else if (!mInFastRelayout && mInLayoutSearchFocus) {
             // For full layout we dispatchChildSelected() in createItem() unless searched all
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/GuidanceStylist.java b/v17/leanback/src/android/support/v17/leanback/widget/GuidanceStylist.java
index 3485e93..3fcdbba 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/GuidanceStylist.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/GuidanceStylist.java
@@ -176,6 +176,10 @@
      * Called when destroy the View created by GuidanceStylist.
      */
     public void onDestroyView() {
+        mBreadcrumbView = null;
+        mDescriptionView = null;
+        mIconView = null;
+        mTitleView = null;
     }
 
     /**
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/GuidedAction.java b/v17/leanback/src/android/support/v17/leanback/widget/GuidedAction.java
index 4031677..21986d5 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/GuidedAction.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/GuidedAction.java
@@ -37,8 +37,18 @@
 
     private static final String TAG = "GuidedAction";
 
+    /**
+     * Special check set Id that is neither checkbox nor radio.
+     */
     public static final int NO_CHECK_SET = 0;
+    /**
+     * Default checkset Id for radio.
+     */
     public static final int DEFAULT_CHECK_SET_ID = 1;
+    /**
+     * Checkset Id for checkbox.
+     */
+    public static final int CHECKBOX_CHECK_SET_ID = -1;
 
     /**
      * When finishing editing, goes to next action.
@@ -371,10 +381,11 @@
         }
 
         /**
-         * Indicates whether this action is part of a single-select group similar to radio buttons.
-         * When one item in a check set is checked, all others with the same check set ID will be
-         * unchecked automatically.
-         * @param checkSetId The check set ID, or {@link #NO_CHECK_SET) to indicate no check set.
+         * Indicates whether this action is part of a single-select group similar to radio buttons
+         * or this action is a checkbox. When one item in a check set is checked, all others with
+         * the same check set ID will be nchecked automatically.
+         * @param checkSetId The check set ID, or {@link GuidedAction#NO_CHECK_SET} to indicate not
+         * radio or checkbox, or {@link GuidedAction#CHECKBOX_CHECK_SET_ID} to indicate a checkbox.
          */
         public Builder checkSetId(int checkSetId) {
             mCheckSetId = checkSetId;
@@ -604,13 +615,13 @@
     }
 
     /**
-     * Returns the check set id this action is a part of. All actions in the
-     * same list with the same check set id are considered linked. When one
-     * of the actions within that set is selected, that action becomes
-     * checked, while all the other actions become unchecked.
+     * Returns the check set id this action is a part of. All actions in the same list with the same
+     * check set id are considered linked. When one of the actions within that set is selected, that
+     * action becomes checked, while all the other actions become unchecked.
      *
      * @return an integer representing the check set this action is a part of, or
-     *         {@link #NO_CHECK_SET} if this action isn't a part of a check set.
+     *         {@link #CHECKBOX_CHECK_SET_ID} if this is a checkbox, or {@link #NO_CHECK_SET} if
+     *         this action is not a checkbox or radiobutton.
      */
     public int getCheckSetId() {
         return mCheckSetId;
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/GuidedActionsStylist.java b/v17/leanback/src/android/support/v17/leanback/widget/GuidedActionsStylist.java
index ab50399..8cdcdc8 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/GuidedActionsStylist.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/GuidedActionsStylist.java
@@ -27,6 +27,7 @@
 import android.support.annotation.NonNull;
 import android.support.v17.leanback.R;
 import android.support.v17.leanback.widget.VerticalGridView;
+import android.support.v4.content.ContextCompat;
 import android.support.v4.view.ViewCompat;
 import android.support.v7.widget.RecyclerView;
 import android.support.v7.widget.RecyclerView.ViewHolder;
@@ -34,6 +35,7 @@
 import android.util.Log;
 import android.util.TypedValue;
 import android.view.animation.DecelerateInterpolator;
+import android.view.inputmethod.EditorInfo;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -41,6 +43,7 @@
 import android.view.ViewPropertyAnimator;
 import android.view.ViewTreeObserver;
 import android.view.WindowManager;
+import android.widget.Checkable;
 import android.widget.EditText;
 import android.widget.ImageView;
 import android.widget.TextView;
@@ -101,8 +104,6 @@
  * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionItemTitleStyle
  * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionItemDescriptionStyle
  * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionItemChevronStyle
- * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionCheckedAnimation
- * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionUncheckedAnimation
  * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionPressedAnimation
  * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionUnpressedAnimation
  * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionEnabledChevronAlpha
@@ -111,6 +112,8 @@
  * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionTitleMaxLines
  * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionDescriptionMinLines
  * @attr ref android.support.v17.leanback.R.styleable#LeanbackGuidedStepTheme_guidedActionVerticalPadding
+ * @see android.R.styleable#Theme_listChoiceIndicatorSingle
+ * @see android.R.styleable#Theme_listChoiceIndicatorMultiple
  * @see android.support.v17.leanback.app.GuidedStepFragment
  * @see GuidedAction
  */
@@ -386,6 +389,10 @@
             mActionsGridView.getViewTreeObserver().removeOnGlobalFocusChangeListener(
                     mGlobalFocusChangeListener);
         }
+        mActionsGridView = null;
+        mSelectorView = null;
+        mBgView = null;
+        mMainView = null;
     }
 
     /**
@@ -515,14 +522,12 @@
             vh.mDescriptionView.setFocusable(action.isDescriptionEditable());
         }
         // Clients might want the check mark view to be gone entirely, in which case, ignore it.
-        if (vh.mCheckmarkView != null && vh.mCheckmarkView.getVisibility() != View.GONE) {
-            vh.mCheckmarkView.setVisibility(action.isChecked() ? View.VISIBLE : View.INVISIBLE);
+        if (vh.mCheckmarkView != null) {
+            onBindCheckMarkView(vh, action);
         }
 
         if (vh.mChevronView != null) {
-            vh.mChevronView.setVisibility(action.hasNext() ? View.VISIBLE : View.GONE);
-            vh.mChevronView.setAlpha(action.isEnabled() ? mEnabledChevronAlpha :
-                    mDisabledChevronAlpha);
+            onBindChevronView(vh, action);
         }
 
         if (action.hasMultilineDescription()) {
@@ -553,6 +558,24 @@
                 ((ViewGroup) vh.view).setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
             }
         }
+        setupImeOptions(vh, action);
+    }
+
+    /**
+     * Called by {@link #onBindViewHolder(ViewHolder, GuidedAction)} to setup IME options.  Default
+     * implementation assigns {@link EditorInfo#IME_ACTION_DONE}.  Subclass may override.
+     * @param vh The view holder to be associated with the given action.
+     * @param action The guided action to be displayed by the view holder's view.
+     */
+    protected void setupImeOptions(ViewHolder vh, GuidedAction action) {
+        setupNextImeOptions(vh.getEditableTitleView());
+        setupNextImeOptions(vh.getEditableDescriptionView());
+    }
+
+    private void setupNextImeOptions(EditText edit) {
+        if (edit != null) {
+            edit.setImeOptions(EditorInfo.IME_ACTION_NEXT);
+        }
     }
 
     public void setEditingMode(ViewHolder vh, GuidedAction action, boolean editing) {
@@ -640,31 +663,69 @@
     }
 
     /**
-     * Animates the view holder's view (or subviews thereof) when the action has had its check
-     * state changed.
+     * Animates the view holder's view (or subviews thereof) when the action has had its check state
+     * changed. Default implementation calls setChecked() if {@link ViewHolder#getCheckmarkView()}
+     * is instance of {@link Checkable}.
+     *
      * @param vh The view holder associated with the relevant action.
      * @param checked True if the action has become checked, false if it has become unchecked.
+     * @see #onBindCheckMarkView(ViewHolder, GuidedAction)
      */
     public void onAnimateItemChecked(ViewHolder vh, boolean checked) {
-        final View checkView = vh.mCheckmarkView;
-        if (checkView != null) {
-            if (checked) {
-                checkView.setVisibility(View.VISIBLE);
-                createAnimator(checkView, R.attr.guidedActionCheckedAnimation).start();
-            } else {
-                Animator animator = createAnimator(checkView,
-                        R.attr.guidedActionUncheckedAnimation);
-                animator.addListener(new AnimatorListenerAdapter() {
-                    @Override
-                    public void onAnimationEnd(Animator animation) {
-                        checkView.setVisibility(View.INVISIBLE);
-                    }
-                });
-                animator.start();
-            }
+        if (vh.mCheckmarkView instanceof Checkable) {
+            ((Checkable) vh.mCheckmarkView).setChecked(checked);
         }
     }
 
+    /**
+     * Sets states of check mark view, called by {@link #onBindViewHolder(ViewHolder, GuidedAction)}
+     * when action's checkset Id is other than {@link GuidedAction#NO_CHECK_SET}. Default
+     * implementation assigns drawable loaded from theme attribute
+     * {@link android.R.attr#listChoiceIndicatorMultiple} for checkbox or
+     * {@link android.R.attr#listChoiceIndicatorSingle} for radio button. Subclass rarely needs
+     * override the method, instead app can provide its own drawable that supports transition
+     * animations, change theme attributes {@link android.R.attr#listChoiceIndicatorMultiple} and
+     * {@link android.R.attr#listChoiceIndicatorSingle} in {android.support.v17.leanback.R.
+     * styleable#LeanbackGuidedStepTheme}.
+     *
+     * @param vh The view holder associated with the relevant action.
+     * @param action The GuidedAction object to bind to.
+     * @see #onAnimateItemChecked(ViewHolder, boolean)
+     */
+    public void onBindCheckMarkView(ViewHolder vh, GuidedAction action) {
+        if (action.getCheckSetId() != GuidedAction.NO_CHECK_SET) {
+            vh.mCheckmarkView.setVisibility(View.VISIBLE);
+            int attrId = action.getCheckSetId() == GuidedAction.CHECKBOX_CHECK_SET_ID ?
+                    android.R.attr.listChoiceIndicatorMultiple :
+                    android.R.attr.listChoiceIndicatorSingle;
+            final Context context = vh.mCheckmarkView.getContext();
+            Drawable drawable = null;
+            TypedValue typedValue = new TypedValue();
+            if (context.getTheme().resolveAttribute(attrId, typedValue, true)) {
+                drawable = ContextCompat.getDrawable(context, typedValue.resourceId);
+            }
+            vh.mCheckmarkView.setImageDrawable(drawable);
+            if (vh.mCheckmarkView instanceof Checkable) {
+                ((Checkable) vh.mCheckmarkView).setChecked(action.isChecked());
+            }
+        } else {
+            vh.mCheckmarkView.setVisibility(View.GONE);
+        }
+    }
+
+    /**
+     * Sets states of chevron view, called by {@link #onBindViewHolder(ViewHolder, GuidedAction)}.
+     * Subclass may override.
+     *
+     * @param vh The view holder associated with the relevant action.
+     * @param action The GuidedAction object to bind to.
+     */
+    public void onBindChevronView(ViewHolder vh, GuidedAction action) {
+        vh.mChevronView.setVisibility(action.hasNext() ? View.VISIBLE : View.GONE);
+        vh.mChevronView.setAlpha(action.isEnabled() ? mEnabledChevronAlpha :
+                mDisabledChevronAlpha);
+    }
+
     /*
      * ==========================================
      * FragmentAnimationProvider overrides
diff --git a/v17/tests/src/android/support/v17/leanback/widget/GridActivity.java b/v17/tests/src/android/support/v17/leanback/widget/GridActivity.java
index 145ae48..902a665 100644
--- a/v17/tests/src/android/support/v17/leanback/widget/GridActivity.java
+++ b/v17/tests/src/android/support/v17/leanback/widget/GridActivity.java
@@ -360,7 +360,8 @@
                 holder.mItemAlignment = null;
             }
             if (mChildLayout == -1) {
-                ((TextView) holder.itemView).setText("Item "+mItemLengths[position]);
+                ((TextView) holder.itemView).setText("Item "+mItemLengths[position]
+                        + " type=" + getItemViewType(position));
                 boolean focusable = true;
                 if (mItemFocusables != null) {
                     focusable = mItemFocusables[position];
@@ -370,7 +371,8 @@
                 holder.itemView.setBackgroundColor(Color.LTGRAY);
             } else {
                 if (holder.itemView instanceof TextView) {
-                    ((TextView) holder.itemView).setText("Item "+mItemLengths[position]);
+                    ((TextView) holder.itemView).setText("Item "+mItemLengths[position]
+                            + " type=" + getItemViewType(position));
                 }
             }
             updateSize(holder.itemView, position);
@@ -380,6 +382,7 @@
         public int getItemCount() {
             return mNumItems;
         }
+
     }
 
     void updateSize(View view, int position) {
diff --git a/v17/tests/src/android/support/v17/leanback/widget/GridWidgetTest.java b/v17/tests/src/android/support/v17/leanback/widget/GridWidgetTest.java
index a24e1f6..335f449 100644
--- a/v17/tests/src/android/support/v17/leanback/widget/GridWidgetTest.java
+++ b/v17/tests/src/android/support/v17/leanback/widget/GridWidgetTest.java
@@ -21,6 +21,7 @@
 import android.text.Spannable;
 import android.util.Log;
 import android.util.SparseArray;
+import android.util.SparseIntArray;
 import android.view.KeyEvent;
 import android.view.View;
 import android.view.ViewGroup;
@@ -1886,6 +1887,20 @@
         }
     }
 
+    static class ChangeableViewTypesProvider implements ViewTypeProvider {
+        static SparseIntArray sViewTypes = new SparseIntArray();
+        @Override
+        public int getViewType(int position) {
+            return sViewTypes.get(position);
+        }
+        public static void clear() {
+            sViewTypes.clear();
+        }
+        public static void setViewType(int position, int type) {
+            sViewTypes.put(position, type);
+        }
+    }
+
     static class PositionItemAlignmentFacetProviderForRelativeLayout1
             implements ItemAlignmentFacetProvider {
         ItemAlignmentFacet mMultipleFacet;
@@ -2101,6 +2116,38 @@
         assertEquals(0, mGridView.getSelectedPosition());
     }
 
+    public void testNotifyItemTypeChangedSelectionEvent() throws Throwable {
+        mInstrumentation = getInstrumentation();
+        Intent intent = new Intent(mInstrumentation.getContext(), GridActivity.class);
+        intent.putExtra(GridActivity.EXTRA_LAYOUT_RESOURCE_ID,
+                R.layout.vertical_linear);
+        intent.putExtra(GridActivity.EXTRA_NUM_ITEMS, 10);
+        intent.putExtra(GridActivity.EXTRA_VIEWTYPEPROVIDER_CLASS,
+                ChangeableViewTypesProvider.class.getName());
+        ChangeableViewTypesProvider.clear();
+        initActivity(intent);
+        mOrientation = BaseGridView.HORIZONTAL;
+        mNumRows = 1;
+
+        final ArrayList<Integer> selectedLog = new ArrayList<Integer>();
+        mGridView.setOnChildSelectedListener(new OnChildSelectedListener() {
+            public void onChildSelected(ViewGroup parent, View view, int position, long id) {
+                selectedLog.add(position);
+            }
+        });
+
+        runTestOnUiThread(new Runnable() {
+            public void run() {
+                ChangeableViewTypesProvider.setViewType(0, 1);
+                mGridView.getAdapter().notifyItemChanged(0, 1);
+            }
+        });
+        waitForTransientStateGone(null);
+        assertEquals(0, mGridView.getSelectedPosition());
+        assertEquals(selectedLog.size(), 1);
+        assertEquals((int) selectedLog.get(0), 0);
+    }
+
     public void testSelectionSmoothAndAddItemInOneCycle() throws Throwable {
         mInstrumentation = getInstrumentation();
         Intent intent = new Intent(mInstrumentation.getContext(), GridActivity.class);
diff --git a/v4/api21/android/service/media/IMediaBrowserServiceCallbacks.java b/v4/api21/android/service/media/IMediaBrowserServiceCallbacks.java
index 4bea5d9..fe988fe 100644
--- a/v4/api21/android/service/media/IMediaBrowserServiceCallbacks.java
+++ b/v4/api21/android/service/media/IMediaBrowserServiceCallbacks.java
@@ -18,8 +18,11 @@
 
 import android.content.pm.ParceledListSlice;
 import android.media.session.MediaSession;
+import android.os.Binder;
 import android.os.Bundle;
+import android.os.IBinder;
 import android.os.IInterface;
+import android.os.Parcel;
 import android.os.RemoteException;
 
 /**
@@ -30,6 +33,56 @@
  * @hide
  */
 public interface IMediaBrowserServiceCallbacks extends IInterface {
+    public static abstract class Stub extends Binder implements IMediaBrowserServiceCallbacks
+    {
+        public Stub() {
+        }
+
+        public static IMediaBrowserServiceCallbacks asInterface(IBinder obj) {
+            return null;
+        }
+
+        @Override
+        public IBinder asBinder() {
+            return null;
+        }
+
+        @Override
+        public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
+                throws RemoteException {
+            return false;
+        }
+
+        private static class Proxy implements IMediaBrowserServiceCallbacks
+        {
+            Proxy(IBinder remote) {
+            }
+
+            @Override
+            public IBinder asBinder() {
+                return null;
+            }
+
+            public String getInterfaceDescriptor() {
+                return null;
+            }
+
+            @Override
+            public void onConnect(String root, MediaSession.Token session, Bundle extras)
+                    throws RemoteException {
+            }
+
+            @Override
+            public void onConnectFailed() throws RemoteException {
+            }
+
+            @Override
+            public void onLoadChildren(String mediaId, ParceledListSlice list)
+                    throws RemoteException {
+            }
+        }
+    }
+
     public void onConnect(String root, MediaSession.Token session, Bundle extras)
             throws RemoteException;
     public void onConnectFailed() throws RemoteException;
diff --git a/v4/java/android/support/v4/view/PagerAdapter.java b/v4/java/android/support/v4/view/PagerAdapter.java
index ef52404..55fb9c1 100644
--- a/v4/java/android/support/v4/view/PagerAdapter.java
+++ b/v4/java/android/support/v4/view/PagerAdapter.java
@@ -76,7 +76,8 @@
  * the method {@link #getItemPosition(Object)}.</p>
  */
 public abstract class PagerAdapter {
-    private DataSetObservable mObservable = new DataSetObservable();
+    private final DataSetObservable mObservable = new DataSetObservable();
+    private DataSetObserver mViewPagerObserver;
 
     public static final int POSITION_UNCHANGED = -1;
     public static final int POSITION_NONE = -2;
@@ -273,6 +274,11 @@
      * and associated views should update.
      */
     public void notifyDataSetChanged() {
+        synchronized (this) {
+            if (mViewPagerObserver != null) {
+                mViewPagerObserver.onChanged();
+            }
+        }
         mObservable.notifyChanged();
     }
 
@@ -294,6 +300,12 @@
         mObservable.unregisterObserver(observer);
     }
 
+    void setViewPagerObserver(DataSetObserver observer) {
+        synchronized (this) {
+            mViewPagerObserver = observer;
+        }
+    }
+
     /**
      * This method may be called by the ViewPager to obtain a title string
      * to describe the specified page. This method may return null
diff --git a/v4/java/android/support/v4/view/ViewPager.java b/v4/java/android/support/v4/view/ViewPager.java
index 454ac62..c6f3648 100644
--- a/v4/java/android/support/v4/view/ViewPager.java
+++ b/v4/java/android/support/v4/view/ViewPager.java
@@ -418,7 +418,7 @@
      */
     public void setAdapter(PagerAdapter adapter) {
         if (mAdapter != null) {
-            mAdapter.unregisterDataSetObserver(mObserver);
+            mAdapter.setViewPagerObserver(null);
             mAdapter.startUpdate(this);
             for (int i = 0; i < mItems.size(); i++) {
                 final ItemInfo ii = mItems.get(i);
@@ -439,7 +439,7 @@
             if (mObserver == null) {
                 mObserver = new PagerObserver();
             }
-            mAdapter.registerDataSetObserver(mObserver);
+            mAdapter.setViewPagerObserver(mObserver);
             mPopulatePending = false;
             final boolean wasFirstLayout = mFirstLayout;
             mFirstLayout = true;
diff --git a/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplV7.java b/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplV7.java
index d2c7b91..e147b7d 100644
--- a/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplV7.java
+++ b/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplV7.java
@@ -115,6 +115,8 @@
     private PanelFeatureState[] mPanels;
     private PanelFeatureState mPreparedPanel;
 
+    private boolean mLongPressBackDown;
+
     private boolean mInvalidatePanelMenuPosted;
     private int mInvalidatePanelMenuFeatures;
     private final Runnable mInvalidatePanelMenuRunnable = new Runnable() {
@@ -874,9 +876,17 @@
                 onKeyUpPanel(Window.FEATURE_OPTIONS_PANEL, event);
                 return true;
             case KeyEvent.KEYCODE_BACK:
+                final boolean wasLongPressBackDown = mLongPressBackDown;
+                mLongPressBackDown = false;
+
                 PanelFeatureState st = getPanelState(Window.FEATURE_OPTIONS_PANEL, false);
                 if (st != null && st.isOpen) {
-                    closePanel(st, true);
+                    if (!wasLongPressBackDown) {
+                        // Certain devices allow opening the options menu via a long press of the
+                        // back button. We should only close the open options menu if it wasn't
+                        // opened via a long press gesture.
+                        closePanel(st, true);
+                    }
                     return true;
                 }
                 if (onBackPressed()) {
@@ -895,6 +905,11 @@
                 // For empty menus, PhoneWindow's KEYCODE_BACK handling will steals all events,
                 // not allowing the Activity to call onBackPressed().
                 return true;
+            case KeyEvent.KEYCODE_BACK:
+                // Certain devices allow opening the options menu via a long press of the back
+                // button. We keep a record of whether the last event is from a long press.
+                mLongPressBackDown = (event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0;
+                break;
         }
 
         // On API v7-10 we need to manually call onKeyShortcut() as this is not called
diff --git a/v7/appcompat/src/android/support/v7/widget/AppCompatDrawableManager.java b/v7/appcompat/src/android/support/v7/widget/AppCompatDrawableManager.java
index eb04b01..89deb68 100644
--- a/v7/appcompat/src/android/support/v7/widget/AppCompatDrawableManager.java
+++ b/v7/appcompat/src/android/support/v7/widget/AppCompatDrawableManager.java
@@ -663,7 +663,7 @@
         return getPorterDuffColorFilter(color, tintMode);
     }
 
-    private static PorterDuffColorFilter getPorterDuffColorFilter(int color, PorterDuff.Mode mode) {
+    public static PorterDuffColorFilter getPorterDuffColorFilter(int color, PorterDuff.Mode mode) {
         // First, lets see if the cache already contains the color filter
         PorterDuffColorFilter filter = COLOR_FILTER_CACHE.get(color, mode);
 
diff --git a/v7/mediarouter/src/android/support/v7/app/MediaRouteChooserDialog.java b/v7/mediarouter/src/android/support/v7/app/MediaRouteChooserDialog.java
index 9beb8d9..8e5e2c6 100644
--- a/v7/mediarouter/src/android/support/v7/app/MediaRouteChooserDialog.java
+++ b/v7/mediarouter/src/android/support/v7/app/MediaRouteChooserDialog.java
@@ -28,7 +28,6 @@
 import android.os.Bundle;
 import android.preference.PreferenceManager;
 import android.support.annotation.NonNull;
-import android.support.v7.media.MediaControlIntent;
 import android.support.v7.media.MediaRouteSelector;
 import android.support.v7.media.MediaRouter;
 import android.support.v7.mediarouter.R;
@@ -65,9 +64,6 @@
 public class MediaRouteChooserDialog extends Dialog {
     private static final String TAG = "MediaRouteChooserDialog";
 
-    // Should match to SystemMediaRouteProvider.PACKAGE_NAME.
-    static final String SYSTEM_MEDIA_ROUTE_PROVIDER_PACKAGE_NAME = "android";
-
     private final MediaRouter mRouter;
     private final MediaRouterCallback mCallback;
 
@@ -322,7 +318,7 @@
                 // Only speakers can be grouped for now.
                 return mSpeakerGroupIcon;
             }
-            if (isSystemLiveAudioOnlyRoute(route)) {
+            if (route.isDeviceTypeBluetooth()) {
                 return mBluetoothIcon;
             }
             return mDefaultIcon;
@@ -365,11 +361,16 @@
 
         @Override
         public int compare(MediaRouter.RouteInfo lhs, MediaRouter.RouteInfo rhs) {
-            if (isSystemLiveAudioOnlyRoute(lhs)) {
-                if (!isSystemLiveAudioOnlyRoute(rhs)) {
+            if (lhs == null) {
+                return rhs == null ? 0 : -1;
+            } else if (rhs == null) {
+                return 1;
+            }
+            if (lhs.isDeviceTypeBluetooth()) {
+                if (!rhs.isDeviceTypeBluetooth()) {
                     return 1;
                 }
-            } else if (isSystemLiveAudioOnlyRoute(rhs)) {
+            } else if (rhs.isDeviceTypeBluetooth()) {
                 return -1;
             }
             Float lhsUsageScore = sRouteUsageScoreMap.get(lhs.getId());
@@ -430,17 +431,4 @@
             prefEditor.commit();
         }
     }
-
-    // Used to determine whether the route represents a bluetooth device.
-    // TODO: Find a better way to precisely detect bluetooth routes.
-    private static boolean isSystemLiveAudioOnlyRoute(MediaRouter.RouteInfo route) {
-        return isSystemMediaRouteProvider(route)
-                && route.supportsControlCategory(MediaControlIntent.CATEGORY_LIVE_AUDIO)
-                && !route.supportsControlCategory(MediaControlIntent.CATEGORY_LIVE_VIDEO);
-    }
-
-    private static boolean isSystemMediaRouteProvider(MediaRouter.RouteInfo route) {
-        return TextUtils.equals(route.getProviderInstance().getMetadata().getPackageName(),
-                SYSTEM_MEDIA_ROUTE_PROVIDER_PACKAGE_NAME);
-    }
 }
diff --git a/v7/mediarouter/src/android/support/v7/app/MediaRouteControllerDialog.java b/v7/mediarouter/src/android/support/v7/app/MediaRouteControllerDialog.java
index 537b382..547daa7d 100644
--- a/v7/mediarouter/src/android/support/v7/app/MediaRouteControllerDialog.java
+++ b/v7/mediarouter/src/android/support/v7/app/MediaRouteControllerDialog.java
@@ -37,7 +37,6 @@
 import android.support.v4.media.session.PlaybackStateCompat;
 import android.support.v4.view.accessibility.AccessibilityEventCompat;
 import android.support.v7.graphics.Palette;
-import android.support.v7.media.MediaControlIntent;
 import android.support.v7.media.MediaRouteSelector;
 import android.support.v7.media.MediaRouter;
 import android.support.v7.mediarouter.R;
@@ -319,12 +318,12 @@
                     if (pi != null) {
                         try {
                             pi.send();
+                            dismiss();
                         } catch (PendingIntent.CanceledException e) {
                             Log.e(TAG, pi + " was not sent, it had been canceled.");
                         }
                     }
                 }
-                dismiss();
             }
         };
         mArtView = (ImageView) findViewById(R.id.mr_art);
@@ -467,14 +466,7 @@
     }
 
     private boolean canShowPlaybackControlLayout() {
-        // If a route does not support remote playback, it means that the route is dedicated for
-        // audio or video streaming such as A2DP speaker or headset. In this case, the route
-        // provider does not provide any playback information such as metadata or playback status.
-        // But, for live video, playback control UI shows a message that the screen is being
-        // mirrored, while it does not show anything for live audio.
-        return mCustomControlView == null && (mDescription != null || mState != null)
-                && (mRoute.supportsControlCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)
-                || mRoute.supportsControlCategory(MediaControlIntent.CATEGORY_LIVE_VIDEO));
+        return mCustomControlView == null && (mDescription != null || mState != null);
     }
 
     /**
@@ -718,8 +710,12 @@
                 mTitleView.setText(R.string.mr_controller_casting_screen);
                 showTitle = true;
             } else if (mState == null || mState.getState() == PlaybackStateCompat.STATE_NONE) {
-                mTitleView.setText(R.string.mr_controller_no_media_selected);
-                showTitle = true;
+                // Show "No media selected" as we don't yet know the playback state.
+                // (Only exception is bluetooth where we don't show anything.)
+                if (!mRoute.isDeviceTypeBluetooth()) {
+                    mTitleView.setText(R.string.mr_controller_no_media_selected);
+                    showTitle = true;
+                }
             } else if (!hasTitle && !hasSubtitle) {
                 mTitleView.setText(R.string.mr_controller_no_info_available);
                 showTitle = true;
diff --git a/v7/mediarouter/src/android/support/v7/media/MediaRouter.java b/v7/mediarouter/src/android/support/v7/media/MediaRouter.java
index 18bcc85..b2e74e4 100644
--- a/v7/mediarouter/src/android/support/v7/media/MediaRouter.java
+++ b/v7/mediarouter/src/android/support/v7/media/MediaRouter.java
@@ -40,6 +40,7 @@
 import android.support.v4.util.Pair;
 import android.support.v7.media.MediaRouteProvider.ProviderMetadata;
 import android.support.v7.media.MediaRouteProvider.RouteController;
+import android.text.TextUtils;
 import android.util.Log;
 import android.view.Display;
 
@@ -913,6 +914,9 @@
         static final int CHANGE_VOLUME = 1 << 1;
         static final int CHANGE_PRESENTATION_DISPLAY = 1 << 2;
 
+        // Should match to SystemMediaRouteProvider.PACKAGE_NAME.
+        static final String SYSTEM_MEDIA_ROUTE_PROVIDER_PACKAGE_NAME = "android";
+
         RouteInfo(ProviderInfo provider, String descriptorId, String uniqueId) {
             mProvider = provider;
             mDescriptorId = descriptorId;
@@ -1226,6 +1230,33 @@
             return mDeviceType;
         }
 
+
+        /**
+         * Gets whether the type of the receiver device associated with this route is
+         * {@link #DEVICE_TYPE_BLUETOOTH}.
+         * <p>
+         * This is a workaround for platform version 23 or below where the system route provider
+         * doesn't specify device type for bluetooth media routes.
+         * </p>
+         *
+         * @return True if the receiver device type can be assumed to be
+         *         {@link #DEVICE_TYPE_BLUETOOTH}, false otherwise.
+         * @hide
+         */
+        public boolean isDeviceTypeBluetooth() {
+            if (mDeviceType == DEVICE_TYPE_BLUETOOTH) {
+                return true;
+            }
+            return isSystemMediaRouteProvider(this)
+                    && supportsControlCategory(MediaControlIntent.CATEGORY_LIVE_AUDIO)
+                    && !supportsControlCategory(MediaControlIntent.CATEGORY_LIVE_VIDEO);
+        }
+
+        private static boolean isSystemMediaRouteProvider(MediaRouter.RouteInfo route) {
+            return TextUtils.equals(route.getProviderInstance().getMetadata().getPackageName(),
+                    SYSTEM_MEDIA_ROUTE_PROVIDER_PACKAGE_NAME);
+        }
+
         /**
          * Gets information about how volume is handled on the route.
          *
diff --git a/v7/palette/api/current.txt b/v7/palette/api/current.txt
index fac6a55..3b24b77 100644
--- a/v7/palette/api/current.txt
+++ b/v7/palette/api/current.txt
@@ -7,6 +7,7 @@
     method public static deprecated android.support.v7.graphics.Palette generate(android.graphics.Bitmap, int);
     method public static deprecated android.os.AsyncTask<android.graphics.Bitmap, java.lang.Void, android.support.v7.graphics.Palette> generateAsync(android.graphics.Bitmap, android.support.v7.graphics.Palette.PaletteAsyncListener);
     method public static deprecated android.os.AsyncTask<android.graphics.Bitmap, java.lang.Void, android.support.v7.graphics.Palette> generateAsync(android.graphics.Bitmap, int, android.support.v7.graphics.Palette.PaletteAsyncListener);
+    method public int getColorForTarget(android.support.v7.graphics.Target, int);
     method public int getDarkMutedColor(int);
     method public android.support.v7.graphics.Palette.Swatch getDarkMutedSwatch();
     method public int getDarkVibrantColor(int);
@@ -17,7 +18,9 @@
     method public android.support.v7.graphics.Palette.Swatch getLightVibrantSwatch();
     method public int getMutedColor(int);
     method public android.support.v7.graphics.Palette.Swatch getMutedSwatch();
+    method public android.support.v7.graphics.Palette.Swatch getSwatchForTarget(android.support.v7.graphics.Target);
     method public java.util.List<android.support.v7.graphics.Palette.Swatch> getSwatches();
+    method public java.util.List<android.support.v7.graphics.Target> getTargets();
     method public int getVibrantColor(int);
     method public android.support.v7.graphics.Palette.Swatch getVibrantSwatch();
   }
@@ -26,12 +29,15 @@
     ctor public Palette.Builder(android.graphics.Bitmap);
     ctor public Palette.Builder(java.util.List<android.support.v7.graphics.Palette.Swatch>);
     method public android.support.v7.graphics.Palette.Builder addFilter(android.support.v7.graphics.Palette.Filter);
+    method public android.support.v7.graphics.Palette.Builder addTarget(android.support.v7.graphics.Target);
     method public android.support.v7.graphics.Palette.Builder clearFilters();
     method public android.support.v7.graphics.Palette.Builder clearRegion();
+    method public android.support.v7.graphics.Palette.Builder clearTargets();
     method public android.support.v7.graphics.Palette generate();
     method public android.os.AsyncTask<android.graphics.Bitmap, java.lang.Void, android.support.v7.graphics.Palette> generate(android.support.v7.graphics.Palette.PaletteAsyncListener);
     method public android.support.v7.graphics.Palette.Builder maximumColorCount(int);
-    method public android.support.v7.graphics.Palette.Builder resizeBitmapSize(int);
+    method public android.support.v7.graphics.Palette.Builder resizeBitmapArea(int);
+    method public deprecated android.support.v7.graphics.Palette.Builder resizeBitmapSize(int);
     method public android.support.v7.graphics.Palette.Builder setRegion(int, int, int, int);
   }
 
@@ -52,5 +58,40 @@
     method public int getTitleTextColor();
   }
 
+  public final class Target {
+    method public float getLightnessWeight();
+    method public float getMaximumLightness();
+    method public float getMaximumSaturation();
+    method public float getMinimumLightness();
+    method public float getMinimumSaturation();
+    method public float getPopulationWeight();
+    method public float getSaturationWeight();
+    method public float getTargetLightness();
+    method public float getTargetSaturation();
+    method public boolean isExclusive();
+    field public static final android.support.v7.graphics.Target DARK_MUTED;
+    field public static final android.support.v7.graphics.Target DARK_VIBRANT;
+    field public static final android.support.v7.graphics.Target LIGHT_MUTED;
+    field public static final android.support.v7.graphics.Target LIGHT_VIBRANT;
+    field public static final android.support.v7.graphics.Target MUTED;
+    field public static final android.support.v7.graphics.Target VIBRANT;
+  }
+
+  public static final class Target.Builder {
+    ctor public Target.Builder();
+    ctor public Target.Builder(android.support.v7.graphics.Target);
+    method public android.support.v7.graphics.Target build();
+    method public android.support.v7.graphics.Target.Builder setExclusive(boolean);
+    method public android.support.v7.graphics.Target.Builder setLightnessWeight(float);
+    method public android.support.v7.graphics.Target.Builder setMaximumLightness(float);
+    method public android.support.v7.graphics.Target.Builder setMaximumSaturation(float);
+    method public android.support.v7.graphics.Target.Builder setMinimumLightness(float);
+    method public android.support.v7.graphics.Target.Builder setMinimumSaturation(float);
+    method public android.support.v7.graphics.Target.Builder setPopulationWeight(float);
+    method public android.support.v7.graphics.Target.Builder setSaturationWeight(float);
+    method public android.support.v7.graphics.Target.Builder setTargetLightness(float);
+    method public android.support.v7.graphics.Target.Builder setTargetSaturation(float);
+  }
+
 }
 
diff --git a/v7/palette/src/main/java/android/support/v7/graphics/DefaultGenerator.java b/v7/palette/src/main/java/android/support/v7/graphics/DefaultGenerator.java
deleted file mode 100644
index 3ee2bfa..0000000
--- a/v7/palette/src/main/java/android/support/v7/graphics/DefaultGenerator.java
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- * Copyright 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *       http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.support.v7.graphics;
-
-import android.support.v4.graphics.ColorUtils;
-import android.support.v7.graphics.Palette.Swatch;
-
-import java.util.List;
-
-class DefaultGenerator extends Palette.Generator {
-
-    private static final float TARGET_DARK_LUMA = 0.26f;
-    private static final float MAX_DARK_LUMA = 0.45f;
-
-    private static final float MIN_LIGHT_LUMA = 0.55f;
-    private static final float TARGET_LIGHT_LUMA = 0.74f;
-
-    private static final float MIN_NORMAL_LUMA = 0.3f;
-    private static final float TARGET_NORMAL_LUMA = 0.5f;
-    private static final float MAX_NORMAL_LUMA = 0.7f;
-
-    private static final float TARGET_MUTED_SATURATION = 0.3f;
-    private static final float MAX_MUTED_SATURATION = 0.4f;
-
-    private static final float TARGET_VIBRANT_SATURATION = 1f;
-    private static final float MIN_VIBRANT_SATURATION = 0.35f;
-
-    private static final float WEIGHT_SATURATION = 3f;
-    private static final float WEIGHT_LUMA = 6f;
-    private static final float WEIGHT_POPULATION = 1f;
-
-    private List<Swatch> mSwatches;
-
-    private int mHighestPopulation;
-
-    private Swatch mVibrantSwatch;
-    private Swatch mMutedSwatch;
-    private Swatch mDarkVibrantSwatch;
-    private Swatch mDarkMutedSwatch;
-    private Swatch mLightVibrantSwatch;
-    private Swatch mLightMutedSwatch;
-
-    @Override
-    public void generate(final List<Swatch> swatches) {
-        mSwatches = swatches;
-
-        mHighestPopulation = findMaxPopulation();
-
-        generateVariationColors();
-
-        // Now try and generate any missing colors
-        generateEmptySwatches();
-    }
-
-    @Override
-    public Swatch getVibrantSwatch() {
-        return mVibrantSwatch;
-    }
-
-    @Override
-    public Swatch getLightVibrantSwatch() {
-        return mLightVibrantSwatch;
-    }
-
-    @Override
-    public Swatch getDarkVibrantSwatch() {
-        return mDarkVibrantSwatch;
-    }
-
-    @Override
-    public Swatch getMutedSwatch() {
-        return mMutedSwatch;
-    }
-
-    @Override
-    public Swatch getLightMutedSwatch() {
-        return mLightMutedSwatch;
-    }
-
-    @Override
-    public Swatch getDarkMutedSwatch() {
-        return mDarkMutedSwatch;
-    }
-
-    private void generateVariationColors() {
-        mVibrantSwatch = findColorVariation(TARGET_NORMAL_LUMA, MIN_NORMAL_LUMA, MAX_NORMAL_LUMA,
-                TARGET_VIBRANT_SATURATION, MIN_VIBRANT_SATURATION, 1f);
-
-        mLightVibrantSwatch = findColorVariation(TARGET_LIGHT_LUMA, MIN_LIGHT_LUMA, 1f,
-                TARGET_VIBRANT_SATURATION, MIN_VIBRANT_SATURATION, 1f);
-
-        mDarkVibrantSwatch = findColorVariation(TARGET_DARK_LUMA, 0f, MAX_DARK_LUMA,
-                TARGET_VIBRANT_SATURATION, MIN_VIBRANT_SATURATION, 1f);
-
-        mMutedSwatch = findColorVariation(TARGET_NORMAL_LUMA, MIN_NORMAL_LUMA, MAX_NORMAL_LUMA,
-                TARGET_MUTED_SATURATION, 0f, MAX_MUTED_SATURATION);
-
-        mLightMutedSwatch = findColorVariation(TARGET_LIGHT_LUMA, MIN_LIGHT_LUMA, 1f,
-                TARGET_MUTED_SATURATION, 0f, MAX_MUTED_SATURATION);
-
-        mDarkMutedSwatch = findColorVariation(TARGET_DARK_LUMA, 0f, MAX_DARK_LUMA,
-                TARGET_MUTED_SATURATION, 0f, MAX_MUTED_SATURATION);
-    }
-
-    /**
-     * Try and generate any missing swatches from the swatches we did find.
-     */
-    private void generateEmptySwatches() {
-        if (mVibrantSwatch == null) {
-            // If we do not have a vibrant color...
-            if (mDarkVibrantSwatch != null) {
-                // ...but we do have a dark vibrant, generate the value by modifying the luma
-                final float[] newHsl = copyHslValues(mDarkVibrantSwatch);
-                newHsl[2] = TARGET_NORMAL_LUMA;
-                mVibrantSwatch = new Swatch(ColorUtils.HSLToColor(newHsl), 0);
-            }
-        }
-
-        if (mDarkVibrantSwatch == null) {
-            // If we do not have a dark vibrant color...
-            if (mVibrantSwatch != null) {
-                // ...but we do have a vibrant, generate the value by modifying the luma
-                final float[] newHsl = copyHslValues(mVibrantSwatch);
-                newHsl[2] = TARGET_DARK_LUMA;
-                mDarkVibrantSwatch = new Swatch(ColorUtils.HSLToColor(newHsl), 0);
-            }
-        }
-    }
-
-    /**
-     * Find the {@link Palette.Swatch} with the highest population value and return the population.
-     */
-    private int findMaxPopulation() {
-        int population = 0;
-        for (Swatch swatch : mSwatches) {
-            population = Math.max(population, swatch.getPopulation());
-        }
-        return population;
-    }
-
-    private Swatch findColorVariation(float targetLuma, float minLuma, float maxLuma,
-            float targetSaturation, float minSaturation, float maxSaturation) {
-        Swatch max = null;
-        float maxValue = 0f;
-
-        for (Swatch swatch : mSwatches) {
-            final float sat = swatch.getHsl()[1];
-            final float luma = swatch.getHsl()[2];
-
-            if (sat >= minSaturation && sat <= maxSaturation &&
-                    luma >= minLuma && luma <= maxLuma &&
-                    !isAlreadySelected(swatch)) {
-                float value = createComparisonValue(sat, targetSaturation, luma, targetLuma,
-                        swatch.getPopulation(), mHighestPopulation);
-                if (max == null || value > maxValue) {
-                    max = swatch;
-                    maxValue = value;
-                }
-            }
-        }
-
-        return max;
-    }
-
-    /**
-     * @return true if we have already selected {@code swatch}
-     */
-    private boolean isAlreadySelected(Swatch swatch) {
-        return mVibrantSwatch == swatch || mDarkVibrantSwatch == swatch ||
-                mLightVibrantSwatch == swatch || mMutedSwatch == swatch ||
-                mDarkMutedSwatch == swatch || mLightMutedSwatch == swatch;
-    }
-
-    private static float createComparisonValue(float saturation, float targetSaturation,
-            float luma, float targetLuma,
-            int population, int maxPopulation) {
-        return createComparisonValue(saturation, targetSaturation, WEIGHT_SATURATION,
-                luma, targetLuma, WEIGHT_LUMA,
-                population, maxPopulation, WEIGHT_POPULATION);
-    }
-
-    private static float createComparisonValue(
-            float saturation, float targetSaturation, float saturationWeight,
-            float luma, float targetLuma, float lumaWeight,
-            int population, int maxPopulation, float populationWeight) {
-        return weightedMean(
-                invertDiff(saturation, targetSaturation), saturationWeight,
-                invertDiff(luma, targetLuma), lumaWeight,
-                population / (float) maxPopulation, populationWeight
-        );
-    }
-
-    /**
-     * Copy a {@link Swatch}'s HSL values into a new float[].
-     */
-    private static float[] copyHslValues(Swatch color) {
-        final float[] newHsl = new float[3];
-        System.arraycopy(color.getHsl(), 0, newHsl, 0, 3);
-        return newHsl;
-    }
-
-    /**
-     * Returns a value in the range 0-1. 1 is returned when {@code value} equals the
-     * {@code targetValue} and then decreases as the absolute difference between {@code value} and
-     * {@code targetValue} increases.
-     *
-     * @param value the item's value
-     * @param targetValue the value which we desire
-     */
-    private static float invertDiff(float value, float targetValue) {
-        return 1f - Math.abs(value - targetValue);
-    }
-
-    private static float weightedMean(float... values) {
-        float sum = 0f;
-        float sumWeight = 0f;
-
-        for (int i = 0; i < values.length; i += 2) {
-            float value = values[i];
-            float weight = values[i + 1];
-
-            sum += (value * weight);
-            sumWeight += weight;
-        }
-
-        return sum / sumWeight;
-    }
-}
diff --git a/v7/palette/src/main/java/android/support/v7/graphics/Palette.java b/v7/palette/src/main/java/android/support/v7/graphics/Palette.java
index 57f34a6..d0dff30 100644
--- a/v7/palette/src/main/java/android/support/v7/graphics/Palette.java
+++ b/v7/palette/src/main/java/android/support/v7/graphics/Palette.java
@@ -21,16 +21,20 @@
 import android.graphics.Rect;
 import android.os.AsyncTask;
 import android.support.annotation.ColorInt;
+import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.support.v4.graphics.ColorUtils;
 import android.support.v4.os.AsyncTaskCompat;
+import android.support.v4.util.ArrayMap;
 import android.util.Log;
+import android.util.SparseBooleanArray;
 import android.util.TimingLogger;
 
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
+import java.util.Map;
 
 /**
  * A helper class to extract prominent colors from an image.
@@ -80,7 +84,7 @@
         void onGenerated(Palette palette);
     }
 
-    private static final int DEFAULT_RESIZE_BITMAP_MAX_DIMENSION = 192;
+    private static final int DEFAULT_RESIZE_BITMAP_AREA = 160 * 160;
     private static final int DEFAULT_CALCULATE_NUMBER_COLORS = 16;
 
     private static final float MIN_CONTRAST_TITLE_TEXT = 3.0f;
@@ -140,151 +144,266 @@
     }
 
     private final List<Swatch> mSwatches;
-    private final Generator mGenerator;
+    private final List<Target> mTargets;
 
-    private Palette(List<Swatch> swatches, Generator generator) {
+    private final Map<Target, Swatch> mSelectedSwatches;
+    private final SparseBooleanArray mUsedColors;
+
+    private final int mMaxPopulation;
+
+    private Palette(List<Swatch> swatches, List<Target> targets) {
         mSwatches = swatches;
-        mGenerator = generator;
+        mTargets = targets;
+
+        mUsedColors = new SparseBooleanArray();
+        mSelectedSwatches = new ArrayMap<>();
+
+        mMaxPopulation = findMaxPopulation();
     }
 
     /**
      * Returns all of the swatches which make up the palette.
      */
+    @NonNull
     public List<Swatch> getSwatches() {
         return Collections.unmodifiableList(mSwatches);
     }
 
     /**
+     * Returns the targets used to generate this palette.
+     */
+    @NonNull
+    public List<Target> getTargets() {
+        return Collections.unmodifiableList(mTargets);
+    }
+
+    /**
      * Returns the most vibrant swatch in the palette. Might be null.
+     *
+     * @see Target#VIBRANT
      */
     @Nullable
     public Swatch getVibrantSwatch() {
-        return mGenerator.getVibrantSwatch();
+        return getSwatchForTarget(Target.VIBRANT);
     }
 
     /**
      * Returns a light and vibrant swatch from the palette. Might be null.
+     *
+     * @see Target#LIGHT_VIBRANT
      */
     @Nullable
     public Swatch getLightVibrantSwatch() {
-        return mGenerator.getLightVibrantSwatch();
+        return getSwatchForTarget(Target.LIGHT_VIBRANT);
     }
 
     /**
      * Returns a dark and vibrant swatch from the palette. Might be null.
+     *
+     * @see Target#DARK_VIBRANT
      */
     @Nullable
     public Swatch getDarkVibrantSwatch() {
-        return mGenerator.getDarkVibrantSwatch();
+        return getSwatchForTarget(Target.DARK_VIBRANT);
     }
 
     /**
      * Returns a muted swatch from the palette. Might be null.
+     *
+     * @see Target#MUTED
      */
     @Nullable
     public Swatch getMutedSwatch() {
-        return mGenerator.getMutedSwatch();
+        return getSwatchForTarget(Target.MUTED);
     }
 
     /**
      * Returns a muted and light swatch from the palette. Might be null.
+     *
+     * @see Target#LIGHT_MUTED
      */
     @Nullable
     public Swatch getLightMutedSwatch() {
-        return mGenerator.getLightMutedSwatch();
+        return getSwatchForTarget(Target.LIGHT_MUTED);
     }
 
     /**
      * Returns a muted and dark swatch from the palette. Might be null.
+     *
+     * @see Target#DARK_MUTED
      */
     @Nullable
     public Swatch getDarkMutedSwatch() {
-        return mGenerator.getDarkMutedSwatch();
+        return getSwatchForTarget(Target.DARK_MUTED);
     }
 
     /**
      * Returns the most vibrant color in the palette as an RGB packed int.
      *
      * @param defaultColor value to return if the swatch isn't available
+     * @see #getVibrantSwatch()
      */
     @ColorInt
-    public int getVibrantColor(@ColorInt int defaultColor) {
-        Swatch swatch = getVibrantSwatch();
-        return swatch != null ? swatch.getRgb() : defaultColor;
+    public int getVibrantColor(@ColorInt final int defaultColor) {
+        return getColorForTarget(Target.VIBRANT, defaultColor);
     }
 
     /**
      * Returns a light and vibrant color from the palette as an RGB packed int.
      *
      * @param defaultColor value to return if the swatch isn't available
+     * @see #getLightVibrantSwatch()
      */
     @ColorInt
-    public int getLightVibrantColor(@ColorInt int defaultColor) {
-        Swatch swatch = getLightVibrantSwatch();
-        return swatch != null ? swatch.getRgb() : defaultColor;
+    public int getLightVibrantColor(@ColorInt final int defaultColor) {
+        return getColorForTarget(Target.LIGHT_VIBRANT, defaultColor);
     }
 
     /**
      * Returns a dark and vibrant color from the palette as an RGB packed int.
      *
      * @param defaultColor value to return if the swatch isn't available
+     * @see #getDarkVibrantSwatch()
      */
     @ColorInt
-    public int getDarkVibrantColor(@ColorInt int defaultColor) {
-        Swatch swatch = getDarkVibrantSwatch();
-        return swatch != null ? swatch.getRgb() : defaultColor;
+    public int getDarkVibrantColor(@ColorInt final int defaultColor) {
+        return getColorForTarget(Target.DARK_VIBRANT, defaultColor);
     }
 
     /**
      * Returns a muted color from the palette as an RGB packed int.
      *
      * @param defaultColor value to return if the swatch isn't available
+     * @see #getMutedSwatch()
      */
     @ColorInt
-    public int getMutedColor(@ColorInt int defaultColor) {
-        Swatch swatch = getMutedSwatch();
-        return swatch != null ? swatch.getRgb() : defaultColor;
+    public int getMutedColor(@ColorInt final int defaultColor) {
+        return getColorForTarget(Target.MUTED, defaultColor);
     }
 
     /**
      * Returns a muted and light color from the palette as an RGB packed int.
      *
      * @param defaultColor value to return if the swatch isn't available
+     * @see #getLightMutedSwatch()
      */
     @ColorInt
-    public int getLightMutedColor(@ColorInt int defaultColor) {
-        Swatch swatch = getLightMutedSwatch();
-        return swatch != null ? swatch.getRgb() : defaultColor;
+    public int getLightMutedColor(@ColorInt final int defaultColor) {
+        return getColorForTarget(Target.LIGHT_MUTED, defaultColor);
     }
 
     /**
      * Returns a muted and dark color from the palette as an RGB packed int.
      *
      * @param defaultColor value to return if the swatch isn't available
+     * @see #getDarkMutedSwatch()
      */
     @ColorInt
-    public int getDarkMutedColor(@ColorInt int defaultColor) {
-        Swatch swatch = getDarkMutedSwatch();
-        return swatch != null ? swatch.getRgb() : defaultColor;
+    public int getDarkMutedColor(@ColorInt final int defaultColor) {
+        return getColorForTarget(Target.DARK_MUTED, defaultColor);
     }
 
     /**
-     * Scale the bitmap down so that it's largest dimension is {@code targetMaxDimension}.
-     * If {@code bitmap} is smaller than this, then it is returned.
+     * Returns the selected swatch for the given target from the palette, or {@code null} if one
+     * could not be found.
      */
-    private static Bitmap scaleBitmapDown(Bitmap bitmap, final int targetMaxDimension) {
-        final int maxDimension = Math.max(bitmap.getWidth(), bitmap.getHeight());
+    @Nullable
+    public Swatch getSwatchForTarget(@NonNull final Target target) {
+        return mSelectedSwatches.get(target);
+    }
 
-        if (maxDimension <= targetMaxDimension) {
-            // If the bitmap is small enough already, just return it
-            return bitmap;
+    /**
+     * Returns the selected color for the given target from the palette as an RGB packed int.
+     *
+     * @param defaultColor value to return if the swatch isn't available
+     */
+    @ColorInt
+    public int getColorForTarget(@NonNull final Target target, @ColorInt final int defaultColor) {
+        Swatch swatch = getSwatchForTarget(target);
+        return swatch != null ? swatch.getRgb() : defaultColor;
+    }
+
+    private void generate() {
+        // We need to make sure that the scored targets are generated first. This is so that
+        // inherited targets have something to inherit from
+        for (int i = 0, count = mTargets.size(); i < count; i++) {
+            final Target target = mTargets.get(i);
+            target.normalizeWeights();
+            mSelectedSwatches.put(target, generateScoredTarget(target));
+        }
+        // We now clear out the used colors
+        mUsedColors.clear();
+    }
+
+    private Swatch generateScoredTarget(final Target target) {
+        final Swatch maxScoreSwatch = getMaxScoredSwatchForTarget(target);
+        if (maxScoreSwatch != null && target.isExclusive()) {
+            // If we have a swatch, and the target is exclusive, add the color to the used list
+            mUsedColors.append(maxScoreSwatch.getRgb(), true);
+        }
+        return maxScoreSwatch;
+    }
+
+    private Swatch getMaxScoredSwatchForTarget(final Target target) {
+        float maxScore = 0;
+        Swatch maxScoreSwatch = null;
+        for (int i = 0, count = mSwatches.size(); i < count; i++) {
+            final Swatch swatch = mSwatches.get(i);
+            if (shouldBeScoredForTarget(swatch, target)) {
+                final float score = generateScore(swatch, target);
+                if (maxScoreSwatch == null || score > maxScore) {
+                    maxScoreSwatch = swatch;
+                    maxScore = score;
+                }
+            }
+        }
+        return maxScoreSwatch;
+    }
+
+    private boolean shouldBeScoredForTarget(final Swatch swatch, final Target target) {
+        // Check whether the HSL values are within the correct ranges, and this color hasn't
+        // been used yet.
+        final float hsl[] = swatch.getHsl();
+        return hsl[1] >= target.getMinimumSaturation() && hsl[1] <= target.getMaximumSaturation()
+                && hsl[2] >= target.getMinimumLightness() && hsl[2] <= target.getMaximumLightness()
+                && !mUsedColors.get(swatch.getRgb());
+    }
+
+    private float generateScore(Swatch swatch, Target target) {
+        final float[] hsl = swatch.getHsl();
+
+        float saturationScore = 0;
+        float luminanceScore = 0;
+        float populationScore = 0;
+
+        if (target.getSaturationWeight() > 0) {
+            saturationScore = target.getSaturationWeight()
+                    * (1f - Math.abs(hsl[1] - target.getTargetSaturation()));
+        }
+        if (target.getLightnessWeight() > 0) {
+            luminanceScore = target.getLightnessWeight()
+                    * (1f - Math.abs(hsl[2] - target.getTargetLightness()));
+        }
+        if (target.getPopulationWeight() > 0) {
+            populationScore = target.getPopulationWeight()
+                    * (swatch.getPopulation() / (float) mMaxPopulation);
         }
 
-        final double scaleRatio = targetMaxDimension / (double) maxDimension;
-        return Bitmap.createScaledBitmap(bitmap,
-                (int) Math.ceil(bitmap.getWidth() * scaleRatio),
-                (int) Math.ceil(bitmap.getHeight() * scaleRatio),
-                false);
+        return saturationScore + luminanceScore + populationScore;
+    }
+
+    private int findMaxPopulation() {
+        int max = 0;
+        for (int i = 0, count = mSwatches.size(); i < count; i++) {
+            max = Math.max(mSwatches.get(i).getPopulation(), max);
+        }
+        return max;
+    }
+
+    private static float[] copyHslValues(Swatch color) {
+        final float[] newHsl = new float[3];
+        System.arraycopy(color.getHsl(), 0, newHsl, 0, 3);
+        return newHsl;
     }
 
     /**
@@ -318,6 +437,11 @@
             mPopulation = population;
         }
 
+        Swatch(float[] hsl, int population) {
+            this(ColorUtils.HSLToColor(hsl), population);
+            mHsl = hsl;
+        }
+
         /**
          * @return this swatch's RGB color value
          */
@@ -335,8 +459,8 @@
         public float[] getHsl() {
             if (mHsl == null) {
                 mHsl = new float[3];
-                ColorUtils.RGBToHSL(mRed, mGreen, mBlue, mHsl);
             }
+            ColorUtils.RGBToHSL(mRed, mGreen, mBlue, mHsl);
             return mHsl;
         }
 
@@ -445,13 +569,16 @@
     public static final class Builder {
         private final List<Swatch> mSwatches;
         private final Bitmap mBitmap;
+
+        private final List<Target> mTargets = new ArrayList<>();
+
         private int mMaxColors = DEFAULT_CALCULATE_NUMBER_COLORS;
-        private int mResizeMaxDimension = DEFAULT_RESIZE_BITMAP_MAX_DIMENSION;
+        private int mResizeArea = DEFAULT_RESIZE_BITMAP_AREA;
+        private int mResizeMaxDimension = -1;
+
         private final List<Filter> mFilters = new ArrayList<>();
         private Rect mRegion;
 
-        private Generator mGenerator;
-
         /**
          * Construct a new {@link Builder} using a source {@link Bitmap}
          */
@@ -462,6 +589,14 @@
             mFilters.add(DEFAULT_FILTER);
             mBitmap = bitmap;
             mSwatches = null;
+
+            // Add the default targets
+            mTargets.add(Target.LIGHT_VIBRANT);
+            mTargets.add(Target.VIBRANT);
+            mTargets.add(Target.DARK_VIBRANT);
+            mTargets.add(Target.LIGHT_MUTED);
+            mTargets.add(Target.MUTED);
+            mTargets.add(Target.DARK_MUTED);
         }
 
         /**
@@ -478,15 +613,6 @@
         }
 
         /**
-         * Set the {@link Generator} to use when generating the {@link Palette}. If this is called
-         * with {@code null} then the default generator will be used.
-         */
-        Builder generator(Generator generator) {
-            mGenerator = generator;
-            return this;
-        }
-
-        /**
          * Set the maximum number of colors to use in the quantization step when using a
          * {@link android.graphics.Bitmap} as the source.
          * <p>
@@ -494,6 +620,7 @@
          * the range 10-16. For images which are largely made up of people's faces then this
          * value should be increased to ~24.
          */
+        @NonNull
         public Builder maximumColorCount(int colors) {
             mMaxColors = colors;
             return this;
@@ -504,13 +631,38 @@
          * If the bitmap's largest dimension is greater than the value specified, then the bitmap
          * will be resized so that it's largest dimension matches {@code maxDimension}. If the
          * bitmap is smaller or equal, the original is used as-is.
+         *
+         * @deprecated Using {@link #resizeBitmapArea(int)} is preferred since it can handle
+         * abnormal aspect ratios more gracefully.
+         *
+         * @param maxDimension the number of pixels that the max dimension should be scaled down to,
+         *                     or any value <= 0 to disable resizing.
+         */
+        @NonNull
+        @Deprecated
+        public Builder resizeBitmapSize(final int maxDimension) {
+            mResizeMaxDimension = maxDimension;
+            mResizeArea = -1;
+            return this;
+        }
+
+        /**
+         * Set the resize value when using a {@link android.graphics.Bitmap} as the source.
+         * If the bitmap's area is greater than the value specified, then the bitmap
+         * will be resized so that it's area matches {@code area}. If the
+         * bitmap is smaller or equal, the original is used as-is.
          * <p>
          * This value has a large effect on the processing time. The larger the resized image is,
          * the greater time it will take to generate the palette. The smaller the image is, the
          * more detail is lost in the resulting image and thus less precision for color selection.
+         *
+         * @param area the number of pixels that the intemediary scaled down Bitmap should cover,
+         *             or any value <= 0 to disable resizing.
          */
-        public Builder resizeBitmapSize(int maxDimension) {
-            mResizeMaxDimension = maxDimension;
+        @NonNull
+        public Builder resizeBitmapArea(final int area) {
+            mResizeArea = area;
+            mResizeMaxDimension = -1;
             return this;
         }
 
@@ -518,6 +670,7 @@
          * Clear all added filters. This includes any default filters added automatically by
          * {@link Palette}.
          */
+        @NonNull
         public Builder clearFilters() {
             mFilters.clear();
             return this;
@@ -529,6 +682,7 @@
          *
          * @param filter filter to add.
          */
+        @NonNull
         public Builder addFilter(Filter filter) {
             if (filter != null) {
                 mFilters.add(filter);
@@ -545,6 +699,7 @@
          * @param right The right side of the rectangle used for the region.
          * @param bottom The bottom of the rectangle used for the region.
          */
+        @NonNull
         public Builder setRegion(int left, int top, int right, int bottom) {
             if (mBitmap != null) {
                 if (mRegion == null) mRegion = new Rect();
@@ -562,14 +717,41 @@
         /**
          * Clear any previously region set via {@link #setRegion(int, int, int, int)}.
          */
+        @NonNull
         public Builder clearRegion() {
             mRegion = null;
             return this;
         }
 
         /**
+         * Add a target profile to be generated in the palette.
+         *
+         * <p>You can retrieve the result via {@link Palette#getSwatchForTarget(Target)}.</p>
+         */
+        @NonNull
+        public Builder addTarget(@NonNull final Target target) {
+            if (!mTargets.contains(target)) {
+                mTargets.add(target);
+            }
+            return this;
+        }
+
+        /**
+         * Clear all added targets. This includes any default targets added automatically by
+         * {@link Palette}.
+         */
+        @NonNull
+        public Builder clearTargets() {
+            if (mTargets != null) {
+                mTargets.clear();
+            }
+            return this;
+        }
+
+        /**
          * Generate and return the {@link Palette} synchronously.
          */
+        @NonNull
         public Palette generate() {
             final TimingLogger logger = LOG_TIMINGS
                     ? new TimingLogger(LOG_TAG, "Generation")
@@ -578,15 +760,10 @@
             List<Swatch> swatches;
 
             if (mBitmap != null) {
-                // We have a Bitmap so we need to quantization to reduce the number of colors
+                // We have a Bitmap so we need to use quantization to reduce the number of colors
 
-                if (mResizeMaxDimension <= 0) {
-                    throw new IllegalArgumentException(
-                            "Minimum dimension size for resizing should should be >= 1");
-                }
-
-                // First we'll scale down the bitmap so it's largest dimension is as specified
-                final Bitmap bitmap = scaleBitmapDown(mBitmap, mResizeMaxDimension);
+                // First we'll scale down the bitmap if needed
+                final Bitmap bitmap = scaleBitmapDown(mBitmap);
 
                 if (logger != null) {
                     logger.addSplit("Processed Bitmap");
@@ -613,6 +790,7 @@
                 if (bitmap != mBitmap) {
                     bitmap.recycle();
                 }
+
                 swatches = quantizer.getQuantizedColors();
 
                 if (logger != null) {
@@ -623,20 +801,10 @@
                 swatches = mSwatches;
             }
 
-            // If we haven't been provided with a generator, use the default
-            if (mGenerator == null) {
-                mGenerator = new DefaultGenerator();
-            }
-
-            // Now call let the Generator do it's thing
-            mGenerator.generate(swatches);
-
-            if (logger != null) {
-                logger.addSplit("Generator.generate() completed");
-            }
-
             // Now create a Palette instance
-            Palette p = new Palette(swatches, mGenerator);
+            final Palette p = new Palette(swatches, mTargets);
+            // And make it generate itself
+            p.generate();
 
             if (logger != null) {
                 logger.addSplit("Created Palette");
@@ -651,6 +819,7 @@
          * {@link PaletteAsyncListener#onGenerated} method will be called with the palette when
          * generated.
          */
+        @NonNull
         public AsyncTask<Bitmap, Void, Palette> generate(final PaletteAsyncListener listener) {
             if (listener == null) {
                 throw new IllegalArgumentException("listener can not be null");
@@ -702,59 +871,34 @@
                 return subsetPixels;
             }
         }
-    }
-
-    static abstract class Generator {
 
         /**
-         * This method will be called with the {@link Palette.Swatch} that represent an image.
-         * You should process this list so that you have appropriate values when the other methods in
-         * class are called.
-         * <p>
-         * This method will probably be called on a background thread.
+         * Scale the bitmap down as needed.
          */
-        public abstract void generate(List<Palette.Swatch> swatches);
+        private Bitmap scaleBitmapDown(final Bitmap bitmap) {
+            double scaleRatio = -1;
 
-        /**
-         * Return the most vibrant {@link Palette.Swatch}
-         */
-        public Palette.Swatch getVibrantSwatch() {
-            return null;
-        }
+            if (mResizeArea > 0) {
+                final int bitmapArea = bitmap.getWidth() * bitmap.getHeight();
+                if (bitmapArea > mResizeArea) {
+                    scaleRatio = mResizeArea / (double) bitmapArea;
+                }
+            } else if (mResizeMaxDimension > 0) {
+                final int maxDimension = Math.max(bitmap.getWidth(), bitmap.getHeight());
+                if (maxDimension > mResizeMaxDimension) {
+                    scaleRatio = mResizeMaxDimension / (double) maxDimension;
+                }
+            }
 
-        /**
-         * Return a light and vibrant {@link Palette.Swatch}
-         */
-        public Palette.Swatch getLightVibrantSwatch() {
-            return null;
-        }
+            if (scaleRatio <= 0) {
+                // Scaling has been disabled or not needed so just return the Bitmap
+                return bitmap;
+            }
 
-        /**
-         * Return a dark and vibrant {@link Palette.Swatch}
-         */
-        public Palette.Swatch getDarkVibrantSwatch() {
-            return null;
-        }
-
-        /**
-         * Return a muted {@link Palette.Swatch}
-         */
-        public Palette.Swatch getMutedSwatch() {
-            return null;
-        }
-
-        /**
-         * Return a muted and light {@link Palette.Swatch}
-         */
-        public Palette.Swatch getLightMutedSwatch() {
-            return null;
-        }
-
-        /**
-         * Return a muted and dark {@link Palette.Swatch}
-         */
-        public Palette.Swatch getDarkMutedSwatch() {
-            return null;
+            return Bitmap.createScaledBitmap(bitmap,
+                    (int) Math.ceil(bitmap.getWidth() * scaleRatio),
+                    (int) Math.ceil(bitmap.getHeight() * scaleRatio),
+                    false);
         }
     }
 
diff --git a/v7/palette/src/main/java/android/support/v7/graphics/Target.java b/v7/palette/src/main/java/android/support/v7/graphics/Target.java
new file mode 100644
index 0000000..8ac8205
--- /dev/null
+++ b/v7/palette/src/main/java/android/support/v7/graphics/Target.java
@@ -0,0 +1,381 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.support.v7.graphics;
+
+import android.support.annotation.FloatRange;
+
+/**
+ * A class which allows custom selection of colors in a {@link Palette}'s generation. Instances
+ * can be created via the {@link Builder} class.
+ *
+ * <p>To use the target, use the {@link Palette.Builder#addTarget(Target)} API when building a
+ * Palette.</p>
+ */
+public final class Target {
+
+    private static final float TARGET_DARK_LUMA = 0.26f;
+    private static final float MAX_DARK_LUMA = 0.45f;
+
+    private static final float MIN_LIGHT_LUMA = 0.55f;
+    private static final float TARGET_LIGHT_LUMA = 0.74f;
+
+    private static final float MIN_NORMAL_LUMA = 0.3f;
+    private static final float TARGET_NORMAL_LUMA = 0.5f;
+    private static final float MAX_NORMAL_LUMA = 0.7f;
+
+    private static final float TARGET_MUTED_SATURATION = 0.3f;
+    private static final float MAX_MUTED_SATURATION = 0.4f;
+
+    private static final float TARGET_VIBRANT_SATURATION = 1f;
+    private static final float MIN_VIBRANT_SATURATION = 0.35f;
+
+    private static final float WEIGHT_SATURATION = 0.24f;
+    private static final float WEIGHT_LUMA = 0.52f;
+    private static final float WEIGHT_POPULATION = 0.24f;
+
+    private static final int INDEX_MIN = 0;
+    private static final int INDEX_TARGET = 1;
+    private static final int INDEX_MAX = 2;
+
+    private static final int INDEX_WEIGHT_SAT = 0;
+    private static final int INDEX_WEIGHT_LUMA = 1;
+    private static final int INDEX_WEIGHT_POP = 2;
+
+    /**
+     * A target which has the characteristics of a vibrant color which is light in luminance.
+    */
+    public static final Target LIGHT_VIBRANT;
+
+    /**
+     * A target which has the characteristics of a vibrant color which is neither light or dark.
+     */
+    public static final Target VIBRANT;
+
+    /**
+     * A target which has the characteristics of a vibrant color which is dark in luminance.
+     */
+    public static final Target DARK_VIBRANT;
+
+    /**
+     * A target which has the characteristics of a muted color which is light in luminance.
+     */
+    public static final Target LIGHT_MUTED;
+
+    /**
+     * A target which has the characteristics of a muted color which is neither light or dark.
+     */
+    public static final Target MUTED;
+
+    /**
+     * A target which has the characteristics of a muted color which is dark in luminance.
+     */
+    public static final Target DARK_MUTED;
+
+    static {
+        LIGHT_VIBRANT = new Target();
+        setDefaultLightLightnessValues(LIGHT_VIBRANT);
+        setDefaultVibrantSaturationValues(LIGHT_VIBRANT);
+
+        VIBRANT = new Target();
+        setDefaultNormalLightnessValues(VIBRANT);
+        setDefaultVibrantSaturationValues(VIBRANT);
+
+        DARK_VIBRANT = new Target();
+        setDefaultDarkLightnessValues(DARK_VIBRANT);
+        setDefaultVibrantSaturationValues(DARK_VIBRANT);
+
+        LIGHT_MUTED = new Target();
+        setDefaultLightLightnessValues(LIGHT_MUTED);
+        setDefaultMutedSaturationValues(LIGHT_MUTED);
+
+        MUTED = new Target();
+        setDefaultNormalLightnessValues(MUTED);
+        setDefaultMutedSaturationValues(MUTED);
+
+        DARK_MUTED = new Target();
+        setDefaultDarkLightnessValues(DARK_MUTED);
+        setDefaultMutedSaturationValues(DARK_MUTED);
+    }
+
+    private final float[] mSaturationTargets = new float[3];
+    private final float[] mLightnessTargets = new float[3];
+    private final float[] mWeights = new float[3];
+    private boolean mIsExclusive = true; // default to true
+
+    private Target() {
+        setTargetDefaultValues(mSaturationTargets);
+        setTargetDefaultValues(mLightnessTargets);
+        setDefaultWeights();
+    }
+
+    private Target(Target from) {
+        System.arraycopy(from.mSaturationTargets, 0, mSaturationTargets, 0,
+                mSaturationTargets.length);
+        System.arraycopy(from.mLightnessTargets, 0, mLightnessTargets, 0,
+                mLightnessTargets.length);
+        System.arraycopy(from.mWeights, 0, mWeights, 0, mWeights.length);
+    }
+
+    /**
+     * The minimum saturation value for this target.
+     */
+    @FloatRange(from = 0, to = 1)
+    public float getMinimumSaturation() {
+        return mSaturationTargets[INDEX_MIN];
+    }
+
+    /**
+     * The target saturation value for this target.
+     */
+    @FloatRange(from = 0, to = 1)
+    public float getTargetSaturation() {
+        return mSaturationTargets[INDEX_TARGET];
+    }
+
+    /**
+     * The maximum saturation value for this target.
+     */
+    @FloatRange(from = 0, to = 1)
+    public float getMaximumSaturation() {
+        return mSaturationTargets[INDEX_MAX];
+    }
+
+    /**
+     * The minimum lightness value for this target.
+     */
+    @FloatRange(from = 0, to = 1)
+    public float getMinimumLightness() {
+        return mLightnessTargets[INDEX_MIN];
+    }
+
+    /**
+     * The target lightness value for this target.
+     */
+    @FloatRange(from = 0, to = 1)
+    public float getTargetLightness() {
+        return mLightnessTargets[INDEX_TARGET];
+    }
+
+    /**
+     * The maximum lightness value for this target.
+     */
+    @FloatRange(from = 0, to = 1)
+    public float getMaximumLightness() {
+        return mLightnessTargets[INDEX_MAX];
+    }
+
+    /**
+     * The weight of important that a color's saturation value has on selection.
+     */
+    public float getSaturationWeight() {
+        return mWeights[INDEX_WEIGHT_SAT];
+    }
+
+    /**
+     * The weight of important that a color's lightness value has on selection.
+     */
+    public float getLightnessWeight() {
+        return mWeights[INDEX_WEIGHT_LUMA];
+    }
+
+    /**
+     * The weight of important that a color's population value has on selection.
+     */
+    public float getPopulationWeight() {
+        return mWeights[INDEX_WEIGHT_POP];
+    }
+
+    /**
+     * Returns whether any color selected for this target is exclusive for this target only.
+     *
+     * <p>If false, then the color can be selected for other targets.</p>
+     */
+    public boolean isExclusive() {
+        return mIsExclusive;
+    }
+
+    private static void setTargetDefaultValues(final float[] values) {
+        values[INDEX_MIN] = 0f;
+        values[INDEX_TARGET] = 0.5f;
+        values[INDEX_MAX] = 1f;
+    }
+
+    private void setDefaultWeights() {
+        mWeights[INDEX_WEIGHT_SAT] = WEIGHT_SATURATION;
+        mWeights[INDEX_WEIGHT_LUMA] = WEIGHT_LUMA;
+        mWeights[INDEX_WEIGHT_POP] = WEIGHT_POPULATION;
+    }
+
+    void normalizeWeights() {
+        float sum = 0;
+        for (int i = 0, z = mWeights.length; i < z; i++) {
+            float weight = mWeights[i];
+            if (weight > 0) {
+                sum += weight;
+            }
+        }
+        if (sum != 0) {
+            for (int i = 0, z = mWeights.length; i < z; i++) {
+                if (mWeights[i] > 0) {
+                    mWeights[i] /= sum;
+                }
+            }
+        }
+    }
+
+    private static void setDefaultDarkLightnessValues(Target target) {
+        target.mLightnessTargets[INDEX_TARGET] = TARGET_DARK_LUMA;
+        target.mLightnessTargets[INDEX_MAX] = MAX_DARK_LUMA;
+    }
+
+    private static void setDefaultNormalLightnessValues(Target target) {
+        target.mLightnessTargets[INDEX_MIN] = MIN_NORMAL_LUMA;
+        target.mLightnessTargets[INDEX_TARGET] = TARGET_NORMAL_LUMA;
+        target.mLightnessTargets[INDEX_MAX] = MAX_NORMAL_LUMA;
+    }
+
+    private static void setDefaultLightLightnessValues(Target target) {
+        target.mLightnessTargets[INDEX_MIN] = MIN_LIGHT_LUMA;
+        target.mLightnessTargets[INDEX_TARGET] = TARGET_LIGHT_LUMA;
+    }
+
+    private static void setDefaultVibrantSaturationValues(Target target) {
+        target.mSaturationTargets[INDEX_MIN] = MIN_VIBRANT_SATURATION;
+        target.mSaturationTargets[INDEX_TARGET] = TARGET_VIBRANT_SATURATION;
+    }
+
+    private static void setDefaultMutedSaturationValues(Target target) {
+        target.mSaturationTargets[INDEX_TARGET] = TARGET_MUTED_SATURATION;
+        target.mSaturationTargets[INDEX_MAX] = MAX_MUTED_SATURATION;
+    }
+
+    /**
+     * Builder class for generating custom {@link Target} instances.
+     */
+    public final static class Builder {
+        private final Target mTarget;
+
+        /**
+         * Create a new {@link Target} builder from scratch.
+         */
+        public Builder() {
+            mTarget = new Target();
+        }
+
+        /**
+         * Create a new builder based on an existing {@link Target}.
+         */
+        public Builder(Target target) {
+            mTarget = new Target(target);
+        }
+
+        /**
+         * Set the minimum saturation value for this target.
+         */
+        public Builder setMinimumSaturation(@FloatRange(from = 0, to = 1) float value) {
+            mTarget.mSaturationTargets[INDEX_MIN] = value;
+            return this;
+        }
+
+        /**
+         * Set the target/ideal saturation value for this target.
+         */
+        public Builder setTargetSaturation(@FloatRange(from = 0, to = 1) float value) {
+            mTarget.mSaturationTargets[INDEX_TARGET] = value;
+            return this;
+        }
+
+        /**
+         * Set the maximum saturation value for this target.
+         */
+        public Builder setMaximumSaturation(@FloatRange(from = 0, to = 1) float value) {
+            mTarget.mSaturationTargets[INDEX_MAX] = value;
+            return this;
+        }
+
+        /**
+         * Set the minimum lightness value for this target.
+         */
+        public Builder setMinimumLightness(@FloatRange(from = 0, to = 1) float value) {
+            mTarget.mLightnessTargets[INDEX_MIN] = value;
+            return this;
+        }
+
+        /**
+         * Set the target/ideal lightness value for this target.
+         */
+        public Builder setTargetLightness(@FloatRange(from = 0, to = 1) float value) {
+            mTarget.mLightnessTargets[INDEX_TARGET] = value;
+            return this;
+        }
+
+        /**
+         * Set the maximum lightness value for this target.
+         */
+        public Builder setMaximumLightness(@FloatRange(from = 0, to = 1) float value) {
+            mTarget.mLightnessTargets[INDEX_MAX] = value;
+            return this;
+        }
+
+        /**
+         * Set the weight of important that a color's saturation value has on selection. A weight
+         * of <= 0 means that it has no weight and is ignored.
+         */
+        public Builder setSaturationWeight(@FloatRange(from = 0) float weight) {
+            mTarget.mWeights[INDEX_WEIGHT_SAT] = weight;
+            return this;
+        }
+
+        /**
+         * Set the weight of important that a color's lightness value has on selection. A weight
+         * of <= 0 means that it has no weight and is ignored.
+         */
+        public Builder setLightnessWeight(@FloatRange(from = 0) float weight) {
+            mTarget.mWeights[INDEX_WEIGHT_LUMA] = weight;
+            return this;
+        }
+
+        /**
+         * Set the weight of important that a color's population value has on selection. A weight
+         * of <= 0 means that it has no weight and is ignored.
+         */
+        public Builder setPopulationWeight(@FloatRange(from = 0) float weight) {
+            mTarget.mWeights[INDEX_WEIGHT_POP] = weight;
+            return this;
+        }
+
+        /**
+         * Set whether any color selected for this target is exclusive to this target only.
+         * Defaults to true.
+         *
+         * @param exclusive true if any the color is exclusive to this target, or false is the
+         *                  color can be selected for other targets.
+         */
+        public Builder setExclusive(boolean exclusive) {
+            mTarget.mIsExclusive = exclusive;
+            return this;
+        }
+
+        /**
+         * Builds and returns the resulting {@link Target}.
+         */
+        public Target build() {
+            return mTarget;
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/v7/recyclerview/build.gradle b/v7/recyclerview/build.gradle
index 25b686d..c9f1a22 100644
--- a/v7/recyclerview/build.gradle
+++ b/v7/recyclerview/build.gradle
@@ -78,6 +78,17 @@
     artifacts.add('archives', sourcesJarTask);
 }
 
+// TODO make this generic for all projects
+afterEvaluate {
+    def originalTask = tasks['packageDebugAndroidTest']
+    tasks['assembleDebugAndroidTest'].doLast {
+        copy {
+            from(originalTask.outputFile)
+            into(rootProject.ext.testApkDistOut)
+        }
+    }
+}
+
 uploadArchives {
     repositories {
         mavenDeployer {