am 5ba742a3: Merge "Fix leak for MenuInflater + setSupportActionBar" into lmp-mr1-ub-dev

* commit '5ba742a37d06a0961f20e41c18cc6f8f4d5fd514':
  Fix leak for MenuInflater + setSupportActionBar
diff --git a/.gitignore b/.gitignore
index eee06e7..c8c3ed8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,8 @@
+.classpath
 .gradle
 .idea/
+.project
+.settings/
+project.properties
+**/bin
+**/gen
diff --git a/build.gradle b/build.gradle
index 5d8a0cb..fb4083b 100644
--- a/build.gradle
+++ b/build.gradle
@@ -9,8 +9,8 @@
     }
 }
 
-ext.supportVersion = '22.2.0'
-ext.extraVersion = 14
+ext.supportVersion = '23.0.0-rc1'
+ext.extraVersion = 15
 ext.supportRepoOut = ''
 ext.buildToolsVersion = '22.1.0'
 ext.buildNumber = Integer.toString(ext.extraVersion)
@@ -166,7 +166,6 @@
     project.plugins.whenPluginAdded { plugin ->
         if ("com.android.build.gradle.LibraryPlugin".equals(plugin.class.name)) {
             project.android.buildToolsVersion = rootProject.buildToolsVersion
-            project.android.aaptOptions.useNewCruncher = false
         }
     }
 }
diff --git a/design/build.gradle b/design/build.gradle
index ca8018c..3517cfc 100644
--- a/design/build.gradle
+++ b/design/build.gradle
@@ -13,7 +13,7 @@
     sourceSets {
         main.manifest.srcFile 'AndroidManifest.xml'
         main.java.srcDirs = ['base', 'eclair-mr1', 'honeycomb', 'honeycomb-mr1', 'lollipop', 'src']
-        main.res.srcDir 'res'
+        main.res.srcDirs 'res', 'res-public'
         main.assets.srcDir 'assets'
         main.resources.srcDir 'src'
 
diff --git a/design/res-public/values/public_attrs.xml b/design/res-public/values/public_attrs.xml
new file mode 100644
index 0000000..737596b
--- /dev/null
+++ b/design/res-public/values/public_attrs.xml
@@ -0,0 +1,62 @@
+<?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.
+-->
+
+<!-- Definitions of attributes to be exposed as public -->
+<resources>
+    <public type="attr" name="backgroundTint"/>
+    <public type="attr" name="backgroundTintMode"/>
+    <public type="attr" name="borderWidth"/>
+    <public type="attr" name="collapsedTitleTextAppearance"/>
+    <public type="attr" name="contentScrim"/>
+    <public type="attr" name="elevation"/>
+    <public type="attr" name="errorEnabled"/>
+    <public type="attr" name="errorTextAppearance"/>
+    <public type="attr" name="expandedTitleMargin"/>
+    <public type="attr" name="expandedTitleMarginBottom"/>
+    <public type="attr" name="expandedTitleMarginEnd"/>
+    <public type="attr" name="expandedTitleMarginStart"/>
+    <public type="attr" name="expandedTitleMarginTop"/>
+    <public type="attr" name="expandedTitleTextAppearance"/>
+    <public type="attr" name="fabSize"/>
+    <public type="attr" name="headerLayout"/>
+    <public type="attr" name="hintTextAppearance"/>
+    <public type="attr" name="itemBackground"/>
+    <public type="attr" name="itemIconTint"/>
+    <public type="attr" name="itemTextColor"/>
+    <public type="attr" name="keylines"/>
+    <public type="attr" name="menu"/>
+    <public type="attr" name="pressedTranslationZ"/>
+    <public type="attr" name="rippleColor"/>
+    <public type="attr" name="statusBarBackground"/>
+    <public type="attr" name="statusBarScrim"/>
+    <public type="attr" name="tabBackground"/>
+    <public type="attr" name="tabContentStart"/>
+    <public type="attr" name="tabGravity"/>
+    <public type="attr" name="tabIndicatorColor"/>
+    <public type="attr" name="tabIndicatorHeight"/>
+    <public type="attr" name="tabMaxWidth"/>
+    <public type="attr" name="tabMinWidth"/>
+    <public type="attr" name="tabMode"/>
+    <public type="attr" name="tabPadding"/>
+    <public type="attr" name="tabPaddingBottom"/>
+    <public type="attr" name="tabPaddingEnd"/>
+    <public type="attr" name="tabPaddingStart"/>
+    <public type="attr" name="tabPaddingTop"/>
+    <public type="attr" name="tabSelectedTextColor"/>
+    <public type="attr" name="tabTextAppearance"/>
+    <public type="attr" name="tabTextColor"/>
+    <public type="attr" name="toolbarId"/>
+</resources>
diff --git a/design/res-public/values/public_styles.xml b/design/res-public/values/public_styles.xml
new file mode 100644
index 0000000..f65e5e3
--- /dev/null
+++ b/design/res-public/values/public_styles.xml
@@ -0,0 +1,30 @@
+<?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.
+-->
+
+<!-- Definitions of styles to be exposed as public -->
+<resources>
+    <public type="style" name="TextAppearance.Design.Error"/>
+    <public type="style" name="TextAppearance.Design.Hint"/>
+    <public type="style" name="TextAppearance.Design.Tab"/>
+    <public type="style" name="Widget.Design.AppBarLayout"/>
+    <public type="style" name="Widget.Design.CollapsingToolbar"/>
+    <public type="style" name="Widget.Design.CoordinatorLayout"/>
+    <public type="style" name="Widget.Design.FloatingActionButton"/>
+    <public type="style" name="Widget.Design.NavigationView"/>
+    <public type="style" name="Widget.Design.Snackbar"/>
+    <public type="style" name="Widget.Design.TabLayout"/>
+    <public type="style" name="Widget.Design.TextInputLayout"/>
+</resources>
diff --git a/design/src/android/support/design/widget/CoordinatorLayout.java b/design/src/android/support/design/widget/CoordinatorLayout.java
index 8675e6d..c3d0ff2 100644
--- a/design/src/android/support/design/widget/CoordinatorLayout.java
+++ b/design/src/android/support/design/widget/CoordinatorLayout.java
@@ -490,6 +490,7 @@
                 final Class<Behavior> clazz = (Class<Behavior>) Class.forName(fullName, true,
                         context.getClassLoader());
                 c = clazz.getConstructor(CONSTRUCTOR_PARAMS);
+                c.setAccessible(true);
                 constructors.put(fullName, c);
             }
             return c.newInstance(context, attrs);
diff --git a/design/src/android/support/design/widget/FloatingActionButton.java b/design/src/android/support/design/widget/FloatingActionButton.java
index b275174..0a7eef8 100644
--- a/design/src/android/support/design/widget/FloatingActionButton.java
+++ b/design/src/android/support/design/widget/FloatingActionButton.java
@@ -24,6 +24,7 @@
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.os.Build;
+import android.support.annotation.ColorInt;
 import android.support.annotation.Nullable;
 import android.support.design.R;
 import android.support.v4.view.ViewCompat;
@@ -161,7 +162,7 @@
      *
      * @param color ARGB color to use for the ripple.
      */
-    public void setRippleColor(int color) {
+    public void setRippleColor(@ColorInt int color) {
         if (mRippleColor != color) {
             mRippleColor = color;
             mImpl.setRippleColor(color);
diff --git a/graphics/Android.mk b/graphics/Android.mk
new file mode 100644
index 0000000..365b3b1
--- /dev/null
+++ b/graphics/Android.mk
@@ -0,0 +1,16 @@
+# 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.
+
+LOCAL_PATH:= $(call my-dir)
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/graphics/drawable/Android.mk b/graphics/drawable/Android.mk
new file mode 100644
index 0000000..63e93b7
--- /dev/null
+++ b/graphics/drawable/Android.mk
@@ -0,0 +1,41 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+#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_JAVA_LIBRARIES := android-support-v4
+
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res \
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+#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_JAVA_LIBRARIES := android-support-v4
+
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res \
+
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-v7-vectordrawable
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
\ No newline at end of file
diff --git a/graphics/drawable/AndroidManifest.xml b/graphics/drawable/AndroidManifest.xml
new file mode 100644
index 0000000..83124c7
--- /dev/null
+++ b/graphics/drawable/AndroidManifest.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android.support.graphics.drawable">
+    <application />
+</manifest>
diff --git a/graphics/drawable/animated/src/android/support/graphics/drawable/AnimatedVectorDrawableCompat.java b/graphics/drawable/animated/src/android/support/graphics/drawable/AnimatedVectorDrawableCompat.java
new file mode 100644
index 0000000..78ef62d
--- /dev/null
+++ b/graphics/drawable/animated/src/android/support/graphics/drawable/AnimatedVectorDrawableCompat.java
@@ -0,0 +1,504 @@
+/*
+ * 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.animation.Animator;
+import android.animation.AnimatorInflater;
+import android.animation.ObjectAnimator;
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.content.res.Resources;
+import android.content.res.Resources.Theme;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.PorterDuff.Mode;
+import android.graphics.Rect;
+import android.graphics.drawable.Animatable;
+import android.graphics.drawable.Drawable;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.annotation.DrawableRes;
+import android.support.v4.util.ArrayMap;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.Xml;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+/**
+ * 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.
+ * <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
+ * 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>
+ * <li>Here is a simple VectorDrawable in this vectordrawable.xml file.
+ * <pre>
+ * &lt;vector xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
+ *     android:height=&quot;64dp&quot;
+ *     android:width=&quot;64dp&quot;
+ *     android:viewportHeight=&quot;600&quot;
+ *     android:viewportWidth=&quot;600&quot; &gt;
+ *     &lt;group
+ *         android:name=&quot;rotationGroup&quot;
+ *         android:pivotX=&quot;300.0&quot;
+ *         android:pivotY=&quot;300.0&quot;
+ *         android:rotation=&quot;45.0&quot; &gt;
+ *         &lt;path
+ *             android:name=&quot;v&quot;
+ *             android:fillColor=&quot;#000000&quot;
+ *             android:pathData=&quot;M300,70 l 0,-70 70,70 0,0 -70,70z&quot; /&gt;
+ *     &lt;/group&gt;
+ * &lt;/vector&gt;
+ * </pre></li>
+ * <p>
+ * Second is the AnimatedVectorDrawableCompat's XML file, which defines the target
+ * VectorDrawableCompat, the target paths and groups to animate, the properties of the path and
+ * group to animate and the animations defined as the ObjectAnimators or AnimatorSets.
+ * </p>
+ * <li>Here is a simple AnimatedVectorDrawable defined in this avd.xml file.
+ * Note how we use the names to refer to the groups and paths in the vectordrawable.xml.
+ * <pre>
+ * &lt;animated-vector xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
+ *   android:drawable=&quot;@drawable/vectordrawable&quot; &gt;
+ *     &lt;target
+ *         android:name=&quot;rotationGroup&quot;
+ *         android:animation=&quot;@anim/rotation&quot; /&gt;
+ *     &lt;target
+ *         android:name=&quot;v&quot;
+ *         android:animation=&quot;@anim/path_morph&quot; /&gt;
+ * &lt;/animated-vector&gt;
+ * </pre></li>
+ * <p>
+ * Last is the Animator XML file, which is the same as a normal ObjectAnimator or AnimatorSet. To
+ * complete this example, here are the 2 animator files used in avd.xml: rotation.xml and
+ * path_morph.xml.
+ * </p>
+ * <li>Here is the rotation.xml, which will rotate the target group for 360 degrees.
+ * <pre>
+ * &lt;objectAnimator
+ *     android:duration=&quot;6000&quot;
+ *     android:propertyName=&quot;rotation&quot;
+ *     android:valueFrom=&quot;0&quot;
+ *     android:valueTo=&quot;360&quot; /&gt;
+ * </pre></li>
+ * <li>Here is the path_morph.xml, which will morph the path from one shape to
+ * the other. Note that the paths must be compatible for morphing.
+ * In more details, the paths should have exact same length of commands, and
+ * exact same length of parameters for each commands.
+ * Note that the path strings are better stored in strings.xml for reusing.
+ * <pre>
+ * &lt;set xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;&gt;
+ *     &lt;objectAnimator
+ *         android:duration=&quot;3000&quot;
+ *         android:propertyName=&quot;pathData&quot;
+ *         android:valueFrom=&quot;M300,70 l 0,-70 70,70 0,0   -70,70z&quot;
+ *         android:valueTo=&quot;M300,70 l 0,-70 70,0  0,140 -70,0 z&quot;
+ *         android:valueType=&quot;pathType&quot;/&gt;
+ * &lt;/set&gt;
+ * </pre></li>
+ *
+ * @attr ref android.R.styleable#AnimatedVectorDrawableCompat_drawable
+ * @attr ref android.R.styleable#AnimatedVectorDrawableCompatTarget_name
+ * @attr ref android.R.styleable#AnimatedVectorDrawableCompatTarget_animation
+ */
+public class AnimatedVectorDrawableCompat extends Drawable implements Animatable {
+    private static final String LOGTAG = "AnimatedVectorDrawableCompat";
+
+    private static final String ANIMATED_VECTOR = "animated-vector";
+    private static final String TARGET = "target";
+
+    private static final boolean DBG_ANIMATION_VECTOR_DRAWABLE = false;
+
+    private AnimatedVectorDrawableCompatState mAnimatedVectorState;
+
+    private boolean mMutated;
+
+    private Context mContext;
+
+    // Currently the only useful ctor.
+    public AnimatedVectorDrawableCompat(Context context) {
+        this(context, null, null);
+    }
+
+    private AnimatedVectorDrawableCompat(Context context, AnimatedVectorDrawableCompatState state,
+            Resources res) {
+        mContext = context;
+        if (state != null) {
+            mAnimatedVectorState = state;
+        } else {
+            mAnimatedVectorState = new AnimatedVectorDrawableCompatState(context, state, mCallback,
+                res);
+        }
+    }
+
+    @Override
+    public Drawable mutate() {
+        if (!mMutated && super.mutate() == this) {
+            mAnimatedVectorState =
+                    new AnimatedVectorDrawableCompatState(null, mAnimatedVectorState, mCallback,
+                            null);
+            mMutated = true;
+        }
+        return this;
+    }
+
+
+    /**
+     * Create a AnimatedVectorDrawableCompat object.
+     *
+     * @param context the context for creating the animators.
+     * @param resId the resource ID for AnimatedVectorDrawableCompat object.
+     * @return a new AnimatedVectorDrawableCompat or null if parsing error is found.
+     */
+    @Nullable
+    public static AnimatedVectorDrawableCompat create(@NonNull Context context,
+            @DrawableRes int resId) {
+        Resources resources = context.getResources();
+        try {
+            final XmlPullParser parser = resources.getXml(resId);
+            final AttributeSet attrs = Xml.asAttributeSet(parser);
+            int type;
+            while ((type = parser.next()) != XmlPullParser.START_TAG
+                    && type != XmlPullParser.END_DOCUMENT) {
+                // Empty loop
+            }
+            if (type != XmlPullParser.START_TAG) {
+                throw new XmlPullParserException("No start tag found");
+            }
+
+            final AnimatedVectorDrawableCompat drawable = new AnimatedVectorDrawableCompat(context);
+            drawable.inflate(resources, parser, attrs, context.getTheme());
+
+            return drawable;
+        } catch (XmlPullParserException e) {
+            Log.e(LOGTAG, "parser error", e);
+        } catch (IOException e) {
+            Log.e(LOGTAG, "parser error", e);
+        }
+        return null;
+    }
+
+    @Override
+    public ConstantState getConstantState() {
+        mAnimatedVectorState.mChangingConfigurations = getChangingConfigurations();
+        return mAnimatedVectorState;
+    }
+
+    @Override
+    public int getChangingConfigurations() {
+        return super.getChangingConfigurations() | mAnimatedVectorState.mChangingConfigurations;
+    }
+
+    @Override
+    public void draw(Canvas canvas) {
+        mAnimatedVectorState.mVectorDrawable.draw(canvas);
+        if (isStarted()) {
+            invalidateSelf();
+        }
+    }
+
+    @Override
+    protected void onBoundsChange(Rect bounds) {
+        mAnimatedVectorState.mVectorDrawable.setBounds(bounds);
+    }
+
+    @Override
+    protected boolean onStateChange(int[] state) {
+        return mAnimatedVectorState.mVectorDrawable.setState(state);
+    }
+
+    @Override
+    protected boolean onLevelChange(int level) {
+        return mAnimatedVectorState.mVectorDrawable.setLevel(level);
+    }
+
+    // @Override
+    public int getAlpha() {
+        return mAnimatedVectorState.mVectorDrawable.getAlpha();
+    }
+
+    // @Override
+    public void setAlpha(int alpha) {
+        mAnimatedVectorState.mVectorDrawable.setAlpha(alpha);
+    }
+
+    @Override
+    public void setColorFilter(ColorFilter colorFilter) {
+        mAnimatedVectorState.mVectorDrawable.setColorFilter(colorFilter);
+    }
+
+    public void setTintList(ColorStateList tint) {
+        mAnimatedVectorState.mVectorDrawable.setTintList(tint);
+    }
+
+    public void setTintMode(Mode tintMode) {
+        mAnimatedVectorState.mVectorDrawable.setTintMode(tintMode);
+    }
+
+    @Override
+    public boolean setVisible(boolean visible, boolean restart) {
+        mAnimatedVectorState.mVectorDrawable.setVisible(visible, restart);
+        return super.setVisible(visible, restart);
+    }
+
+    @Override
+    public boolean isStateful() {
+        return mAnimatedVectorState.mVectorDrawable.isStateful();
+    }
+
+    @Override
+    public int getOpacity() {
+        return mAnimatedVectorState.mVectorDrawable.getOpacity();
+    }
+
+    public int getIntrinsicWidth() {
+        return mAnimatedVectorState.mVectorDrawable.getIntrinsicWidth();
+    }
+
+    public int getIntrinsicHeight() {
+        return mAnimatedVectorState.mVectorDrawable.getIntrinsicHeight();
+    }
+
+    /**
+     * Obtains styled attributes from the theme, if available, or unstyled
+     * resources if the theme is null.
+     */
+    static TypedArray obtainAttributes(
+            Resources res, Theme theme, AttributeSet set, int[] attrs) {
+        if (theme == null) {
+            return res.obtainAttributes(set, attrs);
+        }
+        return theme.obtainStyledAttributes(set, attrs, 0, 0);
+    }
+
+    public void inflate(Resources res, XmlPullParser parser, AttributeSet attrs, Theme theme)
+            throws XmlPullParserException, IOException {
+        int eventType = parser.getEventType();
+        float pathErrorScale = 1;
+        while (eventType != XmlPullParser.END_DOCUMENT) {
+            if (eventType == XmlPullParser.START_TAG) {
+                final String tagName = parser.getName();
+                if (DBG_ANIMATION_VECTOR_DRAWABLE) {
+                    Log.v(LOGTAG, "tagName is " + tagName);
+                }
+                if (ANIMATED_VECTOR.equals(tagName)) {
+                    final TypedArray a =
+                            obtainAttributes(res, theme, attrs, R.styleable.AnimatedVectorDrawable);
+
+                    int drawableRes = a.getResourceId(R.styleable.AnimatedVectorDrawable_drawable,
+                            0);
+                    if (DBG_ANIMATION_VECTOR_DRAWABLE) {
+                        Log.v(LOGTAG, "drawableRes is " + drawableRes);
+                    }
+                    if (drawableRes != 0) {
+                        VectorDrawableCompat vectorDrawable = VectorDrawableCompat.create(res,
+                                drawableRes, theme);
+                        vectorDrawable.setAllowCaching(false);
+                        vectorDrawable.setCallback(mCallback);
+                        pathErrorScale = vectorDrawable.getPixelSize();
+                        if (mAnimatedVectorState.mVectorDrawable != null) {
+                            mAnimatedVectorState.mVectorDrawable.setCallback(null);
+                        }
+                        mAnimatedVectorState.mVectorDrawable = vectorDrawable;
+                    }
+                    a.recycle();
+                } else if (TARGET.equals(tagName)) {
+                    final TypedArray a =
+                            res.obtainAttributes(attrs, R.styleable.AnimatedVectorDrawableTarget);
+                    final String target = a.getString(
+                            R.styleable.AnimatedVectorDrawableTarget_name);
+
+                    int id = a.getResourceId(R.styleable.AnimatedVectorDrawableTarget_animation, 0);
+                    if (id != 0) {
+                        Animator objectAnimator = AnimatorInflater.loadAnimator(mContext, id);
+                        setupAnimatorsForTarget(target, objectAnimator);
+                    }
+                    a.recycle();
+                }
+            }
+
+            eventType = parser.next();
+        }
+    }
+
+    @Override
+    public void inflate(Resources res, XmlPullParser parser, AttributeSet attrs)
+            throws XmlPullParserException, IOException {
+        inflate(res, parser, attrs, null);
+    }
+
+    public boolean canApplyTheme() {
+        return false;
+    }
+
+    private static class AnimatedVectorDrawableCompatState extends ConstantState {
+        int mChangingConfigurations;
+        VectorDrawableCompat mVectorDrawable;
+        ArrayList<Animator> mAnimators;
+        ArrayMap<Animator, String> mTargetNameMap;
+        Context mContext;
+
+        public AnimatedVectorDrawableCompatState(Context context,
+                AnimatedVectorDrawableCompatState copy, Callback owner, Resources res) {
+            if (copy != null) {
+                mChangingConfigurations = copy.mChangingConfigurations;
+                if (copy.mVectorDrawable != null) {
+                    final ConstantState cs = copy.mVectorDrawable.getConstantState();
+                    if (res != null) {
+                        mVectorDrawable = (VectorDrawableCompat) cs.newDrawable(res);
+                    } else {
+                        mVectorDrawable = (VectorDrawableCompat) cs.newDrawable();
+                    }
+                    mVectorDrawable = (VectorDrawableCompat) mVectorDrawable.mutate();
+                    mVectorDrawable.setCallback(owner);
+                    mVectorDrawable.setBounds(copy.mVectorDrawable.getBounds());
+                    mVectorDrawable.setAllowCaching(false);
+                }
+                if (copy.mAnimators != null) {
+                    final int numAnimators = copy.mAnimators.size();
+                    mAnimators = new ArrayList<Animator>(numAnimators);
+                    mTargetNameMap = new ArrayMap<Animator, String>(numAnimators);
+                    for (int i = 0; i < numAnimators; ++i) {
+                        Animator anim = copy.mAnimators.get(i);
+                        Animator animClone = anim.clone();
+                        String targetName = copy.mTargetNameMap.get(anim);
+                        Object targetObject = mVectorDrawable.getTargetByName(targetName);
+                        animClone.setTarget(targetObject);
+                        mAnimators.add(animClone);
+                        mTargetNameMap.put(animClone, targetName);
+                    }
+                }
+            }
+
+            if (context != null) {
+                mContext = context;
+            } else {
+                mContext = copy.mContext;
+            }
+
+        }
+
+        @Override
+        public Drawable newDrawable() {
+            return new AnimatedVectorDrawableCompat(mContext, this, null);
+        }
+
+        @Override
+        public Drawable newDrawable(Resources res) {
+            return new AnimatedVectorDrawableCompat(mContext, this, res);
+        }
+
+        @Override
+        public int getChangingConfigurations() {
+            return mChangingConfigurations;
+        }
+    }
+
+    private void setupAnimatorsForTarget(String name, Animator animator) {
+        Object target = mAnimatedVectorState.mVectorDrawable.getTargetByName(name);
+        animator.setTarget(target);
+        if (mAnimatedVectorState.mAnimators == null) {
+            mAnimatedVectorState.mAnimators = new ArrayList<Animator>();
+            mAnimatedVectorState.mTargetNameMap = new ArrayMap<Animator, String>();
+        }
+        mAnimatedVectorState.mAnimators.add(animator);
+        mAnimatedVectorState.mTargetNameMap.put(animator, name);
+        if (DBG_ANIMATION_VECTOR_DRAWABLE) {
+            Log.v(LOGTAG, "add animator  for target " + name + " " + animator);
+        }
+    }
+
+    @Override
+    public boolean isRunning() {
+        final ArrayList<Animator> animators = mAnimatedVectorState.mAnimators;
+        final int size = animators.size();
+        for (int i = 0; i < size; i++) {
+            final Animator animator = animators.get(i);
+            if (animator.isRunning()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean isStarted() {
+        final ArrayList<Animator> animators = mAnimatedVectorState.mAnimators;
+        if (animators == null) {
+            return false;
+        }
+        final int size = animators.size();
+        for (int i = 0; i < size; i++) {
+            final Animator animator = animators.get(i);
+            if (animator.isRunning()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public void start() {
+        // If any one of the animator has not ended, do nothing.
+        if (isStarted()) {
+            return;
+        }
+        // Otherwise, kick off every animator.
+        final ArrayList<Animator> animators = mAnimatedVectorState.mAnimators;
+        final int size = animators.size();
+        for (int i = 0; i < size; i++) {
+            final Animator animator = animators.get(i);
+            animator.start();
+        }
+        invalidateSelf();
+    }
+
+    @Override
+    public void stop() {
+        final ArrayList<Animator> animators = mAnimatedVectorState.mAnimators;
+        final int size = animators.size();
+        for (int i = 0; i < size; i++) {
+            final Animator animator = animators.get(i);
+            animator.end();
+        }
+    }
+
+    private final Callback mCallback = new Callback() {
+        @Override
+        public void invalidateDrawable(Drawable who) {
+            invalidateSelf();
+        }
+
+        @Override
+        public void scheduleDrawable(Drawable who, Runnable what, long when) {
+            scheduleSelf(what, when);
+        }
+
+        @Override
+        public void unscheduleDrawable(Drawable who, Runnable what) {
+            unscheduleSelf(what);
+        }
+    };
+}
diff --git a/graphics/drawable/res/values/attrs.xml b/graphics/drawable/res/values/attrs.xml
new file mode 100644
index 0000000..b54c9a6
--- /dev/null
+++ b/graphics/drawable/res/values/attrs.xml
@@ -0,0 +1,183 @@
+<?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.
+-->
+<resources>
+  <!-- If set, specifies the color to apply to the drawable as a tint. By default,
+       no tint is applied. May be a color state list. -->
+  <attr name="tint" format="color" />
+  <!-- When a tint color is set, specifies its Porter-Duff blending mode. The
+       default value is src_in, which treats the drawable as an alpha mask. -->
+  <attr name="tintMode">
+    <!-- The tint is drawn on top of the drawable.
+         [Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc] -->
+    <enum name="src_over" value="3" />
+    <!-- The tint is masked by the alpha channel of the drawable. The drawable’s
+         color channels are thrown out. [Sa * Da, Sc * Da] -->
+    <enum name="src_in" value="5" />
+    <!-- The tint is drawn above the drawable, but with the drawable’s alpha
+         channel masking the result. [Da, Sc * Da + (1 - Sa) * Dc] -->
+    <enum name="src_atop" value="9" />
+    <!-- Multiplies the color and alpha channels of the drawable with those of
+         the tint. [Sa * Da, Sc * Dc] -->
+    <enum name="multiply" value="14" />
+    <!-- [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc] -->
+    <enum name="screen" value="15" />
+    <!-- Combines the tint and drawable color and alpha channels, clamping the
+         result to valid color values. Saturate(S + D) -->
+    <enum name="add" value="16" />
+  </attr>
+  <!-- Animation to use on each child. -->
+  <attr name="animation" format="reference" />
+  <!-- alpha property of the view, as a value between 0 (completely transparent) and 1
+             (completely opaque). -->
+  <attr name="alpha" format="float" />
+  <attr name="pivotX" format="float|fraction" />
+  <attr name="pivotY" format="float|fraction" />
+  <!-- rotation of the view, in degrees. -->
+  <attr name="rotation" format="float" />
+
+  <!-- scale of the view in the x direction. -->
+  <attr name="scaleX" format="float" />
+
+  <!-- scale of the view in the y direction. -->
+  <attr name="scaleY" format="float" />
+  <!-- Makes the TextView be exactly this many pixels tall.
+       You could get the same effect by specifying this number in the
+       layout parameters. -->
+  <attr name="height" format="dimension" />
+  <!-- Makes the TextView be exactly this many pixels wide.
+       You could get the same effect by specifying this number in the
+       layout parameters. -->
+  <attr name="width" format="dimension" />
+  <!-- A unique name for the given item.  This must use a Java-style naming
+       convention to ensure the name is unique, for example
+       "com.mycompany.MyName". -->
+  <attr name="name" format="string" />
+
+  <!-- ========================== -->
+  <!--   VectorDrawable class   -->
+  <!-- ========================== -->
+  <eat-comment />
+
+  <!-- Drawable used to draw vector paths. -->
+  <declare-styleable name="VectorDrawable">
+    <!-- If set, specifies the color to apply to the drawable as a tint. By default,
+         no tint is applied. May be a color state list. -->
+    <attr name="tint" />
+    <!-- When a tint color is set, specifies its Porter-Duff blending mode. The
+         default value is src_in, which treats the drawable as an alpha mask. -->
+    <attr name="tintMode" />
+    <!-- Indicates if the drawable needs to be mirrored when its layout direction is
+         RTL (right-to-left). -->
+    <attr name="autoMirrored" format="boolean" />
+    <!-- The intrinsic width of the Vector Drawable. -->
+    <attr name="width" />
+    <!-- The intrinsic height of the Vector Drawable. -->
+    <attr name="height" />
+    <!-- The width of the canvas the drawing is on. -->
+    <attr name="viewportWidth" format="float"/>
+    <!-- The height of the canvas the drawing is on. -->
+    <attr name="viewportHeight" format="float"/>
+    <!-- The name of this vector drawable -->
+    <attr name="name" />
+    <!-- The opacity of the whole vector drawable, as a value between 0
+         (completely transparent) and 1 (completely opaque). -->
+    <attr name="alpha" />
+  </declare-styleable>
+
+  <!-- Defines the group used in VectorDrawables. -->
+  <declare-styleable name="VectorDrawableGroup">
+    <!-- The name of this group -->
+    <attr name="name" />
+    <!-- The amount to rotate the group -->
+    <attr name="rotation" />
+    <!-- The X coordinate of the center of rotation of a group -->
+    <attr name="pivotX" />
+    <!-- The Y coordinate of the center of rotation of a group -->
+    <attr name="pivotY" />
+    <!-- The amount to translate the group on X coordinate -->
+    <attr name="translateX" format="float"/>
+    <!-- The amount to translate the group on Y coordinate -->
+    <attr name="translateY" format="float"/>
+    <!-- The amount to scale the group on X coordinate -->
+    <attr name="scaleX" />
+    <!-- The amount to scale the group on X coordinate -->
+    <attr name="scaleY" />
+  </declare-styleable>
+
+  <!-- Defines the path used in VectorDrawables. -->
+  <declare-styleable name="VectorDrawablePath">
+    <!-- The name of this path -->
+    <attr name="name" />
+    <!-- The width a path stroke -->
+    <attr name="strokeWidth" format="float" />
+    <!-- The color to stroke the path if not defined implies no stroke-->
+    <attr name="strokeColor" format="color" />
+    <!-- The opacity of a path stroke, as a value between 0 (completely transparent)
+         and 1 (completely opaque) -->
+    <attr name="strokeAlpha" format="float" />
+    <!-- The color to fill the path if not defined implies no fill-->
+    <attr name="fillColor" format="color" />
+    <!-- The alpha of the path fill, as a value between 0 (completely transparent)
+         and 1 (completely opaque)-->
+    <attr name="fillAlpha" format="float" />
+    <!-- The specification of the operations that define the path  -->
+    <attr name="pathData" format="string" />
+    <!-- The fraction of the path to trim from the start from 0 to 1 -->
+    <attr name="trimPathStart" format="float" />
+    <!-- The fraction of the path to trim from the end from 0 to 1  -->
+    <attr name="trimPathEnd" format="float" />
+    <!-- Shift trim region (allows visible region to include the start and end) from 0 to 1  -->
+    <attr name="trimPathOffset" format="float" />
+    <!-- The linecap for a stroked path -->
+    <attr name="strokeLineCap" format="enum">
+      <enum name="butt" value="0"/>
+      <enum name="round" value="1"/>
+      <enum name="square" value="2"/>
+    </attr>
+    <!-- The lineJoin for a stroked path -->
+    <attr name="strokeLineJoin" format="enum">
+      <enum name="miter" value="0"/>
+      <enum name="round" value="1"/>
+      <enum name="bevel" value="2"/>
+    </attr>
+    <!-- The Miter limit for a stroked path -->
+    <attr name="strokeMiterLimit" format="float"/>
+  </declare-styleable>
+
+  <!-- Defines the clip path used in VectorDrawables. -->
+  <declare-styleable name="VectorDrawableClipPath">
+    <!-- The Name of this path -->
+    <attr name="name" />
+    <!-- The specification of the operations that define the path  -->
+    <attr name="pathData"/>
+  </declare-styleable>
+
+  <!-- ========================== -->
+  <!--   AnimatedVectorDrawable class   -->
+  <!-- ========================== -->
+  <eat-comment />
+
+  <!-- Define the AnimatedVectorDrawable. -->
+  <declare-styleable name="AnimatedVectorDrawable">
+    <!-- The static vector drawable. -->
+    <attr name="drawable" format="reference" />
+  </declare-styleable>
+
+  <!-- Defines the target used in the AnimatedVectorDrawable. -->
+  <declare-styleable name="AnimatedVectorDrawableTarget">
+    <!-- The name of the target path, group or vector drawable -->
+    <attr name="name" />
+    <!-- The animation for the target path, group or vector drawable -->
+    <attr name="animation" />
+  </declare-styleable>
+</resources>
diff --git a/graphics/drawable/runavdtest.sh b/graphics/drawable/runavdtest.sh
new file mode 100755
index 0000000..023ad3e
--- /dev/null
+++ b/graphics/drawable/runavdtest.sh
@@ -0,0 +1,5 @@
+. ../../../../build/envsetup.sh
+mmm -j20 . && mmm -j20 ./testanimated/ && \
+adb install -r $OUT/data/app/AndroidAnimatedVectorDrawableTests/AndroidAnimatedVectorDrawableTests.apk && \
+adb shell am start -n android.support.test.vectordrawable/android.support.test.vectordrawable.TestAVDActivity
+
diff --git a/graphics/drawable/runtest.sh b/graphics/drawable/runtest.sh
new file mode 100755
index 0000000..6f69780
--- /dev/null
+++ b/graphics/drawable/runtest.sh
@@ -0,0 +1,5 @@
+. ../../../../build/envsetup.sh
+mmm -j20 . && mmm -j20 ./teststatic/ && \
+adb install -r $OUT/data/app/AndroidVectorDrawableTests/AndroidVectorDrawableTests.apk && \
+adb shell am start -n android.support.test.vectordrawable/android.support.test.vectordrawable.TestActivity
+
diff --git a/graphics/drawable/static/src/android/support/graphics/drawable/PathParser.java b/graphics/drawable/static/src/android/support/graphics/drawable/PathParser.java
new file mode 100644
index 0000000..a92c3e5
--- /dev/null
+++ b/graphics/drawable/static/src/android/support/graphics/drawable/PathParser.java
@@ -0,0 +1,718 @@
+/*
+ * 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.graphics.Path;
+import android.util.Log;
+
+import java.util.ArrayList;
+
+// This class is a duplicate from the PathParser.java of frameworks/base, with slight
+// update on incompatible API like copyOfRange().
+class PathParser {
+    private static final String LOGTAG = "PathParser";
+
+    // Copy from Arrays.copyOfRange() which is only available from API level 9.
+    /**
+     * Copies elements from {@code original} into a new array, from indexes start (inclusive) to
+     * end (exclusive). The original order of elements is preserved.
+     * If {@code end} is greater than {@code original.length}, the result is padded
+     * with the value {@code 0.0f}.
+     *
+     * @param original the original array
+     * @param start the start index, inclusive
+     * @param end the end index, exclusive
+     * @return the new array
+     * @throws ArrayIndexOutOfBoundsException if {@code start < 0 || start > original.length}
+     * @throws IllegalArgumentException if {@code start > end}
+     * @throws NullPointerException if {@code original == null}
+     */
+    private static float[] copyOfRange(float[] original, int start, int end) {
+        if (start > end) {
+            throw new IllegalArgumentException();
+        }
+        int originalLength = original.length;
+        if (start < 0 || start > originalLength) {
+            throw new ArrayIndexOutOfBoundsException();
+        }
+        int resultLength = end - start;
+        int copyLength = Math.min(resultLength, originalLength - start);
+        float[] result = new float[resultLength];
+        System.arraycopy(original, start, result, 0, copyLength);
+        return result;
+    }
+
+    /**
+     * @param pathData The string representing a path, the same as "d" string in svg file.
+     * @return the generated Path object.
+     */
+    public static Path createPathFromPathData(String pathData) {
+        Path path = new Path();
+        PathDataNode[] nodes = createNodesFromPathData(pathData);
+        if (nodes != null) {
+            try {
+                PathDataNode.nodesToPath(nodes, path);
+            } catch (RuntimeException e) {
+                throw new RuntimeException("Error in parsing " + pathData, e);
+            }
+            return path;
+        }
+        return null;
+    }
+
+    /**
+     * @param pathData The string representing a path, the same as "d" string in svg file.
+     * @return an array of the PathDataNode.
+     */
+    public static PathDataNode[] createNodesFromPathData(String pathData) {
+        if (pathData == null) {
+            return null;
+        }
+        int start = 0;
+        int end = 1;
+
+        ArrayList<PathDataNode> list = new ArrayList<PathDataNode>();
+        while (end < pathData.length()) {
+            end = nextStart(pathData, end);
+            String s = pathData.substring(start, end).trim();
+            if (s.length() > 0) {
+                float[] val = getFloats(s);
+                addNode(list, s.charAt(0), val);
+            }
+
+            start = end;
+            end++;
+        }
+        if ((end - start) == 1 && start < pathData.length()) {
+            addNode(list, pathData.charAt(start), new float[0]);
+        }
+        return list.toArray(new PathDataNode[list.size()]);
+    }
+
+    /**
+     * @param source The array of PathDataNode to be duplicated.
+     * @return a deep copy of the <code>source</code>.
+     */
+    public static PathDataNode[] deepCopyNodes(PathDataNode[] source) {
+        if (source == null) {
+            return null;
+        }
+        PathDataNode[] copy = new PathParser.PathDataNode[source.length];
+        for (int i = 0; i < source.length; i ++) {
+            copy[i] = new PathDataNode(source[i]);
+        }
+        return copy;
+    }
+
+    /**
+     * @param nodesFrom The source path represented in an array of PathDataNode
+     * @param nodesTo The target path represented in an array of PathDataNode
+     * @return whether the <code>nodesFrom</code> can morph into <code>nodesTo</code>
+     */
+    public static boolean canMorph(PathDataNode[] nodesFrom, PathDataNode[] nodesTo) {
+        if (nodesFrom == null || nodesTo == null) {
+            return false;
+        }
+
+        if (nodesFrom.length != nodesTo.length) {
+            return false;
+        }
+
+        for (int i = 0; i < nodesFrom.length; i ++) {
+            if (nodesFrom[i].mType != nodesTo[i].mType
+                    || nodesFrom[i].mParams.length != nodesTo[i].mParams.length) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Update the target's data to match the source.
+     * Before calling this, make sure canMorph(target, source) is true.
+     *
+     * @param target The target path represented in an array of PathDataNode
+     * @param source The source path represented in an array of PathDataNode
+     */
+    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];
+            }
+        }
+    }
+
+    private static int nextStart(String s, int end) {
+        char c;
+
+        while (end < s.length()) {
+            c = s.charAt(end);
+            // Note that 'e' or 'E' are not valid path commands, but could be
+            // used for floating point numbers' scientific notation.
+            // Therefore, when searching for next command, we should ignore 'e'
+            // and 'E'.
+            if ((((c - 'A') * (c - 'Z') <= 0) || ((c - 'a') * (c - 'z') <= 0))
+                    && c != 'e' && c != 'E') {
+                return end;
+            }
+            end++;
+        }
+        return end;
+    }
+
+    private static void addNode(ArrayList<PathDataNode> list, char cmd, float[] val) {
+        list.add(new PathDataNode(cmd, val));
+    }
+
+    private static class ExtractFloatResult {
+        // We need to return the position of the next separator and whether the
+        // next float starts with a '-' or a '.'.
+        int mEndPosition;
+        boolean mEndWithNegOrDot;
+    }
+
+    /**
+     * Parse the floats in the string.
+     * This is an optimized version of parseFloat(s.split(",|\\s"));
+     *
+     * @param s the string containing a command and list of floats
+     * @return array of floats
+     */
+    private static float[] getFloats(String s) {
+        if (s.charAt(0) == 'z' | s.charAt(0) == 'Z') {
+            return new float[0];
+        }
+        try {
+            float[] results = new float[s.length()];
+            int count = 0;
+            int startPosition = 1;
+            int endPosition = 0;
+
+            ExtractFloatResult result = new ExtractFloatResult();
+            int totalLength = s.length();
+
+            // The startPosition should always be the first character of the
+            // current number, and endPosition is the character after the current
+            // number.
+            while (startPosition < totalLength) {
+                extract(s, startPosition, result);
+                endPosition = result.mEndPosition;
+
+                if (startPosition < endPosition) {
+                    results[count++] = Float.parseFloat(
+                            s.substring(startPosition, endPosition));
+                }
+
+                if (result.mEndWithNegOrDot) {
+                    // Keep the '-' or '.' sign with next number.
+                    startPosition = endPosition;
+                } else {
+                    startPosition = endPosition + 1;
+                }
+            }
+            return copyOfRange(results, 0, count);
+        } catch (NumberFormatException e) {
+            throw new RuntimeException("error in parsing \"" + s + "\"", e);
+        }
+    }
+
+    /**
+     * Calculate the position of the next comma or space or negative sign
+     * @param s the string to search
+     * @param start the position to start searching
+     * @param result the result of the extraction, including the position of the
+     * the starting position of next number, whether it is ending with a '-'.
+     */
+    private static void extract(String s, int start, ExtractFloatResult result) {
+        // Now looking for ' ', ',', '.' or '-' from the start.
+        int currentIndex = start;
+        boolean foundSeparator = false;
+        result.mEndWithNegOrDot = false;
+        boolean secondDot = false;
+        boolean isExponential = false;
+        for (; currentIndex < s.length(); currentIndex++) {
+            boolean isPrevExponential = isExponential;
+            isExponential = false;
+            char currentChar = s.charAt(currentIndex);
+            switch (currentChar) {
+                case ' ':
+                case ',':
+                    foundSeparator = true;
+                    break;
+                case '-':
+                    // The negative sign following a 'e' or 'E' is not a separator.
+                    if (currentIndex != start && !isPrevExponential) {
+                        foundSeparator = true;
+                        result.mEndWithNegOrDot = true;
+                    }
+                    break;
+                case '.':
+                    if (!secondDot) {
+                        secondDot = true;
+                    } else {
+                        // This is the second dot, and it is considered as a separator.
+                        foundSeparator = true;
+                        result.mEndWithNegOrDot = true;
+                    }
+                    break;
+                case 'e':
+                case 'E':
+                    isExponential = true;
+                    break;
+            }
+            if (foundSeparator) {
+                break;
+            }
+        }
+        // When there is nothing found, then we put the end position to the end
+        // of the string.
+        result.mEndPosition = currentIndex;
+    }
+
+    /**
+     * Each PathDataNode represents one command in the "d" attribute of the svg
+     * file.
+     * An array of PathDataNode can represent the whole "d" attribute.
+     */
+    public static class PathDataNode {
+        private char mType;
+        private float[] mParams;
+
+        private PathDataNode(char type, float[] params) {
+            mType = type;
+            mParams = params;
+        }
+
+        private PathDataNode(PathDataNode n) {
+            mType = n.mType;
+            mParams = copyOfRange(n.mParams, 0, n.mParams.length);
+        }
+
+        /**
+         * Convert an array of PathDataNode to Path.
+         *
+         * @param node The source array of PathDataNode.
+         * @param path The target Path object.
+         */
+        public static void nodesToPath(PathDataNode[] node, Path path) {
+            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;
+            }
+        }
+
+        /**
+         * The current PathDataNode will be interpolated between the
+         * <code>nodeFrom</code> and <code>nodeTo</code> according to the
+         * <code>fraction</code>.
+         *
+         * @param nodeFrom The start value as a PathDataNode.
+         * @param nodeTo The end value as a PathDataNode
+         * @param fraction The fraction to interpolate.
+         */
+        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;
+            }
+        }
+
+        private static void addCommand(Path path, float[] current,
+                char previousCmd, char cmd, float[] val) {
+
+            int incr = 2;
+            float currentX = current[0];
+            float currentY = current[1];
+            float ctrlPointX = current[2];
+            float ctrlPointY = current[3];
+            float currentSegmentStartX = current[4];
+            float currentSegmentStartY = current[5];
+            float reflectiveCtrlPointX;
+            float reflectiveCtrlPointY;
+
+            switch (cmd) {
+                case 'z':
+                case 'Z':
+                    path.close();
+                    // Path is closed here, but we need to move the pen to the
+                    // closed position. So we cache the segment's starting position,
+                    // and restore it here.
+                    currentX = currentSegmentStartX;
+                    currentY = currentSegmentStartY;
+                    ctrlPointX = currentSegmentStartX;
+                    ctrlPointY = currentSegmentStartY;
+                    path.moveTo(currentX, currentY);
+                    break;
+                case 'm':
+                case 'M':
+                case 'l':
+                case 'L':
+                case 't':
+                case 'T':
+                    incr = 2;
+                    break;
+                case 'h':
+                case 'H':
+                case 'v':
+                case 'V':
+                    incr = 1;
+                    break;
+                case 'c':
+                case 'C':
+                    incr = 6;
+                    break;
+                case 's':
+                case 'S':
+                case 'q':
+                case 'Q':
+                    incr = 4;
+                    break;
+                case 'a':
+                case 'A':
+                    incr = 7;
+                    break;
+            }
+
+            for (int k = 0; k < val.length; k += incr) {
+                switch (cmd) {
+                    case 'm': // moveto - Start a new sub-path (relative)
+                        path.rMoveTo(val[k + 0], val[k + 1]);
+                        currentX += val[k + 0];
+                        currentY += val[k + 1];
+                        currentSegmentStartX = currentX;
+                        currentSegmentStartY = currentY;
+                        break;
+                    case 'M': // moveto - Start a new sub-path
+                        path.moveTo(val[k + 0], val[k + 1]);
+                        currentX = val[k + 0];
+                        currentY = val[k + 1];
+                        currentSegmentStartX = currentX;
+                        currentSegmentStartY = currentY;
+                        break;
+                    case 'l': // lineto - Draw a line from the current point (relative)
+                        path.rLineTo(val[k + 0], val[k + 1]);
+                        currentX += val[k + 0];
+                        currentY += val[k + 1];
+                        break;
+                    case 'L': // lineto - Draw a line from the current point
+                        path.lineTo(val[k + 0], val[k + 1]);
+                        currentX = val[k + 0];
+                        currentY = val[k + 1];
+                        break;
+                    case 'h': // horizontal lineto - Draws a horizontal line (relative)
+                        path.rLineTo(val[k + 0], 0);
+                        currentX += val[k + 0];
+                        break;
+                    case 'H': // horizontal lineto - Draws a horizontal line
+                        path.lineTo(val[k + 0], currentY);
+                        currentX = val[k + 0];
+                        break;
+                    case 'v': // vertical lineto - Draws a vertical line from the current point (r)
+                        path.rLineTo(0, val[k + 0]);
+                        currentY += val[k + 0];
+                        break;
+                    case 'V': // vertical lineto - Draws a vertical line from the current point
+                        path.lineTo(currentX, val[k + 0]);
+                        currentY = val[k + 0];
+                        break;
+                    case 'c': // curveto - Draws a cubic Bézier curve (relative)
+                        path.rCubicTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3],
+                                val[k + 4], val[k + 5]);
+
+                        ctrlPointX = currentX + val[k + 2];
+                        ctrlPointY = currentY + val[k + 3];
+                        currentX += val[k + 4];
+                        currentY += val[k + 5];
+
+                        break;
+                    case 'C': // curveto - Draws a cubic Bézier curve
+                        path.cubicTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3],
+                                val[k + 4], val[k + 5]);
+                        currentX = val[k + 4];
+                        currentY = val[k + 5];
+                        ctrlPointX = val[k + 2];
+                        ctrlPointY = val[k + 3];
+                        break;
+                    case 's': // smooth curveto - Draws a cubic Bézier curve (reflective cp)
+                        reflectiveCtrlPointX = 0;
+                        reflectiveCtrlPointY = 0;
+                        if (previousCmd == 'c' || previousCmd == 's'
+                                || previousCmd == 'C' || previousCmd == 'S') {
+                            reflectiveCtrlPointX = currentX - ctrlPointX;
+                            reflectiveCtrlPointY = currentY - ctrlPointY;
+                        }
+                        path.rCubicTo(reflectiveCtrlPointX, reflectiveCtrlPointY,
+                                val[k + 0], val[k + 1],
+                                val[k + 2], val[k + 3]);
+
+                        ctrlPointX = currentX + val[k + 0];
+                        ctrlPointY = currentY + val[k + 1];
+                        currentX += val[k + 2];
+                        currentY += val[k + 3];
+                        break;
+                    case 'S': // shorthand/smooth curveto Draws a cubic Bézier curve(reflective cp)
+                        reflectiveCtrlPointX = currentX;
+                        reflectiveCtrlPointY = currentY;
+                        if (previousCmd == 'c' || previousCmd == 's'
+                                || previousCmd == 'C' || previousCmd == 'S') {
+                            reflectiveCtrlPointX = 2 * currentX - ctrlPointX;
+                            reflectiveCtrlPointY = 2 * currentY - ctrlPointY;
+                        }
+                        path.cubicTo(reflectiveCtrlPointX, reflectiveCtrlPointY,
+                                val[k + 0], val[k + 1], val[k + 2], val[k + 3]);
+                        ctrlPointX = val[k + 0];
+                        ctrlPointY = val[k + 1];
+                        currentX = val[k + 2];
+                        currentY = val[k + 3];
+                        break;
+                    case 'q': // Draws a quadratic Bézier (relative)
+                        path.rQuadTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3]);
+                        ctrlPointX = currentX + val[k + 0];
+                        ctrlPointY = currentY + val[k + 1];
+                        currentX += val[k + 2];
+                        currentY += val[k + 3];
+                        break;
+                    case 'Q': // Draws a quadratic Bézier
+                        path.quadTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3]);
+                        ctrlPointX = val[k + 0];
+                        ctrlPointY = val[k + 1];
+                        currentX = val[k + 2];
+                        currentY = val[k + 3];
+                        break;
+                    case 't': // Draws a quadratic Bézier curve(reflective control point)(relative)
+                        reflectiveCtrlPointX = 0;
+                        reflectiveCtrlPointY = 0;
+                        if (previousCmd == 'q' || previousCmd == 't'
+                                || previousCmd == 'Q' || previousCmd == 'T') {
+                            reflectiveCtrlPointX = currentX - ctrlPointX;
+                            reflectiveCtrlPointY = currentY - ctrlPointY;
+                        }
+                        path.rQuadTo(reflectiveCtrlPointX, reflectiveCtrlPointY,
+                                val[k + 0], val[k + 1]);
+                        ctrlPointX = currentX + reflectiveCtrlPointX;
+                        ctrlPointY = currentY + reflectiveCtrlPointY;
+                        currentX += val[k + 0];
+                        currentY += val[k + 1];
+                        break;
+                    case 'T': // Draws a quadratic Bézier curve (reflective control point)
+                        reflectiveCtrlPointX = currentX;
+                        reflectiveCtrlPointY = currentY;
+                        if (previousCmd == 'q' || previousCmd == 't'
+                                || previousCmd == 'Q' || previousCmd == 'T') {
+                            reflectiveCtrlPointX = 2 * currentX - ctrlPointX;
+                            reflectiveCtrlPointY = 2 * currentY - ctrlPointY;
+                        }
+                        path.quadTo(reflectiveCtrlPointX, reflectiveCtrlPointY,
+                                val[k + 0], val[k + 1]);
+                        ctrlPointX = reflectiveCtrlPointX;
+                        ctrlPointY = reflectiveCtrlPointY;
+                        currentX = val[k + 0];
+                        currentY = val[k + 1];
+                        break;
+                    case 'a': // Draws an elliptical arc
+                        // (rx ry x-axis-rotation large-arc-flag sweep-flag x y)
+                        drawArc(path,
+                                currentX,
+                                currentY,
+                                val[k + 5] + currentX,
+                                val[k + 6] + currentY,
+                                val[k + 0],
+                                val[k + 1],
+                                val[k + 2],
+                                val[k + 3] != 0,
+                                val[k + 4] != 0);
+                        currentX += val[k + 5];
+                        currentY += val[k + 6];
+                        ctrlPointX = currentX;
+                        ctrlPointY = currentY;
+                        break;
+                    case 'A': // Draws an elliptical arc
+                        drawArc(path,
+                                currentX,
+                                currentY,
+                                val[k + 5],
+                                val[k + 6],
+                                val[k + 0],
+                                val[k + 1],
+                                val[k + 2],
+                                val[k + 3] != 0,
+                                val[k + 4] != 0);
+                        currentX = val[k + 5];
+                        currentY = val[k + 6];
+                        ctrlPointX = currentX;
+                        ctrlPointY = currentY;
+                        break;
+                }
+                previousCmd = cmd;
+            }
+            current[0] = currentX;
+            current[1] = currentY;
+            current[2] = ctrlPointX;
+            current[3] = ctrlPointY;
+            current[4] = currentSegmentStartX;
+            current[5] = currentSegmentStartY;
+        }
+
+        private static void drawArc(Path p,
+                float x0,
+                float y0,
+                float x1,
+                float y1,
+                float a,
+                float b,
+                float theta,
+                boolean isMoreThanHalf,
+                boolean isPositiveArc) {
+
+            /* Convert rotation angle from degrees to radians */
+            double thetaD = Math.toRadians(theta);
+            /* Pre-compute rotation matrix entries */
+            double cosTheta = Math.cos(thetaD);
+            double sinTheta = Math.sin(thetaD);
+            /* Transform (x0, y0) and (x1, y1) into unit space */
+            /* using (inverse) rotation, followed by (inverse) scale */
+            double x0p = (x0 * cosTheta + y0 * sinTheta) / a;
+            double y0p = (-x0 * sinTheta + y0 * cosTheta) / b;
+            double x1p = (x1 * cosTheta + y1 * sinTheta) / a;
+            double y1p = (-x1 * sinTheta + y1 * cosTheta) / b;
+
+            /* Compute differences and averages */
+            double dx = x0p - x1p;
+            double dy = y0p - y1p;
+            double xm = (x0p + x1p) / 2;
+            double ym = (y0p + y1p) / 2;
+            /* Solve for intersecting unit circles */
+            double dsq = dx * dx + dy * dy;
+            if (dsq == 0.0) {
+                Log.w(LOGTAG, " Points are coincident");
+                return; /* Points are coincident */
+            }
+            double disc = 1.0 / dsq - 1.0 / 4.0;
+            if (disc < 0.0) {
+                Log.w(LOGTAG, "Points are too far apart " + dsq);
+                float adjust = (float) (Math.sqrt(dsq) / 1.99999);
+                drawArc(p, x0, y0, x1, y1, a * adjust,
+                        b * adjust, theta, isMoreThanHalf, isPositiveArc);
+                return; /* Points are too far apart */
+            }
+            double s = Math.sqrt(disc);
+            double sdx = s * dx;
+            double sdy = s * dy;
+            double cx;
+            double cy;
+            if (isMoreThanHalf == isPositiveArc) {
+                cx = xm - sdy;
+                cy = ym + sdx;
+            } else {
+                cx = xm + sdy;
+                cy = ym - sdx;
+            }
+
+            double eta0 = Math.atan2((y0p - cy), (x0p - cx));
+
+            double eta1 = Math.atan2((y1p - cy), (x1p - cx));
+
+            double sweep = (eta1 - eta0);
+            if (isPositiveArc != (sweep >= 0)) {
+                if (sweep > 0) {
+                    sweep -= 2 * Math.PI;
+                } else {
+                    sweep += 2 * Math.PI;
+                }
+            }
+
+            cx *= a;
+            cy *= b;
+            double tcx = cx;
+            cx = cx * cosTheta - cy * sinTheta;
+            cy = tcx * sinTheta + cy * cosTheta;
+
+            arcToBezier(p, cx, cy, a, b, x0, y0, thetaD, eta0, sweep);
+        }
+
+        /**
+         * Converts an arc to cubic Bezier segments and records them in p.
+         *
+         * @param p The target for the cubic Bezier segments
+         * @param cx The x coordinate center of the ellipse
+         * @param cy The y coordinate center of the ellipse
+         * @param a The radius of the ellipse in the horizontal direction
+         * @param b The radius of the ellipse in the vertical direction
+         * @param e1x E(eta1) x coordinate of the starting point of the arc
+         * @param e1y E(eta2) y coordinate of the starting point of the arc
+         * @param theta The angle that the ellipse bounding rectangle makes with horizontal plane
+         * @param start The start angle of the arc on the ellipse
+         * @param sweep The angle (positive or negative) of the sweep of the arc on the ellipse
+         */
+        private static void arcToBezier(Path p,
+                double cx,
+                double cy,
+                double a,
+                double b,
+                double e1x,
+                double e1y,
+                double theta,
+                double start,
+                double sweep) {
+            // Taken from equations at: http://spaceroots.org/documents/ellipse/node8.html
+            // and http://www.spaceroots.org/documents/ellipse/node22.html
+
+            // Maximum of 45 degrees per cubic Bezier segment
+            int numSegments = Math.abs((int) Math.ceil(sweep * 4 / Math.PI));
+
+            double eta1 = start;
+            double cosTheta = Math.cos(theta);
+            double sinTheta = Math.sin(theta);
+            double cosEta1 = Math.cos(eta1);
+            double sinEta1 = Math.sin(eta1);
+            double ep1x = (-a * cosTheta * sinEta1) - (b * sinTheta * cosEta1);
+            double ep1y = (-a * sinTheta * sinEta1) + (b * cosTheta * cosEta1);
+
+            double anglePerSegment = sweep / numSegments;
+            for (int i = 0; i < numSegments; i++) {
+                double eta2 = eta1 + anglePerSegment;
+                double sinEta2 = Math.sin(eta2);
+                double cosEta2 = Math.cos(eta2);
+                double e2x = cx + (a * cosTheta * cosEta2) - (b * sinTheta * sinEta2);
+                double e2y = cy + (a * sinTheta * cosEta2) + (b * cosTheta * sinEta2);
+                double ep2x = -a * cosTheta * sinEta2 - b * sinTheta * cosEta2;
+                double ep2y = -a * sinTheta * sinEta2 + b * cosTheta * cosEta2;
+                double tanDiff2 = Math.tan((eta2 - eta1) / 2);
+                double alpha =
+                        Math.sin(eta2 - eta1) * (Math.sqrt(4 + (3 * tanDiff2 * tanDiff2)) - 1) / 3;
+                double q1x = e1x + alpha * ep1x;
+                double q1y = e1y + alpha * ep1y;
+                double q2x = e2x - alpha * ep2x;
+                double q2y = e2y - alpha * ep2y;
+
+                p.cubicTo((float) q1x,
+                        (float) q1y,
+                        (float) q2x,
+                        (float) q2y,
+                        (float) e2x,
+                        (float) e2y);
+                eta1 = eta2;
+                e1x = e2x;
+                e1y = e2y;
+                ep1x = ep2x;
+                ep1y = ep2y;
+            }
+        }
+    }
+}
diff --git a/graphics/drawable/static/src/android/support/graphics/drawable/VectorDrawableCompat.java b/graphics/drawable/static/src/android/support/graphics/drawable/VectorDrawableCompat.java
new file mode 100644
index 0000000..d33c204
--- /dev/null
+++ b/graphics/drawable/static/src/android/support/graphics/drawable/VectorDrawableCompat.java
@@ -0,0 +1,1470 @@
+/*
+ * 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.ColorStateList;
+import android.content.res.Resources;
+import android.content.res.Resources.Theme;
+import android.content.res.TypedArray;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.ColorFilter;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.PathMeasure;
+import android.graphics.PixelFormat;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuff.Mode;
+import android.graphics.PorterDuffColorFilter;
+import android.graphics.Rect;
+import android.graphics.Region;
+import android.graphics.drawable.Drawable;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.annotation.DrawableRes;
+import android.support.v4.util.ArrayMap;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.Xml;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Stack;
+
+/**
+ * This lets you create a drawable based on an XML vector graphic. It can be defined in an XML file
+ * with the <code>&lt;vector></code> element.
+ * <p/>
+ * The vector drawable has the following elements:
+ * <p/>
+ * <dt><code>&lt;vector></code></dt>
+ * <dl>
+ * <dd>Used to define a vector drawable
+ * <dl>
+ * <dt><code>android:name</code></dt>
+ * <dd>Defines the name of this vector drawable.</dd>
+ * <dt><code>android:width</code></dt>
+ * <dd>Used to define the intrinsic width of the drawable. This support all the dimension units,
+ * normally specified with dp.</dd>
+ * <dt><code>android:height</code></dt>
+ * <dd>Used to define the intrinsic height the drawable. This support all the dimension units,
+ * normally specified with dp.</dd>
+ * <dt><code>android:viewportWidth</code></dt>
+ * <dd>Used to define the width of the viewport space. Viewport is basically the virtual canvas
+ * where the paths are drawn on.</dd>
+ * <dt><code>android:viewportHeight</code></dt>
+ * <dd>Used to define the height of the viewport space. Viewport is basically the virtual canvas
+ * where the paths are drawn on.</dd>
+ * <dt><code>android:tint</code></dt>
+ * <dd>The color to apply to the drawable as a tint. By default, no tint is applied.</dd>
+ * <dt><code>android:tintMode</code></dt>
+ * <dd>The Porter-Duff blending mode for the tint color. The default value is src_in.</dd>
+ * <dt><code>android:autoMirrored</code></dt>
+ * <dd>Indicates if the drawable needs to be mirrored when its layout direction is RTL
+ * (right-to-left).</dd>
+ * <dt><code>android:alpha</code></dt>
+ * <dd>The opacity of this drawable.</dd>
+ * </dl>
+ * </dd>
+ * </dl>
+ * <dl>
+ * <dt><code>&lt;group></code></dt>
+ * <dd>Defines a group of paths or subgroups, plus transformation information. The transformations
+ * are defined in the same coordinates as the viewport. And the transformations are applied in the
+ * order of scale, rotate then translate.
+ * <dl>
+ * <dt><code>android:name</code></dt>
+ * <dd>Defines the name of the group.</dd>
+ * <dt><code>android:rotation</code></dt>
+ * <dd>The degrees of rotation of the group.</dd>
+ * <dt><code>android:pivotX</code></dt>
+ * <dd>The X coordinate of the pivot for the scale and rotation of the group. This is defined in the
+ * viewport space.</dd>
+ * <dt><code>android:pivotY</code></dt>
+ * <dd>The Y coordinate of the pivot for the scale and rotation of the group. This is defined in the
+ * viewport space.</dd>
+ * <dt><code>android:scaleX</code></dt>
+ * <dd>The amount of scale on the X Coordinate.</dd>
+ * <dt><code>android:scaleY</code></dt>
+ * <dd>The amount of scale on the Y coordinate.</dd>
+ * <dt><code>android:translateX</code></dt>
+ * <dd>The amount of translation on the X coordinate. This is defined in the viewport space.</dd>
+ * <dt><code>android:translateY</code></dt>
+ * <dd>The amount of translation on the Y coordinate. This is defined in the viewport space.</dd>
+ * </dl>
+ * </dd>
+ * </dl>
+ * <dl>
+ * <dt><code>&lt;path></code></dt>
+ * <dd>Defines paths to be drawn.
+ * <dl>
+ * <dt><code>android:name</code></dt>
+ * <dd>Defines the name of the path.</dd>
+ * <dt><code>android:pathData</code></dt>
+ * <dd>Defines path data using exactly same format as "d" attribute in the SVG's path
+ * data. This is defined in the viewport space.</dd>
+ * <dt><code>android:fillColor</code></dt>
+ * <dd>Defines the color to fill the path (none if not present).</dd>
+ * <dt><code>android:strokeColor</code></dt>
+ * <dd>Defines the color to draw the path outline (none if not present).</dd>
+ * <dt><code>android:strokeWidth</code></dt>
+ * <dd>The width a path stroke.</dd>
+ * <dt><code>android:strokeAlpha</code></dt>
+ * <dd>The opacity of a path stroke.</dd>
+ * <dt><code>android:fillAlpha</code></dt>
+ * <dd>The opacity to fill the path with.</dd>
+ * <dt><code>android:trimPathStart</code></dt>
+ * <dd>The fraction of the path to trim from the start, in the range from 0 to 1.</dd>
+ * <dt><code>android:trimPathEnd</code></dt>
+ * <dd>The fraction of the path to trim from the end, in the range from 0 to 1.</dd>
+ * <dt><code>android:trimPathOffset</code></dt>
+ * <dd>Shift trim region (allows showed region to include the start and end), in the range from 0 to
+ * 1.</dd>
+ * <dt><code>android:strokeLineCap</code></dt>
+ * <dd>Sets the linecap for a stroked path: butt, round, square.</dd>
+ * <dt><code>android:strokeLineJoin</code></dt>
+ * <dd>Sets the lineJoin for a stroked path: miter,round,bevel.</dd>
+ * <dt><code>android:strokeMiterLimit</code></dt>
+ * <dd>Sets the Miter limit for a stroked path.</dd>
+ * </dl>
+ * </dd>
+ * </dl>
+ * <dl>
+ * <dt><code>&lt;clip-path></code></dt>
+ * <dd>Defines path to be the current clip.
+ * <dl>
+ * <dt><code>android:name</code></dt>
+ * <dd>Defines the name of the clip path.</dd>
+ * <dt><code>android:pathData</code></dt>
+ * <dd>Defines clip path data using the same format as "d" attribute in the SVG's
+ * path data.</dd>
+ * </dl>
+ * </dd>
+ * </dl>
+ * <li>Here is a simple VectorDrawable in this vectordrawable.xml file.
+ * <pre>
+ * &lt;vector xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
+ *     android:height=&quot;64dp&quot;
+ *     android:width=&quot;64dp&quot;
+ *     android:viewportHeight=&quot;600&quot;
+ *     android:viewportWidth=&quot;600&quot; &gt;
+ *     &lt;group
+ *         android:name=&quot;rotationGroup&quot;
+ *         android:pivotX=&quot;300.0&quot;
+ *         android:pivotY=&quot;300.0&quot;
+ *         android:rotation=&quot;45.0&quot; &gt;
+ *         &lt;path
+ *             android:name=&quot;v&quot;
+ *             android:fillColor=&quot;#000000&quot;
+ *             android:pathData=&quot;M300,70 l 0,-70 70,70 0,0 -70,70z&quot; /&gt;
+ *     &lt;/group&gt;
+ * &lt;/vector&gt;
+ * </pre></li>
+ */
+public class VectorDrawableCompat extends Drawable {
+    static final String LOGTAG = "VectorDrawableCompat";
+
+    static final PorterDuff.Mode DEFAULT_TINT_MODE = PorterDuff.Mode.SRC_IN;
+
+    private static final String SHAPE_CLIP_PATH = "clip-path";
+    private static final String SHAPE_GROUP = "group";
+    private static final String SHAPE_PATH = "path";
+    private static final String SHAPE_VECTOR = "vector";
+
+    private static final int LINECAP_BUTT = 0;
+    private static final int LINECAP_ROUND = 1;
+    private static final int LINECAP_SQUARE = 2;
+
+    private static final int LINEJOIN_MITER = 0;
+    private static final int LINEJOIN_ROUND = 1;
+    private static final int LINEJOIN_BEVEL = 2;
+
+    private static final boolean DBG_VECTOR_DRAWABLE = true;
+
+    private VectorDrawableState mVectorState;
+
+    private PorterDuffColorFilter mTintFilter;
+    private ColorFilter mColorFilter;
+
+    private boolean mMutated;
+
+    // AnimatedVectorDrawable needs to turn off the cache all the time, otherwise,
+    // caching the bitmap by default is allowed.
+    private boolean mAllowCaching = true;
+
+    private VectorDrawableCompat() {
+        mVectorState = new VectorDrawableState();
+    }
+
+    private VectorDrawableCompat(VectorDrawableState state) {
+        mVectorState = state;
+        mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode);
+    }
+
+    @Override
+    public Drawable mutate() {
+        if (!mMutated && super.mutate() == this) {
+            mVectorState = new VectorDrawableState(mVectorState);
+            mMutated = true;
+        }
+        return this;
+    }
+
+    Object getTargetByName(String name) {
+        return mVectorState.mVPathRenderer.mVGTargetsMap.get(name);
+    }
+
+    @Override
+    public ConstantState getConstantState() {
+        mVectorState.mChangingConfigurations = getChangingConfigurations();
+        return mVectorState;
+    }
+
+    @Override
+    public void draw(Canvas canvas) {
+        final Rect bounds = getBounds();
+        if (bounds.width() == 0 || bounds.height() == 0) {
+            // too small to draw
+            return;
+        }
+
+        final int saveCount = canvas.save();
+        final boolean needMirroring = needMirroring();
+
+        canvas.translate(bounds.left, bounds.top);
+        if (needMirroring) {
+            canvas.translate(bounds.width(), 0);
+            canvas.scale(-1.0f, 1.0f);
+        }
+
+        // Color filters always override tint filters.
+        final ColorFilter colorFilter = mColorFilter == null ? mTintFilter : mColorFilter;
+
+        if (!mAllowCaching) {
+            // AnimatedVectorDrawable
+            if (!mVectorState.hasTranslucentRoot()) {
+                mVectorState.mVPathRenderer.draw(
+                        canvas, bounds.width(), bounds.height(), colorFilter);
+            } else {
+                mVectorState.createCachedBitmapIfNeeded(bounds);
+                mVectorState.updateCachedBitmap(bounds);
+                mVectorState.drawCachedBitmapWithRootAlpha(canvas, colorFilter);
+            }
+        } else {
+            // Static Vector Drawable case.
+            mVectorState.createCachedBitmapIfNeeded(bounds);
+            if (!mVectorState.canReuseCache()) {
+                mVectorState.updateCachedBitmap(bounds);
+                mVectorState.updateCacheStates();
+            }
+            mVectorState.drawCachedBitmapWithRootAlpha(canvas, colorFilter);
+        }
+
+        canvas.restoreToCount(saveCount);
+    }
+
+    public int getAlpha() {
+        return mVectorState.mVPathRenderer.getRootAlpha();
+    }
+
+    @Override
+    public void setAlpha(int alpha) {
+        if (mVectorState.mVPathRenderer.getRootAlpha() != alpha) {
+            mVectorState.mVPathRenderer.setRootAlpha(alpha);
+            invalidateSelf();
+        }
+    }
+
+    @Override
+    public void setColorFilter(ColorFilter colorFilter) {
+        mColorFilter = colorFilter;
+        invalidateSelf();
+    }
+
+    /**
+     * Ensures the tint filter is consistent with the current tint color and
+     * mode.
+     */
+    PorterDuffColorFilter updateTintFilter(PorterDuffColorFilter tintFilter, ColorStateList tint,
+            PorterDuff.Mode tintMode) {
+        if (tint == null || tintMode == null) {
+            return null;
+        }
+        // setMode, setColor of PorterDuffColorFilter are not public method in SDK v7.
+        // Therefore we create a new one all the time here. Don't expect this is called often.
+        final int color = tint.getColorForState(getState(), Color.TRANSPARENT);
+        return new PorterDuffColorFilter(color, tintMode);
+    }
+
+    public void setTint(int tint) {
+        setTintList(ColorStateList.valueOf(tint));
+    }
+
+    public void setTintList(ColorStateList tint) {
+        final VectorDrawableState state = mVectorState;
+        if (state.mTint != tint) {
+            state.mTint = tint;
+            mTintFilter = updateTintFilter(mTintFilter, tint, state.mTintMode);
+            invalidateSelf();
+        }
+    }
+
+    public void setTintMode(Mode tintMode) {
+        final VectorDrawableState state = mVectorState;
+        if (state.mTintMode != tintMode) {
+            state.mTintMode = tintMode;
+            mTintFilter = updateTintFilter(mTintFilter, state.mTint, tintMode);
+            invalidateSelf();
+        }
+    }
+
+    @Override
+    public boolean isStateful() {
+        return super.isStateful() || (mVectorState != null && mVectorState.mTint != null
+                && mVectorState.mTint.isStateful());
+    }
+
+    @Override
+    protected boolean onStateChange(int[] stateSet) {
+        final VectorDrawableState state = mVectorState;
+        if (state.mTint != null && state.mTintMode != null) {
+            // mTintFilter = updateTintFilter(this, mTintFilter, state.mTint, state.mTintMode);
+            invalidateSelf();
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public int getOpacity() {
+        return PixelFormat.TRANSLUCENT;
+    }
+
+    @Override
+    public int getIntrinsicWidth() {
+        return (int) mVectorState.mVPathRenderer.mBaseWidth;
+    }
+
+    @Override
+    public int getIntrinsicHeight() {
+        return (int) mVectorState.mVPathRenderer.mBaseHeight;
+    }
+
+    // Don't support re-applying themes. The initial theme loading is working.
+    public boolean canApplyTheme() {
+        return false;
+    }
+
+    /**
+     * The size of a pixel when scaled from the intrinsic dimension to the viewport dimension. This
+     * is used to calculate the path animation accuracy.
+     *
+     * @hide
+     */
+    public float getPixelSize() {
+        if (mVectorState == null && mVectorState.mVPathRenderer == null ||
+                mVectorState.mVPathRenderer.mBaseWidth == 0 ||
+                mVectorState.mVPathRenderer.mBaseHeight == 0 ||
+                mVectorState.mVPathRenderer.mViewportHeight == 0 ||
+                mVectorState.mVPathRenderer.mViewportWidth == 0) {
+            return 1; // fall back to 1:1 pixel mapping.
+        }
+        float intrinsicWidth = mVectorState.mVPathRenderer.mBaseWidth;
+        float intrinsicHeight = mVectorState.mVPathRenderer.mBaseHeight;
+        float viewportWidth = mVectorState.mVPathRenderer.mViewportWidth;
+        float viewportHeight = mVectorState.mVPathRenderer.mViewportHeight;
+        float scaleX = viewportWidth / intrinsicWidth;
+        float scaleY = viewportHeight / intrinsicHeight;
+        return Math.min(scaleX, scaleY);
+    }
+
+    /**
+     * Create a VectorDrawableCompat object.
+     *
+     * @param res the resources.
+     * @param resId the resource ID for VectorDrawableCompat object.
+     * @param theme the theme of this vector drawable, it can be null.
+     * @return a new VectorDrawableCompat or null if parsing error is found.
+     */
+    @Nullable
+    public static VectorDrawableCompat create(@NonNull Resources res, @DrawableRes int resId,
+            @Nullable Theme theme) {
+        try {
+            final XmlPullParser parser = res.getXml(resId);
+            final AttributeSet attrs = Xml.asAttributeSet(parser);
+            int type;
+            while ((type = parser.next()) != XmlPullParser.START_TAG &&
+                    type != XmlPullParser.END_DOCUMENT) {
+                // Empty loop
+            }
+            if (type != XmlPullParser.START_TAG) {
+                throw new XmlPullParserException("No start tag found");
+            }
+
+            final VectorDrawableCompat drawable = new VectorDrawableCompat();
+            drawable.inflate(res, parser, attrs, theme);
+
+            return drawable;
+        } catch (XmlPullParserException e) {
+            Log.e(LOGTAG, "parser error", e);
+        } catch (IOException e) {
+            Log.e(LOGTAG, "parser error", e);
+        }
+        return null;
+    }
+
+    private static int applyAlpha(int color, float alpha) {
+        int alphaBytes = Color.alpha(color);
+        color &= 0x00FFFFFF;
+        color |= ((int) (alphaBytes * alpha)) << 24;
+        return color;
+    }
+
+    /**
+     * Obtains styled attributes from the theme, if available, or unstyled
+     * resources if the theme is null.
+     */
+    static TypedArray obtainAttributes(
+            Resources res, Theme theme, AttributeSet set, int[] attrs) {
+        if (theme == null) {
+            return res.obtainAttributes(set, attrs);
+        }
+        return theme.obtainStyledAttributes(set, attrs, 0, 0);
+    }
+
+
+    @Override
+    public void inflate(Resources res, XmlPullParser parser, AttributeSet attrs)
+            throws XmlPullParserException, IOException {
+        inflate(res, parser, attrs, null);
+    }
+
+    public void inflate(Resources res, XmlPullParser parser, AttributeSet attrs, Theme theme)
+            throws XmlPullParserException, IOException {
+        final VectorDrawableState state = mVectorState;
+        final VPathRenderer pathRenderer = new VPathRenderer();
+        state.mVPathRenderer = pathRenderer;
+
+        final TypedArray a = obtainAttributes(res, theme, attrs, R.styleable.VectorDrawable);
+        updateStateFromTypedArray(a);
+        a.recycle();
+        state.mChangingConfigurations = getChangingConfigurations();
+        state.mCacheDirty = true;
+        inflateInternal(res, parser, attrs, theme);
+
+        mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode);
+    }
+
+    private void updateStateFromTypedArray(TypedArray a) 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 ColorStateList tint = a.getColorStateList(R.styleable.VectorDrawable_tint);
+        if (tint != null) {
+            state.mTint = tint;
+        }
+
+        state.mAutoMirrored = a.getBoolean(
+                R.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);
+
+        if (pathRenderer.mViewportWidth <= 0) {
+            throw new XmlPullParserException(a.getPositionDescription() +
+                    "<vector> tag requires viewportWidth > 0");
+        } else if (pathRenderer.mViewportHeight <= 0) {
+            throw new XmlPullParserException(a.getPositionDescription() +
+                    "<vector> tag requires viewportHeight > 0");
+        }
+
+        pathRenderer.mBaseWidth = a.getDimension(
+                R.styleable.VectorDrawable_width, pathRenderer.mBaseWidth);
+        pathRenderer.mBaseHeight = a.getDimension(
+                R.styleable.VectorDrawable_height, pathRenderer.mBaseHeight);
+
+        if (pathRenderer.mBaseWidth <= 0) {
+            throw new XmlPullParserException(a.getPositionDescription() +
+                    "<vector> tag requires width > 0");
+        } else if (pathRenderer.mBaseHeight <= 0) {
+            throw new XmlPullParserException(a.getPositionDescription() +
+                    "<vector> tag requires height > 0");
+        }
+
+        final float alphaInFloat = a.getFloat(R.styleable.VectorDrawable_alpha,
+                pathRenderer.getAlpha());
+        pathRenderer.setAlpha(alphaInFloat);
+
+        final String name = a.getString(R.styleable.VectorDrawable_name);
+        if (name != null) {
+            pathRenderer.mRootName = name;
+            pathRenderer.mVGTargetsMap.put(name, pathRenderer);
+        }
+    }
+
+    private void inflateInternal(Resources res, XmlPullParser parser, AttributeSet attrs,
+            Theme theme) throws XmlPullParserException, IOException {
+        final VectorDrawableState state = mVectorState;
+        final VPathRenderer pathRenderer = state.mVPathRenderer;
+        boolean noPathTag = true;
+
+        // Use a stack to help to build the group tree.
+        // The top of the stack is always the current group.
+        final Stack<VGroup> groupStack = new Stack<VGroup>();
+        groupStack.push(pathRenderer.mRootGroup);
+
+        int eventType = parser.getEventType();
+        while (eventType != XmlPullParser.END_DOCUMENT) {
+            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);
+                    currentGroup.mChildren.add(path);
+                    if (path.getPathName() != null) {
+                        pathRenderer.mVGTargetsMap.put(path.getPathName(), path);
+                    }
+                    noPathTag = false;
+                    state.mChangingConfigurations |= path.mChangingConfigurations;
+                } else if (SHAPE_CLIP_PATH.equals(tagName)) {
+                    final VClipPath path = new VClipPath();
+                    path.inflate(res, attrs, theme);
+                    currentGroup.mChildren.add(path);
+                    if (path.getPathName() != null) {
+                        pathRenderer.mVGTargetsMap.put(path.getPathName(), path);
+                    }
+                    state.mChangingConfigurations |= path.mChangingConfigurations;
+                } else if (SHAPE_GROUP.equals(tagName)) {
+                    VGroup newChildGroup = new VGroup();
+                    newChildGroup.inflate(res, attrs, theme);
+                    currentGroup.mChildren.add(newChildGroup);
+                    groupStack.push(newChildGroup);
+                    if (newChildGroup.getGroupName() != null) {
+                        pathRenderer.mVGTargetsMap.put(newChildGroup.getGroupName(),
+                                newChildGroup);
+                    }
+                    state.mChangingConfigurations |= newChildGroup.mChangingConfigurations;
+                }
+            } else if (eventType == XmlPullParser.END_TAG) {
+                final String tagName = parser.getName();
+                if (SHAPE_GROUP.equals(tagName)) {
+                    groupStack.pop();
+                }
+            }
+            eventType = parser.next();
+        }
+
+        // Print the tree out for debug.
+        if (DBG_VECTOR_DRAWABLE) {
+            printGroupTree(pathRenderer.mRootGroup, 0);
+        }
+
+        if (noPathTag) {
+            final StringBuffer tag = new StringBuffer();
+
+            if (tag.length() > 0) {
+                tag.append(" or ");
+            }
+            tag.append(SHAPE_PATH);
+
+            throw new XmlPullParserException("no " + tag + " defined");
+        }
+    }
+
+    private void printGroupTree(VGroup currentGroup, int level) {
+        String indent = "";
+        for (int i = 0; i < level; i++) {
+            indent += "    ";
+        }
+        // Print the current node
+        Log.v(LOGTAG, indent + "current group is :" + currentGroup.getGroupName()
+                + " rotation is " + currentGroup.mRotate);
+        Log.v(LOGTAG, indent + "matrix is :" + currentGroup.getLocalMatrix().toString());
+        // Then print all the children groups
+        for (int i = 0; i < currentGroup.mChildren.size(); i++) {
+            Object child = currentGroup.mChildren.get(i);
+            if (child instanceof VGroup) {
+                printGroupTree((VGroup) child, level + 1);
+            }
+        }
+    }
+
+    void setAllowCaching(boolean allowCaching) {
+        mAllowCaching = allowCaching;
+    }
+
+    // We don't support RTL auto mirroring since the getLayoutDirection() is for API 17+.
+    private boolean needMirroring() {
+        return false;
+    }
+
+    private static class VectorDrawableState extends ConstantState {
+        int mChangingConfigurations;
+        VPathRenderer mVPathRenderer;
+        ColorStateList mTint = null;
+        Mode mTintMode = DEFAULT_TINT_MODE;
+        boolean mAutoMirrored;
+
+        Bitmap mCachedBitmap;
+        int[] mCachedThemeAttrs;
+        ColorStateList mCachedTint;
+        Mode mCachedTintMode;
+        int mCachedRootAlpha;
+        boolean mCachedAutoMirrored;
+        boolean mCacheDirty;
+
+        /** Temporary paint object used to draw cached bitmaps. */
+        Paint mTempPaint;
+
+        // Deep copy for mutate() or implicitly mutate.
+        public VectorDrawableState(VectorDrawableState copy) {
+            if (copy != null) {
+                mChangingConfigurations = copy.mChangingConfigurations;
+                mVPathRenderer = new VPathRenderer(copy.mVPathRenderer);
+                if (copy.mVPathRenderer.mFillPaint != null) {
+                    mVPathRenderer.mFillPaint = new Paint(copy.mVPathRenderer.mFillPaint);
+                }
+                if (copy.mVPathRenderer.mStrokePaint != null) {
+                    mVPathRenderer.mStrokePaint = new Paint(copy.mVPathRenderer.mStrokePaint);
+                }
+                mTint = copy.mTint;
+                mTintMode = copy.mTintMode;
+                mAutoMirrored = copy.mAutoMirrored;
+            }
+        }
+
+        public void drawCachedBitmapWithRootAlpha(Canvas canvas, ColorFilter filter) {
+            // The bitmap's size is the same as the bounds.
+            final Paint p = getPaint(filter);
+            canvas.drawBitmap(mCachedBitmap, 0, 0, p);
+        }
+
+        public boolean hasTranslucentRoot() {
+            return mVPathRenderer.getRootAlpha() < 255;
+        }
+
+        /**
+         * @return null when there is no need for alpha paint.
+         */
+        public Paint getPaint(ColorFilter filter) {
+            if (!hasTranslucentRoot() && filter == null) {
+                return null;
+            }
+
+            if (mTempPaint == null) {
+                mTempPaint = new Paint();
+                mTempPaint.setFilterBitmap(true);
+            }
+            mTempPaint.setAlpha(mVPathRenderer.getRootAlpha());
+            mTempPaint.setColorFilter(filter);
+            return mTempPaint;
+        }
+
+        public void updateCachedBitmap(Rect bounds) {
+            mCachedBitmap.eraseColor(Color.TRANSPARENT);
+            Canvas tmpCanvas = new Canvas(mCachedBitmap);
+            mVPathRenderer.draw(tmpCanvas, bounds.width(), bounds.height(), null);
+        }
+
+        public void createCachedBitmapIfNeeded(Rect bounds) {
+            if (mCachedBitmap == null || !canReuseBitmap(bounds.width(),
+                    bounds.height())) {
+                mCachedBitmap = Bitmap.createBitmap(bounds.width(), bounds.height(),
+                        Bitmap.Config.ARGB_8888);
+                mCacheDirty = true;
+            }
+
+        }
+
+        public boolean canReuseBitmap(int width, int height) {
+            if (width == mCachedBitmap.getWidth()
+                    && height == mCachedBitmap.getHeight()) {
+                return true;
+            }
+            return false;
+        }
+
+        public boolean canReuseCache() {
+            if (!mCacheDirty
+                    && mCachedTint == mTint
+                    && mCachedTintMode == mTintMode
+                    && mCachedAutoMirrored == mAutoMirrored
+                    && mCachedRootAlpha == mVPathRenderer.getRootAlpha()) {
+                return true;
+            }
+            return false;
+        }
+
+        public void updateCacheStates() {
+            // Use shallow copy here and shallow comparison in canReuseCache(),
+            // likely hit cache miss more, but practically not much difference.
+            mCachedTint = mTint;
+            mCachedTintMode = mTintMode;
+            mCachedRootAlpha = mVPathRenderer.getRootAlpha();
+            mCachedAutoMirrored = mAutoMirrored;
+            mCacheDirty = false;
+        }
+
+        public VectorDrawableState() {
+            mVPathRenderer = new VPathRenderer();
+        }
+
+        @Override
+        public Drawable newDrawable() {
+            return new VectorDrawableCompat(this);
+        }
+
+        @Override
+        public Drawable newDrawable(Resources res) {
+            return new VectorDrawableCompat(this);
+        }
+
+        @Override
+        public int getChangingConfigurations() {
+            return mChangingConfigurations;
+        }
+    }
+
+    private static class VPathRenderer {
+        /* Right now the internal data structure is organized as a tree.
+         * Each node can be a group node, or a path.
+         * A group node can have groups or paths as children, but a path node has
+         * no children.
+         * One example can be:
+         *                 Root Group
+         *                /    |     \
+         *           Group    Path    Group
+         *          /     \             |
+         *         Path   Path         Path
+         *
+         */
+        // Variables that only used temporarily inside the draw() call, so there
+        // is no need for deep copying.
+        private final Path mPath;
+        private final Path mRenderPath;
+        private static final Matrix IDENTITY_MATRIX = new Matrix();
+        private final Matrix mFinalPathMatrix = new Matrix();
+
+        private Paint mStrokePaint;
+        private Paint mFillPaint;
+        private PathMeasure mPathMeasure;
+
+        /////////////////////////////////////////////////////
+        // Variables below need to be copied (deep copy if applicable) for mutation.
+        private int mChangingConfigurations;
+        private final VGroup mRootGroup;
+        float mBaseWidth = 0;
+        float mBaseHeight = 0;
+        float mViewportWidth = 0;
+        float mViewportHeight = 0;
+        int mRootAlpha = 0xFF;
+        String mRootName = null;
+
+        final ArrayMap<String, Object> mVGTargetsMap = new ArrayMap<String, Object>();
+
+        public VPathRenderer() {
+            mRootGroup = new VGroup();
+            mPath = new Path();
+            mRenderPath = new Path();
+        }
+
+        public void setRootAlpha(int alpha) {
+            mRootAlpha = alpha;
+        }
+
+        public int getRootAlpha() {
+            return mRootAlpha;
+        }
+
+        // setAlpha() and getAlpha() are used mostly for animation purpose, since
+        // Animator like to use alpha from 0 to 1.
+        public void setAlpha(float alpha) {
+            setRootAlpha((int) (alpha * 255));
+        }
+
+        @SuppressWarnings("unused")
+        public float getAlpha() {
+            return getRootAlpha() / 255.0f;
+        }
+
+        public VPathRenderer(VPathRenderer copy) {
+            mRootGroup = new VGroup(copy.mRootGroup, mVGTargetsMap);
+            mPath = new Path(copy.mPath);
+            mRenderPath = new Path(copy.mRenderPath);
+            mBaseWidth = copy.mBaseWidth;
+            mBaseHeight = copy.mBaseHeight;
+            mViewportWidth = copy.mViewportWidth;
+            mViewportHeight = copy.mViewportHeight;
+            mChangingConfigurations = copy.mChangingConfigurations;
+            mRootAlpha = copy.mRootAlpha;
+            mRootName = copy.mRootName;
+            if (copy.mRootName != null) {
+                mVGTargetsMap.put(copy.mRootName, this);
+            }
+        }
+
+        private void drawGroupTree(VGroup currentGroup, Matrix currentMatrix,
+                Canvas canvas, int w, int h, ColorFilter filter) {
+            // Calculate current group's matrix by preConcat the parent's and
+            // and the current one on the top of the stack.
+            // Basically the Mfinal = Mviewport * M0 * M1 * M2;
+            // Mi the local matrix at level i of the group tree.
+            currentGroup.mStackedMatrix.set(currentMatrix);
+
+            currentGroup.mStackedMatrix.preConcat(currentGroup.mLocalMatrix);
+
+            // Draw the group tree in the same order as the XML file.
+            for (int i = 0; i < currentGroup.mChildren.size(); i++) {
+                Object child = currentGroup.mChildren.get(i);
+                if (child instanceof VGroup) {
+                    VGroup childGroup = (VGroup) child;
+                    drawGroupTree(childGroup, currentGroup.mStackedMatrix,
+                            canvas, w, h, filter);
+                } else if (child instanceof VPath) {
+                    VPath childPath = (VPath) child;
+                    drawPath(currentGroup, childPath, canvas, w, h, filter);
+                }
+            }
+        }
+
+        public void draw(Canvas canvas, int w, int h, ColorFilter filter) {
+            // Travese the tree in pre-order to draw.
+            drawGroupTree(mRootGroup, IDENTITY_MATRIX, canvas, w, h, filter);
+        }
+
+        private void drawPath(VGroup vGroup, VPath vPath, Canvas canvas, int w, int h,
+                ColorFilter filter) {
+            final float scaleX = w / mViewportWidth;
+            final float scaleY = h / mViewportHeight;
+            final float minScale = Math.min(scaleX, scaleY);
+
+            mFinalPathMatrix.set(vGroup.mStackedMatrix);
+            mFinalPathMatrix.postScale(scaleX, scaleY);
+
+            vPath.toPath(mPath);
+            final Path path = mPath;
+
+            mRenderPath.reset();
+
+            if (vPath.isClipPath()) {
+                mRenderPath.addPath(path, mFinalPathMatrix);
+                canvas.clipPath(mRenderPath, Region.Op.REPLACE);
+            } else {
+                VFullPath fullPath = (VFullPath) vPath;
+                if (fullPath.mTrimPathStart != 0.0f || fullPath.mTrimPathEnd != 1.0f) {
+                    float start = (fullPath.mTrimPathStart + fullPath.mTrimPathOffset) % 1.0f;
+                    float end = (fullPath.mTrimPathEnd + fullPath.mTrimPathOffset) % 1.0f;
+
+                    if (mPathMeasure == null) {
+                        mPathMeasure = new PathMeasure();
+                    }
+                    mPathMeasure.setPath(mPath, false);
+
+                    float len = mPathMeasure.getLength();
+                    start = start * len;
+                    end = end * len;
+                    path.reset();
+                    if (start > end) {
+                        mPathMeasure.getSegment(start, len, path, true);
+                        mPathMeasure.getSegment(0f, end, path, true);
+                    } else {
+                        mPathMeasure.getSegment(start, end, path, true);
+                    }
+                    path.rLineTo(0, 0); // fix bug in measure
+                }
+                mRenderPath.addPath(path, mFinalPathMatrix);
+
+                if (fullPath.mFillColor != Color.TRANSPARENT) {
+                    if (mFillPaint == null) {
+                        mFillPaint = new Paint();
+                        mFillPaint.setStyle(Paint.Style.FILL);
+                        mFillPaint.setAntiAlias(true);
+                    }
+
+                    final Paint fillPaint = mFillPaint;
+                    fillPaint.setColor(applyAlpha(fullPath.mFillColor, fullPath.mFillAlpha));
+                    fillPaint.setColorFilter(filter);
+                    canvas.drawPath(mRenderPath, fillPaint);
+                }
+
+                if (fullPath.mStrokeColor != Color.TRANSPARENT) {
+                    if (mStrokePaint == null) {
+                        mStrokePaint = new Paint();
+                        mStrokePaint.setStyle(Paint.Style.STROKE);
+                        mStrokePaint.setAntiAlias(true);
+                    }
+
+                    final Paint strokePaint = mStrokePaint;
+                    if (fullPath.mStrokeLineJoin != null) {
+                        strokePaint.setStrokeJoin(fullPath.mStrokeLineJoin);
+                    }
+
+                    if (fullPath.mStrokeLineCap != null) {
+                        strokePaint.setStrokeCap(fullPath.mStrokeLineCap);
+                    }
+
+                    strokePaint.setStrokeMiter(fullPath.mStrokeMiterlimit);
+                    strokePaint.setColor(applyAlpha(fullPath.mStrokeColor, fullPath.mStrokeAlpha));
+                    strokePaint.setColorFilter(filter);
+                    strokePaint.setStrokeWidth(fullPath.mStrokeWidth * minScale);
+                    canvas.drawPath(mRenderPath, strokePaint);
+                }
+            }
+        }
+    }
+
+    private static class VGroup {
+        // mStackedMatrix is only used temporarily when drawing, it combines all
+        // the parents' local matrices with the current one.
+        private final Matrix mStackedMatrix = new Matrix();
+
+        /////////////////////////////////////////////////////
+        // Variables below need to be copied (deep copy if applicable) for mutation.
+        final ArrayList<Object> mChildren = new ArrayList<Object>();
+
+        private float mRotate = 0;
+        private float mPivotX = 0;
+        private float mPivotY = 0;
+        private float mScaleX = 1;
+        private float mScaleY = 1;
+        private float mTranslateX = 0;
+        private float mTranslateY = 0;
+
+        // mLocalMatrix is updated based on the update of transformation information,
+        // either parsed from the XML or by animation.
+        private final Matrix mLocalMatrix = new Matrix();
+        private int mChangingConfigurations;
+        private int[] mThemeAttrs;
+        private String mGroupName = null;
+
+        public VGroup(VGroup copy, ArrayMap<String, Object> targetsMap) {
+            mRotate = copy.mRotate;
+            mPivotX = copy.mPivotX;
+            mPivotY = copy.mPivotY;
+            mScaleX = copy.mScaleX;
+            mScaleY = copy.mScaleY;
+            mTranslateX = copy.mTranslateX;
+            mTranslateY = copy.mTranslateY;
+            mThemeAttrs = copy.mThemeAttrs;
+            mGroupName = copy.mGroupName;
+            mChangingConfigurations = copy.mChangingConfigurations;
+            if (mGroupName != null) {
+                targetsMap.put(mGroupName, this);
+            }
+
+            mLocalMatrix.set(copy.mLocalMatrix);
+
+            final ArrayList<Object> children = copy.mChildren;
+            for (int i = 0; i < children.size(); i++) {
+                Object copyChild = children.get(i);
+                if (copyChild instanceof VGroup) {
+                    VGroup copyGroup = (VGroup) copyChild;
+                    mChildren.add(new VGroup(copyGroup, targetsMap));
+                } else {
+                    VPath newPath = null;
+                    if (copyChild instanceof VFullPath) {
+                        newPath = new VFullPath((VFullPath) copyChild);
+                    } else if (copyChild instanceof VClipPath) {
+                        newPath = new VClipPath((VClipPath) copyChild);
+                    } else {
+                        throw new IllegalStateException("Unknown object in the tree!");
+                    }
+                    mChildren.add(newPath);
+                    if (newPath.mPathName != null) {
+                        targetsMap.put(newPath.mPathName, newPath);
+                    }
+                }
+            }
+        }
+
+        public VGroup() {
+        }
+
+        public String getGroupName() {
+            return mGroupName;
+        }
+
+        public Matrix getLocalMatrix() {
+            return mLocalMatrix;
+        }
+
+        public void inflate(Resources res, AttributeSet attrs, Theme theme) {
+            final TypedArray a = obtainAttributes(res, theme, attrs,
+                    R.styleable.VectorDrawableGroup);
+            updateStateFromTypedArray(a);
+            a.recycle();
+        }
+
+        private void updateStateFromTypedArray(TypedArray a) {
+            // 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);
+
+            final String groupName = a.getString(R.styleable.VectorDrawableGroup_name);
+            if (groupName != null) {
+                mGroupName = groupName;
+            }
+
+            updateLocalMatrix();
+        }
+
+        private void updateLocalMatrix() {
+            // The order we apply is the same as the
+            // RenderNode.cpp::applyViewPropertyTransforms().
+            mLocalMatrix.reset();
+            mLocalMatrix.postTranslate(-mPivotX, -mPivotY);
+            mLocalMatrix.postScale(mScaleX, mScaleY);
+            mLocalMatrix.postRotate(mRotate, 0, 0);
+            mLocalMatrix.postTranslate(mTranslateX + mPivotX, mTranslateY + mPivotY);
+        }
+
+        /* Setters and Getters, used by animator from AnimatedVectorDrawable. */
+        @SuppressWarnings("unused")
+        public float getRotation() {
+            return mRotate;
+        }
+
+        @SuppressWarnings("unused")
+        public void setRotation(float rotation) {
+            if (rotation != mRotate) {
+                mRotate = rotation;
+                updateLocalMatrix();
+            }
+        }
+
+        @SuppressWarnings("unused")
+        public float getPivotX() {
+            return mPivotX;
+        }
+
+        @SuppressWarnings("unused")
+        public void setPivotX(float pivotX) {
+            if (pivotX != mPivotX) {
+                mPivotX = pivotX;
+                updateLocalMatrix();
+            }
+        }
+
+        @SuppressWarnings("unused")
+        public float getPivotY() {
+            return mPivotY;
+        }
+
+        @SuppressWarnings("unused")
+        public void setPivotY(float pivotY) {
+            if (pivotY != mPivotY) {
+                mPivotY = pivotY;
+                updateLocalMatrix();
+            }
+        }
+
+        @SuppressWarnings("unused")
+        public float getScaleX() {
+            return mScaleX;
+        }
+
+        @SuppressWarnings("unused")
+        public void setScaleX(float scaleX) {
+            if (scaleX != mScaleX) {
+                mScaleX = scaleX;
+                updateLocalMatrix();
+            }
+        }
+
+        @SuppressWarnings("unused")
+        public float getScaleY() {
+            return mScaleY;
+        }
+
+        @SuppressWarnings("unused")
+        public void setScaleY(float scaleY) {
+            if (scaleY != mScaleY) {
+                mScaleY = scaleY;
+                updateLocalMatrix();
+            }
+        }
+
+        @SuppressWarnings("unused")
+        public float getTranslateX() {
+            return mTranslateX;
+        }
+
+        @SuppressWarnings("unused")
+        public void setTranslateX(float translateX) {
+            if (translateX != mTranslateX) {
+                mTranslateX = translateX;
+                updateLocalMatrix();
+            }
+        }
+
+        @SuppressWarnings("unused")
+        public float getTranslateY() {
+            return mTranslateY;
+        }
+
+        @SuppressWarnings("unused")
+        public void setTranslateY(float translateY) {
+            if (translateY != mTranslateY) {
+                mTranslateY = translateY;
+                updateLocalMatrix();
+            }
+        }
+    }
+
+    /**
+     * Common Path information for clip path and normal path.
+     */
+    private static class VPath {
+        protected PathParser.PathDataNode[] mNodes = null;
+        String mPathName;
+        int mChangingConfigurations;
+
+        public VPath() {
+            // Empty constructor.
+        }
+
+        public VPath(VPath copy) {
+            mPathName = copy.mPathName;
+            mChangingConfigurations = copy.mChangingConfigurations;
+            mNodes = PathParser.deepCopyNodes(copy.mNodes);
+        }
+
+        public void toPath(Path path) {
+            path.reset();
+            if (mNodes != null) {
+                PathParser.PathDataNode.nodesToPath(mNodes, path);
+            }
+        }
+
+        public String getPathName() {
+            return mPathName;
+        }
+
+        public boolean canApplyTheme() {
+            return false;
+        }
+
+        public void applyTheme(Theme t) {
+        }
+
+        public boolean isClipPath() {
+            return false;
+        }
+
+        /* Setters and Getters, used by animator from AnimatedVectorDrawable. */
+        @SuppressWarnings("unused")
+        public PathParser.PathDataNode[] getPathData() {
+            return mNodes;
+        }
+
+        @SuppressWarnings("unused")
+        public void setPathData(PathParser.PathDataNode[] nodes) {
+            if (!PathParser.canMorph(mNodes, nodes)) {
+                // This should not happen in the middle of animation.
+                mNodes = PathParser.deepCopyNodes(nodes);
+            } else {
+                PathParser.updateNodes(mNodes, nodes);
+            }
+        }
+    }
+
+    /**
+     * Clip path, which only has name and pathData.
+     */
+    private static class VClipPath extends VPath {
+        public VClipPath() {
+            // Empty constructor.
+        }
+
+        public VClipPath(VClipPath copy) {
+            super(copy);
+        }
+
+        public void inflate(Resources r, AttributeSet attrs, Theme theme) {
+            // TODO TINT THEME Not supported yet
+            final TypedArray a = obtainAttributes(r, theme, attrs,
+                    R.styleable.VectorDrawableClipPath);
+            updateStateFromTypedArray(a);
+            a.recycle();
+        }
+
+        private void updateStateFromTypedArray(TypedArray a) {
+            // Account for any configuration changes.
+            // mChangingConfigurations |= Utils.getChangingConfigurations(a);;
+
+            final String pathName = a.getString(R.styleable.VectorDrawableClipPath_name);
+            if (pathName != null) {
+                mPathName = pathName;
+            }
+
+            final String pathData = a.getString(R.styleable.VectorDrawableClipPath_pathData);
+            if (pathData != null) {
+                mNodes = PathParser.createNodesFromPathData(pathData);
+            }
+        }
+
+        @Override
+        public boolean isClipPath() {
+            return true;
+        }
+    }
+
+    /**
+     * Normal path, which contains all the fill / paint information.
+     */
+    private static class VFullPath extends VPath {
+        /////////////////////////////////////////////////////
+        // Variables below need to be copied (deep copy if applicable) for mutation.
+        private int[] mThemeAttrs;
+
+        int mStrokeColor = Color.TRANSPARENT;
+        float mStrokeWidth = 0;
+
+        int mFillColor = Color.TRANSPARENT;
+        float mStrokeAlpha = 1.0f;
+        int mFillRule;
+        float mFillAlpha = 1.0f;
+        float mTrimPathStart = 0;
+        float mTrimPathEnd = 1;
+        float mTrimPathOffset = 0;
+
+        Paint.Cap mStrokeLineCap = Paint.Cap.BUTT;
+        Paint.Join mStrokeLineJoin = Paint.Join.MITER;
+        float mStrokeMiterlimit = 4;
+
+        public VFullPath() {
+            // Empty constructor.
+        }
+
+        public VFullPath(VFullPath copy) {
+            super(copy);
+            mThemeAttrs = copy.mThemeAttrs;
+
+            mStrokeColor = copy.mStrokeColor;
+            mStrokeWidth = copy.mStrokeWidth;
+            mStrokeAlpha = copy.mStrokeAlpha;
+            mFillColor = copy.mFillColor;
+            mFillRule = copy.mFillRule;
+            mFillAlpha = copy.mFillAlpha;
+            mTrimPathStart = copy.mTrimPathStart;
+            mTrimPathEnd = copy.mTrimPathEnd;
+            mTrimPathOffset = copy.mTrimPathOffset;
+
+            mStrokeLineCap = copy.mStrokeLineCap;
+            mStrokeLineJoin = copy.mStrokeLineJoin;
+            mStrokeMiterlimit = copy.mStrokeMiterlimit;
+        }
+
+        private Paint.Cap getStrokeLineCap(int id, Paint.Cap defValue) {
+            switch (id) {
+                case LINECAP_BUTT:
+                    return Paint.Cap.BUTT;
+                case LINECAP_ROUND:
+                    return Paint.Cap.ROUND;
+                case LINECAP_SQUARE:
+                    return Paint.Cap.SQUARE;
+                default:
+                    return defValue;
+            }
+        }
+
+        private Paint.Join getStrokeLineJoin(int id, Paint.Join defValue) {
+            switch (id) {
+                case LINEJOIN_MITER:
+                    return Paint.Join.MITER;
+                case LINEJOIN_ROUND:
+                    return Paint.Join.ROUND;
+                case LINEJOIN_BEVEL:
+                    return Paint.Join.BEVEL;
+                default:
+                    return defValue;
+            }
+        }
+
+        @Override
+        public boolean canApplyTheme() {
+            return mThemeAttrs != null;
+        }
+
+        public void inflate(Resources r, AttributeSet attrs, Theme theme) {
+            final TypedArray a = obtainAttributes(r, theme, attrs,
+                    R.styleable.VectorDrawablePath);
+            updateStateFromTypedArray(a);
+            a.recycle();
+        }
+
+        private void updateStateFromTypedArray(TypedArray a) {
+            // 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);
+            if (pathName != null) {
+                mPathName = pathName;
+            }
+
+            final String pathData = a.getString(R.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);
+        }
+
+        @Override
+        public void applyTheme(Theme t) {
+            if (mThemeAttrs == null) {
+                return;
+            }
+
+            /*
+             * TODO TINT THEME Not supported yet final TypedArray a =
+             * t.resolveAttributes(mThemeAttrs, R.styleable.VectorDrawablePath);
+             * updateStateFromTypedArray(a); a.recycle();
+             */
+        }
+
+        /* Setters and Getters, used by animator from AnimatedVectorDrawable. */
+        @SuppressWarnings("unused")
+        int getStrokeColor() {
+            return mStrokeColor;
+        }
+
+        @SuppressWarnings("unused")
+        void setStrokeColor(int strokeColor) {
+            mStrokeColor = strokeColor;
+        }
+
+        @SuppressWarnings("unused")
+        float getStrokeWidth() {
+            return mStrokeWidth;
+        }
+
+        @SuppressWarnings("unused")
+        void setStrokeWidth(float strokeWidth) {
+            mStrokeWidth = strokeWidth;
+        }
+
+        @SuppressWarnings("unused")
+        float getStrokeAlpha() {
+            return mStrokeAlpha;
+        }
+
+        @SuppressWarnings("unused")
+        void setStrokeAlpha(float strokeAlpha) {
+            mStrokeAlpha = strokeAlpha;
+        }
+
+        @SuppressWarnings("unused")
+        int getFillColor() {
+            return mFillColor;
+        }
+
+        @SuppressWarnings("unused")
+        void setFillColor(int fillColor) {
+            mFillColor = fillColor;
+        }
+
+        @SuppressWarnings("unused")
+        float getFillAlpha() {
+            return mFillAlpha;
+        }
+
+        @SuppressWarnings("unused")
+        void setFillAlpha(float fillAlpha) {
+            mFillAlpha = fillAlpha;
+        }
+
+        @SuppressWarnings("unused")
+        float getTrimPathStart() {
+            return mTrimPathStart;
+        }
+
+        @SuppressWarnings("unused")
+        void setTrimPathStart(float trimPathStart) {
+            mTrimPathStart = trimPathStart;
+        }
+
+        @SuppressWarnings("unused")
+        float getTrimPathEnd() {
+            return mTrimPathEnd;
+        }
+
+        @SuppressWarnings("unused")
+        void setTrimPathEnd(float trimPathEnd) {
+            mTrimPathEnd = trimPathEnd;
+        }
+
+        @SuppressWarnings("unused")
+        float getTrimPathOffset() {
+            return mTrimPathOffset;
+        }
+
+        @SuppressWarnings("unused")
+        void setTrimPathOffset(float trimPathOffset) {
+            mTrimPathOffset = trimPathOffset;
+        }
+    }
+}
diff --git a/graphics/drawable/testanimated/Android.mk b/graphics/drawable/testanimated/Android.mk
new file mode 100644
index 0000000..c888d9e
--- /dev/null
+++ b/graphics/drawable/testanimated/Android.mk
@@ -0,0 +1,35 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SDK_VERSION := 11
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_RESOURCE_DIR = \
+        $(LOCAL_PATH)/res \
+        frameworks/support/graphics/drawable/res \
+
+LOCAL_PACKAGE_NAME := AndroidAnimatedVectorDrawableTests
+
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-v11-animatedvectordrawable android-support-v4
+
+LOCAL_AAPT_FLAGS += --auto-add-overlay --extra-packages android.support.graphics.drawable
+
+include $(BUILD_PACKAGE)
diff --git a/graphics/drawable/testanimated/AndroidManifest.xml b/graphics/drawable/testanimated/AndroidManifest.xml
new file mode 100644
index 0000000..16171f2
--- /dev/null
+++ b/graphics/drawable/testanimated/AndroidManifest.xml
@@ -0,0 +1,31 @@
+<?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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.support.test.vectordrawable" >
+
+    <uses-sdk android:minSdkVersion="11" />
+
+    <application android:icon="@drawable/app_sample_code" android:label="AnimatedVectorDrawableCompatTest" >
+        <activity android:name="android.support.test.vectordrawable.TestAVDActivity" />
+        <intent-filter>
+            <action android:name="android.intent.action.MAIN" />
+
+            <category android:name="android.intent.category.LAUNCHER" />
+        </intent-filter>
+    </application>
+
+</manifest>
\ No newline at end of file
diff --git a/graphics/drawable/testanimated/res/anim/alpha_animation_progress_bar.xml b/graphics/drawable/testanimated/res/anim/alpha_animation_progress_bar.xml
new file mode 100644
index 0000000..2463a89
--- /dev/null
+++ b/graphics/drawable/testanimated/res/anim/alpha_animation_progress_bar.xml
@@ -0,0 +1,24 @@
+<!-- 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.
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <objectAnimator
+        android:duration="3350"
+        android:propertyName="alpha"
+        android:valueFrom="1"
+        android:valueTo="0.2" />
+
+</set>
\ No newline at end of file
diff --git a/graphics/drawable/testanimated/res/anim/animation_grouping_1_01.xml b/graphics/drawable/testanimated/res/anim/animation_grouping_1_01.xml
new file mode 100644
index 0000000..36c297f
--- /dev/null
+++ b/graphics/drawable/testanimated/res/anim/animation_grouping_1_01.xml
@@ -0,0 +1,22 @@
+<?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="3300"
+    android:propertyName="rotation"
+    android:valueFrom="0"
+    android:valueTo="450" />
diff --git a/graphics/drawable/testanimated/res/anim/trim_path_animation_progress_bar.xml b/graphics/drawable/testanimated/res/anim/trim_path_animation_progress_bar.xml
new file mode 100644
index 0000000..388c759
--- /dev/null
+++ b/graphics/drawable/testanimated/res/anim/trim_path_animation_progress_bar.xml
@@ -0,0 +1,45 @@
+<?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.
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <objectAnimator
+        android:duration="1300"
+        android:interpolator="@android:anim/linear_interpolator"
+        android:propertyName="trimPathStart"
+        android:repeatCount="-1"
+        android:valueFrom="0"
+        android:valueTo="0.75"
+        android:valueType="floatType" />
+    <objectAnimator
+        android:duration="1300"
+        android:interpolator="@android:anim/linear_interpolator"
+        android:propertyName="trimPathEnd"
+        android:repeatCount="-1"
+        android:valueFrom="0.25"
+        android:valueTo="1.0"
+        android:valueType="floatType" />
+    <objectAnimator
+        android:duration="1300"
+        android:interpolator="@android:anim/linear_interpolator"
+        android:propertyName="trimPathOffset"
+        android:repeatCount="-1"
+        android:valueFrom="0"
+        android:valueTo="0.25"
+        android:valueType="floatType" />
+
+</set>
\ No newline at end of file
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
new file mode 100644
index 0000000..7c3b1de
--- /dev/null
+++ b/graphics/drawable/testanimated/res/drawable/animation_vector_drawable_grouping_1.xml
@@ -0,0 +1,27 @@
+<!--
+ 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.
+-->
+<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" >
+
+    <target
+        auto:name="sun"
+        auto:animation="@anim/animation_grouping_1_01" />
+    <target
+        auto:name="earth"
+        auto: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
new file mode 100644
index 0000000..e37d2a1
--- /dev/null
+++ b/graphics/drawable/testanimated/res/drawable/animation_vector_progress_bar.xml
@@ -0,0 +1,26 @@
+<!--
+ 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.
+-->
+<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" >
+
+    <target
+        auto:name="pie1"
+        auto:animation="@anim/trim_path_animation_progress_bar" />
+    <target
+        auto:name="root_bar"
+        auto:animation="@anim/alpha_animation_progress_bar" />
+</animated-vector>
\ No newline at end of file
diff --git a/graphics/drawable/testanimated/res/drawable/app_sample_code.png b/graphics/drawable/testanimated/res/drawable/app_sample_code.png
new file mode 100755
index 0000000..66a1984
--- /dev/null
+++ b/graphics/drawable/testanimated/res/drawable/app_sample_code.png
Binary files differ
diff --git a/graphics/drawable/testanimated/res/drawable/vector_drawable_grouping_1.xml b/graphics/drawable/testanimated/res/drawable/vector_drawable_grouping_1.xml
new file mode 100644
index 0000000..eceda71
--- /dev/null
+++ b/graphics/drawable/testanimated/res/drawable/vector_drawable_grouping_1.xml
@@ -0,0 +1,53 @@
+<!--
+ 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"
+        xmlns:auto="http://schemas.android.com/apk/res-auto"
+        auto:height="64dp"
+        auto:width="64dp"
+        auto:viewportHeight="256"
+        auto:viewportWidth="256" >
+
+    <group
+        auto:name="shape_layer_1"
+        auto:translateX="128"
+        auto:translateY="128" >
+        <group auto: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" />
+
+            <group
+                auto:name="earth"
+                auto: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" />
+
+                <group
+                    auto:name="moon"
+                    auto: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" />
+                </group>
+            </group>
+        </group>
+    </group>
+
+</vector>
\ No newline at end of file
diff --git a/graphics/drawable/testanimated/res/drawable/vector_drawable_progress_bar.xml b/graphics/drawable/testanimated/res/drawable/vector_drawable_progress_bar.xml
new file mode 100644
index 0000000..0b8884b
--- /dev/null
+++ b/graphics/drawable/testanimated/res/drawable/vector_drawable_progress_bar.xml
@@ -0,0 +1,50 @@
+<!--
+ 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"
+        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" >
+
+    <group
+        auto:name="root"
+        auto:pivotX="0.0"
+        auto:pivotY="0.0"
+        auto:rotation="0"
+        auto:translateX="32.0"
+        auto:translateY="32.0" >
+        <group
+            auto:name="rotationGroup"
+            auto:pivotX="0.0"
+            auto:pivotY="0.0"
+            auto: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" />
+        </group>
+    </group>
+
+</vector>
\ No newline at end of file
diff --git a/graphics/drawable/testanimated/res/values/strings.xml b/graphics/drawable/testanimated/res/values/strings.xml
new file mode 100644
index 0000000..c5451c8
--- /dev/null
+++ b/graphics/drawable/testanimated/res/values/strings.xml
@@ -0,0 +1,28 @@
+<?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.
+-->
+
+<resources>
+
+    <string name="twoLinePathData">"M 0,0 v 100 M 0,0 h 100"</string>
+    <string name="triangle"> "M300,70 l 0,-70 70,70 0,0   -70,70z"</string>
+    <string name="rectangle">"M300,70 l 0,-70 70,0  0,140 -70,0 z"</string>
+    <string name="rectangle2">"M300,70 l 0,-70 70,0  0,70z M300,70  l 70,0 0,70 -70,0z"</string>
+    <string name="equal2">    "M300,35 l 0,-35 70,0  0,35z M300,105 l 70,0 0,35 -70,0z"</string>
+    <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
diff --git a/graphics/drawable/testanimated/src/android/support/test/vectordrawable/TestAVDActivity.java b/graphics/drawable/testanimated/src/android/support/test/vectordrawable/TestAVDActivity.java
new file mode 100644
index 0000000..c63c69f
--- /dev/null
+++ b/graphics/drawable/testanimated/src/android/support/test/vectordrawable/TestAVDActivity.java
@@ -0,0 +1,98 @@
+/*
+ * 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.test.vectordrawable;
+
+import android.animation.ObjectAnimator;
+import android.app.Activity;
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.support.graphics.drawable.AnimatedVectorDrawableCompat;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import android.widget.ScrollView;
+import android.widget.TextView;
+
+import java.text.DecimalFormat;
+
+public class TestAVDActivity extends Activity implements View.OnClickListener{
+    private static final String LOG_TAG = "TestActivity";
+
+    private static final String LOGCAT = "VectorDrawable1";
+    protected int[] icon = {
+        R.drawable.animation_vector_drawable_grouping_1,
+        R.drawable.animation_vector_progress_bar,
+    };
+
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        ObjectAnimator oa = new ObjectAnimator();
+        super.onCreate(savedInstanceState);
+        ScrollView scrollView = new ScrollView(this);
+        LinearLayout container = new LinearLayout(this);
+        scrollView.addView(container);
+        container.setOrientation(LinearLayout.VERTICAL);
+        Resources res = this.getResources();
+        container.setBackgroundColor(0xFF888888);
+        AnimatedVectorDrawableCompat []d = new AnimatedVectorDrawableCompat[icon.length];
+        long time =  android.os.SystemClock.currentThreadTimeMillis();
+        for (int i = 0; i < icon.length; i++) {
+             d[i] = AnimatedVectorDrawableCompat.create(this, icon[i]);
+        }
+        time =  android.os.SystemClock.currentThreadTimeMillis()-time;
+        TextView t = new TextView(this);
+        DecimalFormat df = new DecimalFormat("#.##");
+        t.setText("avgL=" + df.format(time / (icon.length)) + " ms");
+        container.addView(t);
+
+        addDrawableButtons(container, d);
+
+        // Now test constant state and mutate a bit.
+        AnimatedVectorDrawableCompat []copies = new AnimatedVectorDrawableCompat[3];
+        copies[0] = (AnimatedVectorDrawableCompat) d[0].getConstantState().newDrawable();
+        copies[1] = (AnimatedVectorDrawableCompat) d[0].getConstantState().newDrawable();
+        copies[2] = (AnimatedVectorDrawableCompat) d[0].getConstantState().newDrawable();
+        copies[0].setAlpha(128);
+
+        // Expect to see the copies[0, 1] are showing alpha 128, and [2] are showing 255.
+        copies[2].mutate();
+        copies[2].setAlpha(255);
+
+        addDrawableButtons(container, copies);
+
+        setContentView(scrollView);
+    }
+
+    private void addDrawableButtons(LinearLayout container, AnimatedVectorDrawableCompat[] d) {
+        for (int i = 0; i < d.length; i++) {
+            Button button = new Button(this);
+            button.setWidth(200);
+            button.setHeight(200);
+            button.setBackgroundDrawable(d[i]);
+            container.addView(button);
+            button.setOnClickListener(this);
+        }
+    }
+
+    @Override
+    public void onClick(View v) {
+        AnimatedVectorDrawableCompat d = (AnimatedVectorDrawableCompat) v.getBackground();
+        d.start();
+    }
+}
diff --git a/graphics/drawable/teststatic/Android.mk b/graphics/drawable/teststatic/Android.mk
new file mode 100644
index 0000000..d8a0fd7
--- /dev/null
+++ b/graphics/drawable/teststatic/Android.mk
@@ -0,0 +1,38 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SDK_VERSION := 7
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_RESOURCE_DIR = \
+        $(LOCAL_PATH)/res \
+        frameworks/support/graphics/drawable/res \
+
+LOCAL_PACKAGE_NAME := AndroidVectorDrawableTests
+
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-v7-vectordrawable android-support-v4
+
+LOCAL_AAPT_FLAGS := \
+        --auto-add-overlay \
+        --extra-packages android.support.graphics.drawable
+
+include $(BUILD_PACKAGE)
+
diff --git a/graphics/drawable/teststatic/AndroidManifest.xml b/graphics/drawable/teststatic/AndroidManifest.xml
new file mode 100644
index 0000000..19586fb
--- /dev/null
+++ b/graphics/drawable/teststatic/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.support.test.vectordrawable" >
+
+    <uses-sdk android:minSdkVersion="7" />
+
+    <application android:icon="@drawable/app_sample_code" android:label="VectorDrawableCompatTest" >
+        <activity android:name="android.support.test.vectordrawable.TestActivity" />
+
+        <intent-filter>
+            <action android:name="android.intent.action.MAIN" />
+
+            <category android:name="android.intent.category.LAUNCHER" />
+        </intent-filter>
+    </application>
+
+</manifest>
\ No newline at end of file
diff --git a/graphics/drawable/teststatic/res/drawable/app_sample_code.png b/graphics/drawable/teststatic/res/drawable/app_sample_code.png
new file mode 100755
index 0000000..66a1984
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/app_sample_code.png
Binary files differ
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable01.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable01.xml
new file mode 100644
index 0000000..12357ef
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable01.xml
@@ -0,0 +1,34 @@
+<?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.
+-->
+<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" >
+
+    <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" />
+    </group>
+
+</vector>
\ No newline at end of file
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable02.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable02.xml
new file mode 100644
index 0000000..cb6b9df
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable02.xml
@@ -0,0 +1,37 @@
+<!--
+ Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<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" >
+
+    <group
+        auto:pivotX="70"
+        auto:pivotY="120"
+        auto:rotation="180" >
+        <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" />
+    </group>
+
+</vector>
\ No newline at end of file
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable03.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable03.xml
new file mode 100644
index 0000000..37d0086
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable03.xml
@@ -0,0 +1,72 @@
+<!--
+ 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"
+        xmlns:auto="http://schemas.android.com/apk/res-auto"
+    auto:height="64dp"
+    auto:viewportHeight="12.25"
+    auto:viewportWidth="7.30625"
+    auto:width="64dp" >
+
+    <group
+        auto:pivotX="3.65"
+        auto:pivotY="6.125"
+        auto:rotation="-30" >
+        <clip-path
+            auto:name="clip1"
+            auto: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
+                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
+        auto:pivotX="3.65"
+        auto:pivotY="6.125"
+        auto:rotation="-30" >
+        <clip-path
+            auto:name="clip2"
+            auto: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
+                        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
+                        q-0.609375,0.1875-1.3125,0.59375l 0.0-1.203125q 0.71875-0.28125 1.328125-0.421875
+                        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" />
+    </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
new file mode 100644
index 0000000..4e2086f
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable04.xml
@@ -0,0 +1,58 @@
+<!-- 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"
+        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">
+
+    <group>
+        <clip-path
+                auto:name="clip1"
+                auto: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"/>
+
+        <clip-path
+                auto:name="clip2"
+                auto: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"/>
+        <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
+                        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
+                        q-0.609375,0.1875-1.3125,0.59375l 0.0-1.203125q 0.71875-0.28125 1.328125-0.421875
+                        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"/>
+    </group>
+</vector>
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable05.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable05.xml
new file mode 100644
index 0000000..48801e3
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable05.xml
@@ -0,0 +1,44 @@
+<!--
+ 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"
+        xmlns:auto="http://schemas.android.com/apk/res-auto"
+        auto:height="64dp"
+        auto:width="64dp"
+        auto:viewportHeight="12.25"
+        auto: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
+                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
+                        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
+                        q-0.609375,0.1875-1.3125,0.59375l 0.0-1.203125q 0.71875-0.28125 1.328125-0.421875
+                        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" />
+    </group>
+</vector>
\ No newline at end of file
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable06.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable06.xml
new file mode 100644
index 0000000..24173e2
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable06.xml
@@ -0,0 +1,49 @@
+<!-- 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"
+        xmlns:auto="http://schemas.android.com/apk/res-auto"
+            auto:width="64dp"
+            auto:height="64dp"
+            auto:viewportWidth="700"
+            auto: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"/>
+    </group>
+</vector>
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable07.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable07.xml
new file mode 100644
index 0000000..90435d3
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable07.xml
@@ -0,0 +1,30 @@
+<!-- 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"
+        xmlns:auto="http://schemas.android.com/apk/res-auto"
+            auto:width="64dp"
+            auto:height="64dp" auto:viewportWidth="140"
+          auto: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
+              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"
+                />
+    </group>
+</vector>
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable08.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable08.xml
new file mode 100644
index 0000000..251d694
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable08.xml
@@ -0,0 +1,30 @@
+<!-- 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"
+        xmlns:auto="http://schemas.android.com/apk/res-auto"
+            auto:width="64dp"
+            auto:height="64dp" auto:viewportWidth="600"
+          auto: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"/>
+    </group>
+
+</vector>
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable09.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable09.xml
new file mode 100644
index 0000000..eccb0d0
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable09.xml
@@ -0,0 +1,33 @@
+<!--
+ 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"
+        xmlns:auto="http://schemas.android.com/apk/res-auto"
+        auto:height="64dp"
+        auto:width="64dp"
+        auto:viewportHeight="200"
+        auto:viewportWidth="200" >
+
+    <group
+        auto:pivotX="100"
+        auto:pivotY="100"
+        auto: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"/>
+    </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
new file mode 100644
index 0000000..b26d30d
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable10.xml
@@ -0,0 +1,43 @@
+<?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.
+-->
+<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">
+
+    <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" />
+        <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" />
+        <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" />
+        <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" />
+    </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
new file mode 100644
index 0000000..eb440f5
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable11.xml
@@ -0,0 +1,36 @@
+<!--
+ 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"
+        xmlns:auto="http://schemas.android.com/apk/res-auto"
+        auto:height="64dp"
+        auto:width="64dp"
+        auto:viewportHeight="80"
+        auto: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" />
+        <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" />
+    </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
new file mode 100644
index 0000000..94a23e8
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable12.xml
@@ -0,0 +1,98 @@
+<!--
+ 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"
+        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" >
+
+    <group
+        auto:name="rotationGroup"
+        auto:pivotX="300.0"
+        auto:pivotY="300.0"
+        auto: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" />
+        <path
+            auto:name="v"
+            auto:fillColor="#000000"
+            auto: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" >
+            <group
+                auto:name="rotationGroup2"
+                auto:pivotX="0.0"
+                auto:pivotY="0.0"
+                auto:rotation="-45.0" >
+                <path
+                    auto:name="twoLines1"
+                    auto:pathData="@string/twoLinePathData"
+                    auto:strokeColor="#FFFF0000"
+                    auto:strokeWidth="20" />
+
+                <group
+                    auto:name="translateGroupHalf"
+                    auto:translateX="65.0"
+                    auto:translateY="80.0" >
+                    <group
+                        auto:name="rotationGroup3"
+                        auto:pivotX="-65.0"
+                        auto:pivotY="-80.0"
+                        auto:rotation="-45.0" >
+                        <path
+                            auto:name="twoLines2"
+                            auto:fillColor="#FF00FF00"
+                            auto:pathData="@string/twoLinePathData"
+                            auto:strokeColor="#FF00FF00"
+                            auto:strokeWidth="20" />
+
+                        <group
+                            auto:name="translateGroup"
+                            auto:translateX="65.0"
+                            auto:translateY="80.0" >
+                            <group
+                                auto:name="rotationGroupBlue"
+                                auto:pivotX="-65.0"
+                                auto:pivotY="-80.0"
+                                auto:rotation="-45.0" >
+                                <path
+                                    auto:name="twoLines3"
+                                    auto:pathData="@string/twoLinePathData"
+                                    auto:strokeColor="#FF0000FF"
+                                    auto:strokeWidth="20" />
+                            </group>
+                        </group>
+                    </group>
+                </group>
+            </group>
+        </group>
+    </group>
+
+</vector>
\ No newline at end of file
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable13.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable13.xml
new file mode 100644
index 0000000..43fc7ea
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable13.xml
@@ -0,0 +1,38 @@
+<!--
+ 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"
+        xmlns:auto="http://schemas.android.com/apk/res-auto"
+        auto:height="64dp"
+        auto:width="64dp"
+        auto:viewportHeight="400"
+        auto: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" />
+        <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" />
+    </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
new file mode 100644
index 0000000..5b4fdd1
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable14.xml
@@ -0,0 +1,39 @@
+<!--
+ 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"
+        xmlns:auto="http://schemas.android.com/apk/res-auto"
+        auto:height="64dp"
+        auto:width="64dp"
+        auto:viewportHeight="500"
+        auto:viewportWidth="800" >
+
+    <group
+        auto:pivotX="90"
+        auto:pivotY="100"
+        auto:rotation="20">
+        <path
+            auto:name="pie2"
+            auto: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" />
+    </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
new file mode 100644
index 0000000..f4ef87f
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable15.xml
@@ -0,0 +1,35 @@
+<!--
+ 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"
+        xmlns:auto="http://schemas.android.com/apk/res-auto"
+        auto:height="64dp"
+        auto:width="64dp"
+        auto:viewportHeight="400"
+        auto:viewportWidth="500" >
+
+    <group
+        auto:pivotX="250"
+        auto:pivotY="200"
+        auto: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" />
+    </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
new file mode 100644
index 0000000..0c64bca
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable16.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"
+        xmlns:auto="http://schemas.android.com/apk/res-auto"
+        auto:height="64dp"
+        auto:width="64dp"
+        auto:viewportHeight="200"
+        auto: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"/>
+        <path
+            auto:name="background2"
+            auto:pathData="M 100,100 l 100,0 l 0, 100 l -100, 0 z"
+            auto: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">
+        <path
+            auto:name="twoLines"
+            auto:pathData="M 100,10 v 90 M 10,100 h 90"
+            auto:strokeColor="#FF00FF00"
+            auto: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
new file mode 100644
index 0000000..28cf09a
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable17.xml
@@ -0,0 +1,30 @@
+<!-- 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"
+        xmlns:auto="http://schemas.android.com/apk/res-auto"
+            auto:width="64dp"
+            auto:height="64dp" auto:viewportWidth="1200"
+          auto: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"/>
+    </group>
+
+</vector>
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable18.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable18.xml
new file mode 100644
index 0000000..d66d4ff
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable18.xml
@@ -0,0 +1,32 @@
+<!--
+ 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"
+        xmlns:auto="http://schemas.android.com/apk/res-auto"
+        auto:height="64dp"
+        auto:width="64dp"
+        auto:viewportHeight="400"
+        auto: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" />
+    </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
new file mode 100644
index 0000000..3a6559d
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable19.xml
@@ -0,0 +1,34 @@
+<!--
+ 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"
+        xmlns:auto="http://schemas.android.com/apk/res-auto"
+        auto:height="64dp"
+        auto:width="64dp"
+        auto:viewportHeight="800"
+        auto: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" />
+    </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
new file mode 100644
index 0000000..d6fd704
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable20.xml
@@ -0,0 +1,35 @@
+<!--
+ 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"
+        xmlns:auto="http://schemas.android.com/apk/res-auto"
+        auto:height="64dp"
+        auto:width="64dp"
+        auto:viewportHeight="480"
+        auto:viewportWidth="480" >
+
+    <group>
+        <path
+            auto:name="edit"
+            auto:fillColor="#FF00FFFF"
+            auto: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" />
+    </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
new file mode 100644
index 0000000..9136b73
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable21.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"
+        xmlns:auto="http://schemas.android.com/apk/res-auto"
+        auto:height="64dp"
+        auto:width="64dp"
+        auto:viewportHeight="200"
+        auto: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"/>
+        <path
+            auto:name="background2"
+            auto:pathData="M 100,100 l 100,0 l 0, 100 l -100, 0 z"
+            auto: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">
+        <path
+            auto:name="twoLines"
+            auto:pathData="M 100,10 v 90 M 10,100 h 90"
+            auto:strokeColor="#FF00FF00"
+            auto: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
new file mode 100644
index 0000000..2b33a89
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable22.xml
@@ -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.
+-->
+<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" >
+
+    <group auto:name="backgroundGroup" >
+        <path
+            auto:name="background1"
+            auto:fillColor="#80000000"
+            auto: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" />
+    </group>
+    <group
+        auto:name="translateToCenterGroup"
+        auto:translateX="50.0"
+        auto: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" />
+
+        <group
+            auto:name="rotationGroup"
+            auto:pivotX="0.0"
+            auto:pivotY="0.0"
+            auto: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" />
+
+            <group
+                auto:name="translateGroup"
+                auto:translateX="130.0"
+                auto:translateY="160.0" >
+                <group auto:name="scaleGroup" >
+                    <path
+                        auto:name="twoLines2"
+                        auto:pathData="M 0,0 v 100 M 0,0 h 100"
+                        auto:strokeColor="#FF0000FF"
+                        auto:strokeWidth="20" />
+                </group>
+            </group>
+        </group>
+    </group>
+
+</vector>
\ No newline at end of file
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable23.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable23.xml
new file mode 100644
index 0000000..d5759f9
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable23.xml
@@ -0,0 +1,83 @@
+<!--
+ 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"
+        xmlns:auto="http://schemas.android.com/apk/res-auto"
+        auto:height="64dp"
+        auto:width="64dp"
+        auto:viewportHeight="400"
+        auto:viewportWidth="400" >
+
+    <group auto:name="backgroundGroup" >
+        <path
+            auto:name="background1"
+            auto:fillColor="#80000000"
+            auto: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" />
+    </group>
+    <group
+        auto:name="translateToCenterGroup"
+        auto:translateX="50.0"
+        auto:translateY="90.0" >
+        <path
+            auto:name="twoLines"
+            auto:pathData="@string/twoLinePathData"
+            auto:strokeColor="#FFFF0000"
+            auto:strokeWidth="20" />
+
+        <group
+            auto:name="rotationGroup"
+            auto:pivotX="0.0"
+            auto:pivotY="0.0"
+            auto:rotation="-45.0" >
+            <path
+                auto:name="twoLines1"
+                auto:pathData="@string/twoLinePathData"
+                auto:strokeColor="#FF00FF00"
+                auto:strokeWidth="20" />
+
+            <group
+                auto:name="translateGroup"
+                auto:translateX="130.0"
+                auto:translateY="160.0" >
+                <group auto:name="scaleGroup" >
+                    <path
+                        auto:name="twoLines3"
+                        auto:pathData="@string/twoLinePathData"
+                        auto:strokeColor="#FF0000FF"
+                        auto:strokeWidth="20" />
+                </group>
+            </group>
+
+            <group
+                auto:name="translateGroupHalf"
+                auto:translateX="65.0"
+                auto:translateY="80.0" >
+                <group auto:name="scaleGroup" >
+                    <path
+                        auto:name="twoLines2"
+                        auto:pathData="@string/twoLinePathData"
+                        auto:fillColor="#FFFFFFFF"
+                        auto:strokeColor="#FFFFFFFF"
+                        auto:strokeWidth="20" />
+                </group>
+            </group>
+        </group>
+    </group>
+
+</vector>
\ No newline at end of file
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable24.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable24.xml
new file mode 100644
index 0000000..b054692
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable24.xml
@@ -0,0 +1,83 @@
+<!--
+ 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"
+        xmlns:auto="http://schemas.android.com/apk/res-auto"
+        auto:height="64dp"
+        auto:width="64dp"
+        auto:viewportHeight="400"
+        auto:viewportWidth="400" >
+
+    <group auto:name="backgroundGroup">
+        <path
+            auto:name="background1"
+            auto:fillColor="#FF000000"
+            auto: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" />
+    </group>
+    <group
+        auto:name="translateToCenterGroup"
+        auto:translateX="50.0"
+        auto:translateY="90.0" >
+        <path
+            auto:name="twoLines"
+            auto:pathData="@string/twoLinePathData"
+            auto:strokeColor="#FFFF0000"
+            auto:strokeWidth="20" />
+
+        <group
+            auto:name="rotationGroup"
+            auto:pivotX="0.0"
+            auto:pivotY="0.0"
+            auto:rotation="-45.0">
+            <path
+                auto:name="twoLines1"
+                auto:pathData="@string/twoLinePathData"
+                auto:strokeColor="#FF00FF00"
+                auto:strokeWidth="20" />
+
+            <group
+                auto:name="translateGroup"
+                auto:translateX="130.0"
+                auto:translateY="160.0">
+                <group auto:name="scaleGroup" >
+                    <path
+                        auto:name="twoLines3"
+                        auto:pathData="@string/twoLinePathData"
+                        auto:strokeColor="#FF0000FF"
+                        auto:strokeWidth="20" />
+                </group>
+            </group>
+
+            <group
+                auto:name="translateGroupHalf"
+                auto:translateX="65.0"
+                auto:translateY="80.0">
+                <group auto:name="scaleGroup" >
+                    <path
+                        auto:name="twoLines2"
+                        auto:pathData="@string/twoLinePathData"
+                        auto:fillColor="#FFFFFFFF"
+                        auto:strokeColor="#FFFFFFFF"
+                        auto:strokeWidth="20" />
+                </group>
+            </group>
+        </group>
+    </group>
+
+</vector>
\ No newline at end of file
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable25.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable25.xml
new file mode 100644
index 0000000..7a94ed6
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable25.xml
@@ -0,0 +1,83 @@
+<!--
+ 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"
+        xmlns:auto="http://schemas.android.com/apk/res-auto"
+        auto:height="64dp"
+        auto:width="64dp"
+        auto:viewportHeight="400"
+        auto:viewportWidth="400" >
+
+    <group
+        auto:name="FirstLevelGroup"
+        auto:translateX="100.0"
+        auto:translateY="0.0" >
+        <group
+            auto:name="SecondLevelGroup1"
+            auto:translateX="-100.0"
+            auto:translateY="50.0" >
+            <path
+                auto:fillColor="#FF00FF00"
+                auto:pathData="@string/rectangle200" />
+
+            <group
+                auto:name="ThridLevelGroup1"
+                auto:translateX="-100.0"
+                auto:translateY="50.0" >
+                <path
+                    auto:fillColor="#FF0000FF"
+                    auto:pathData="@string/rectangle200" />
+            </group>
+            <group
+                auto:name="ThridLevelGroup2"
+                auto:translateX="100.0"
+                auto:translateY="50.0" >
+                <path
+                    auto:fillColor="#FF000000"
+                    auto:pathData="@string/rectangle200" />
+            </group>
+        </group>
+        <group
+            auto:name="SecondLevelGroup2"
+            auto:translateX="100.0"
+            auto:translateY="50.0" >
+            <path
+                auto:fillColor="#FF0000FF"
+                auto:pathData="@string/rectangle200" />
+
+            <group
+                auto:name="ThridLevelGroup3"
+                auto:translateX="-100.0"
+                auto:translateY="50.0" >
+                <path
+                    auto:fillColor="#FFFF0000"
+                    auto:pathData="@string/rectangle200" />
+            </group>
+            <group
+                auto:name="ThridLevelGroup4"
+                auto:translateX="100.0"
+                auto:translateY="50.0" >
+                <path
+                    auto:fillColor="#FF00FF00"
+                    auto:pathData="@string/rectangle200" />
+            </group>
+        </group>
+
+        <path
+            auto:fillColor="#FFFF0000"
+            auto: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
new file mode 100644
index 0000000..b2dd4a3
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable26.xml
@@ -0,0 +1,46 @@
+<!--
+ 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"
+        xmlns:auto="http://schemas.android.com/apk/res-auto"
+    auto:height="64dp"
+    auto:viewportHeight="200"
+    auto:viewportWidth="200"
+    auto: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" />
+        <path
+            auto:name="background2"
+            auto:fillColor="#FF000000"
+            auto:pathData="M 100,100 l 100,0 l 0, 100 l -100, 0 z" />
+    </group>
+    <group
+        auto:translateX="50"
+        auto: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" />
+    </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
new file mode 100644
index 0000000..b8f88ce
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable27.xml
@@ -0,0 +1,46 @@
+<!--
+ 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"
+        xmlns:auto="http://schemas.android.com/apk/res-auto"
+    auto:height="64dp"
+    auto:viewportHeight="200"
+    auto:viewportWidth="200"
+    auto: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" />
+        <path
+            auto:name="background2"
+            auto:fillColor="#FF000000"
+            auto:pathData="M 100,100 l 100,0 l 0, 100 l -100, 0 z" />
+    </group>
+    <group
+        auto:translateX="50"
+        auto: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" />
+    </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
new file mode 100644
index 0000000..30c7fce
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable28.xml
@@ -0,0 +1,47 @@
+<!--
+ 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"
+        xmlns:auto="http://schemas.android.com/apk/res-auto"
+    auto:height="64dp"
+    auto:viewportHeight="200"
+    auto:viewportWidth="200"
+    auto:width="64dp"
+    auto: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" />
+        <path
+            auto:name="background2"
+            auto:fillColor="#FF000000"
+            auto:pathData="M 100,100 l 100,0 l 0, 100 l -100, 0 z" />
+    </group>
+    <group
+        auto:translateX="50"
+        auto: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" />
+    </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
new file mode 100644
index 0000000..2ac1d42
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable29.xml
@@ -0,0 +1,29 @@
+<!--
+ 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"
+        xmlns:auto="http://schemas.android.com/apk/res-auto"
+        auto:height="48dp"
+        auto:width="48dp"
+        auto:viewportHeight="1"
+        auto:viewportWidth="1" >
+
+    <group>
+        <path
+            auto:name="box1"
+            auto:pathData="l0.0.0.5.0.0.5-0.5.0.0-.5z"
+            auto:fillColor="#ff00ff00"/>
+    </group>
+</vector>
diff --git a/graphics/drawable/teststatic/res/drawable/vector_drawable30.xml b/graphics/drawable/teststatic/res/drawable/vector_drawable30.xml
new file mode 100644
index 0000000..6abb455
--- /dev/null
+++ b/graphics/drawable/teststatic/res/drawable/vector_drawable30.xml
@@ -0,0 +1,29 @@
+<!--
+ 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"
+        xmlns:auto="http://schemas.android.com/apk/res-auto"
+        auto:height="48dp"
+        auto:width="48dp"
+        auto:viewportHeight="48"
+        auto: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"/>
+    </group>
+</vector>
diff --git a/graphics/drawable/teststatic/res/raw/vector_drawable01.xml b/graphics/drawable/teststatic/res/raw/vector_drawable01.xml
new file mode 100644
index 0000000..baa3fc7
--- /dev/null
+++ b/graphics/drawable/teststatic/res/raw/vector_drawable01.xml
@@ -0,0 +1,32 @@
+<!--
+ 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"
+        xmlns:auto="http://schemas.android.com/apk/res-auto"
+        android:height="48dp"
+        android:width="48dp"
+        android:viewportHeight="480"
+        android:viewportWidth="480" >
+
+    <group>
+        <path
+            android:name="box1"
+            android:pathData="m20,200l100,90l180-180l-35-35l-145,145l-60-60l-40,40z"
+            android:fillColor="?android:attr/colorControlActivated"
+            android:strokeColor="?android:attr/colorControlActivated"
+            android:strokeLineCap="round"
+            android:strokeLineJoin="round" />
+    </group>
+</vector>
diff --git a/graphics/drawable/teststatic/res/values/strings.xml b/graphics/drawable/teststatic/res/values/strings.xml
new file mode 100644
index 0000000..c5451c8
--- /dev/null
+++ b/graphics/drawable/teststatic/res/values/strings.xml
@@ -0,0 +1,28 @@
+<?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.
+-->
+
+<resources>
+
+    <string name="twoLinePathData">"M 0,0 v 100 M 0,0 h 100"</string>
+    <string name="triangle"> "M300,70 l 0,-70 70,70 0,0   -70,70z"</string>
+    <string name="rectangle">"M300,70 l 0,-70 70,0  0,140 -70,0 z"</string>
+    <string name="rectangle2">"M300,70 l 0,-70 70,0  0,70z M300,70  l 70,0 0,70 -70,0z"</string>
+    <string name="equal2">    "M300,35 l 0,-35 70,0  0,35z M300,105 l 70,0 0,35 -70,0z"</string>
+    <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
diff --git a/graphics/drawable/teststatic/src/android/support/test/vectordrawable/TestActivity.java b/graphics/drawable/teststatic/src/android/support/test/vectordrawable/TestActivity.java
new file mode 100644
index 0000000..8bb766e
--- /dev/null
+++ b/graphics/drawable/teststatic/src/android/support/test/vectordrawable/TestActivity.java
@@ -0,0 +1,128 @@
+/*
+ * 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.test.vectordrawable;
+
+import android.app.Activity;
+import android.content.res.Resources;
+import android.graphics.PorterDuff.Mode;
+import android.graphics.drawable.Drawable.ConstantState;
+import android.os.Bundle;
+import android.support.graphics.drawable.VectorDrawableCompat;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import android.widget.ScrollView;
+import android.widget.TextView;
+
+import java.text.DecimalFormat;
+
+public class TestActivity extends Activity {
+    private static final String LOG_TAG = "TestActivity";
+
+    private static final String LOGCAT = "VectorDrawable1";
+    protected int[] icon = {
+            R.drawable.vector_drawable01,
+            R.drawable.vector_drawable02,
+            R.drawable.vector_drawable03,
+            R.drawable.vector_drawable04,
+            R.drawable.vector_drawable05,
+            R.drawable.vector_drawable06,
+            R.drawable.vector_drawable07,
+            R.drawable.vector_drawable08,
+            R.drawable.vector_drawable09,
+            R.drawable.vector_drawable10,
+            R.drawable.vector_drawable11,
+            R.drawable.vector_drawable12,
+            R.drawable.vector_drawable13,
+            R.drawable.vector_drawable14,
+            R.drawable.vector_drawable15,
+            R.drawable.vector_drawable16,
+            R.drawable.vector_drawable17,
+            R.drawable.vector_drawable18,
+            R.drawable.vector_drawable19,
+            R.drawable.vector_drawable20,
+            R.drawable.vector_drawable21,
+            R.drawable.vector_drawable22,
+            R.drawable.vector_drawable23,
+            R.drawable.vector_drawable24,
+            R.drawable.vector_drawable25,
+            R.drawable.vector_drawable26,
+            R.drawable.vector_drawable27,
+            R.drawable.vector_drawable28,
+            R.drawable.vector_drawable29,
+            R.drawable.vector_drawable30,
+    };
+
+    private static final int EXTRA_TESTS = 2;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        ScrollView scrollView = new ScrollView(this);
+        LinearLayout container = new LinearLayout(this);
+        scrollView.addView(container);
+        container.setOrientation(LinearLayout.VERTICAL);
+        Resources res = this.getResources();
+        container.setBackgroundColor(0xFF888888);
+        VectorDrawableCompat []d = new VectorDrawableCompat[icon.length];
+        long time =  android.os.SystemClock.currentThreadTimeMillis();
+        for (int i = 0; i < icon.length; i++) {
+             d[i] = VectorDrawableCompat.create(res, icon[i], getTheme());
+        }
+        time =  android.os.SystemClock.currentThreadTimeMillis()-time;
+
+        // Testing Tint on one particular case.
+        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.
+        VectorDrawableCompat []extras = new VectorDrawableCompat[EXTRA_TESTS];
+        ConstantState state = d[0].getConstantState();
+        extras[0] = (VectorDrawableCompat) state.newDrawable();
+        extras[1] = (VectorDrawableCompat) state.newDrawable();
+
+        // This alpha change is expected to affect both extra 0, 1, and d0.
+        extras[0].setAlpha(128);
+
+        d[0].mutate();
+        d[0].setAlpha(255);
+
+        // Just show the average create time as the first view.
+        TextView t = new TextView(this);
+        DecimalFormat df = new DecimalFormat("#.##");
+        t.setText("avgL=" + df.format(time / (icon.length)) + " ms");
+        container.addView(t);
+
+        addDrawableButtons(container, extras);
+
+        addDrawableButtons(container, d);
+
+        setContentView(scrollView);
+    }
+
+    private void addDrawableButtons(LinearLayout container, VectorDrawableCompat[] d) {
+        // Add the VD into consequent views.
+        for (int i = 0; i < d.length; i++) {
+            Button button = new Button(this);
+            button.setWidth(200);
+            // Note that setBackgroundResource() will fail b/c createFromXmlInner() failed
+            // to recognize <vector> pre-L.
+            button.setBackgroundDrawable(d[i]);
+            container.addView(button);
+        }
+    }
+}
diff --git a/percent/src/android/support/percent/PercentFrameLayout.java b/percent/src/android/support/percent/PercentFrameLayout.java
index 994be4c..90c238d 100644
--- a/percent/src/android/support/percent/PercentFrameLayout.java
+++ b/percent/src/android/support/percent/PercentFrameLayout.java
@@ -134,6 +134,10 @@
 
         @Override
         public PercentLayoutHelper.PercentLayoutInfo getPercentLayoutInfo() {
+            if (mPercentLayoutInfo == null) {
+                mPercentLayoutInfo = new PercentLayoutHelper.PercentLayoutInfo();
+            }
+
             return mPercentLayoutInfo;
         }
 
diff --git a/percent/src/android/support/percent/PercentRelativeLayout.java b/percent/src/android/support/percent/PercentRelativeLayout.java
index 1a06b8d..07c08cf 100644
--- a/percent/src/android/support/percent/PercentRelativeLayout.java
+++ b/percent/src/android/support/percent/PercentRelativeLayout.java
@@ -120,6 +120,10 @@
 
         @Override
         public PercentLayoutHelper.PercentLayoutInfo getPercentLayoutInfo() {
+            if (mPercentLayoutInfo == null) {
+                mPercentLayoutInfo = new PercentLayoutHelper.PercentLayoutInfo();
+            }
+
             return mPercentLayoutInfo;
         }
 
diff --git a/previewsdk/Android.mk b/previewsdk/Android.mk
new file mode 100644
index 0000000..95f5dba
--- /dev/null
+++ b/previewsdk/Android.mk
@@ -0,0 +1,32 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+# Here is the final static library that apps can link against.
+include $(CLEAR_VARS)
+
+previewsdk_generate_constants_exe := $(LOCAL_PATH)/previewconstants.sh
+previewsdk_gen_java_files := $(TARGET_OUT_COMMON_GEN)/previewsdk/PreviewSdkConstants.java
+
+$(previewsdk_gen_java_files): $(previewsdk_generate_constants_exe)
+	$(hide) mkdir -p $(dir $@)
+	$(hide) PLATFORM_PREVIEW_SDK_VERSION="$(PLATFORM_PREVIEW_SDK_VERSION)" \
+		bash $< > $@
+
+LOCAL_MODULE := android-support-previewsdk
+LOCAL_SDK_VERSION := current
+LOCAL_GENERATED_SOURCES := $(previewsdk_gen_java_files)
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/previewsdk/previewconstants.sh b/previewsdk/previewconstants.sh
new file mode 100755
index 0000000..de94f84
--- /dev/null
+++ b/previewsdk/previewconstants.sh
@@ -0,0 +1,8 @@
+#!/bin/bash
+
+echo "/** Begin preview constants"
+echo " * autogenerated by previewconstants.sh */"
+echo "package android.support.previewsdk;"
+echo "class PreviewConstants {"
+echo "    public static final int PREVIEW_SDK_VERSION = $PLATFORM_PREVIEW_SDK_VERSION;"
+echo "}"
diff --git a/previewsdk/src/android/support/previewsdk/PreviewSdk.java b/previewsdk/src/android/support/previewsdk/PreviewSdk.java
new file mode 100644
index 0000000..8b494c7
--- /dev/null
+++ b/previewsdk/src/android/support/previewsdk/PreviewSdk.java
@@ -0,0 +1,46 @@
+/*
+ * 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.previewsdk;
+
+import android.os.Build;
+
+/**
+ * Utility class for performing version checks on Android platform preview SDKs.
+ *
+ * <p>Apps must be very careful when targeting preview builds because binary compatibility
+ * is not guaranteed. APIs can be renamed or drastically changed before they are finalized
+ * into a new API level. The new SDK constant <code>Build.VERSION.PREVIEW_SDK_INT</code>
+ * marks a precise snapshot version of prerelease API.</p>
+ *
+ * <p>{@link #isKnownPreviewDevice()} will return <code>true</code> if the current device
+ * is running a preview build with the same SDK snapshot this support lib was built with.
+ * If it returns <code>true</code> it is safe to call prerelease APIs. If not, the app
+ * should fall back to only assuming the presence of the latest public, final API level.</p>
+ */
+public class PreviewSdk {
+    /**
+     * Check if the current device is running a prerelease platform preview build matching
+     * the SDK this library was built for. If it returns true, it is safe to call prerelease
+     * APIs known to this SDK.
+     *
+     * @return true if the device is running a preview build that matches the SDK.
+     */
+    public static boolean isKnownPreviewDevice() {
+        return "MNC".equals(Build.VERSION.CODENAME)
+                && Build.VERSION.PREVIEW_SDK_INT == PreviewConstants.PREVIEW_SDK_VERSION;
+    }
+}
diff --git a/recommendation/Android.mk b/recommendation/Android.mk
new file mode 100644
index 0000000..3d8edf8
--- /dev/null
+++ b/recommendation/Android.mk
@@ -0,0 +1,60 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+LOCAL_SDK_VERSION := 21
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+
+LOCAL_JAVA_LIBRARIES := \
+    android-support-v4
+
+LOCAL_MODULE := android-support-recommendation
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+# ===========================================================
+# Common Droiddoc vars
+recommendation.docs.src_files := \
+    $(call all-java-files-under, src) \
+    $(call all-html-files-under, src)
+recommendation.docs.java_libraries := \
+    framework \
+    android-support-v4 \
+    android-support-recommendation
+
+# Documentation
+# ===========================================================
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := android-support-recommendation
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(recommendation.docs.src_files)
+
+LOCAL_SDK_VERSION := 21
+LOCAL_IS_HOST_MODULE := false
+LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR := build/tools/droiddoc/templates-sdk
+
+LOCAL_JAVA_LIBRARIES := $(recommendation.docs.java_libraries)
+
+LOCAL_DROIDDOC_OPTIONS := \
+    -offlinemode \
+    -hdf android.whichdoc offline \
+    -federate Android http://developer.android.com \
+    -federationapi Android prebuilts/sdk/api/21.txt \
+    -hide 113
+
+include $(BUILD_DROIDDOC)
+
+
+# API Check
+# ---------------------------------------------
+support_module := $(LOCAL_MODULE)
+support_module_api_dir := $(LOCAL_PATH)/api
+support_module_src_files := $(recommendation.docs.src_files)
+support_module_java_libraries := $(recommendation.docs.java_libraries)
+support_module_java_packages := android.support.app.recommendation*
+include $(SUPPORT_API_CHECK)
diff --git a/recommendation/AndroidManifest.xml b/recommendation/AndroidManifest.xml
new file mode 100644
index 0000000..ef1223e
--- /dev/null
+++ b/recommendation/AndroidManifest.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="android.support.recommendation">
+    <uses-sdk android:minSdkVersion="21"/>
+    <application />
+</manifest>
diff --git a/recommendation/api/current.txt b/recommendation/api/current.txt
new file mode 100644
index 0000000..ce69b31
--- /dev/null
+++ b/recommendation/api/current.txt
@@ -0,0 +1,132 @@
+package android.support.app.recommendation {
+
+  public final class ContentRecommendation {
+    method public java.lang.String getBackgroundImageUri();
+    method public int getBadgeImageResourceId();
+    method public int getColor();
+    method public android.graphics.Bitmap getContentImage();
+    method public android.support.app.recommendation.ContentRecommendation.IntentData getContentIntent();
+    method public java.lang.String[] getContentTypes();
+    method public android.support.app.recommendation.ContentRecommendation.IntentData getDismissIntent();
+    method public java.lang.String[] getGenres();
+    method public java.lang.String getGroup();
+    method public java.lang.String getIdTag();
+    method public java.lang.String getMaturityRating();
+    method public android.app.Notification getNotificationObject(android.content.Context);
+    method public java.lang.String getPricingType();
+    method public java.lang.String getPricingValue();
+    method public java.lang.String getPrimaryContentType();
+    method public int getProgressMax();
+    method public int getProgressValue();
+    method public long getRunningTime();
+    method public java.lang.String getSortKey();
+    method public java.lang.String getSourceName();
+    method public int getStatus();
+    method public java.lang.String getText();
+    method public java.lang.String getTitle();
+    method public boolean hasProgressInfo();
+    method public boolean isAutoDismiss();
+    method public void setAutoDismiss(boolean);
+    method public void setGroup(java.lang.String);
+    method public void setProgress(int, int);
+    method public void setSortKey(java.lang.String);
+    method public void setStatus(int);
+    field public static final java.lang.String CONTENT_MATURITY_ALL = "android.contentMaturity.all";
+    field public static final java.lang.String CONTENT_MATURITY_HIGH = "android.contentMaturity.high";
+    field public static final java.lang.String CONTENT_MATURITY_LOW = "android.contentMaturity.low";
+    field public static final java.lang.String CONTENT_MATURITY_MEDIUM = "android.contentMaturity.medium";
+    field public static final java.lang.String CONTENT_PRICING_FREE = "android.contentPrice.free";
+    field public static final java.lang.String CONTENT_PRICING_PREORDER = "android.contentPrice.preorder";
+    field public static final java.lang.String CONTENT_PRICING_PURCHASE = "android.contentPrice.purchase";
+    field public static final java.lang.String CONTENT_PRICING_RENTAL = "android.contentPrice.rental";
+    field public static final java.lang.String CONTENT_PRICING_SUBSCRIPTION = "android.contentPrice.subscription";
+    field public static final int CONTENT_STATUS_AVAILABLE = 2; // 0x2
+    field public static final int CONTENT_STATUS_PENDING = 1; // 0x1
+    field public static final int CONTENT_STATUS_READY = 0; // 0x0
+    field public static final int CONTENT_STATUS_UNAVAILABLE = 3; // 0x3
+    field public static final java.lang.String CONTENT_TYPE_APP = "android.contentType.app";
+    field public static final java.lang.String CONTENT_TYPE_BOOK = "android.contentType.book";
+    field public static final java.lang.String CONTENT_TYPE_COMIC = "android.contentType.comic";
+    field public static final java.lang.String CONTENT_TYPE_GAME = "android.contentType.game";
+    field public static final java.lang.String CONTENT_TYPE_MAGAZINE = "android.contentType.magazine";
+    field public static final java.lang.String CONTENT_TYPE_MOVIE = "android.contentType.movie";
+    field public static final java.lang.String CONTENT_TYPE_MUSIC = "android.contentType.music";
+    field public static final java.lang.String CONTENT_TYPE_NEWS = "android.contentType.news";
+    field public static final java.lang.String CONTENT_TYPE_PODCAST = "android.contentType.podcast";
+    field public static final java.lang.String CONTENT_TYPE_RADIO = "android.contentType.radio";
+    field public static final java.lang.String CONTENT_TYPE_SERIAL = "android.contentType.serial";
+    field public static final java.lang.String CONTENT_TYPE_SPORTS = "android.contentType.sports";
+    field public static final java.lang.String CONTENT_TYPE_TRAILER = "android.contentType.trailer";
+    field public static final java.lang.String CONTENT_TYPE_VIDEO = "android.contentType.video";
+    field public static final java.lang.String CONTENT_TYPE_WEBSITE = "android.contentType.website";
+    field public static final int INTENT_TYPE_ACTIVITY = 1; // 0x1
+    field public static final int INTENT_TYPE_BROADCAST = 2; // 0x2
+    field public static final int INTENT_TYPE_SERVICE = 3; // 0x3
+  }
+
+  public static final class ContentRecommendation.Builder {
+    ctor public ContentRecommendation.Builder();
+    method public android.support.app.recommendation.ContentRecommendation build();
+    method public android.support.app.recommendation.ContentRecommendation.Builder setAutoDismiss(boolean);
+    method public android.support.app.recommendation.ContentRecommendation.Builder setBackgroundImageUri(java.lang.String);
+    method public android.support.app.recommendation.ContentRecommendation.Builder setBadgeIcon(int);
+    method public android.support.app.recommendation.ContentRecommendation.Builder setColor(int);
+    method public android.support.app.recommendation.ContentRecommendation.Builder setContentImage(android.graphics.Bitmap);
+    method public android.support.app.recommendation.ContentRecommendation.Builder setContentIntentData(int, android.content.Intent, int, android.os.Bundle);
+    method public android.support.app.recommendation.ContentRecommendation.Builder setContentTypes(java.lang.String[]);
+    method public android.support.app.recommendation.ContentRecommendation.Builder setDismissIntentData(int, android.content.Intent, int, android.os.Bundle);
+    method public android.support.app.recommendation.ContentRecommendation.Builder setGenres(java.lang.String[]);
+    method public android.support.app.recommendation.ContentRecommendation.Builder setGroup(java.lang.String);
+    method public android.support.app.recommendation.ContentRecommendation.Builder setIdTag(java.lang.String);
+    method public android.support.app.recommendation.ContentRecommendation.Builder setMaturityRating(java.lang.String);
+    method public android.support.app.recommendation.ContentRecommendation.Builder setPricingInformation(java.lang.String, java.lang.String);
+    method public android.support.app.recommendation.ContentRecommendation.Builder setProgress(int, int);
+    method public android.support.app.recommendation.ContentRecommendation.Builder setRunningTime(long);
+    method public android.support.app.recommendation.ContentRecommendation.Builder setSortKey(java.lang.String);
+    method public android.support.app.recommendation.ContentRecommendation.Builder setSourceName(java.lang.String);
+    method public android.support.app.recommendation.ContentRecommendation.Builder setStatus(int);
+    method public android.support.app.recommendation.ContentRecommendation.Builder setText(java.lang.String);
+    method public android.support.app.recommendation.ContentRecommendation.Builder setTitle(java.lang.String);
+  }
+
+  public static abstract class ContentRecommendation.ContentMaturity implements java.lang.annotation.Annotation {
+  }
+
+  public static abstract class ContentRecommendation.ContentPricing implements java.lang.annotation.Annotation {
+  }
+
+  public static abstract class ContentRecommendation.ContentStatus implements java.lang.annotation.Annotation {
+  }
+
+  public static abstract class ContentRecommendation.ContentType implements java.lang.annotation.Annotation {
+  }
+
+  public static class ContentRecommendation.IntentData {
+    ctor public ContentRecommendation.IntentData();
+  }
+
+  public static abstract class ContentRecommendation.IntentType implements java.lang.annotation.Annotation {
+  }
+
+  public final class RecommendationExtender implements android.app.Notification.Extender {
+    ctor public RecommendationExtender();
+    ctor public RecommendationExtender(android.app.Notification);
+    method public android.app.Notification.Builder extend(android.app.Notification.Builder);
+    method public java.lang.String[] getContentTypes();
+    method public java.lang.String[] getGenres();
+    method public java.lang.String getMaturityRating();
+    method public java.lang.String getPricingType();
+    method public java.lang.String getPricingValue();
+    method public java.lang.String getPrimaryContentType();
+    method public long getRunningTime();
+    method public int getStatus();
+    method public android.support.app.recommendation.RecommendationExtender setContentTypes(java.lang.String[]);
+    method public android.support.app.recommendation.RecommendationExtender setGenres(java.lang.String[]);
+    method public android.support.app.recommendation.RecommendationExtender setMaturityRating(java.lang.String);
+    method public android.support.app.recommendation.RecommendationExtender setPricingInformation(java.lang.String, java.lang.String);
+    method public android.support.app.recommendation.RecommendationExtender setRunningTime(long);
+    method public android.support.app.recommendation.RecommendationExtender setStatus(int);
+  }
+
+}
+
diff --git a/recommendation/api/removed.txt b/recommendation/api/removed.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/recommendation/api/removed.txt
diff --git a/recommendation/src/android/support/app/recommendation/ContentRecommendation.java b/recommendation/src/android/support/app/recommendation/ContentRecommendation.java
new file mode 100644
index 0000000..fdc0907
--- /dev/null
+++ b/recommendation/src/android/support/app/recommendation/ContentRecommendation.java
@@ -0,0 +1,1153 @@
+/*
+ * 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.app.recommendation;
+
+import android.app.Notification;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.os.Bundle;
+import android.support.annotation.IntDef;
+import android.support.annotation.Nullable;
+import android.support.annotation.StringDef;
+import android.text.TextUtils;
+
+import java.util.Arrays;
+
+/**
+ * The ContentRecommendation object encapsulates all application provided data for a single content
+ * recommendation item.
+ */
+public final class ContentRecommendation
+{
+    @StringDef({
+        CONTENT_TYPE_VIDEO,
+        CONTENT_TYPE_MOVIE,
+        CONTENT_TYPE_TRAILER,
+        CONTENT_TYPE_SERIAL,
+        CONTENT_TYPE_MUSIC,
+        CONTENT_TYPE_RADIO,
+        CONTENT_TYPE_PODCAST,
+        CONTENT_TYPE_NEWS,
+        CONTENT_TYPE_SPORTS,
+        CONTENT_TYPE_APP,
+        CONTENT_TYPE_GAME,
+        CONTENT_TYPE_BOOK,
+        CONTENT_TYPE_COMIC,
+        CONTENT_TYPE_MAGAZINE,
+        CONTENT_TYPE_WEBSITE,
+    })
+    public @interface ContentType {}
+
+    /**
+     * Value to be used with {@link Builder#setContentTypes} to indicate that the content referred
+     * by the notification item is a video clip.
+     */
+    public static final String CONTENT_TYPE_VIDEO = "android.contentType.video";
+
+    /**
+     * Value to be used with {@link Builder#setContentTypes} to indicate that the content referred
+     * by the notification item is a movie.
+     */
+    public static final String CONTENT_TYPE_MOVIE = "android.contentType.movie";
+
+    /**
+     * Value to be used with {@link Builder#setContentTypes} to indicate that the content referred
+     * by the notification item is a trailer.
+     */
+    public static final String CONTENT_TYPE_TRAILER = "android.contentType.trailer";
+
+    /**
+     * Value to be used with {@link Builder#setContentTypes} to indicate that the content referred
+     * by the notification item is serial. It can refer to an entire show, a single season or
+     * series, or a single episode.
+     */
+    public static final String CONTENT_TYPE_SERIAL = "android.contentType.serial";
+
+    /**
+     * Value to be used with {@link Builder#setContentTypes} to indicate that the content referred
+     * by the notification item is a song or album.
+     */
+    public static final String CONTENT_TYPE_MUSIC = "android.contentType.music";
+
+    /**
+     * Value to be used with {@link Builder#setContentTypes} to indicate that the content referred
+     * by the notification item is a radio station.
+     */
+    public static final String CONTENT_TYPE_RADIO = "android.contentType.radio";
+
+    /**
+     * Value to be used with {@link Builder#setContentTypes} to indicate that the content referred
+     * by the notification item is a podcast.
+     */
+    public static final String CONTENT_TYPE_PODCAST = "android.contentType.podcast";
+
+    /**
+     * Value to be used with {@link Builder#setContentTypes} to indicate that the content referred
+     * by the notification item is a news item.
+     */
+    public static final String CONTENT_TYPE_NEWS = "android.contentType.news";
+
+    /**
+     * Value to be used with {@link Builder#setContentTypes} to indicate that the content referred
+     * by the notification item is sports.
+     */
+    public static final String CONTENT_TYPE_SPORTS = "android.contentType.sports";
+
+    /**
+     * Value to be used with {@link Builder#setContentTypes} to indicate that the content referred
+     * by the notification item is an application.
+     */
+    public static final String CONTENT_TYPE_APP = "android.contentType.app";
+
+    /**
+     * Value to be used with {@link Builder#setContentTypes} to indicate that the content referred
+     * by the notification item is a game.
+     */
+    public static final String CONTENT_TYPE_GAME = "android.contentType.game";
+
+    /**
+     * Value to be used with {@link Builder#setContentTypes} to indicate that the content referred
+     * by the notification item is a book.
+     */
+    public static final String CONTENT_TYPE_BOOK = "android.contentType.book";
+
+    /**
+     * Value to be used with {@link Builder#setContentTypes} to indicate that the content referred
+     * by the notification item is a comic book.
+     */
+    public static final String CONTENT_TYPE_COMIC = "android.contentType.comic";
+
+    /**
+     * Value to be used with {@link Builder#setContentTypes} to indicate that the content referred
+     * by the notification item is a magazine.
+     */
+    public static final String CONTENT_TYPE_MAGAZINE = "android.contentType.magazine";
+
+    /**
+     * Value to be used with {@link Builder#setContentTypes} to indicate that the content referred
+     * by the notification item is a website.
+     */
+    public static final String CONTENT_TYPE_WEBSITE = "android.contentType.website";
+
+    @StringDef({
+        CONTENT_PRICING_FREE,
+        CONTENT_PRICING_RENTAL,
+        CONTENT_PRICING_PURCHASE,
+        CONTENT_PRICING_PREORDER,
+        CONTENT_PRICING_SUBSCRIPTION,
+    })
+    public @interface ContentPricing {}
+
+    /**
+     * Value to be used with {@link Builder#setPricingInformation} to indicate that the content
+     * referred by the notification item is free to consume.
+     */
+    public static final String CONTENT_PRICING_FREE = "android.contentPrice.free";
+
+    /**
+     * Value to be used with {@link Builder#setPricingInformation} to indicate that the content
+     * referred by the notification item is available as a rental, and the price value provided is
+     * the rental price for the item.
+     */
+    public static final String CONTENT_PRICING_RENTAL = "android.contentPrice.rental";
+
+    /**
+     * Value to be used with {@link Builder#setPricingInformation} to indicate that the content
+     * referred by the notification item is available for purchase, and the price value provided is
+     * the purchase price for the item.
+     */
+    public static final String CONTENT_PRICING_PURCHASE = "android.contentPrice.purchase";
+
+    /**
+     * Value to be used with {@link Builder#setPricingInformation} to indicate that the content
+     * referred by the notification item is available currently as a pre-order, and the price value
+     * provided is the purchase price for the item.
+     */
+    public static final String CONTENT_PRICING_PREORDER = "android.contentPrice.preorder";
+
+    /**
+     * Value to be used with {@link Builder#setPricingInformation} to indicate that the content
+     * referred by the notification item is available as part of a subscription based service, and
+     * the price value provided is the subscription price for the service.
+     */
+    public static final String CONTENT_PRICING_SUBSCRIPTION =
+            "android.contentPrice.subscription";
+
+    @IntDef({
+        CONTENT_STATUS_READY,
+        CONTENT_STATUS_PENDING,
+        CONTENT_STATUS_AVAILABLE,
+        CONTENT_STATUS_UNAVAILABLE,
+    })
+    public @interface ContentStatus {}
+
+    /**
+     * Value to be used with {@link Builder#setStatus} to indicate that the content referred by the
+     * notification is available and ready to be consumed immediately.
+     */
+    public static final int CONTENT_STATUS_READY = 0;
+
+    /**
+     * Value to be used with {@link Builder#setStatus} to indicate that the content referred by the
+     * notification is pending, waiting on either a download or purchase operation to complete
+     * before it can be consumed.
+     */
+    public static final int CONTENT_STATUS_PENDING = 1;
+
+    /**
+     * Value to be used with {@link Builder#setStatus} to indicate that the content referred by the
+     * notification is available, but needs to be first purchased, rented, subscribed or downloaded
+     * before it can be consumed.
+     */
+    public static final int CONTENT_STATUS_AVAILABLE = 2;
+
+    /**
+     * Value to be used with {@link Builder#setStatus} to indicate that the content referred by the
+     * notification is not available. This could be content not available in a certain region or
+     * incompatible with the device in use.
+     */
+    public static final int CONTENT_STATUS_UNAVAILABLE = 3;
+
+    @StringDef({
+        CONTENT_MATURITY_ALL,
+        CONTENT_MATURITY_LOW,
+        CONTENT_MATURITY_MEDIUM,
+        CONTENT_MATURITY_HIGH,
+    })
+    public @interface ContentMaturity {}
+
+    /**
+     * Value to be used with {@link Builder#setMaturityRating} to indicate that the content referred
+     * by the notification is suitable for all audiences.
+     */
+    public static final String CONTENT_MATURITY_ALL = "android.contentMaturity.all";
+
+    /**
+     * Value to be used with {@link Builder#setMaturityRating} to indicate that the content referred
+     * by the notification is suitable for audiences of low maturity and above.
+     */
+    public static final String CONTENT_MATURITY_LOW = "android.contentMaturity.low";
+
+    /**
+     * Value to be used with {@link Builder#setMaturityRating} to indicate that the content referred
+     * by the notification is suitable for audiences of medium maturity and above.
+     */
+    public static final String CONTENT_MATURITY_MEDIUM = "android.contentMaturity.medium";
+
+    /**
+     * Value to be used with {@link Builder#setMaturityRating} to indicate that the content referred
+     * by the notification is suitable for audiences of high maturity and above.
+     */
+    public static final String CONTENT_MATURITY_HIGH = "android.contentMaturity.high";
+
+    @IntDef({
+            INTENT_TYPE_ACTIVITY,
+            INTENT_TYPE_BROADCAST,
+            INTENT_TYPE_SERVICE,
+    })
+    public @interface IntentType {
+    }
+
+    /**
+     * Value to be used with {@link Builder#setContentIntentData} and
+     * {@link Builder#setDismissIntentData} to indicate that a {@link PendingIntent} for an Activity
+     * should be created when posting the recommendation to the HomeScreen.
+     */
+    public static final int INTENT_TYPE_ACTIVITY = 1;
+
+    /**
+     * Value to be used with {@link Builder#setContentIntentData} and
+     * {@link Builder#setDismissIntentData} to indicate that a {@link PendingIntent} for a Broadcast
+     * should be created when posting the recommendation to the HomeScreen.
+     */
+    public static final int INTENT_TYPE_BROADCAST = 2;
+
+    /**
+     * Value to be used with {@link Builder#setContentIntentData} and
+     * {@link Builder#setDismissIntentData} to indicate that a {@link PendingIntent} for a Service
+     * should be created when posting the recommendation to the HomeScreen.
+     */
+    public static final int INTENT_TYPE_SERVICE = 3;
+
+    /**
+     * Object used to encapsulate the data to be used to build the {@link PendingIntent} object
+     * associated with a given content recommendation, at the time this recommendation gets posted
+     * to the home Screen.
+     * <p>
+     * The members of this object correspond to the fields passed into the {@link PendingIntent}
+     * factory methods, when creating a new PendingIntent.
+     */
+    public static class IntentData {
+        int mType;
+        Intent mIntent;
+        int mRequestCode;
+        Bundle mOptions;
+    }
+
+    private final String mIdTag;
+    private final String mTitle;
+    private final String mText;
+    private final String mSourceName;
+    private final Bitmap mContentImage;
+    private final int mBadgeIconId;
+    private final String mBackgroundImageUri;
+    private final int mColor;
+    private final IntentData mContentIntentData;
+    private final IntentData mDismissIntentData;
+    private final String[] mContentTypes;
+    private final String[] mContentGenres;
+    private final String mPriceType;
+    private final String mPriceValue;
+    private final String mMaturityRating;
+    private final long mRunningTime;
+
+    // Mutable fields
+    private String mGroup;
+    private String mSortKey;
+    private int mProgressAmount;
+    private int mProgressMax;
+    private boolean mAutoDismiss;
+    private int mStatus;
+
+    private ContentRecommendation(Builder builder) {
+        mIdTag = builder.mBuilderIdTag;
+        mTitle = builder.mBuilderTitle;
+        mText = builder.mBuilderText;
+        mSourceName = builder.mBuilderSourceName;
+        mContentImage = builder.mBuilderContentImage;
+        mBadgeIconId = builder.mBuilderBadgeIconId;
+        mBackgroundImageUri = builder.mBuilderBackgroundImageUri;
+        mColor = builder.mBuilderColor;
+        mContentIntentData = builder.mBuilderContentIntentData;
+        mDismissIntentData = builder.mBuilderDismissIntentData;
+        mContentTypes = builder.mBuilderContentTypes;
+        mContentGenres = builder.mBuilderContentGenres;
+        mPriceType = builder.mBuilderPriceType;
+        mPriceValue = builder.mBuilderPriceValue;
+        mMaturityRating = builder.mBuilderMaturityRating;
+        mRunningTime = builder.mBuilderRunningTime;
+
+        mGroup = builder.mBuilderGroup;
+        mSortKey = builder.mBuilderSortKey;
+        mProgressAmount = builder.mBuilderProgressAmount;
+        mProgressMax = builder.mBuilderProgressMax;
+        mAutoDismiss = builder.mBuilderAutoDismiss;
+        mStatus = builder.mBuilderStatus;
+    }
+
+    /**
+     * Returns the String Id tag which uniquely identifies this recommendation.
+     *
+     * @return The String Id tag for this recommendation.
+     */
+    public String getIdTag() {
+        return mIdTag;
+    }
+
+    /**
+     * Returns the content title for this recommendation.
+     *
+     * @return A String containing the recommendation content title.
+     */
+    public String getTitle() {
+        return mTitle;
+    }
+
+    /**
+     * Returns the description text for this recommendation.
+     *
+     * @return A String containing the recommendation description text.
+     */
+    public String getText() {
+        return mText;
+    }
+
+    /**
+     * Returns the source application name for this recommendation.
+     *
+     * @return A String containing the recommendation source name.
+     */
+    public String getSourceName() {
+        return mSourceName;
+    }
+
+    /**
+     * Returns the Bitmap containing the recommendation image.
+     *
+     * @return A Bitmap containing the recommendation image.
+     */
+    public Bitmap getContentImage() {
+        return mContentImage;
+    }
+
+    /**
+     * Returns the resource id for the recommendation badging icon.
+     * <p>
+     * The resource id represents the icon resource in the source application package.
+     *
+     * @return An integer id for the badge icon resource.
+     */
+    public int getBadgeImageResourceId() {
+        return mBadgeIconId;
+    }
+
+    /**
+     * Returns a Content URI that can be used to retrieve the background image for this
+     * recommendation.
+     *
+     * @return A Content URI pointing to the recommendation background image.
+     */
+    public String getBackgroundImageUri() {
+        return mBackgroundImageUri;
+    }
+
+    /**
+     * Returns the accent color value to be used in the UI when displaying this content
+     * recommendation to the user.
+     *
+     * @return An integer value representing the accent color for this recommendation.
+     */
+    public int getColor() {
+        return mColor;
+    }
+
+    /**
+     * Sets the String group ID tag for this recommendation.
+     * <p>
+     * Recommendations in the same group are ranked by the Home Screen together, and the sort order
+     * within a group is respected. This can be useful if the application has different sources for
+     * recommendations, like "trending", "subscriptions", and "new music" categories for YouTube,
+     * where the user can be more interested in recommendations from one group than another.
+     *
+     * @param groupTag A String containing the group ID tag for this recommendation.
+     */
+    public void setGroup(String groupTag) {
+        mGroup = groupTag;
+    }
+
+    /**
+     * Returns the String group ID tag for this recommendation.
+     *
+     * @return A String containing the group ID tag for this recommendation.
+     */
+    public String getGroup() {
+        return mGroup;
+    }
+
+    /**
+     * Sets the String sort key for this recommendation.
+     * <p>
+     * The sort key must be a String representation of a float number between 0.0 and 1.0, and is
+     * used to indicate the relative importance (and sort order) of a single recommendation within
+     * its specified group. The recommendations will be ordered in decreasing order of importance
+     * within a given group.
+     *
+     * @param sortKey A String containing the sort key for this recommendation.
+     */
+    public void setSortKey(String sortKey) {
+        mSortKey = sortKey;
+    }
+
+    /**
+     * Returns the String sort key for this recommendation.
+     *
+     * @return A String containing the sort key for this recommendation.
+     */
+    public String getSortKey() {
+        return mSortKey;
+    }
+
+    /**
+     * Sets the progress information for the content pointed to by this recommendation.
+     *
+     * @param max The maximum value for the progress of this content.
+     * @param progress The progress amount for this content. Must be in the range (0 - max).
+     */
+    public void setProgress(int max, int progress) {
+        if (max < 0 || progress < 0) {
+            throw new IllegalArgumentException();
+        }
+        mProgressMax = max;
+        mProgressAmount = progress;
+    }
+
+    /**
+     * Indicates if this recommendation contains valid progress information.
+     *
+     * @return true if the recommendation contains valid progress data, false otherwise.
+     */
+    public boolean hasProgressInfo() {
+        return mProgressMax != 0;
+    }
+
+    /**
+     * Returns the maximum value for the progress data of this recommendation.
+     *
+     * @return An integer representing the maximum progress value.
+     */
+    public int getProgressMax() {
+        return mProgressMax;
+    }
+
+    /**
+     * Returns the progress amount for this recommendation.
+     *
+     * @return An integer representing the recommendation progress amount.
+     */
+    public int getProgressValue() {
+        return mProgressAmount;
+    }
+
+    /**
+     * Sets the flag indicating if this recommendation should be dismissed automatically.
+     * <p>
+     * Auto-dismiss notifications are automatically removed from the Home Screen when the user
+     * clicks on them.
+     *
+     * @param autoDismiss A boolean indicating if the recommendation should be auto dismissed or
+     *            not.
+     */
+    public void setAutoDismiss(boolean autoDismiss) {
+        mAutoDismiss = autoDismiss;
+    }
+
+    /**
+     * Indicates whether this recommendation should be dismissed automatically.
+     * <p>
+     * Auto-dismiss notifications are automatically removed from the Home Screen when the user
+     * clicks on them.
+     *
+     * @return true if the recommendation is marked for auto dismissal, or false otherwise.
+     */
+    public boolean isAutoDismiss() {
+        return mAutoDismiss;
+    }
+
+    /**
+     * Returns the data for the Intent that will be issued when the user clicks on the
+     * recommendation.
+     *
+     * @return An IntentData object, containing the data for the Intent that gets issued when the
+     *         recommendation is clicked on.
+     */
+    public IntentData getContentIntent() {
+        return mContentIntentData;
+    }
+
+    /**
+     * Returns the data for the Intent that will be issued when the recommendation gets dismissed
+     * from the Home Screen, due to an user action.
+     *
+     * @return An IntentData object, containing the data for the Intent that gets issued when the
+     *         recommendation is dismissed from the Home Screen.
+     */
+    public IntentData getDismissIntent() {
+        return mDismissIntentData;
+    }
+
+    /**
+     * Returns an array containing the content types tags that describe the content. The first tag
+     * entry is considered the primary type for the content, and is used for content ranking
+     * purposes.
+     *
+     * @return An array of predefined type tags (see the <code>CONTENT_TYPE_*</code> constants) that
+     *         describe the recommended content.
+     */
+    public String[] getContentTypes() {
+        if (mContentTypes != null) {
+            return Arrays.copyOf(mContentTypes, mContentTypes.length);
+        }
+        return mContentTypes;
+    }
+
+    /**
+     * Returns the primary content type tag for the recommendation, or null if no content types have
+     * been specified.
+     *
+     * @return A predefined type tag (see the <code>CONTENT_TYPE_*</code> constants) indicating the
+     *         primary content type for the recommendation.
+     */
+    public String getPrimaryContentType() {
+        if (mContentTypes != null && mContentTypes.length > 0) {
+            return mContentTypes[0];
+        }
+        return null;
+    }
+
+    /**
+     * Returns an array containing the genres that describe the content. Genres are open ended
+     * String tags.
+     *
+     * @return An array of genre tags that describe the recommended content.
+     */
+    public String[] getGenres() {
+        if (mContentGenres != null) {
+            return Arrays.copyOf(mContentGenres, mContentGenres.length);
+        }
+        return mContentGenres;
+    }
+
+    /**
+     * Gets the pricing type for the content.
+     *
+     * @return A predefined tag indicating the pricing type for the content (see the <code>
+     *         CONTENT_PRICING_*</code> constants).
+     */
+    public String getPricingType() {
+        return mPriceType;
+    }
+
+    /**
+     * Gets the price value (when applicable) for the content. The value will be provided as a
+     * String containing the price in the appropriate currency for the current locale.
+     *
+     * @return A string containing a representation of the content price in the current locale and
+     *         currency.
+     */
+    public String getPricingValue() {
+        return mPriceValue;
+    }
+
+    /**
+     * Sets the availability status value for the content. This status indicates whether the content
+     * is ready to be consumed on the device, or if the user must first purchase, rent, subscribe
+     * to, or download the content.
+     *
+     * @param status The status value for the content. (see the <code>CONTENT_STATUS_*</code> for
+     *            the valid status values).
+     */
+    public void setStatus(@ContentStatus int status) {
+        mStatus = status;
+    }
+
+    /**
+     * Returns availability status value for the content. This status indicates whether the content
+     * is ready to be consumed on the device, or if the user must first purchase, rent, subscribe
+     * to, or download the content.
+     *
+     * @return The status value for the content, or -1 is a valid status has not been specified (see
+     *         the <code>CONTENT_STATUS_*</code> constants for the valid status values).
+     */
+    public int getStatus() {
+        return mStatus;
+    }
+
+    /**
+     * Returns the maturity level rating for the content.
+     *
+     * @return returns a predefined tag indicating the maturity level rating for the content (see
+     *         the <code>CONTENT_MATURITY_*</code> constants).
+     */
+    public String getMaturityRating() {
+        return mMaturityRating;
+    }
+
+    /**
+     * Returns the running time for the content.
+     *
+     * @return The run length, in seconds, of the content associated with the notification.
+     */
+    public long getRunningTime() {
+        return mRunningTime;
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (other instanceof ContentRecommendation) {
+            return TextUtils.equals(mIdTag, ((ContentRecommendation) other).getIdTag());
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        if (mIdTag != null) {
+            return mIdTag.hashCode();
+        }
+        return Integer.MAX_VALUE;
+    }
+
+    /**
+     * Builder class for {@link ContentRecommendation} objects. Provides a convenient way to set the
+     * various fields of a {@link ContentRecommendation}.
+     * <p>
+     * Example:
+     *
+     * <pre class="prettyprint">
+     * ContentRecommendation rec = new ContentRecommendation.Builder()
+     *         .setIdInfo(id, &quot;MyTagId&quot;)
+     *         .setTitle(&quot;My Content Recommendation&quot;)
+     *         .setText(&quot;An example of content recommendation&quot;)
+     *         .setContentImage(myBitmap)
+     *         .setBadgeIcon(R.drawable.app_icon)
+     *         .setGroup(&quot;Trending&quot;)
+     *         .build();
+     * </pre>
+     */
+    public static final class Builder {
+        private String mBuilderIdTag;
+        private String mBuilderTitle;
+        private String mBuilderText;
+        private String mBuilderSourceName;
+        private Bitmap mBuilderContentImage;
+        private int mBuilderBadgeIconId;
+        private String mBuilderBackgroundImageUri;
+        private int mBuilderColor;
+        private String mBuilderGroup;
+        private String mBuilderSortKey;
+        private int mBuilderProgressAmount;
+        private int mBuilderProgressMax;
+        private boolean mBuilderAutoDismiss;
+        private IntentData mBuilderContentIntentData;
+        private IntentData mBuilderDismissIntentData;
+        private String[] mBuilderContentTypes;
+        private String[] mBuilderContentGenres;
+        private String mBuilderPriceType;
+        private String mBuilderPriceValue;
+        private int mBuilderStatus;
+        private String mBuilderMaturityRating;
+        private long mBuilderRunningTime;
+
+        /**
+         * Constructs a new Builder.
+         *
+         */
+        public Builder() {
+        }
+
+        /**
+         * Sets the Id tag that uniquely identifies this recommendation object.
+         *
+         * @param idTag A String tag identifier for this recommendation.
+         * @return The Builder object, for chaining.
+         */
+        public Builder setIdTag(String idTag) {
+            mBuilderIdTag = checkNotNull(idTag);
+            return this;
+        }
+
+        /**
+         * Sets the content title for the recommendation.
+         *
+         * @param title A String containing the recommendation content title.
+         * @return The Builder object, for chaining.
+         */
+        public Builder setTitle(String title) {
+            mBuilderTitle = checkNotNull(title);
+            return this;
+        }
+
+        /**
+         * Sets the description text for the recommendation.
+         *
+         * @param description A String containing the recommendation description text.
+         * @return The Builder object, for chaining.
+         */
+        public Builder setText(@Nullable String description) {
+            mBuilderText = description;
+            return this;
+        }
+
+        /**
+         * Sets the source application name for the recommendation.
+         * <P>
+         * If the source name is never set, or set to null, the application name retrieved from its
+         * package will be used by default.
+         *
+         * @param source A String containing the recommendation source name.
+         * @return The Builder object, for chaining.
+         */
+        public Builder setSourceName(@Nullable String source) {
+            mBuilderSourceName = source;
+            return this;
+        }
+
+        /**
+         * Sets the recommendation image.
+         *
+         * @param image A Bitmap containing the recommendation image.
+         * @return The Builder object, for chaining.
+         */
+        public Builder setContentImage(Bitmap image) {
+            mBuilderContentImage = checkNotNull(image);
+            return this;
+        }
+
+        /**
+         * Sets the resource ID for the recommendation badging icon.
+         * <p>
+         * The resource id represents the icon resource in the source application package. If not
+         * set, or an invalid resource ID is specified, the application icon retrieved from its
+         * package will be used by default.
+         *
+         * @param iconResourceId An integer id for the badge icon resource.
+         * @return The Builder object, for chaining.
+         */
+        public Builder setBadgeIcon(int iconResourceId) {
+            mBuilderBadgeIconId = iconResourceId;
+            return this;
+        }
+
+        /**
+         * Sets the Content URI that will be used to retrieve the background image for the
+         * recommendation.
+         *
+         * @param imageUri A Content URI pointing to the recommendation background image.
+         * @return The Builder object, for chaining.
+         */
+        public Builder setBackgroundImageUri(@Nullable String imageUri) {
+            mBuilderBackgroundImageUri = imageUri;
+            return this;
+        }
+
+        /**
+         * Sets the accent color value to be used in the UI when displaying this content
+         * recommendation to the user.
+         *
+         * @param color An integer value representing the accent color for this recommendation.
+         * @return The Builder object, for chaining.
+         */
+        public Builder setColor(int color) {
+            mBuilderColor = color;
+            return this;
+        }
+
+        /**
+         * Sets the String group ID tag for the recommendation.
+         * <p>
+         * Recommendations in the same group are ranked by the Home Screen together, and the sort
+         * order within a group is respected. This can be useful if the application has different
+         * sources for recommendations, like "trending", "subscriptions", and "new music" categories
+         * for YouTube, where the user can be more interested in recommendations from one group than
+         * another.
+         *
+         * @param groupTag A String containing the group ID tag for this recommendation.
+         * @return The Builder object, for chaining.
+         */
+        public Builder setGroup(@Nullable String groupTag) {
+            mBuilderGroup = groupTag;
+            return this;
+        }
+
+        /**
+         * Sets the String sort key for the recommendation.
+         * <p>
+         * The sort key must be a String representation of a float number between 0.0 and 1.0, and
+         * is used to indicate the relative importance (and sort order) of a single recommendation
+         * within its specified group. The recommendations will be ordered in decreasing order of
+         * importance within a given group.
+         *
+         * @param sortKey A String containing the sort key for this recommendation.
+         * @return The Builder object, for chaining.
+         */
+        public Builder setSortKey(@Nullable String sortKey) {
+            mBuilderSortKey = sortKey;
+            return this;
+        }
+
+        /**
+         * Sets the progress information for the content pointed to by the recommendation.
+         *
+         * @param max The maximum value for the progress of this content.
+         * @param progress The progress amount for this content. Must be in the range (0 - max).
+         * @return The Builder object, for chaining.
+         */
+        public Builder setProgress(int max, int progress) {
+            if (max < 0 || progress < 0) {
+                throw new IllegalArgumentException();
+            }
+            mBuilderProgressMax = max;
+            mBuilderProgressAmount = progress;
+            return this;
+        }
+
+        /**
+         * Sets the flag indicating if the recommendation should be dismissed automatically.
+         * <p>
+         * Auto-dismiss notifications are automatically removed from the Home Screen when the user
+         * clicks on them.
+         *
+         * @param autoDismiss A boolean indicating if the recommendation should be auto dismissed or
+         *            not.
+         * @return The Builder object, for chaining.
+         */
+        public Builder setAutoDismiss(boolean autoDismiss) {
+            mBuilderAutoDismiss = autoDismiss;
+            return this;
+        }
+
+        /**
+         * Sets the data for the Intent that will be issued when the user clicks on the
+         * recommendation.
+         * <p>
+         * The Intent data fields provided correspond to the fields passed into the
+         * {@link PendingIntent} factory methods, when creating a new PendingIntent. The actual
+         * PengindIntent object will only be created at the time a recommendation is posted to the
+         * Home Screen.
+         *
+         * @param intentType The type of {@link PendingIntent} to be created when posting this
+         *            recommendation.
+         * @param intent The Intent which to be issued when the recommendation is clicked on.
+         * @param requestCode The private request code to be used when creating the
+         *            {@link PendingIntent}
+         * @param options Only used for the Activity Intent type. Additional options for how the
+         *            Activity should be started. May be null if there are no options.
+         * @return The Builder object, for chaining.
+         */
+        public Builder setContentIntentData(@IntentType int intentType, Intent intent,
+                int requestCode, @Nullable Bundle options) {
+            if (intentType != INTENT_TYPE_ACTIVITY &&
+                    intentType != INTENT_TYPE_BROADCAST &&
+                    intentType != INTENT_TYPE_SERVICE) {
+                throw new IllegalArgumentException("Invalid Intent type specified.");
+            }
+
+            mBuilderContentIntentData = new IntentData();
+            mBuilderContentIntentData.mType = intentType;
+            mBuilderContentIntentData.mIntent = checkNotNull(intent);
+            mBuilderContentIntentData.mRequestCode = requestCode;
+            mBuilderContentIntentData.mOptions = options;
+
+            return this;
+        }
+
+        /**
+         * Sets the data for the Intent that will be issued when the recommendation gets dismissed
+         * from the Home Screen, due to an user action.
+         * <p>
+         * The Intent data fields provided correspond to the fields passed into the
+         * {@link PendingIntent} factory methods, when creating a new PendingIntent. The actual
+         * PengindIntent object will only be created at the time a recommendation is posted to the
+         * Home Screen.
+         *
+         * @param intentType The type of {@link PendingIntent} to be created when posting this
+         *            recommendation.
+         * @param intent The Intent which gets issued when the recommendation is dismissed from the
+         *            Home Screen.
+         * @param requestCode The private request code to be used when creating the
+         *            {@link PendingIntent}
+         * @param options Only used for the Activity Intent type. Additional options for how the
+         *            Activity should be started. May be null if there are no options.
+         * @return The Builder object, for chaining.
+         */
+        public Builder setDismissIntentData(@IntentType int intentType, @Nullable Intent intent,
+                int requestCode, @Nullable Bundle options) {
+            if (intent != null) {
+                if (intentType != INTENT_TYPE_ACTIVITY &&
+                        intentType != INTENT_TYPE_BROADCAST &&
+                        intentType != INTENT_TYPE_SERVICE) {
+                    throw new IllegalArgumentException("Invalid Intent type specified.");
+                }
+
+                mBuilderDismissIntentData = new IntentData();
+                mBuilderDismissIntentData.mType = intentType;
+                mBuilderDismissIntentData.mIntent = intent;
+                mBuilderDismissIntentData.mRequestCode = requestCode;
+                mBuilderDismissIntentData.mOptions = options;
+            } else {
+                mBuilderDismissIntentData = null;
+            }
+            return this;
+        }
+
+        /**
+         * Sets the content types associated with the content recommendation. The first tag entry
+         * will be considered the primary type for the content and will be used for ranking
+         * purposes. Other secondary type tags may be provided, if applicable, and may be used for
+         * filtering purposes.
+         *
+         * @param types Array of predefined type tags (see the <code>CONTENT_TYPE_*</code>
+         *            constants) that describe the recommended content.
+         */
+        public Builder setContentTypes(String[] types) {
+            mBuilderContentTypes = checkNotNull(types);
+            return this;
+        }
+
+        /**
+         * Sets the content genres for the recommendation. These genres may be used for content
+         * ranking. Genres are open ended String tags.
+         * <p>
+         * Some examples: "comedy", "action", "dance", "electronica", "racing", etc.
+         *
+         * @param genres Array of genre string tags that describe the recommended content.
+         */
+        public Builder setGenres(String[] genres) {
+            mBuilderContentGenres = genres;
+            return this;
+        }
+
+        /**
+         * Sets the pricing and availability information for the recommendation. The provided
+         * information will indicate the access model for the content (free, rental, purchase or
+         * subscription) and the price value (if not free).
+         *
+         * @param priceType Pricing type for this content. Must be one of the predefined pricing
+         *            type tags (see the <code>CONTENT_PRICING_*</code> constants).
+         * @param priceValue A string containing a representation of the content price in the
+         *            current locale and currency.
+         */
+        public Builder setPricingInformation(@ContentPricing String priceType,
+                @Nullable String priceValue) {
+            mBuilderPriceType = checkNotNull(priceType);
+            mBuilderPriceValue = priceValue;
+            return this;
+        }
+
+        /**
+         * Sets the availability status for the content. This status indicates whether the referred
+         * content is ready to be consumed on the device, or if the user must first purchase, rent,
+         * subscribe to, or download the content.
+         *
+         * @param contentStatus The status value for this content. Must be one of the predefined
+         *            content status values (see the <code>CONTENT_STATUS_*</code> constants).
+         */
+        public Builder setStatus(@ContentStatus int contentStatus) {
+            mBuilderStatus = contentStatus;
+            return this;
+        }
+
+        /**
+         * Sets the maturity level rating for the content.
+         *
+         * @param maturityRating A tag indicating the maturity level rating for the content. This
+         *            tag must be one of the predefined maturity rating tags (see the <code>
+         *            CONTENT_MATURITY_*</code> constants).
+         */
+        public Builder setMaturityRating(@ContentMaturity String maturityRating) {
+            mBuilderMaturityRating = checkNotNull(maturityRating);
+            return this;
+        }
+
+        /**
+         * Sets the running time (when applicable) for the content.
+         *
+         * @param length The running time, in seconds, of the content.
+         */
+        public Builder setRunningTime(long length) {
+            if (length < 0) {
+                throw new IllegalArgumentException();
+            }
+            mBuilderRunningTime = length;
+            return this;
+        }
+
+        /**
+         * Combine all of the options that have been set and return a new
+         * {@link ContentRecommendation} object.
+         */
+        public ContentRecommendation build() {
+            return new ContentRecommendation(this);
+        }
+    }
+
+    /**
+     * Returns a {@link android.app.Notification Notification} object which contains the content
+     * recommendation data encapsulated by this object, which can be used for posting the
+     * recommendation via the {@link android.app.NotificationManager NotificationManager}.
+     *
+     * @param context A {@link Context} that will be used to construct the
+     *            {@link android.app.Notification Notification} object which will carry the
+     *            recommendation data.
+     * @return A {@link android.app.Notification Notification} containing the stored recommendation
+     *         data.
+     */
+    public Notification getNotificationObject(Context context) {
+        Notification.Builder builder = new Notification.Builder(context);
+        RecommendationExtender recExtender = new RecommendationExtender();
+
+        // Encode all the content recommendation data in a Notification object
+
+        builder.setCategory(Notification.CATEGORY_RECOMMENDATION);
+        builder.setContentTitle(mTitle);
+        builder.setContentText(mText);
+        builder.setContentInfo(mSourceName);
+        builder.setLargeIcon(mContentImage);
+        builder.setSmallIcon(mBadgeIconId);
+        if (mBackgroundImageUri != null) {
+            builder.getExtras().putString(Notification.EXTRA_BACKGROUND_IMAGE_URI,
+                    mBackgroundImageUri);
+        }
+        builder.setColor(mColor);
+        builder.setGroup(mGroup);
+        builder.setSortKey(mSortKey);
+        builder.setProgress(mProgressMax, mProgressAmount, false);
+        builder.setAutoCancel(mAutoDismiss);
+
+        if (mContentIntentData != null) {
+            PendingIntent contentPending;
+            if (mContentIntentData.mType == INTENT_TYPE_ACTIVITY) {
+                contentPending = PendingIntent.getActivity(context, mContentIntentData.mRequestCode,
+                        mContentIntentData.mIntent, PendingIntent.FLAG_UPDATE_CURRENT,
+                        mContentIntentData.mOptions);
+            } else if (mContentIntentData.mType == INTENT_TYPE_SERVICE) {
+                contentPending = PendingIntent.getService(context, mContentIntentData.mRequestCode,
+                        mContentIntentData.mIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+            } else { // Default:INTENT_TYPE_BROADCAST{
+                contentPending = PendingIntent.getBroadcast(context,
+                        mContentIntentData.mRequestCode,
+                        mContentIntentData.mIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+            }
+            builder.setContentIntent(contentPending);
+        }
+
+        if (mDismissIntentData != null) {
+            PendingIntent dismissPending;
+            if (mDismissIntentData.mType == INTENT_TYPE_ACTIVITY) {
+                dismissPending = PendingIntent.getActivity(context, mDismissIntentData.mRequestCode,
+                        mDismissIntentData.mIntent, PendingIntent.FLAG_UPDATE_CURRENT,
+                        mDismissIntentData.mOptions);
+            } else if (mDismissIntentData.mType == INTENT_TYPE_SERVICE) {
+                dismissPending = PendingIntent.getService(context, mDismissIntentData.mRequestCode,
+                        mDismissIntentData.mIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+            } else { // Default:INTENT_TYPE_BROADCAST{
+                dismissPending = PendingIntent.getBroadcast(context,
+                        mDismissIntentData.mRequestCode,
+                        mDismissIntentData.mIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+            }
+            builder.setDeleteIntent(dismissPending);
+        }
+
+        recExtender.setContentTypes(mContentTypes);
+        recExtender.setGenres(mContentGenres);
+        recExtender.setPricingInformation(mPriceType, mPriceValue);
+        recExtender.setStatus(mStatus);
+        recExtender.setMaturityRating(mMaturityRating);
+        recExtender.setRunningTime(mRunningTime);
+
+        builder.extend(recExtender);
+        Notification notif = builder.build();
+        return notif;
+    }
+
+    /**
+     * Ensures that an object reference passed as a parameter to the calling method is not null.
+     *
+     * @param reference an object reference
+     * @return the non-null reference that was validated
+     * @throws NullPointerException if {@code reference} is null
+     */
+    private static <T> T checkNotNull(final T reference) {
+        if (reference == null) {
+            throw new NullPointerException();
+        }
+        return reference;
+    }
+
+}
\ No newline at end of file
diff --git a/recommendation/src/android/support/app/recommendation/RecommendationExtender.java b/recommendation/src/android/support/app/recommendation/RecommendationExtender.java
new file mode 100644
index 0000000..5762a28
--- /dev/null
+++ b/recommendation/src/android/support/app/recommendation/RecommendationExtender.java
@@ -0,0 +1,315 @@
+/*
+ * 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.app.recommendation;
+
+import android.app.Notification;
+import android.os.Bundle;
+
+/**
+ * <p>
+ * Helper class to add content info extensions to notifications. To create a notification with
+ * content info extensions:
+ * <ol>
+ * <li>Create an {@link Notification.Builder}, setting any desired properties.
+ * <li>Create a {@link RecommendationExtender}.
+ * <li>Set content info specific properties using the {@code add} and {@code set} methods of
+ * {@link RecommendationExtender}.
+ * <li>Call {@link android.app.Notification.Builder#extend(Notification.Extender) 
+ * Notification.Builder.extend(Notification.Extender)} to apply the extensions to a notification.
+ * </ol>
+ *
+ * <pre class="prettyprint">Notification notification = new Notification.Builder(context) * ... * .extend(new RecommendationExtender() * .set*(...)) * .build(); * </pre>
+ * <p>
+ * Content info extensions can be accessed on an existing notification by using the
+ * {@code RecommendationExtender(Notification)} constructor, and then using the {@code get} methods
+ * to access values.
+ */
+public final class RecommendationExtender implements Notification.Extender {
+    private static final String TAG = "RecommendationExtender";
+
+    // Key for the Content info extensions bundle in the main Notification extras bundle
+    private static final String EXTRA_CONTENT_INFO_EXTENDER = "android.CONTENT_INFO_EXTENSIONS";
+
+    // Keys within EXTRA_CONTENT_INFO_EXTENDER for individual content info options.
+
+    private static final String KEY_CONTENT_TYPE = "android.contentType";
+
+    private static final String KEY_CONTENT_GENRES = "android.contentGenre";
+
+    private static final String KEY_CONTENT_PRICING_TYPE = "android.contentPricing.type";
+
+    private static final String KEY_CONTENT_PRICING_VALUE = "android.contentPricing.value";
+
+    private static final String KEY_CONTENT_STATUS = "android.contentStatus";
+
+    private static final String KEY_CONTENT_MATURITY_RATING = "android.contentMaturity";
+
+    private static final String KEY_CONTENT_RUN_LENGTH = "android.contentLength";
+
+    private String[] mTypes;
+    private String[] mGenres;
+    private String mPricingType;
+    private String mPricingValue;
+    private int mContentStatus = -1;
+    private String mMaturityRating;
+    private long mRunLength = -1;
+
+    /**
+     * Create a {@link RecommendationExtender} with default options.
+     */
+    public RecommendationExtender() {
+    }
+
+    /**
+     * Create a {@link RecommendationExtender} from the RecommendationExtender options of an
+     * existing Notification.
+     *
+     * @param notif The notification from which to copy options.
+     */
+    public RecommendationExtender(Notification notif) {
+        Bundle contentBundle = notif.extras == null ?
+                null : notif.extras.getBundle(EXTRA_CONTENT_INFO_EXTENDER);
+        if (contentBundle != null) {
+            mTypes = contentBundle.getStringArray(KEY_CONTENT_TYPE);
+            mGenres = contentBundle.getStringArray(KEY_CONTENT_GENRES);
+            mPricingType = contentBundle.getString(KEY_CONTENT_PRICING_TYPE);
+            mPricingValue = contentBundle.getString(KEY_CONTENT_PRICING_VALUE);
+            mContentStatus = contentBundle.getInt(KEY_CONTENT_STATUS, -1);
+            mMaturityRating = contentBundle.getString(KEY_CONTENT_MATURITY_RATING);
+            mRunLength = contentBundle.getLong(KEY_CONTENT_RUN_LENGTH, -1);
+        }
+    }
+
+    /**
+     * Apply content extensions to a notification that is being built. This is typically called by
+     * the {@link android.app.Notification.Builder#extend(Notification.Extender) 
+     * Notification.Builder.extend(Notification.Extender)} method of {@link Notification.Builder}.
+     */
+    @Override
+    public Notification.Builder extend(Notification.Builder builder) {
+        Bundle contentBundle = new Bundle();
+
+        if (mTypes != null) {
+            contentBundle.putStringArray(KEY_CONTENT_TYPE, mTypes);
+        }
+        if (mGenres != null) {
+            contentBundle.putStringArray(KEY_CONTENT_GENRES, mGenres);
+        }
+        if (mPricingType != null) {
+            contentBundle.putString(KEY_CONTENT_PRICING_TYPE, mPricingType);
+        }
+        if (mPricingValue != null) {
+            contentBundle.putString(KEY_CONTENT_PRICING_VALUE, mPricingValue);
+        }
+        if (mContentStatus != -1) {
+            contentBundle.putInt(KEY_CONTENT_STATUS, mContentStatus);
+        }
+        if (mMaturityRating != null) {
+            contentBundle.putString(KEY_CONTENT_MATURITY_RATING, mMaturityRating);
+        }
+        if (mRunLength > 0) {
+            contentBundle.putLong(KEY_CONTENT_RUN_LENGTH, mRunLength);
+        }
+
+        builder.getExtras().putBundle(EXTRA_CONTENT_INFO_EXTENDER, contentBundle);
+        return builder;
+    }
+
+    /**
+     * Sets the content types associated with the notification content. The first tag entry will be
+     * considered the primary type for the content and will be used for ranking purposes. Other
+     * secondary type tags may be provided, if applicable, and may be used for filtering purposes.
+     *
+     * @param types Array of predefined type tags (see the <code>CONTENT_TYPE_*</code> constants)
+     *            that describe the content referred to by a notification.
+     */
+    public RecommendationExtender setContentTypes(String[] types) {
+        mTypes = types;
+        return this;
+    }
+
+    /**
+     * Returns an array containing the content types that describe the content associated with the
+     * notification. The first tag entry is considered the primary type for the content, and is used
+     * for content ranking purposes.
+     *
+     * @return An array of predefined type tags (see the <code>CONTENT_TYPE_*</code> constants) that
+     *         describe the content associated with the notification.
+     * @see RecommendationExtender#setContentTypes
+     */
+    public String[] getContentTypes() {
+        return mTypes;
+    }
+
+    /**
+     * Returns the primary content type tag for the content associated with the notification.
+     *
+     * @return A predefined type tag (see the <code>CONTENT_TYPE_*</code> constants) indicating the
+     *         primary type for the content associated with the notification.
+     * @see RecommendationExtender#setContentTypes
+     */
+    public String getPrimaryContentType() {
+        if (mTypes == null || mTypes.length == 0) {
+            return null;
+        }
+        return mTypes[0];
+    }
+
+    /**
+     * Sets the content genres associated with the notification content. These genres may be used
+     * for content ranking. Genres are open ended String tags.
+     * <p>
+     * Some examples: "comedy", "action", "dance", "electronica", "racing", etc.
+     *
+     * @param genres Array of genre string tags that describe the content referred to by a
+     *            notification.
+     */
+    public RecommendationExtender setGenres(String[] genres) {
+        mGenres = genres;
+        return this;
+    }
+
+    /**
+     * Returns an array containing the content genres that describe the content associated with the
+     * notification.
+     *
+     * @return An array of genre tags that describe the content associated with the notification.
+     * @see RecommendationExtender#setGenres
+     */
+    public String[] getGenres() {
+        return mGenres;
+    }
+
+    /**
+     * Sets the pricing and availability information for the content associated with the
+     * notification. The provided information will indicate the access model for the content (free,
+     * rental, purchase or subscription) and the price value (if not free).
+     *
+     * @param priceType Pricing type for this content. Must be one of the predefined pricing type
+     *            tags (see the <code>CONTENT_PRICING_*</code> constants).
+     * @param priceValue A string containing a representation of the content price in the current
+     *            locale and currency.
+     * @return This object for method chaining.
+     */
+    public RecommendationExtender setPricingInformation(
+            @ContentRecommendation.ContentPricing String priceType, String priceValue) {
+        mPricingType = priceType;
+        mPricingValue = priceValue;
+        return this;
+    }
+
+    /**
+     * Gets the pricing type for the content associated with the notification.
+     *
+     * @return A predefined tag indicating the pricing type for the content (see the <code> CONTENT_PRICING_*</code>
+     *         constants).
+     * @see RecommendationExtender#setPricingInformation
+     */
+    public String getPricingType() {
+        return mPricingType;
+    }
+
+    /**
+     * Gets the price value (when applicable) for the content associated with a notification. The
+     * value will be provided as a String containing the price in the appropriate currency for the
+     * current locale.
+     *
+     * @return A string containing a representation of the content price in the current locale and
+     *         currency.
+     * @see RecommendationExtender#setPricingInformation
+     */
+    public String getPricingValue() {
+        if (mPricingType == null) {
+            return null;
+        }
+        return mPricingValue;
+    }
+
+    /**
+     * Sets the availability status for the content associated with the notification. This status
+     * indicates whether the referred content is ready to be consumed on the device, or if the user
+     * must first purchase, rent, subscribe to, or download the content.
+     *
+     * @param contentStatus The status value for this content. Must be one of the predefined content
+     *            status values (see the <code>CONTENT_STATUS_*</code> constants).
+     */
+    public RecommendationExtender setStatus(
+            @ContentRecommendation.ContentStatus int contentStatus) {
+        mContentStatus = contentStatus;
+        return this;
+    }
+
+    /**
+     * Returns status value for the content associated with the notification. This status indicates
+     * whether the referred content is ready to be consumed on the device, or if the user must first
+     * purchase, rent, subscribe to, or download the content.
+     *
+     * @return The status value for this content, or -1 is a valid status has not been specified
+     *         (see the <code>CONTENT_STATUS_*</code> for the defined valid status values).
+     * @see RecommendationExtender#setStatus
+     */
+    public int getStatus() {
+        return mContentStatus;
+    }
+
+    /**
+     * Sets the maturity level rating for the content associated with the notification.
+     *
+     * @param maturityRating A tag indicating the maturity level rating for the content. This tag
+     *            must be one of the predefined maturity rating tags (see the <code> CONTENT_MATURITY_*</code>
+     *            constants).
+     */
+    public RecommendationExtender setMaturityRating(
+            @ContentRecommendation.ContentMaturity String maturityRating) {
+        mMaturityRating = maturityRating;
+        return this;
+    }
+
+    /**
+     * Returns the maturity level rating for the content associated with the notification.
+     *
+     * @return returns a predefined tag indicating the maturity level rating for the content (see
+     *         the <code>CONTENT_MATURITY_*</code> constants).
+     * @see RecommendationExtender#setMaturityRating
+     */
+    public String getMaturityRating() {
+        return mMaturityRating;
+    }
+
+    /**
+     * Sets the running time (when applicable) for the content associated with the notification.
+     *
+     * @param length The runing time, in seconds, of the content associated with the notification.
+     */
+    public RecommendationExtender setRunningTime(long length) {
+        if (length < 0) {
+            throw new IllegalArgumentException("Invalid value for Running Time");
+        }
+        mRunLength = length;
+        return this;
+    }
+
+    /**
+     * Returns the running time for the content associated with the notification.
+     *
+     * @return The running time, in seconds, of the content associated with the notification.
+     * @see RecommendationExtender#setRunningTime
+     */
+    public long getRunningTime() {
+        return mRunLength;
+    }
+}
diff --git a/settings.gradle b/settings.gradle
index ce5bf86..85c9ae1 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -22,6 +22,15 @@
 include ':support-cardview-v7'
 project(':support-cardview-v7').projectDir = new File(rootDir, 'v7/cardview')
 
+include ':support-preference-v7'
+project(':support-preference-v7').projectDir = new File(rootDir, 'v7/preference')
+
+include ':support-preference-v14'
+project(':support-preference-v14').projectDir = new File(rootDir, 'v14/preference')
+
+include ':support-preference-leanback-v17'
+project(':support-preference-leanback-v17').projectDir = new File(rootDir, 'v17/preference-leanback')
+
 include ':support-v13'
 project(':support-v13').projectDir = new File(rootDir, 'v13')
 
diff --git a/tests/java/android/support/v4/text/IcuCompatTest.java b/tests/java/android/support/v4/text/IcuCompatTest.java
new file mode 100644
index 0000000..6f7f459
--- /dev/null
+++ b/tests/java/android/support/v4/text/IcuCompatTest.java
@@ -0,0 +1,28 @@
+/*
+ * 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.v4.text;
+
+import junit.framework.TestCase;
+
+import java.util.Locale;
+
+public class IcuCompatTest extends TestCase {
+    public void testMaximizeAndGetScript() {
+        assertEquals("Latn", ICUCompat.maximizeAndGetScript(new Locale("en", "US")));
+        assertEquals("Visp", ICUCompat.maximizeAndGetScript(Locale.forLanguageTag("en-Visp-US")));
+    }
+}
diff --git a/v13/Android.mk b/v13/Android.mk
index e5a137b..c61b112 100644
--- a/v13/Android.mk
+++ b/v13/Android.mk
@@ -32,6 +32,14 @@
 LOCAL_STATIC_JAVA_LIBRARIES := android-support-v13-ics
 include $(BUILD_STATIC_JAVA_LIBRARY)
 
+# A helper sub-library that makes direct use of MNC APIs.
+include $(CLEAR_VARS)
+LOCAL_MODULE := android-support-v13-mnc
+LOCAL_SDK_VERSION := current
+LOCAL_SRC_FILES := $(call all-java-files-under, api23)
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-v13-ics-mr1
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
 # -----------------------------------------------------------------------
 
 include $(CLEAR_VARS)
@@ -39,7 +47,8 @@
 LOCAL_SDK_VERSION := 13
 LOCAL_SRC_FILES := $(call all-java-files-under, java)
 LOCAL_STATIC_JAVA_LIBRARIES += android-support-v4 \
-        android-support-v13-ics-mr1
+        android-support-v13-ics-mr1 \
+        android-support-v13-mnc
 include $(BUILD_STATIC_JAVA_LIBRARY)
 
 
diff --git a/v13/api/current.txt b/v13/api/current.txt
index 6b070c5..36ea6c0 100644
--- a/v13/api/current.txt
+++ b/v13/api/current.txt
@@ -2,8 +2,14 @@
 
   public class FragmentCompat {
     ctor public FragmentCompat();
+    method public static void requestPermissions(android.app.Fragment, java.lang.String[], int);
     method public static void setMenuVisibility(android.app.Fragment, boolean);
     method public static void setUserVisibleHint(android.app.Fragment, boolean);
+    method public static boolean shouldShowRequestPermissionRationale(android.app.Fragment, java.lang.String);
+  }
+
+  public static abstract interface FragmentCompat.OnRequestPermissionsResultCallback {
+    method public abstract void onRequestPermissionsResult(int, java.lang.String[], int[]);
   }
 
   public abstract class FragmentPagerAdapter extends android.support.v4.view.PagerAdapter {
diff --git a/v13/api23/android/support/v13/app/FragmentCompat23.java b/v13/api23/android/support/v13/app/FragmentCompat23.java
new file mode 100644
index 0000000..5027240
--- /dev/null
+++ b/v13/api23/android/support/v13/app/FragmentCompat23.java
@@ -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.
+ */
+
+package android.support.v13.app;
+
+import android.app.Fragment;
+
+class FragmentCompat23 {
+    public static void requestPermissions(Fragment fragment, String[] permissions,
+            int requestCode) {
+        fragment.requestPermissions(permissions, requestCode);
+    }
+
+    public static boolean shouldShowRequestPermissionRationale(Fragment fragment,
+            String permission) {
+        return fragment.shouldShowRequestPermissionRationale(permission);
+    }
+}
diff --git a/v13/build.gradle b/v13/build.gradle
index d0eb43e..c1e624b 100644
--- a/v13/build.gradle
+++ b/v13/build.gradle
@@ -9,8 +9,9 @@
 
 ext.allSS = []
 
-def icsSS          = createApiSourceset('ics',          'ics',           '14',      null)
-def icsMr1SS       = createApiSourceset('icsmr1',       'ics-mr1',       '15',      icsSS)
+def icsSS          = createApiSourceset('ics',          'ics',         '14',       null)
+def icsMr1SS       = createApiSourceset('icsmr1',       'ics-mr1',     '15',       icsSS)
+def api23SS        = createApiSourceset('api23',        'api23',       'current',  icsMr1SS)
 
 def createApiSourceset(String name, String folder, String apiLevel, SourceSet previousSource) {
     def sourceSet = sourceSets.create(name)
diff --git a/v13/java/android/support/v13/app/FragmentCompat.java b/v13/java/android/support/v13/app/FragmentCompat.java
index eec3ea5..745bf91 100644
--- a/v13/java/android/support/v13/app/FragmentCompat.java
+++ b/v13/java/android/support/v13/app/FragmentCompat.java
@@ -17,6 +17,13 @@
 package android.support.v13.app;
 
 import android.app.Fragment;
+import android.content.pm.PackageManager;
+import android.os.Build;
+import android.os.Handler;
+import android.os.Looper;
+import android.support.annotation.NonNull;
+
+import java.util.Arrays;
 
 /**
  * Helper for accessing features in {@link Fragment} introduced after
@@ -26,6 +33,8 @@
     interface FragmentCompatImpl {
         void setMenuVisibility(Fragment f, boolean visible);
         void setUserVisibleHint(Fragment f, boolean deferStart);
+        void requestPermissions(Fragment fragment, String[] permissions, int requestCode);
+        boolean shouldShowRequestPermissionRationale(Fragment fragment, String permission);
     }
 
     static class BaseFragmentCompatImpl implements FragmentCompatImpl {
@@ -33,6 +42,22 @@
         }
         public void setUserVisibleHint(Fragment f, boolean deferStart) {
         }
+        public void requestPermissions(final Fragment fragment, final String[] permissions,
+                final int requestCode) {
+            Handler handler = new Handler(Looper.getMainLooper());
+            handler.post(new Runnable() {
+                @Override
+                public void run() {
+                    final int[] grantResults = new int[permissions.length];
+                    Arrays.fill(grantResults, PackageManager.PERMISSION_GRANTED);
+                    ((OnRequestPermissionsResultCallback) fragment).onRequestPermissionsResult(
+                            requestCode, permissions, grantResults);
+                }
+            });
+        }
+        public boolean shouldShowRequestPermissionRationale(Fragment fragment, String permission) {
+            return false;
+        }
     }
  
     static class ICSFragmentCompatImpl extends BaseFragmentCompatImpl {
@@ -49,9 +74,24 @@
         }
     }
 
+    static class MncFragmentCompatImpl extends ICSMR1FragmentCompatImpl {
+        @Override
+        public void requestPermissions(Fragment fragment, String[] permissions, int requestCode) {
+            FragmentCompat23.requestPermissions(fragment, permissions, requestCode);
+        }
+
+        @Override
+        public boolean shouldShowRequestPermissionRationale(Fragment fragment, String permission) {
+            return FragmentCompat23.shouldShowRequestPermissionRationale(fragment, permission);
+        }
+    }
+
     static final FragmentCompatImpl IMPL;
     static {
-        if (android.os.Build.VERSION.SDK_INT >= 15) {
+        // TODO: Change to comparison against API 23 once we have it defined.
+        if (Build.VERSION.CODENAME.equals("MNC") || Build.VERSION.SDK_INT > 22) {
+            IMPL = new MncFragmentCompatImpl();
+        } else if (android.os.Build.VERSION.SDK_INT >= 15) {
             IMPL = new ICSMR1FragmentCompatImpl();
         } else if (android.os.Build.VERSION.SDK_INT >= 14) {
             IMPL = new ICSFragmentCompatImpl();
@@ -59,7 +99,30 @@
             IMPL = new BaseFragmentCompatImpl();
         }
     }
- 
+
+    /**
+     * This interface is the contract for receiving the results for permission requests.
+     */
+    public interface OnRequestPermissionsResultCallback {
+
+        /**
+         * Callback for the result from requesting permissions. This method
+         * is invoked for every call on {@link #requestPermissions(android.app.Fragment,
+         * String[], int)}
+         *
+         * @param requestCode The request code passed in {@link #requestPermissions(
+         *     android.app.Fragment, String[], int)}
+         * @param permissions The requested permissions. Never null.
+         * @param grantResults The grant results for the corresponding permissions
+         *     which is either {@link android.content.pm.PackageManager#PERMISSION_GRANTED}
+         *     or {@link android.content.pm.PackageManager#PERMISSION_DENIED}. Never null.
+         *
+         * @see #requestPermissions(android.app.Fragment, String[], int)
+         */
+        public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
+                @NonNull int[] grantResults);
+    }
+
     /**
      * Call {@link Fragment#setMenuVisibility(boolean) Fragment.setMenuVisibility(boolean)}
      * if running on an appropriate version of the platform.
@@ -75,4 +138,86 @@
     public static void setUserVisibleHint(Fragment f, boolean deferStart) {
         IMPL.setUserVisibleHint(f, deferStart);
     }
+
+    /**
+     * Requests permissions to be granted to this application. These permissions
+     * must be requested in your manifest, they should not be granted to your app,
+     * and they should have protection level {@link android.content.pm.PermissionInfo
+     * #PROTECTION_DANGEROUS dangerous}, regardless whether they are declared by
+     * the platform or a third-party app.
+     * <p>
+     * Normal permissions {@link android.content.pm.PermissionInfo#PROTECTION_NORMAL}
+     * are granted at install time if requested in the manifest. Signature permissions
+     * {@link android.content.pm.PermissionInfo#PROTECTION_SIGNATURE} are granted at
+     * install time if requested in the manifest and the signature of your app matches
+     * the signature of the app declaring the permissions.
+     * </p>
+     * <p>
+     * If your app does not have the requested permissions the user will be presented
+     * with UI for accepting them. After the user has accepted or rejected the
+     * requested permissions you will receive a callback reporting whether the
+     * permissions were granted or not. Your fragment has to implement {@link
+     * OnRequestPermissionsResultCallback}
+     * and the results of permission requests will be delivered to its
+     * {@link OnRequestPermissionsResultCallback#onRequestPermissionsResult(
+     * int, String[], int[])}.
+     * </p>
+     * <p>
+     * Note that requesting a permission does not guarantee it will be granted and
+     * your app should be able to run without having this permission.
+     * </p>
+     * <p>
+     * This method may start an activity allowing the user to choose which permissions
+     * to grant and which to reject. Hence, you should be prepared that your activity
+     * may be paused and resumed. Further, granting some permissions may require
+     * a restart of you application. In such a case, the system will recreate the
+     * activity stack before delivering the result to your onRequestPermissionsResult(
+     * int, String[], int[]).
+     * </p>
+     * <p>
+     * When checking whether you have a permission you should use {@link
+     * android.support.v4.content.ContextCompat#checkSelfPermission(
+     * android.content.Context, String)}.
+     * </p>
+     *
+     * @param fragment The target fragment.
+     * @param permissions The requested permissions.
+     * @param requestCode Application specific request code to match with a result
+     *    reported to {@link OnRequestPermissionsResultCallback#onRequestPermissionsResult(
+     *    int, String[], int[])}.
+     *
+     * @see android.support.v4.content.ContextCompat#checkSelfPermission(
+     *     android.content.Context, String)
+     * @see #shouldShowRequestPermissionRationale(android.app.Fragment, String)
+     */
+    public static void requestPermissions(@NonNull Fragment fragment,
+            @NonNull String[] permissions, int requestCode) {
+        IMPL.requestPermissions(fragment, permissions, requestCode);
+    }
+
+    /**
+     * Gets whether you should show UI with rationale for requesting a permission.
+     * You should do this only if you do not have the permission and the context in
+     * which the permission is requested does not clearly communicate to the user
+     * what would be the benefit from granting this permission.
+     * <p>
+     * For example, if you write a camera app, requesting the camera permission
+     * would be expected by the user and no rationale for why it is requested is
+     * needed. If however, the app needs location for tagging photos then a non-tech
+     * savvy user may wonder how location is related to taking photos. In this case
+     * you may choose to show UI with rationale of requesting this permission.
+     * </p>
+     *
+     * @param fragment The target fragment.
+     * @param permission A permission your app wants to request.
+     * @return Whether you can show permission rationale UI.
+     *
+     * @see android.support.v4.content.ContextCompat#checkSelfPermission(
+     *     android.content.Context, String)
+     * @see #requestPermissions(android.app.Fragment, String[], int)
+     */
+    public static boolean shouldShowRequestPermissionRationale(@NonNull Fragment fragment,
+            @NonNull String permission) {
+        return IMPL.shouldShowRequestPermissionRationale(fragment, permission);
+    }
 }
diff --git a/v14/Android.mk b/v14/Android.mk
new file mode 100644
index 0000000..365b3b1
--- /dev/null
+++ b/v14/Android.mk
@@ -0,0 +1,16 @@
+# 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.
+
+LOCAL_PATH:= $(call my-dir)
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/v14/preference/Android.mk b/v14/preference/Android.mk
new file mode 100644
index 0000000..fc7a9aa
--- /dev/null
+++ b/v14/preference/Android.mk
@@ -0,0 +1,59 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+# Build the resources using the current SDK version.
+# We do this here because the final static library must be compiled with an older
+# SDK version than the resources.  The resources library and the R class that it
+# contains will not be linked into the final static library.
+include $(CLEAR_VARS)
+LOCAL_MODULE := android-support-v14-preference-res
+LOCAL_SDK_VERSION := current
+LOCAL_SRC_FILES := $(call all-java-files-under, dummy)
+LOCAL_RESOURCE_DIR := \
+        frameworks/support/v7/appcompat/res \
+        frameworks/support/v7/preference/res \
+        $(LOCAL_PATH)/res
+LOCAL_AAPT_FLAGS := \
+	--auto-add-overlay
+LOCAL_JAR_EXCLUDE_FILES := none
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+# Here is the final static library that apps can link against.
+# The R class is automatically excluded from the generated library.
+# Applications that use this library must specify LOCAL_RESOURCE_DIR
+# in their makefiles to include the resources in their package.
+include $(CLEAR_VARS)
+LOCAL_MODULE := android-support-v14-preference
+LOCAL_SDK_VERSION := 14
+LOCAL_SRC_FILES := $(call all-java-files-under,src)
+# LOCAL_STATIC_JAVA_LIBRARIES :=
+LOCAL_JAVA_LIBRARIES := \
+        android-support-v4 \
+        android-support-v7-appcompat \
+        android-support-v7-recyclerview \
+        android-support-v7-preference \
+        android-support-annotations \
+        android-support-v14-preference-res
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+# API Check
+# ---------------------------------------------
+support_module := $(LOCAL_MODULE)
+support_module_api_dir := $(LOCAL_PATH)/api
+support_module_src_files := $(LOCAL_SRC_FILES)
+support_module_java_libraries := $(LOCAL_JAVA_LIBRARIES)
+support_module_java_packages := android.support.v14.preference
+include $(SUPPORT_API_CHECK)
\ No newline at end of file
diff --git a/v14/preference/AndroidManifest.xml b/v14/preference/AndroidManifest.xml
new file mode 100644
index 0000000..8b502c9
--- /dev/null
+++ b/v14/preference/AndroidManifest.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.support.v14.preference"
+    android:versionCode="1"
+    android:versionName="1.0">
+    <uses-sdk android:minSdkVersion="14" />
+    <application />
+</manifest>
diff --git a/v14/preference/api/current.txt b/v14/preference/api/current.txt
new file mode 100644
index 0000000..cbf8fe5
--- /dev/null
+++ b/v14/preference/api/current.txt
@@ -0,0 +1,95 @@
+package android.support.v14.preference {
+
+  public class EditTextPreferenceDialogFragment extends android.support.v14.preference.PreferenceDialogFragment {
+    ctor public EditTextPreferenceDialogFragment();
+    method public static android.support.v14.preference.EditTextPreferenceDialogFragment newInstance(java.lang.String);
+    method protected void onAddEditTextToDialogView(android.view.View, android.widget.EditText);
+    method public void onDialogClosed(boolean);
+  }
+
+  public class ListPreferenceDialogFragment extends android.support.v14.preference.PreferenceDialogFragment {
+    ctor public ListPreferenceDialogFragment();
+    method public static android.support.v14.preference.ListPreferenceDialogFragment newInstance(java.lang.String);
+    method public void onDialogClosed(boolean);
+  }
+
+  public class MultiSelectListPreference extends android.support.v7.preference.DialogPreference {
+    ctor public MultiSelectListPreference(android.content.Context, android.util.AttributeSet, int, int);
+    ctor public MultiSelectListPreference(android.content.Context, android.util.AttributeSet, int);
+    ctor public MultiSelectListPreference(android.content.Context, android.util.AttributeSet);
+    ctor public MultiSelectListPreference(android.content.Context);
+    method public int findIndexOfValue(java.lang.String);
+    method public java.lang.CharSequence[] getEntries();
+    method public java.lang.CharSequence[] getEntryValues();
+    method protected boolean[] getSelectedItems();
+    method public java.util.Set<java.lang.String> getValues();
+    method public void setEntries(java.lang.CharSequence[]);
+    method public void setEntries(int);
+    method public void setEntryValues(java.lang.CharSequence[]);
+    method public void setEntryValues(int);
+    method public void setValues(java.util.Set<java.lang.String>);
+  }
+
+  public class MultiSelectListPreferenceDialogFragment extends android.support.v14.preference.PreferenceDialogFragment {
+    ctor public MultiSelectListPreferenceDialogFragment();
+    method public static android.support.v14.preference.MultiSelectListPreferenceDialogFragment newInstance(java.lang.String);
+    method public void onDialogClosed(boolean);
+  }
+
+  public abstract class PreferenceDialogFragment extends android.app.DialogFragment implements android.content.DialogInterface.OnClickListener {
+    ctor public PreferenceDialogFragment();
+    method public android.support.v7.preference.DialogPreference getPreference();
+    method protected void onBindDialogView(android.view.View);
+    method public void onClick(android.content.DialogInterface, int);
+    method protected android.view.View onCreateDialogView(android.content.Context);
+    method public abstract void onDialogClosed(boolean);
+    method protected void onPrepareDialogBuilder(android.app.AlertDialog.Builder);
+    field protected static final java.lang.String ARG_KEY = "key";
+  }
+
+  public abstract class PreferenceFragment extends android.app.Fragment implements android.support.v7.preference.PreferenceManager.OnDisplayPreferenceDialogListener android.support.v7.preference.PreferenceManager.OnNavigateToScreenListener android.support.v7.preference.PreferenceManager.OnPreferenceTreeClickListener {
+    ctor public PreferenceFragment();
+    method public void addPreferencesFromResource(int);
+    method public android.support.v7.preference.Preference findPreference(java.lang.CharSequence);
+    method public final android.support.v7.widget.RecyclerView getListView();
+    method public android.support.v7.preference.PreferenceManager getPreferenceManager();
+    method public android.support.v7.preference.PreferenceScreen getPreferenceScreen();
+    method protected android.support.v7.widget.RecyclerView.Adapter onCreateAdapter(android.support.v7.preference.PreferenceScreen);
+    method public android.support.v7.widget.RecyclerView.LayoutManager onCreateLayoutManager();
+    method public abstract void onCreatePreferences(android.os.Bundle, java.lang.String);
+    method public android.support.v7.widget.RecyclerView onCreateRecyclerView(android.view.LayoutInflater, android.view.ViewGroup, android.os.Bundle);
+    method public void onDisplayPreferenceDialog(android.support.v7.preference.Preference);
+    method public void onNavigateToScreen(android.support.v7.preference.PreferenceScreen);
+    method public boolean onPreferenceTreeClick(android.support.v7.preference.Preference);
+    method public void setPreferenceScreen(android.support.v7.preference.PreferenceScreen);
+    method public void setPreferencesFromResource(int, java.lang.String);
+    field public static final java.lang.String ARG_PREFERENCE_ROOT = "android.support.v7.preference.PreferenceFragmentCompat.PREFERENCE_ROOT";
+  }
+
+  public static abstract interface PreferenceFragment.OnPreferenceDisplayDialogCallback {
+    method public abstract boolean onPreferenceDisplayDialog(android.support.v14.preference.PreferenceFragment, android.support.v7.preference.Preference);
+  }
+
+  public static abstract interface PreferenceFragment.OnPreferenceStartFragmentCallback {
+    method public abstract boolean onPreferenceStartFragment(android.support.v14.preference.PreferenceFragment, android.support.v7.preference.Preference);
+  }
+
+  public static abstract interface PreferenceFragment.OnPreferenceStartScreenCallback {
+    method public abstract boolean onPreferenceStartScreen(android.support.v14.preference.PreferenceFragment, android.support.v7.preference.PreferenceScreen);
+  }
+
+  public class SwitchPreference extends android.support.v7.preference.TwoStatePreference {
+    ctor public SwitchPreference(android.content.Context, android.util.AttributeSet, int, int);
+    ctor public SwitchPreference(android.content.Context, android.util.AttributeSet, int);
+    ctor public SwitchPreference(android.content.Context, android.util.AttributeSet);
+    ctor public SwitchPreference(android.content.Context);
+    method public java.lang.CharSequence getSwitchTextOff();
+    method public java.lang.CharSequence getSwitchTextOn();
+    method public void setSwitchTextOff(java.lang.CharSequence);
+    method public void setSwitchTextOff(int);
+    method public void setSwitchTextOn(java.lang.CharSequence);
+    method public void setSwitchTextOn(int);
+  }
+
+}
+
diff --git a/v14/preference/api/removed.txt b/v14/preference/api/removed.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/v14/preference/api/removed.txt
diff --git a/v14/preference/build.gradle b/v14/preference/build.gradle
new file mode 100644
index 0000000..772b353
--- /dev/null
+++ b/v14/preference/build.gradle
@@ -0,0 +1,56 @@
+/*
+ * 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
+ */
+
+
+
+apply plugin: 'android-library'
+
+archivesBaseName = 'preference-v14'
+
+dependencies {
+    compile project(':support-v4')
+    compile project(':support-appcompat-v7')
+    compile project(':support-recyclerview-v7')
+    compile project(':support-preference-v7')
+}
+
+android {
+    compileSdkVersion 'current'
+
+    sourceSets {
+        main.manifest.srcFile 'AndroidManifest.xml'
+        main.java.srcDir 'src'
+        main.res.srcDir 'res'
+        main.assets.srcDir 'assets'
+        main.resources.srcDir 'src'
+
+        // this moves src/instrumentTest to tests so all folders follow:
+        // tests/java, tests/res, tests/assets, ...
+        // This is a *reset* so it replaces the default paths
+        androidTest.setRoot('tests')
+        androidTest.java.srcDir 'tests/src'
+    }
+
+    compileOptions {
+        sourceCompatibility JavaVersion.VERSION_1_7
+        targetCompatibility JavaVersion.VERSION_1_7
+    }
+
+    lintOptions {
+        // TODO: fix errors and reenable.
+        abortOnError false
+    }
+}
diff --git a/v14/preference/res/layout-v21/preference_material.xml b/v14/preference/res/layout-v21/preference_material.xml
new file mode 100644
index 0000000..8d62cc2
--- /dev/null
+++ b/v14/preference/res/layout-v21/preference_material.xml
@@ -0,0 +1,81 @@
+<?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
+  -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:minHeight="?android:attr/listPreferredItemHeightSmall"
+    android:gravity="center_vertical"
+    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+    android:background="?android:attr/activatedBackgroundIndicator"
+    android:clipToPadding="false">
+
+    <LinearLayout
+        android:id="@+id/icon_frame"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="-4dp"
+        android:minWidth="60dp"
+        android:gravity="start|center_vertical"
+        android:orientation="horizontal"
+        android:paddingEnd="12dp"
+        android:paddingTop="4dp"
+        android:paddingBottom="4dp">
+        <android.support.v7.internal.widget.PreferenceImageView
+            android:id="@+id/icon"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            app:maxWidth="48dp"
+            app:maxHeight="48dp" />
+    </LinearLayout>
+
+  <RelativeLayout
+      android:layout_width="wrap_content"
+      android:layout_height="wrap_content"
+      android:layout_weight="1"
+      android:paddingTop="16dp"
+      android:paddingBottom="16dp">
+
+      <TextView android:id="@+id/title"
+          android:layout_width="wrap_content"
+          android:layout_height="wrap_content"
+          android:singleLine="true"
+          android:textAppearance="?android:attr/textAppearanceListItem"
+          android:ellipsize="marquee" />
+
+      <TextView android:id="@+id/summary"
+          android:layout_width="wrap_content"
+          android:layout_height="wrap_content"
+          android:layout_below="@id/title"
+          android:layout_alignStart="@id/title"
+          android:textAppearance="?android:attr/textAppearanceListItemSecondary"
+          android:textColor="?android:attr/textColorSecondary"
+          android:maxLines="10" />
+
+  </RelativeLayout>
+
+  <!-- Preference should place its actual preference widget here. -->
+  <LinearLayout android:id="@+id/widget_frame"
+      android:layout_width="wrap_content"
+      android:layout_height="match_parent"
+      android:gravity="end|center_vertical"
+      android:paddingStart="16dp"
+      android:orientation="vertical" />
+
+</LinearLayout>
diff --git a/v14/preference/res/layout/preference_material.xml b/v14/preference/res/layout/preference_material.xml
new file mode 100644
index 0000000..b9d8f66
--- /dev/null
+++ b/v14/preference/res/layout/preference_material.xml
@@ -0,0 +1,81 @@
+<?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
+  -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:minHeight="?android:attr/listPreferredItemHeightSmall"
+    android:gravity="center_vertical"
+    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+    android:background="?android:attr/activatedBackgroundIndicator"
+    android:clipToPadding="false">
+
+    <LinearLayout
+        android:id="@+id/icon_frame"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="-4dp"
+        android:minWidth="60dp"
+        android:gravity="start|center_vertical"
+        android:orientation="horizontal"
+        android:paddingEnd="12dp"
+        android:paddingTop="4dp"
+        android:paddingBottom="4dp">
+        <android.support.v7.internal.widget.PreferenceImageView
+            android:id="@+id/icon"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            app:maxWidth="48dp"
+            app:maxHeight="48dp" />
+    </LinearLayout>
+
+    <RelativeLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:paddingTop="16dp"
+        android:paddingBottom="16dp">
+
+        <TextView android:id="@+id/title"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:singleLine="true"
+            android:textAppearance="?android:attr/textAppearanceListItem"
+            android:ellipsize="marquee" />
+
+        <TextView android:id="@+id/summary"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_below="@id/title"
+            android:layout_alignStart="@id/title"
+            android:textAppearance="?android:attr/textAppearanceSmall"
+            android:textColor="?android:attr/textColorSecondary"
+            android:maxLines="10" />
+
+    </RelativeLayout>
+
+    <!-- Preference should place its actual preference widget here. -->
+    <LinearLayout android:id="@+id/widget_frame"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:gravity="end|center_vertical"
+        android:paddingStart="16dp"
+        android:orientation="vertical" />
+
+</LinearLayout>
diff --git a/v14/preference/res/layout/preference_widget_switch.xml b/v14/preference/res/layout/preference_widget_switch.xml
new file mode 100644
index 0000000..ae83afa
--- /dev/null
+++ b/v14/preference/res/layout/preference_widget_switch.xml
@@ -0,0 +1,26 @@
+<?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
+  -->
+
+<!-- Layout used by SwitchPreference for the switch widget style. This is inflated
+     inside android.R.layout.preference. -->
+<Switch xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/switchWidget"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:focusable="false"
+    android:clickable="false"
+    android:background="@null" />
diff --git a/v14/preference/res/values/attrs.xml b/v14/preference/res/values/attrs.xml
new file mode 100644
index 0000000..62d9e47
--- /dev/null
+++ b/v14/preference/res/values/attrs.xml
@@ -0,0 +1,55 @@
+<?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
+  -->
+
+<resources>
+    <declare-styleable name="SwitchPreference">
+        <!-- The summary for the Preference in a PreferenceActivity screen when the
+             SwitchPreference is checked. If separate on/off summaries are not
+             needed, the summary attribute can be used instead. -->
+        <attr name="summaryOn" />
+        <attr name="android:summaryOn" />
+        <!-- The summary for the Preference in a PreferenceActivity screen when the
+             SwitchPreference is unchecked. If separate on/off summaries are not
+             needed, the summary attribute can be used instead. -->
+        <attr name="summaryOff" />
+        <attr name="android:summaryOff" />
+        <!-- The text used on the switch itself when in the "on" state.
+             This should be a very SHORT string, as it appears in a small space. -->
+        <attr name="switchTextOn"/>
+        <attr name="android:switchTextOn"/>
+        <!-- The text used on the switch itself when in the "off" state.
+             This should be a very SHORT string, as it appears in a small space. -->
+        <attr name="switchTextOff" />
+        <attr name="android:switchTextOff" />
+        <!-- The state (true for on, or false for off) that causes dependents to be disabled. By default,
+             dependents will be disabled when this is unchecked, so the value of this preference is false. -->
+        <attr name="disableDependentsState" />
+        <attr name="android:disableDependentsState" />
+    </declare-styleable>
+
+    <declare-styleable name="MultiSelectListPreference">
+        <!-- The human-readable array to present as a list. Each entry must have a corresponding
+             index in entryValues. -->
+        <attr name="entries" />
+        <attr name="android:entries" />
+        <!-- The array to find the value to save for a preference when an entry from
+             entries is selected. If a user clicks the second item in entries, the
+             second item in this array will be saved to the preference. -->
+        <attr name="entryValues" />
+        <attr name="android:entryValues" />
+    </declare-styleable>
+</resources>
diff --git a/v14/preference/res/values/styles.xml b/v14/preference/res/values/styles.xml
new file mode 100644
index 0000000..d7cc268
--- /dev/null
+++ b/v14/preference/res/values/styles.xml
@@ -0,0 +1,25 @@
+<?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
+  -->
+
+<resources>
+    <style name="Preference.SwitchPreference">
+        <item name="widgetLayout">@layout/preference_widget_switch</item>
+        <item name="switchTextOn">@string/v7_preference_on</item>
+        <item name="switchTextOff">@string/v7_preference_off</item>
+    </style>
+
+</resources>
diff --git a/v14/preference/res/values/themes.xml b/v14/preference/res/values/themes.xml
new file mode 100644
index 0000000..88d25d2
--- /dev/null
+++ b/v14/preference/res/values/themes.xml
@@ -0,0 +1,22 @@
+<?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
+  -->
+
+<resources>
+    <style name="PreferenceThemeOverlay.v14">
+        <item name="switchPreferenceStyle">@style/Preference.SwitchPreference</item>
+    </style>
+</resources>
diff --git a/v14/preference/src/android/support/v14/preference/EditTextPreferenceDialogFragment.java b/v14/preference/src/android/support/v14/preference/EditTextPreferenceDialogFragment.java
new file mode 100644
index 0000000..caf08a8
--- /dev/null
+++ b/v14/preference/src/android/support/v14/preference/EditTextPreferenceDialogFragment.java
@@ -0,0 +1,94 @@
+/*
+ * 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.v14.preference;
+
+import android.os.Bundle;
+import android.support.v7.preference.EditTextPreference;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewParent;
+import android.widget.EditText;
+
+public class EditTextPreferenceDialogFragment extends PreferenceDialogFragment {
+
+    private EditText mEditText;
+
+    public static EditTextPreferenceDialogFragment newInstance(String key) {
+        final EditTextPreferenceDialogFragment
+                fragment = new EditTextPreferenceDialogFragment();
+        final Bundle b = new Bundle(1);
+        b.putString(ARG_KEY, key);
+        fragment.setArguments(b);
+        return fragment;
+    }
+
+    @Override
+    protected void onBindDialogView(View view) {
+        super.onBindDialogView(view);
+
+        mEditText = new EditText(view.getContext());
+        // Give it an ID so it can be saved/restored
+        mEditText.setId(android.R.id.edit);
+
+        mEditText.setText(getEditTextPreference().getText());
+
+        ViewParent oldParent = mEditText.getParent();
+        if (oldParent != view) {
+            if (oldParent != null) {
+                ((ViewGroup) oldParent).removeView(mEditText);
+            }
+            onAddEditTextToDialogView(view, mEditText);
+        }
+    }
+
+    private EditTextPreference getEditTextPreference() {
+        return (EditTextPreference) getPreference();
+    }
+
+    /** @hide */
+    @Override
+    protected boolean needInputMethod() {
+        // We want the input method to show, if possible, when dialog is displayed
+        return true;
+    }
+
+    /**
+     * Adds the EditText widget of this preference to the dialog's view.
+     *
+     * @param dialogView The dialog view.
+     */
+    protected void onAddEditTextToDialogView(View dialogView, EditText editText) {
+        ViewGroup container = (ViewGroup) dialogView
+                .findViewById(R.id.edittext_container);
+        if (container != null) {
+            container.addView(editText, ViewGroup.LayoutParams.FILL_PARENT,
+                    ViewGroup.LayoutParams.WRAP_CONTENT);
+        }
+    }
+
+    @Override
+    public void onDialogClosed(boolean positiveResult) {
+
+        if (positiveResult) {
+            String value = mEditText.getText().toString();
+            if (getEditTextPreference().callChangeListener(value)) {
+                getEditTextPreference().setText(value);
+            }
+        }
+    }
+
+}
diff --git a/v14/preference/src/android/support/v14/preference/ListPreferenceDialogFragment.java b/v14/preference/src/android/support/v14/preference/ListPreferenceDialogFragment.java
new file mode 100644
index 0000000..c4e922c
--- /dev/null
+++ b/v14/preference/src/android/support/v14/preference/ListPreferenceDialogFragment.java
@@ -0,0 +1,87 @@
+/*
+ * 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.v14.preference;
+
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.support.v7.preference.ListPreference;
+
+public class ListPreferenceDialogFragment extends PreferenceDialogFragment {
+
+    private int mClickedDialogEntryIndex;
+
+    public static ListPreferenceDialogFragment newInstance(String key) {
+        final ListPreferenceDialogFragment fragment = new ListPreferenceDialogFragment();
+        final Bundle b = new Bundle(1);
+        b.putString(ARG_KEY, key);
+        fragment.setArguments(b);
+        return fragment;
+    }
+
+    private ListPreference getListPreference() {
+        return (ListPreference) getPreference();
+    }
+
+    @Override
+    protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
+        super.onPrepareDialogBuilder(builder);
+
+        final ListPreference preference = getListPreference();
+
+        if (preference.getEntries() == null || preference.getEntryValues() == null) {
+            throw new IllegalStateException(
+                    "ListPreference requires an entries array and an entryValues array.");
+        }
+
+        mClickedDialogEntryIndex = preference.findIndexOfValue(preference.getValue());
+        builder.setSingleChoiceItems(preference.getEntries(), mClickedDialogEntryIndex,
+                new DialogInterface.OnClickListener() {
+                    public void onClick(DialogInterface dialog, int which) {
+                        mClickedDialogEntryIndex = which;
+
+                        /*
+                         * Clicking on an item simulates the positive button
+                         * click, and dismisses the dialog.
+                         */
+                        ListPreferenceDialogFragment.this.onClick(dialog,
+                                DialogInterface.BUTTON_POSITIVE);
+                        dialog.dismiss();
+                    }
+                });
+
+        /*
+         * The typical interaction for list-based dialogs is to have
+         * click-on-an-item dismiss the dialog instead of the user having to
+         * press 'Ok'.
+         */
+        builder.setPositiveButton(null, null);
+    }
+
+    @Override
+    public void onDialogClosed(boolean positiveResult) {
+        final ListPreference preference = getListPreference();
+        if (positiveResult && mClickedDialogEntryIndex >= 0 &&
+                preference.getEntryValues() != null) {
+            String value = preference.getEntryValues()[mClickedDialogEntryIndex].toString();
+            if (preference.callChangeListener(value)) {
+                preference.setValue(value);
+            }
+        }
+    }
+
+}
diff --git a/v14/preference/src/android/support/v14/preference/MultiSelectListPreference.java b/v14/preference/src/android/support/v14/preference/MultiSelectListPreference.java
new file mode 100644
index 0000000..2a636fe
--- /dev/null
+++ b/v14/preference/src/android/support/v14/preference/MultiSelectListPreference.java
@@ -0,0 +1,325 @@
+/*
+ * 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.v14.preference;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.res.TypedArray;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.support.annotation.ArrayRes;
+import android.support.annotation.NonNull;
+import android.support.v4.content.SharedPreferencesCompat;
+import android.support.v4.content.res.TypedArrayUtils;
+import android.support.v7.preference.DialogPreference;
+import android.util.AttributeSet;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * A {@link android.support.v7.preference.Preference} that displays a list of entries as
+ * a dialog.
+ * <p>
+ * This preference will store a set of strings into the SharedPreferences.
+ * This set will contain one or more values from the
+ * {@link #setEntryValues(CharSequence[])} array.
+ *
+ * @attr ref android.R.styleable#MultiSelectListPreference_entries
+ * @attr ref android.R.styleable#MultiSelectListPreference_entryValues
+ */
+public class MultiSelectListPreference extends DialogPreference {
+    private CharSequence[] mEntries;
+    private CharSequence[] mEntryValues;
+    private Set<String> mValues = new HashSet<>();
+
+    public MultiSelectListPreference(
+            Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+
+        final TypedArray a = context.obtainStyledAttributes(attrs,
+                R.styleable.MultiSelectListPreference, defStyleAttr,
+                defStyleRes);
+
+        mEntries = TypedArrayUtils.getTextArray(a,
+                R.styleable.MultiSelectListPreference_entries,
+                R.styleable.MultiSelectListPreference_android_entries);
+
+        mEntryValues = TypedArrayUtils.getTextArray(a,
+                R.styleable.MultiSelectListPreference_entryValues,
+                R.styleable.MultiSelectListPreference_android_entryValues);
+
+        a.recycle();
+    }
+
+    public MultiSelectListPreference(Context context, AttributeSet attrs, int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0);
+    }
+
+    public MultiSelectListPreference(Context context, AttributeSet attrs) {
+        this(context, attrs, R.attr.dialogPreferenceStyle);
+    }
+
+    public MultiSelectListPreference(Context context) {
+        this(context, null);
+    }
+
+    /**
+     * Attempts to persist a set of Strings to the {@link android.content.SharedPreferences}.
+     * <p>
+     * This will check if this Preference is persistent, get an editor from
+     * the {@link android.preference.PreferenceManager}, put in the strings, and check if we should
+     * commit (and commit if so).
+     *
+     * @param values The values to persist.
+     * @return True if the Preference is persistent. (This is not whether the
+     *         value was persisted, since we may not necessarily commit if there
+     *         will be a batch commit later.)
+     * @see #getPersistedString
+     *
+     * @hide
+     */
+    protected boolean persistStringSet(Set<String> values) {
+        if (shouldPersist()) {
+            // Shouldn't store null
+            if (values.equals(getPersistedStringSet(null))) {
+                // It's already there, so the same as persisting
+                return true;
+            }
+
+            SharedPreferences.Editor editor = getPreferenceManager().getSharedPreferences().edit();
+            editor.putStringSet(getKey(), values);
+            SharedPreferencesCompat.EditorCompat.getInstance().apply(editor);
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Attempts to get a persisted set of Strings from the
+     * {@link android.content.SharedPreferences}.
+     * <p>
+     * This will check if this Preference is persistent, get the SharedPreferences
+     * from the {@link android.preference.PreferenceManager}, and get the value.
+     *
+     * @param defaultReturnValue The default value to return if either the
+     *            Preference is not persistent or the Preference is not in the
+     *            shared preferences.
+     * @return The value from the SharedPreferences or the default return
+     *         value.
+     * @see #persistStringSet(Set)
+     *
+     * @hide
+     */
+    protected Set<String> getPersistedStringSet(Set<String> defaultReturnValue) {
+        if (!shouldPersist()) {
+            return defaultReturnValue;
+        }
+
+        return getPreferenceManager().getSharedPreferences()
+                .getStringSet(getKey(), defaultReturnValue);
+    }
+
+    /**
+     * Sets the human-readable entries to be shown in the list. This will be
+     * shown in subsequent dialogs.
+     * <p>
+     * Each entry must have a corresponding index in
+     * {@link #setEntryValues(CharSequence[])}.
+     *
+     * @param entries The entries.
+     * @see #setEntryValues(CharSequence[])
+     */
+    public void setEntries(CharSequence[] entries) {
+        mEntries = entries;
+    }
+
+    /**
+     * @see #setEntries(CharSequence[])
+     * @param entriesResId The entries array as a resource.
+     */
+    public void setEntries(@ArrayRes int entriesResId) {
+        setEntries(getContext().getResources().getTextArray(entriesResId));
+    }
+
+    /**
+     * The list of entries to be shown in the list in subsequent dialogs.
+     *
+     * @return The list as an array.
+     */
+    public CharSequence[] getEntries() {
+        return mEntries;
+    }
+
+    /**
+     * The array to find the value to save for a preference when an entry from
+     * entries is selected. If a user clicks on the second item in entries, the
+     * second item in this array will be saved to the preference.
+     *
+     * @param entryValues The array to be used as values to save for the preference.
+     */
+    public void setEntryValues(CharSequence[] entryValues) {
+        mEntryValues = entryValues;
+    }
+
+    /**
+     * @see #setEntryValues(CharSequence[])
+     * @param entryValuesResId The entry values array as a resource.
+     */
+    public void setEntryValues(@ArrayRes int entryValuesResId) {
+        setEntryValues(getContext().getResources().getTextArray(entryValuesResId));
+    }
+
+    /**
+     * Returns the array of values to be saved for the preference.
+     *
+     * @return The array of values.
+     */
+    public CharSequence[] getEntryValues() {
+        return mEntryValues;
+    }
+
+    /**
+     * Sets the value of the key. This should contain entries in
+     * {@link #getEntryValues()}.
+     *
+     * @param values The values to set for the key.
+     */
+    public void setValues(Set<String> values) {
+        mValues.clear();
+        mValues.addAll(values);
+
+        persistStringSet(values);
+    }
+
+    /**
+     * Retrieves the current value of the key.
+     */
+    public Set<String> getValues() {
+        return mValues;
+    }
+
+    /**
+     * Returns the index of the given value (in the entry values array).
+     *
+     * @param value The value whose index should be returned.
+     * @return The index of the value, or -1 if not found.
+     */
+    public int findIndexOfValue(String value) {
+        if (value != null && mEntryValues != null) {
+            for (int i = mEntryValues.length - 1; i >= 0; i--) {
+                if (mEntryValues[i].equals(value)) {
+                    return i;
+                }
+            }
+        }
+        return -1;
+    }
+
+    protected boolean[] getSelectedItems() {
+        final CharSequence[] entries = mEntryValues;
+        final int entryCount = entries.length;
+        final Set<String> values = mValues;
+        boolean[] result = new boolean[entryCount];
+
+        for (int i = 0; i < entryCount; i++) {
+            result[i] = values.contains(entries[i].toString());
+        }
+
+        return result;
+    }
+
+    @Override
+    protected Object onGetDefaultValue(TypedArray a, int index) {
+        final CharSequence[] defaultValues = a.getTextArray(index);
+        final Set<String> result = new HashSet<>();
+
+        for (final CharSequence defaultValue : defaultValues) {
+            result.add(defaultValue.toString());
+        }
+
+        return result;
+    }
+
+    @Override
+    protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
+        setValues(restoreValue ? getPersistedStringSet(mValues) : (Set<String>) defaultValue);
+    }
+
+    @Override
+    protected Parcelable onSaveInstanceState() {
+        final Parcelable superState = super.onSaveInstanceState();
+        if (isPersistent()) {
+            // No need to save instance state
+            return superState;
+        }
+
+        final SavedState myState = new SavedState(superState);
+        myState.values = getValues();
+        return myState;
+    }
+
+    @Override
+    protected void onRestoreInstanceState(Parcelable state) {
+        if (state == null || !state.getClass().equals(SavedState.class)) {
+            // Didn't save state for us in onSaveInstanceState
+            super.onRestoreInstanceState(state);
+            return;
+        }
+
+        SavedState myState = (SavedState) state;
+        super.onRestoreInstanceState(myState.getSuperState());
+        setValues(myState.values);
+    }
+
+    private static class SavedState extends BaseSavedState {
+        Set<String> values;
+
+        public SavedState(Parcel source) {
+            super(source);
+            final int size = source.readInt();
+            values = new HashSet<>();
+            String[] strings = new String[size];
+            source.readStringArray(strings);
+
+            Collections.addAll(values, strings);
+        }
+
+        public SavedState(Parcelable superState) {
+            super(superState);
+        }
+
+        @Override
+        public void writeToParcel(@NonNull Parcel dest, int flags) {
+            super.writeToParcel(dest, flags);
+            dest.writeInt(values.size());
+            dest.writeStringArray(values.toArray(new String[values.size()]));
+        }
+
+        public static final Parcelable.Creator<SavedState> CREATOR =
+                new Parcelable.Creator<SavedState>() {
+                    public SavedState createFromParcel(Parcel in) {
+                        return new SavedState(in);
+                    }
+
+                    public SavedState[] newArray(int size) {
+                        return new SavedState[size];
+                    }
+                };
+    }
+}
diff --git a/v14/preference/src/android/support/v14/preference/MultiSelectListPreferenceDialogFragment.java b/v14/preference/src/android/support/v14/preference/MultiSelectListPreferenceDialogFragment.java
new file mode 100644
index 0000000..ec46aac
--- /dev/null
+++ b/v14/preference/src/android/support/v14/preference/MultiSelectListPreferenceDialogFragment.java
@@ -0,0 +1,85 @@
+/*
+ * 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.v14.preference;
+
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.os.Bundle;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public class MultiSelectListPreferenceDialogFragment extends PreferenceDialogFragment {
+
+    private Set<String> mNewValues = new HashSet<>();
+    private boolean mPreferenceChanged;
+
+    public static MultiSelectListPreferenceDialogFragment newInstance(String key) {
+        final MultiSelectListPreferenceDialogFragment fragment =
+                new MultiSelectListPreferenceDialogFragment();
+        final Bundle b = new Bundle(1);
+        b.putString(ARG_KEY, key);
+        fragment.setArguments(b);
+        return fragment;
+    }
+
+    private MultiSelectListPreference getListPreference() {
+        return (MultiSelectListPreference) getPreference();
+    }
+
+    @Override
+    protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
+        super.onPrepareDialogBuilder(builder);
+
+        final MultiSelectListPreference preference = getListPreference();
+
+        if (preference.getEntries() == null || preference.getEntryValues() == null) {
+            throw new IllegalStateException(
+                    "MultiSelectListPreference requires an entries array and " +
+                            "an entryValues array.");
+        }
+
+        boolean[] checkedItems = preference.getSelectedItems();
+        builder.setMultiChoiceItems(preference.getEntries(), checkedItems,
+                new DialogInterface.OnMultiChoiceClickListener() {
+                    public void onClick(DialogInterface dialog, int which, boolean isChecked) {
+                        if (isChecked) {
+                            mPreferenceChanged |= mNewValues.add(
+                                    preference.getEntryValues()[which].toString());
+                        } else {
+                            mPreferenceChanged |= mNewValues.remove(
+                                    preference.getEntryValues()[which].toString());
+                        }
+                    }
+                });
+        mNewValues.clear();
+        mNewValues.addAll(preference.getValues());
+    }
+
+    @Override
+    public void onDialogClosed(boolean positiveResult) {
+        final MultiSelectListPreference preference = getListPreference();
+        if (positiveResult && mPreferenceChanged) {
+            final Set<String> values = mNewValues;
+            if (preference.callChangeListener(values)) {
+                preference.setValues(values);
+            }
+        }
+        mPreferenceChanged = false;
+    }
+
+}
diff --git a/v14/preference/src/android/support/v14/preference/PreferenceDialogFragment.java b/v14/preference/src/android/support/v14/preference/PreferenceDialogFragment.java
new file mode 100644
index 0000000..b9027a4
--- /dev/null
+++ b/v14/preference/src/android/support/v14/preference/PreferenceDialogFragment.java
@@ -0,0 +1,190 @@
+/*
+ * 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.v14.preference;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.app.Fragment;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.v7.preference.DialogPreference;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.TextView;
+
+public abstract class PreferenceDialogFragment extends DialogFragment implements
+        DialogInterface.OnClickListener {
+
+    protected static final String ARG_KEY = "key";
+
+    private DialogPreference mPreference;
+
+    /** Which button was clicked. */
+    private int mWhichButtonClicked;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        final Fragment rawFragment = getTargetFragment();
+        if (!(rawFragment instanceof DialogPreference.TargetFragment)) {
+            throw new IllegalStateException("Target fragment must implement TargetFragment" +
+                    " interface");
+        }
+
+        final DialogPreference.TargetFragment fragment =
+                (DialogPreference.TargetFragment) rawFragment;
+
+        final String key = getArguments().getString(ARG_KEY);
+        mPreference = (DialogPreference) fragment.findPreference(key);
+    }
+
+    @Override
+    public @NonNull
+    Dialog onCreateDialog(Bundle savedInstanceState) {
+        final Context context = getActivity();
+        mWhichButtonClicked = DialogInterface.BUTTON_NEGATIVE;
+
+        final AlertDialog.Builder builder = new AlertDialog.Builder(context)
+                .setTitle(mPreference.getDialogTitle())
+                .setIcon(mPreference.getDialogIcon())
+                .setPositiveButton(mPreference.getPositiveButtonText(), this)
+                .setNegativeButton(mPreference.getNegativeButtonText(), this);
+
+        View contentView = onCreateDialogView(context);
+        if (contentView != null) {
+            onBindDialogView(contentView);
+            builder.setView(contentView);
+        } else {
+            builder.setMessage(mPreference.getDialogMessage());
+        }
+
+        onPrepareDialogBuilder(builder);
+
+        // Create the dialog
+        final Dialog dialog = builder.create();
+        if (needInputMethod()) {
+            requestInputMethod(dialog);
+        }
+
+
+        return builder.create();
+    }
+
+    /**
+     * Get the preference that requested this dialog. Available after {@link #onCreate(Bundle)} has
+     * been called.
+     *
+     * @return The {@link DialogPreference} associated with this
+     * dialog.
+     */
+    public DialogPreference getPreference() {
+        return mPreference;
+    }
+
+    /**
+     * Prepares the dialog builder to be shown when the preference is clicked.
+     * Use this to set custom properties on the dialog.
+     * <p>
+     * Do not {@link AlertDialog.Builder#create()} or
+     * {@link AlertDialog.Builder#show()}.
+     */
+    protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {}
+
+    /**
+     * Returns whether the preference needs to display a soft input method when the dialog
+     * is displayed. Default is false. Subclasses should override this method if they need
+     * the soft input method brought up automatically.
+     * @hide
+     */
+    protected boolean needInputMethod() {
+        return false;
+    }
+
+    /**
+     * Sets the required flags on the dialog window to enable input method window to show up.
+     */
+    private void requestInputMethod(Dialog dialog) {
+        Window window = dialog.getWindow();
+        window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
+    }
+
+    /**
+     * Creates the content view for the dialog (if a custom content view is
+     * required). By default, it inflates the dialog layout resource if it is
+     * set.
+     *
+     * @return The content View for the dialog.
+     * @see DialogPreference#setLayoutResource(int)
+     */
+    protected View onCreateDialogView(Context context) {
+        final int resId = mPreference.getDialogLayoutResource();
+        if (resId == 0) {
+            return null;
+        }
+
+        LayoutInflater inflater = LayoutInflater.from(context);
+        return inflater.inflate(resId, null);
+    }
+
+    /**
+     * Binds views in the content View of the dialog to data.
+     * <p>
+     * Make sure to call through to the superclass implementation.
+     *
+     * @param view The content View of the dialog, if it is custom.
+     */
+    protected void onBindDialogView(View view) {
+        View dialogMessageView = view.findViewById(android.R.id.message);
+
+        if (dialogMessageView != null) {
+            final CharSequence message = mPreference.getDialogMessage();
+            int newVisibility = View.GONE;
+
+            if (!TextUtils.isEmpty(message)) {
+                if (dialogMessageView instanceof TextView) {
+                    ((TextView) dialogMessageView).setText(message);
+                }
+
+                newVisibility = View.VISIBLE;
+            }
+
+            if (dialogMessageView.getVisibility() != newVisibility) {
+                dialogMessageView.setVisibility(newVisibility);
+            }
+        }
+    }
+
+    @Override
+    public void onClick(DialogInterface dialog, int which) {
+        mWhichButtonClicked = which;
+    }
+
+    @Override
+    public void onDismiss(DialogInterface dialog) {
+        super.onDismiss(dialog);
+        onDialogClosed(mWhichButtonClicked == DialogInterface.BUTTON_POSITIVE);
+    }
+
+    public abstract void onDialogClosed(boolean positiveResult);
+}
diff --git a/v14/preference/src/android/support/v14/preference/PreferenceFragment.java b/v14/preference/src/android/support/v14/preference/PreferenceFragment.java
new file mode 100644
index 0000000..a51dab3
--- /dev/null
+++ b/v14/preference/src/android/support/v14/preference/PreferenceFragment.java
@@ -0,0 +1,577 @@
+/*
+ * 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.v14.preference;
+
+import android.app.DialogFragment;
+import android.app.Fragment;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.support.annotation.Nullable;
+import android.support.annotation.XmlRes;
+import android.support.v7.preference.DialogPreference;
+import android.support.v7.preference.EditTextPreference;
+import android.support.v7.preference.ListPreference;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceGroupAdapter;
+import android.support.v7.preference.PreferenceManager;
+import android.support.v7.preference.PreferenceScreen;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.util.TypedValue;
+import android.view.ContextThemeWrapper;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+/**
+ * Shows a hierarchy of {@link Preference} objects as
+ * lists. These preferences will
+ * automatically save to {@link android.content.SharedPreferences} as the user interacts with
+ * them. To retrieve an instance of {@link android.content.SharedPreferences} that the
+ * preference hierarchy in this fragment will use, call
+ * {@link PreferenceManager#getDefaultSharedPreferences(android.content.Context)}
+ * with a context in the same package as this fragment.
+ * <p>
+ * Furthermore, the preferences shown will follow the visual style of system
+ * preferences. It is easy to create a hierarchy of preferences (that can be
+ * shown on multiple screens) via XML. For these reasons, it is recommended to
+ * use this fragment (as a superclass) to deal with preferences in applications.
+ * <p>
+ * A {@link PreferenceScreen} object should be at the top of the preference
+ * hierarchy. Furthermore, subsequent {@link PreferenceScreen} in the hierarchy
+ * denote a screen break--that is the preferences contained within subsequent
+ * {@link PreferenceScreen} should be shown on another screen. The preference
+ * framework handles showing these other screens from the preference hierarchy.
+ * <p>
+ * The preference hierarchy can be formed in multiple ways:
+ * <li> From an XML file specifying the hierarchy
+ * <li> From different {@link android.app.Activity Activities} that each specify its own
+ * preferences in an XML file via {@link android.app.Activity} meta-data
+ * <li> From an object hierarchy rooted with {@link PreferenceScreen}
+ * <p>
+ * To inflate from XML, use the {@link #addPreferencesFromResource(int)}. The
+ * root element should be a {@link PreferenceScreen}. Subsequent elements can point
+ * to actual {@link Preference} subclasses. As mentioned above, subsequent
+ * {@link PreferenceScreen} in the hierarchy will result in the screen break.
+ * <p>
+ * To specify an object hierarchy rooted with {@link PreferenceScreen}, use
+ * {@link #setPreferenceScreen(PreferenceScreen)}.
+ * <p>
+ * As a convenience, this fragment implements a click listener for any
+ * preference in the current hierarchy, see
+ * {@link #onPreferenceTreeClick(Preference)}.
+ *
+ * <div class="special reference">
+ * <h3>Developer Guides</h3>
+ * <p>For information about using {@code PreferenceFragment},
+ * read the <a href="{@docRoot}guide/topics/ui/settings.html">Settings</a>
+ * guide.</p>
+ * </div>
+ *
+ * <a name="SampleCode"></a>
+ * <h3>Sample Code</h3>
+ *
+ * <p>The following sample code shows a simple preference fragment that is
+ * populated from a resource.  The resource it loads is:</p>
+ *
+ * {@sample development/samples/ApiDemos/res/xml/preferences.xml preferences}
+ *
+ * <p>The fragment implementation itself simply populates the preferences
+ * when created.  Note that the preferences framework takes care of loading
+ * the current values out of the app preferences and writing them when changed:</p>
+ *
+ * {@sample development/samples/ApiDemos/src/com/example/android/apis/preference/FragmentPreferences.java
+ *      fragment}
+ *
+ * @see Preference
+ * @see PreferenceScreen
+ */
+public abstract class PreferenceFragment extends Fragment implements
+        PreferenceManager.OnPreferenceTreeClickListener,
+        PreferenceManager.OnDisplayPreferenceDialogListener,
+        PreferenceManager.OnNavigateToScreenListener,
+        DialogPreference.TargetFragment {
+
+    /**
+     * Fragment argument used to specify the tag of the desired root
+     * {@link android.support.v7.preference.PreferenceScreen} object.
+     */
+    public static final String ARG_PREFERENCE_ROOT =
+            "android.support.v7.preference.PreferenceFragmentCompat.PREFERENCE_ROOT";
+
+    private static final String PREFERENCES_TAG = "android:preferences";
+
+    private static final String DIALOG_FRAGMENT_TAG =
+            "android.support.v14.preference.PreferenceFragment.DIALOG";
+
+    private PreferenceManager mPreferenceManager;
+    private RecyclerView mList;
+    private boolean mHavePrefs;
+    private boolean mInitDone;
+
+    private Context mStyledContext;
+
+    private int mLayoutResId = R.layout.preference_list_fragment;
+
+    /**
+     * The starting request code given out to preference framework.
+     */
+    private static final int FIRST_REQUEST_CODE = 100;
+
+    private static final int MSG_BIND_PREFERENCES = 1;
+    private Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+
+                case MSG_BIND_PREFERENCES:
+                    bindPreferences();
+                    break;
+            }
+        }
+    };
+
+    final private Runnable mRequestFocus = new Runnable() {
+        public void run() {
+            mList.focusableViewAvailable(mList);
+        }
+    };
+
+    /**
+     * Interface that PreferenceFragment's containing activity should
+     * implement to be able to process preference items that wish to
+     * switch to a specified fragment.
+     */
+    public interface OnPreferenceStartFragmentCallback {
+        /**
+         * Called when the user has clicked on a Preference that has
+         * a fragment class name associated with it.  The implementation
+         * should instantiate and switch to an instance of the given
+         * fragment.
+         * @param caller The fragment requesting navigation.
+         * @param pref The preference requesting the fragment.
+         * @return true if the fragment creation has been handled
+         */
+        boolean onPreferenceStartFragment(PreferenceFragment caller, Preference pref);
+    }
+
+    /**
+     * Interface that PreferenceFragment's containing activity should
+     * implement to be able to process preference items that wish to
+     * switch to a new screen of preferences.
+     */
+    public interface OnPreferenceStartScreenCallback {
+        /**
+         * Called when the user has clicked on a PreferenceScreen item in order to navigate to a new
+         * screen of preferences.
+         * @param caller The fragment requesting navigation.
+         * @param pref The preference screen to navigate to.
+         * @return true if the screen navigation has been handled
+         */
+        boolean onPreferenceStartScreen(PreferenceFragment caller, PreferenceScreen pref);
+    }
+
+    public interface OnPreferenceDisplayDialogCallback {
+
+        /**
+         *
+         * @param caller The fragment containing the preference requesting the dialog.
+         * @param pref The preference requesting the dialog.
+         * @return true if the dialog creation has been handled.
+         */
+        boolean onPreferenceDisplayDialog(PreferenceFragment caller, Preference pref);
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        final TypedValue tv = new TypedValue();
+        getActivity().getTheme().resolveAttribute(R.attr.preferenceTheme, tv, true);
+        final int theme = tv.resourceId;
+        if (theme <= 0) {
+            throw new IllegalStateException("Must specify preferenceTheme in theme");
+        }
+        mStyledContext = new ContextThemeWrapper(getActivity(), theme);
+
+        mPreferenceManager = new PreferenceManager(mStyledContext);
+        mPreferenceManager.setOnNavigateToScreenListener(this);
+        final Bundle args = getArguments();
+        final String rootKey;
+        if (args != null) {
+            rootKey = getArguments().getString(ARG_PREFERENCE_ROOT);
+        } else {
+            rootKey = null;
+        }
+        onCreatePreferences(savedInstanceState, rootKey);
+    }
+
+    /**
+     * Called during {@link #onCreate(Bundle)} to supply the preferences for this fragment.
+     * Subclasses are expected to call {@link #setPreferenceScreen(PreferenceScreen)} either
+     * directly or via helper methods such as {@link #addPreferencesFromResource(int)}.
+     *
+     * @param savedInstanceState If the fragment is being re-created from
+     *                           a previous saved state, this is the state.
+     * @param rootKey If non-null, this preference fragment should be rooted at the
+     *                {@link android.support.v7.preference.PreferenceScreen} with this key.
+     */
+    public abstract void onCreatePreferences(Bundle savedInstanceState, String rootKey);
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+
+        TypedArray a = mStyledContext.obtainStyledAttributes(null,
+                R.styleable.PreferenceFragmentCompat,
+                R.attr.preferenceFragmentStyle,
+                0);
+
+        mLayoutResId = a.getResourceId(R.styleable.PreferenceFragmentCompat_layout,
+                mLayoutResId);
+
+        a.recycle();
+
+        final View view = inflater.inflate(mLayoutResId, container, false);
+
+        final View rawListContainer = view.findViewById(R.id.list_container);
+        if (!(rawListContainer instanceof ViewGroup)) {
+            throw new RuntimeException("Content has view with id attribute 'R.id.list_container' "
+                    + "that is not a ViewGroup class");
+        }
+
+        final ViewGroup listContainer = (ViewGroup) rawListContainer;
+
+        final RecyclerView listView = onCreateRecyclerView(inflater, listContainer,
+                savedInstanceState);
+        if (listView == null) {
+            throw new RuntimeException("Could not create RecyclerView");
+        }
+
+        mList = listView;
+        listContainer.addView(mList);
+        mHandler.post(mRequestFocus);
+        return view;
+    }
+
+    @Override
+    public void onActivityCreated(Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+
+        if (mHavePrefs) {
+            bindPreferences();
+        }
+
+        mInitDone = true;
+
+        if (savedInstanceState != null) {
+            Bundle container = savedInstanceState.getBundle(PREFERENCES_TAG);
+            if (container != null) {
+                final PreferenceScreen preferenceScreen = getPreferenceScreen();
+                if (preferenceScreen != null) {
+                    preferenceScreen.restoreHierarchyState(container);
+                }
+            }
+        }
+    }
+
+    @Override
+    public void onStart() {
+        super.onStart();
+        mPreferenceManager.setOnPreferenceTreeClickListener(this);
+        mPreferenceManager.setOnDisplayPreferenceDialogListener(this);
+    }
+
+    @Override
+    public void onStop() {
+        super.onStop();
+        mPreferenceManager.setOnPreferenceTreeClickListener(null);
+        mPreferenceManager.setOnDisplayPreferenceDialogListener(null);
+    }
+
+    @Override
+    public void onDestroyView() {
+        mList = null;
+        mHandler.removeCallbacks(mRequestFocus);
+        mHandler.removeMessages(MSG_BIND_PREFERENCES);
+        super.onDestroyView();
+    }
+
+    @Override
+    public void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+
+        final PreferenceScreen preferenceScreen = getPreferenceScreen();
+        if (preferenceScreen != null) {
+            Bundle container = new Bundle();
+            preferenceScreen.saveHierarchyState(container);
+            outState.putBundle(PREFERENCES_TAG, container);
+        }
+    }
+
+    /**
+     * Returns the {@link PreferenceManager} used by this fragment.
+     * @return The {@link PreferenceManager}.
+     */
+    public PreferenceManager getPreferenceManager() {
+        return mPreferenceManager;
+    }
+
+    /**
+     * Sets the root of the preference hierarchy that this fragment is showing.
+     *
+     * @param preferenceScreen The root {@link PreferenceScreen} of the preference hierarchy.
+     */
+    public void setPreferenceScreen(PreferenceScreen preferenceScreen) {
+        if (mPreferenceManager.setPreferences(preferenceScreen) && preferenceScreen != null) {
+            onUnbindPreferences();
+            mHavePrefs = true;
+            if (mInitDone) {
+                postBindPreferences();
+            }
+        }
+    }
+
+    /**
+     * Gets the root of the preference hierarchy that this fragment is showing.
+     *
+     * @return The {@link PreferenceScreen} that is the root of the preference
+     *         hierarchy.
+     */
+    public PreferenceScreen getPreferenceScreen() {
+        return mPreferenceManager.getPreferenceScreen();
+    }
+
+    /**
+     * Inflates the given XML resource and adds the preference hierarchy to the current
+     * preference hierarchy.
+     *
+     * @param preferencesResId The XML resource ID to inflate.
+     */
+    public void addPreferencesFromResource(@XmlRes int preferencesResId) {
+        requirePreferenceManager();
+
+        setPreferenceScreen(mPreferenceManager.inflateFromResource(mStyledContext,
+                preferencesResId, getPreferenceScreen()));
+    }
+
+    /**
+     * Inflates the given XML resource and replaces the current preference hierarchy (if any) with
+     * the preference hierarchy rooted at {@code key}.
+     *
+     * @param preferencesResId The XML resource ID to inflate.
+     * @param key The preference key of the {@link android.support.v7.preference.PreferenceScreen}
+     *            to use as the root of the preference hierarchy, or null to use the root
+     *            {@link android.support.v7.preference.PreferenceScreen}.
+     */
+    public void setPreferencesFromResource(@XmlRes int preferencesResId, @Nullable String key) {
+        requirePreferenceManager();
+
+        final PreferenceScreen xmlRoot = mPreferenceManager.inflateFromResource(mStyledContext,
+                preferencesResId, null);
+
+        final Preference root;
+        if (key != null) {
+            root = xmlRoot.findPreference(key);
+            if (!(root instanceof PreferenceScreen)) {
+                throw new IllegalArgumentException("Preference object with key " + key
+                        + " is not a PreferenceScreen");
+            }
+        } else {
+            root = xmlRoot;
+        }
+
+        setPreferenceScreen((PreferenceScreen) root);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean onPreferenceTreeClick(Preference preference) {
+        if (preference.getFragment() != null) {
+            boolean handled = false;
+            if (getTargetFragment() instanceof OnPreferenceStartFragmentCallback) {
+                handled = ((OnPreferenceStartFragmentCallback) getTargetFragment())
+                        .onPreferenceStartFragment(this, preference);
+            }
+            if (!handled && getActivity() instanceof OnPreferenceStartFragmentCallback){
+                handled = ((OnPreferenceStartFragmentCallback) getActivity())
+                        .onPreferenceStartFragment(this, preference);
+            }
+            return handled;
+        }
+        return false;
+    }
+
+    /**
+     * Called by
+     * {@link android.support.v7.preference.PreferenceScreen#onClick()} in order to navigate to a
+     * new screen of preferences. Calls
+     * {@link PreferenceFragment.OnPreferenceStartScreenCallback#onPreferenceStartScreen}
+     * if the target fragment or containing activity implements
+     * {@link PreferenceFragment.OnPreferenceStartScreenCallback}.
+     * @param preferenceScreen The {@link android.support.v7.preference.PreferenceScreen} to
+     *                         navigate to.
+     */
+    @Override
+    public void onNavigateToScreen(PreferenceScreen preferenceScreen) {
+        boolean handled = false;
+        if (getTargetFragment() instanceof OnPreferenceStartScreenCallback) {
+            handled = ((OnPreferenceStartScreenCallback) getTargetFragment())
+                    .onPreferenceStartScreen(this, preferenceScreen);
+        }
+        if (!handled && getActivity() instanceof OnPreferenceStartScreenCallback) {
+            ((OnPreferenceStartScreenCallback) getActivity())
+                    .onPreferenceStartScreen(this, preferenceScreen);
+        }
+    }
+
+    /**
+     * Finds a {@link Preference} based on its key.
+     *
+     * @param key The key of the preference to retrieve.
+     * @return The {@link Preference} with the key, or null.
+     * @see android.support.v7.preference.PreferenceGroup#findPreference(CharSequence)
+     */
+    public Preference findPreference(CharSequence key) {
+        if (mPreferenceManager == null) {
+            return null;
+        }
+        return mPreferenceManager.findPreference(key);
+    }
+
+    private void requirePreferenceManager() {
+        if (mPreferenceManager == null) {
+            throw new RuntimeException("This should be called after super.onCreate.");
+        }
+    }
+
+    private void postBindPreferences() {
+        if (mHandler.hasMessages(MSG_BIND_PREFERENCES)) return;
+        mHandler.obtainMessage(MSG_BIND_PREFERENCES).sendToTarget();
+    }
+
+    private void bindPreferences() {
+        final PreferenceScreen preferenceScreen = getPreferenceScreen();
+        if (preferenceScreen != null) {
+            getListView().setAdapter(onCreateAdapter(preferenceScreen));
+        }
+        onBindPreferences();
+    }
+
+    /** @hide */
+    protected void onBindPreferences() {
+    }
+
+    /** @hide */
+    protected void onUnbindPreferences() {
+    }
+
+    public final RecyclerView getListView() {
+        return mList;
+    }
+
+    /**
+     * Creates the {@link android.support.v7.widget.RecyclerView} used to display the preferences.
+     * Subclasses may override this to return a customized
+     * {@link android.support.v7.widget.RecyclerView}.
+     * @param inflater The LayoutInflater object that can be used to inflate the
+     *                 {@link android.support.v7.widget.RecyclerView}.
+     * @param parent The parent {@link android.view.View} that the RecyclerView will be attached to.
+     *               This method should not add the view itself, but this can be used to generate
+     *               the LayoutParams of the view.
+     * @param savedInstanceState If non-null, this view is being re-constructed from a previous
+     *                           saved state as given here
+     * @return A new RecyclerView object to be placed into the view hierarchy
+     */
+    public RecyclerView onCreateRecyclerView(LayoutInflater inflater, ViewGroup parent,
+            Bundle savedInstanceState) {
+        RecyclerView recyclerView = (RecyclerView) inflater
+                .inflate(R.layout.preference_recyclerview, parent, false);
+
+        recyclerView.setLayoutManager(onCreateLayoutManager());
+
+        return recyclerView;
+    }
+
+    /**
+     * Called from {@link #onCreateRecyclerView} to create the
+     * {@link android.support.v7.widget.RecyclerView.LayoutManager} for the created
+     * {@link android.support.v7.widget.RecyclerView}.
+     * @return A new {@link android.support.v7.widget.RecyclerView.LayoutManager} instance.
+     */
+    public RecyclerView.LayoutManager onCreateLayoutManager() {
+        return new LinearLayoutManager(getActivity());
+    }
+
+    /**
+     * Creates the root adapter.
+     *
+     * @param preferenceScreen Preference screen object to create the adapter for.
+     * @return An adapter that contains the preferences contained in this {@link PreferenceScreen}.
+     */
+    protected RecyclerView.Adapter onCreateAdapter(PreferenceScreen preferenceScreen) {
+        return new PreferenceGroupAdapter(preferenceScreen);
+    }
+
+    /**
+     * Called when a preference in the tree requests to display a dialog. Subclasses should
+     * override this method to display custom dialogs or to handle dialogs for custom preference
+     * classes.
+     *
+     * @param preference The Preference object requesting the dialog.
+     */
+    @Override
+    public void onDisplayPreferenceDialog(Preference preference) {
+
+        boolean handled = false;
+        if (getTargetFragment() instanceof OnPreferenceDisplayDialogCallback) {
+            handled = ((OnPreferenceDisplayDialogCallback) getTargetFragment())
+                    .onPreferenceDisplayDialog(this, preference);
+        }
+        if (!handled && getActivity() instanceof OnPreferenceDisplayDialogCallback) {
+            handled = ((OnPreferenceDisplayDialogCallback) getActivity())
+                    .onPreferenceDisplayDialog(this, preference);
+        }
+
+        if (handled) {
+            return;
+        }
+
+        // check if dialog is already showing
+        if (getFragmentManager().findFragmentByTag(DIALOG_FRAGMENT_TAG) != null) {
+            return;
+        }
+
+        final DialogFragment f;
+        if (preference instanceof EditTextPreference) {
+            f = EditTextPreferenceDialogFragment.newInstance(preference.getKey());
+        } else if (preference instanceof ListPreference) {
+            f = ListPreferenceDialogFragment.newInstance(preference.getKey());
+        } else if (preference instanceof MultiSelectListPreference) {
+            f = MultiSelectListPreferenceDialogFragment.newInstance(preference.getKey());
+        } else {
+            throw new IllegalArgumentException("Tried to display dialog for unknown " +
+                    "preference type. Did you forget to override onDisplayPreferenceDialog()?");
+        }
+        f.setTargetFragment(this, 0);
+        f.show(getFragmentManager(), DIALOG_FRAGMENT_TAG);
+    }
+
+}
diff --git a/v14/preference/src/android/support/v14/preference/SwitchPreference.java b/v14/preference/src/android/support/v14/preference/SwitchPreference.java
new file mode 100644
index 0000000..048bc6c
--- /dev/null
+++ b/v14/preference/src/android/support/v14/preference/SwitchPreference.java
@@ -0,0 +1,214 @@
+/*
+* 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.v14.preference;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.support.v4.content.res.TypedArrayUtils;
+import android.support.v7.preference.PreferenceViewHolder;
+import android.support.v7.preference.TwoStatePreference;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.Checkable;
+import android.widget.CompoundButton;
+import android.widget.Switch;
+
+/**
+ * A {@link android.support.v7.preference.Preference} that provides a two-state toggleable option.
+ * <p>
+ * This preference will store a boolean into the SharedPreferences.
+ *
+ * @attr ref android.R.styleable#SwitchPreference_summaryOff
+ * @attr ref android.R.styleable#SwitchPreference_summaryOn
+ * @attr ref android.R.styleable#SwitchPreference_switchTextOff
+ * @attr ref android.R.styleable#SwitchPreference_switchTextOn
+ * @attr ref android.R.styleable#SwitchPreference_disableDependentsState
+ */
+public class SwitchPreference extends TwoStatePreference {
+    private final Listener mListener = new Listener();
+
+    // Switch text for on and off states
+    private CharSequence mSwitchOn;
+    private CharSequence mSwitchOff;
+
+    private class Listener implements CompoundButton.OnCheckedChangeListener {
+        @Override
+        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+            if (!callChangeListener(isChecked)) {
+                // Listener didn't like it, change it back.
+                // CompoundButton will make sure we don't recurse.
+                buttonView.setChecked(!isChecked);
+                return;
+            }
+
+            SwitchPreference.this.setChecked(isChecked);
+        }
+    }
+
+    /**
+     * Construct a new SwitchPreference with the given style options.
+     *
+     * @param context The Context that will style this preference
+     * @param attrs Style attributes that differ from the default
+     * @param defStyleAttr An attribute in the current theme that contains a
+     *        reference to a style resource that supplies default values for
+     *        the view. Can be 0 to not look for defaults.
+     * @param defStyleRes A resource identifier of a style resource that
+     *        supplies default values for the view, used only if
+     *        defStyleAttr is 0 or can not be found in the theme. Can be 0
+     *        to not look for defaults.
+     */
+    public SwitchPreference(Context context, AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+
+        TypedArray a = context.obtainStyledAttributes(attrs,
+                R.styleable.SwitchPreference, defStyleAttr, defStyleRes);
+
+        setSummaryOn(TypedArrayUtils.getString(a, R.styleable.SwitchPreference_summaryOn,
+                R.styleable.SwitchPreference_android_summaryOn));
+
+        setSummaryOff(TypedArrayUtils.getString(a, R.styleable.SwitchPreference_summaryOff,
+                R.styleable.SwitchPreference_android_summaryOff));
+
+        setSwitchTextOn(TypedArrayUtils.getString(a,
+                R.styleable.SwitchPreference_switchTextOn,
+                R.styleable.SwitchPreference_android_switchTextOn));
+
+        setSwitchTextOff(TypedArrayUtils.getString(a,
+                R.styleable.SwitchPreference_switchTextOff,
+                R.styleable.SwitchPreference_android_switchTextOff));
+
+        setDisableDependentsState(TypedArrayUtils.getBoolean(a,
+                R.styleable.SwitchPreference_disableDependentsState,
+                R.styleable.SwitchPreference_android_disableDependentsState, false));
+
+        a.recycle();
+    }
+
+    /**
+     * Construct a new SwitchPreference with the given style options.
+     *
+     * @param context The Context that will style this preference
+     * @param attrs Style attributes that differ from the default
+     * @param defStyleAttr An attribute in the current theme that contains a
+     *        reference to a style resource that supplies default values for
+     *        the view. Can be 0 to not look for defaults.
+     */
+    public SwitchPreference(Context context, AttributeSet attrs, int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0);
+    }
+
+    /**
+     * Construct a new SwitchPreference with the given style options.
+     *
+     * @param context The Context that will style this preference
+     * @param attrs Style attributes that differ from the default
+     */
+    public SwitchPreference(Context context, AttributeSet attrs) {
+        this(context, attrs, R.attr.switchPreferenceStyle);
+    }
+
+    /**
+     * Construct a new SwitchPreference with default style options.
+     *
+     * @param context The Context that will style this preference
+     */
+    public SwitchPreference(Context context) {
+        this(context, null);
+    }
+
+    @Override
+    public void onBindViewHolder(PreferenceViewHolder holder) {
+        super.onBindViewHolder(holder);
+
+        View checkableView = holder.findViewById(R.id.switchWidget);
+        if (checkableView != null && checkableView instanceof Checkable) {
+            if (checkableView instanceof Switch) {
+                final Switch switchView = (Switch) checkableView;
+                switchView.setOnCheckedChangeListener(null);
+            }
+
+            ((Checkable) checkableView).setChecked(mChecked);
+
+            if (checkableView instanceof Switch) {
+                final Switch switchView = (Switch) checkableView;
+                switchView.setTextOn(mSwitchOn);
+                switchView.setTextOff(mSwitchOff);
+                switchView.setOnCheckedChangeListener(mListener);
+            }
+        }
+
+        syncSummaryView(holder);
+    }
+
+    /**
+     * Set the text displayed on the switch widget in the on state.
+     * This should be a very short string; one word if possible.
+     *
+     * @param onText Text to display in the on state
+     */
+    public void setSwitchTextOn(CharSequence onText) {
+        mSwitchOn = onText;
+        notifyChanged();
+    }
+
+    /**
+     * Set the text displayed on the switch widget in the off state.
+     * This should be a very short string; one word if possible.
+     *
+     * @param offText Text to display in the off state
+     */
+    public void setSwitchTextOff(CharSequence offText) {
+        mSwitchOff = offText;
+        notifyChanged();
+    }
+
+    /**
+     * Set the text displayed on the switch widget in the on state.
+     * This should be a very short string; one word if possible.
+     *
+     * @param resId The text as a string resource ID
+     */
+    public void setSwitchTextOn(int resId) {
+        setSwitchTextOn(getContext().getString(resId));
+    }
+
+    /**
+     * Set the text displayed on the switch widget in the off state.
+     * This should be a very short string; one word if possible.
+     *
+     * @param resId The text as a string resource ID
+     */
+    public void setSwitchTextOff(int resId) {
+        setSwitchTextOff(getContext().getString(resId));
+    }
+
+    /**
+     * @return The text that will be displayed on the switch widget in the on state
+     */
+    public CharSequence getSwitchTextOn() {
+        return mSwitchOn;
+    }
+
+    /**
+     * @return The text that will be displayed on the switch widget in the off state
+     */
+    public CharSequence getSwitchTextOff() {
+        return mSwitchOff;
+    }
+}
diff --git a/v17/leanback/api/current.txt b/v17/leanback/api/current.txt
index 336a422..0dd5831 100644
--- a/v17/leanback/api/current.txt
+++ b/v17/leanback/api/current.txt
@@ -504,6 +504,22 @@
 
 }
 
+package android.support.v17.leanback.view {
+
+  public class ViewGroupOverlayHelper {
+    ctor public ViewGroupOverlayHelper();
+    method public static void addChildToOverlay(android.view.ViewGroup, android.view.View);
+    method public static void removeChildFromOverlay(android.view.ViewGroup, android.view.View);
+    method public static boolean supportsOverlay();
+  }
+
+  public static abstract interface ViewGroupOverlayHelper.Impl {
+    method public abstract void addChildToOverlay(android.view.ViewGroup, android.view.View);
+    method public abstract void removeChildFromOverlay(android.view.ViewGroup, android.view.View);
+  }
+
+}
+
 package android.support.v17.leanback.widget {
 
   public abstract class AbstractDetailsDescriptionPresenter extends android.support.v17.leanback.widget.Presenter {
diff --git a/v17/leanback/build.gradle b/v17/leanback/build.gradle
index b34e2a1..8dc79e8 100644
--- a/v17/leanback/build.gradle
+++ b/v17/leanback/build.gradle
@@ -27,6 +27,11 @@
         androidTest.java.srcDir 'tests/java'
     }
 
+    compileOptions {
+        sourceCompatibility JavaVersion.VERSION_1_7
+        targetCompatibility JavaVersion.VERSION_1_7
+    }
+
     lintOptions {
         // TODO: fix errors and reenable.
         abortOnError false
diff --git a/v17/leanback/jbmr2/android/support/v17/leanback/view/ViewGroupOverlayHelperJbmr2.java b/v17/leanback/jbmr2/android/support/v17/leanback/view/ViewGroupOverlayHelperJbmr2.java
new file mode 100644
index 0000000..12dda9a
--- /dev/null
+++ b/v17/leanback/jbmr2/android/support/v17/leanback/view/ViewGroupOverlayHelperJbmr2.java
@@ -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
+ */
+
+package android.support.v17.leanback.view;
+
+import android.view.View;
+import android.view.ViewGroup;
+
+public class ViewGroupOverlayHelperJbmr2 {
+
+    public static void addChildToOverlay(ViewGroup parent, View child) {
+        parent.getOverlay().add(child);
+    }
+
+    public static void removeChildFromOverlay(ViewGroup parent, View child) {
+        parent.getOverlay().remove(child);
+    }
+}
diff --git a/v17/leanback/res/values-af/strings.xml b/v17/leanback/res/values-af/strings.xml
index fa93257..c7109bb 100644
--- a/v17/leanback/res/values-af/strings.xml
+++ b/v17/leanback/res/values-af/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"Praat om te soek"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"Deursoek <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Praat om <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g> te deursoek"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"Speel"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"Laat wag"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"Vinnig vorentoe"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"Spoel vorentoe %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"Spoel terug"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"Spoel terug %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"Slaan volgende oor"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"Slaan vorige oor"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"Nog handelinge"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"Ontkies laaik baie"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"Kies laaik baie"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"Ontkies laaik niks"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"Kies laaik niks"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"Herhaal niks"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"Herhaal alles"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"Herhaal een"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"Aktiveer skommel"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"Deaktiveer skommel"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"Aktiveer hoë gehalte"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Deaktiveer hoë gehalte"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Aktiveer onderskrifte"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Deaktiveer onderskrifte"</string>
 </resources>
diff --git a/v17/leanback/res/values-am/strings.xml b/v17/leanback/res/values-am/strings.xml
index 4b0f26f..d5bf0f5 100644
--- a/v17/leanback/res/values-am/strings.xml
+++ b/v17/leanback/res/values-am/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"ለመፈለግ ይናገሩ"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g> ፈልግ"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>ን ለመፈለግ ይናገሩ"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"አጫውት"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"ለአፍታ አቁም"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"በፍጥነት አሳልፍ"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"በ%1$dX ወደፊት አፍጥን"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"ወደኋላ አጠንጥን"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"በ%1$dX አጠንጥን"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"የሚቀጥለውን ዝለል"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"የቀደመውን ዝለል"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"ተጨማሪ እርምጃዎች"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"አውራጣት ወደ ላይን አትምረጥ"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"አውራ ጣት ወደላይን ምረጥ"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"አውራ ጣት ወደታችን አትምረጥ"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"አውራ ጣት ወደታችን ምረጥ"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"ምንም አትድገም"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"ሁሉንም ድገም"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"አንዱን ድገም"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"መበወዣን አንቃ"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"መበወዣን አሰናክል"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"ከፍተኛ ጥራትን አንቃ"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"ከፍተኛ ጥራትን አሰናክል"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"ዝግ የምስል ስር ጽሑፍ አጻጻፍን አንቃ"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"ዝግ የምስል ስር ጽሑፍ አጻጻፍን አሰናክል"</string>
 </resources>
diff --git a/v17/leanback/res/values-ar/strings.xml b/v17/leanback/res/values-ar/strings.xml
index 6540a3e..31f4d1a 100644
--- a/v17/leanback/res/values-ar/strings.xml
+++ b/v17/leanback/res/values-ar/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"التحدث  للبحث"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"بحث في <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"تحدّث للبحث في <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"تشغيل"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"إيقاف مؤقت"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"تقديم سريع"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"‏التقديم السريع %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"إرجاع"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"‏الترجيع %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"تخطي التالي"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"تخطي السابق"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"مزيد من الإجراءات"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"إلغاء تحديد زر \"أعجبني\""</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"تحديد زر \"أعجبني\""</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"إلغاء تحديد زر \"لم يعجبني\""</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"تحديد زر \"لم يعجبني\""</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"عدم التكرار"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"تكرار الكل"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"تكرار مقطع واحد"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"تمكين الترتيب العشوائي"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"تعطيل الترتيب العشوائي"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"تمكين الجودة العالية"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"تعطيل الجودة العالية"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"تمكين الترجمة المصاحبة"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"تعطيل الترجمة المصاحبة"</string>
 </resources>
diff --git a/v17/leanback/res/values-az-rAZ/strings.xml b/v17/leanback/res/values-az-rAZ/strings.xml
new file mode 100644
index 0000000..d1e685f
--- /dev/null
+++ b/v17/leanback/res/values-az-rAZ/strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+Copyright (C) 2014 The Android Open Source Project
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="orb_search_action" msgid="5651268540267663887">"Axtarış Fəaliyyəti"</string>
+    <string name="lb_search_bar_hint" msgid="8325490927970116252">"Axtarış"</string>
+    <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"Axtarış üçün danışın"</string>
+    <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"Axtarış: <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Axtarış üçün danışın: <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"Oyun"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"Pauza"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"İrəli Ötürmə"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"İrəli sarı %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"Geri ötürmə"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"Geri sarı %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"Növbətini atlayın"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"Öncəkini atlayın"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"Digər fəaliyyətlər"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"Bəyənməkdən imtina edin"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"Bəyənin"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"Bəyənməməkdən imtina edin"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"Bəyənməyin"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"Təkrarlanmasın"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"Hamısını təkrarlayın"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"Biri təkrarlansın"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"Qarışdırma aktiv edilsin"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"Qarışdırma deaktiv edilsin"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"Yüksək keyfiyyəti aktiv edin"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Yüksək keyfiyyəti deaktiv edin"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Qapalı çəkilişi aktiv edin"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Qapalı çəkilişi deaktiv edin"</string>
+</resources>
diff --git a/v17/leanback/res/values-bg/strings.xml b/v17/leanback/res/values-bg/strings.xml
index 9cd9b5c..de0b6f8 100644
--- a/v17/leanback/res/values-bg/strings.xml
+++ b/v17/leanback/res/values-bg/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"Говорете, за да търсите"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"Търсете в/ъв <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Говорете, за да търсите в/ъв <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"Пускане"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"Поставяне на пауза"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"Превъртане напред"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"Превъртане напред със скорост %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"Превъртане назад"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"Превъртане назад със скорост %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"Напред към следващия елемент"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"Назад към предишния елемент"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"Още действия"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"Премахване на избора от „Харесва ми“"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"Избиране на „Харесва ми“"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"Премахване на избора от „Не ми харесва“"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"Избиране на „Не ми харесва“"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"Без повтаряне"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"Повтаряне на всички"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"Повтаряне на един елемент"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"Активиране на разбъркването"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"Деактивиране на разбъркването"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"Активиране на високото качество"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Деактивиране на високото качество"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Активиране на субтитрите"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Деактивиране на субтитрите"</string>
 </resources>
diff --git a/v17/leanback/res/values-bn-rBD/strings.xml b/v17/leanback/res/values-bn-rBD/strings.xml
index 400553a..4f0526c 100644
--- a/v17/leanback/res/values-bn-rBD/strings.xml
+++ b/v17/leanback/res/values-bn-rBD/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"অনুসন্ধান করতে বলুন"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g> অনুসন্ধান করুন"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g> অনুসন্ধান করতে বলুন"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"চালান"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"বিরাম দিন"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"দ্রুত ফরওয়ার্ড"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"দ্রুত ফরওয়ার্ড %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"পেছনের দিকে যান"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"পেছনের দিকে যান %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"সরাসরি পরেরটিতে চলে যান"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"সরাসরি আগেরটিতে চলে যান"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"আরো অ্যাকশন"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"উপরের দিকে বুড়ো আঙ্গুল নির্দেশিত চিহ্ন নির্বাচন মুক্ত করুন"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"উপরের দিকে বুড়ো আঙ্গুল নির্দেশিত চিহ্ন নির্বাচিত করুন"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"নীচের দিকে বুড়ো আঙ্গুল নির্দেশিত চিহ্ন নির্বাচন মুক্ত করুন"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"নীচের দিকে বুড়ো আঙ্গুল নির্দেশিত চিহ্ন নির্বাচন করুন"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"একটিরও পুনরাবৃত্তি করবেন না"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"সবগুলির পুনরাবৃত্তি করুন"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"একটির পুনরাবৃত্তি করুন"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"শাফল করা সক্ষম করুন"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"শাফল করা অক্ষম করুন"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"উচ্চ গুণমান সক্ষম করুন"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"উচ্চ গুণমান অক্ষম করুন"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"সাবটাইটেল সক্ষম করুন"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"সাবটাইটেল অক্ষম করুন"</string>
 </resources>
diff --git a/v17/leanback/res/values-ca/strings.xml b/v17/leanback/res/values-ca/strings.xml
index 9087b56..187f5af 100644
--- a/v17/leanback/res/values-ca/strings.xml
+++ b/v17/leanback/res/values-ca/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"Parla per fer una cerca."</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"Cerca a <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>."</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Parla per cercar a <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>."</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"Reprodueix"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"Posa en pausa"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"Avança ràpidament"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"Avança ràpidament %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"Rebobina"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"Rebobina %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"Passa al següent"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"Passa a l\'anterior"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"Més accions"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"Anul·la \"M\'agrada\""</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"Selecciona \"M\'agrada\""</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"Anul·la \"No m\'agrada\""</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"Selecciona \"M\'agrada\""</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"No en repeteixis cap"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"Repeteix-ho tot"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"Repeteix-ne un"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"Activa la reproducció aleatòria"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"Desactiva la reproducció aleatòria"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"Activa l\'alta qualitat"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Desactiva l\'alta qualitat"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Activa els subtítols tancats"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Desactiva els subtítols tancats"</string>
 </resources>
diff --git a/v17/leanback/res/values-cs/strings.xml b/v17/leanback/res/values-cs/strings.xml
index 7c5b18c..1a60828 100644
--- a/v17/leanback/res/values-cs/strings.xml
+++ b/v17/leanback/res/values-cs/strings.xml
@@ -21,5 +21,29 @@
     <string name="lb_search_bar_hint" msgid="8325490927970116252">"Vyhledávání"</string>
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"Vyhledávejte hlasem"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"Hledat <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
-    <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Vyhledávejte v kontextu <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g> hlasem"</string>
+    <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Vyhledávejte v kategorii „<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>“ hlasem"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$d×"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$d×"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"Přehrát"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"Pozastavit"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"Přetočit vpřed"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"Přetočit vpřed %1$d×"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"Přetočit zpět"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"Přetočit zpět %1$d×"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"Přeskočit na další"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"Přeskočit na předchozí"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"Další akce"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"Zrušit výběr hodnocení palec nahoru"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"Vybrat hodnocení palec nahoru"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"Zrušit výběr hodnocení palec dolů"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"Vybrat hodnocení palec dolů"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"Neopakovat"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"Opakovat vše"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"Opakovat jednu položku"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"Zapnout náhodné přehrávání"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"Vypnout náhodné přehrávání"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"Zapnout vysokou kvalitu"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Vypnout vysokou kvalitu"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Zapnout titulky"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Vypnout titulky"</string>
 </resources>
diff --git a/v17/leanback/res/values-da/strings.xml b/v17/leanback/res/values-da/strings.xml
index 51a195a..e3e0f9f 100644
--- a/v17/leanback/res/values-da/strings.xml
+++ b/v17/leanback/res/values-da/strings.xml
@@ -17,9 +17,33 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="orb_search_action" msgid="5651268540267663887">"Søgehandling"</string>
+    <string name="orb_search_action" msgid="5651268540267663887">"Søg handling"</string>
     <string name="lb_search_bar_hint" msgid="8325490927970116252">"Søg"</string>
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"Tal for at søge"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"Søg efter <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Tal for at søge efter <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"Afspil"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"Sæt på pause"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"Spol frem"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"Spol frem %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"Spol tilbage"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"Spol tilbage %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"Spring til næste"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"Spring til forrige"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"Flere handlinger"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"Fravælg tommelfinger op"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"Vælg tommelfinger op"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"Fravælg tommelfinger ned"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"Vælg tommelfinger ned"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"Gentag ingen"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"Gentag alle"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"Gentag en"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"Aktivér bland"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"Deaktiver bland"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"Aktivér høj aktivitet"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Deaktiver høj kvalitet"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Aktivér undertekster"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Deaktiver undertekster"</string>
 </resources>
diff --git a/v17/leanback/res/values-de/strings.xml b/v17/leanback/res/values-de/strings.xml
index 1b353a0..d729f7c 100644
--- a/v17/leanback/res/values-de/strings.xml
+++ b/v17/leanback/res/values-de/strings.xml
@@ -21,5 +21,29 @@
     <string name="lb_search_bar_hint" msgid="8325490927970116252">"Suchen"</string>
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"Zum Suchen sprechen"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"In <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g> suchen"</string>
-    <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Zum Suchen in <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g> sprechen"</string>
+    <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Zum Suchen in der Kategorie \"<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>\" sprechen"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dx"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dx"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"Wiedergabe"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"Pausieren"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"Vorspulen"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"Vorspulen %1$dx"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"Zurückspulen"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"Zurückspulen %1$dx"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"Nächsten Titel überspringen"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"Vorherigen Titel überspringen"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"Weitere Aktionen"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"\"Mag ich\" deaktivieren"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"\"Mag ich\" aktivieren"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"\"Mag ich nicht\" deaktivieren"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"\"Mag ich nicht\" aktivieren"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"Keinen Titel wiederholen"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"Alle wiederholen"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"Einen Titel wiederholen"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"Zufallsmix aktivieren"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"Zufallsmix deaktivieren"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"Hohe Qualität aktivieren"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Hohe Qualität deaktivieren"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Untertitel aktivieren"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Untertitel deaktivieren"</string>
 </resources>
diff --git a/v17/leanback/res/values-el/strings.xml b/v17/leanback/res/values-el/strings.xml
index fc8c159..9b93dcf 100644
--- a/v17/leanback/res/values-el/strings.xml
+++ b/v17/leanback/res/values-el/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"Μιλήστε για να κάνετε αναζήτηση"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"Αναζήτηση <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Μιλήστε για αναζήτηση <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"Αναπαραγωγή"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"Παύση"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"Γρήγορη προώθηση"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"Γρήγορη προώθηση %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"Επαναφορά"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"Επαναφορά %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"Παράβλεψη επόμενου"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"Παράβλεψη προηγούμενου"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"Περισσότερες ενέργειες"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"Κατάργηση επιλογής \"Μου αρέσουν\""</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"Επιλογή \"Μου αρέσουν\""</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"Κατάργηση επιλογής \"Δεν μου αρέσουν\""</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"Επιλογή \"Δεν μου αρέσουν\""</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"Καμία επανάληψη"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"Επανάληψη όλων"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"Επανάληψη ενός στοιχείου"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"Ενεργοποίηση Τυχαίας αναπαραγωγής"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"Απενεργοποίηση Τυχαίας αναπαραγωγής"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"Ενεργοποίηση Υψηλής ποιότητας"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Απενεργοποίηση Υψηλής ποιότητας"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Ενεργοποίηση υποτίτλων"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Απενεργοποίηση υποτίτλων"</string>
 </resources>
diff --git a/v17/leanback/res/values-en-rAU/strings.xml b/v17/leanback/res/values-en-rAU/strings.xml
new file mode 100644
index 0000000..ed22ccd
--- /dev/null
+++ b/v17/leanback/res/values-en-rAU/strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+Copyright (C) 2014 The Android Open Source Project
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="orb_search_action" msgid="5651268540267663887">"Search Action"</string>
+    <string name="lb_search_bar_hint" msgid="8325490927970116252">"Search"</string>
+    <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"Speak to search"</string>
+    <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"Search <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Speak to search <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"Play"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"Pause"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"Fast-Forward"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"Fast Forward %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"Rewind"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"Rewind %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"Skip Next"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"Skip Previous"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"More Actions"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"Deselect Thumb Up"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"Select Thumb Up"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"Deselect Thumb Down"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"Select Thumb Down"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"Repeat None"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"Repeat All"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"Repeat One"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"Enable Shuffle"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"Disable Shuffle"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"Enable High Quality"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Disable High Quality"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Enable Closed Captioning"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Disable Closed Captioning"</string>
+</resources>
diff --git a/v17/leanback/res/values-en-rGB/strings.xml b/v17/leanback/res/values-en-rGB/strings.xml
index 666fa5c..ed22ccd 100644
--- a/v17/leanback/res/values-en-rGB/strings.xml
+++ b/v17/leanback/res/values-en-rGB/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"Speak to search"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"Search <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Speak to search <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"Play"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"Pause"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"Fast-Forward"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"Fast Forward %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"Rewind"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"Rewind %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"Skip Next"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"Skip Previous"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"More Actions"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"Deselect Thumb Up"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"Select Thumb Up"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"Deselect Thumb Down"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"Select Thumb Down"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"Repeat None"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"Repeat All"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"Repeat One"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"Enable Shuffle"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"Disable Shuffle"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"Enable High Quality"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Disable High Quality"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Enable Closed Captioning"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Disable Closed Captioning"</string>
 </resources>
diff --git a/v17/leanback/res/values-en-rIN/strings.xml b/v17/leanback/res/values-en-rIN/strings.xml
index 666fa5c..ed22ccd 100644
--- a/v17/leanback/res/values-en-rIN/strings.xml
+++ b/v17/leanback/res/values-en-rIN/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"Speak to search"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"Search <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Speak to search <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"Play"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"Pause"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"Fast-Forward"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"Fast Forward %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"Rewind"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"Rewind %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"Skip Next"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"Skip Previous"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"More Actions"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"Deselect Thumb Up"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"Select Thumb Up"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"Deselect Thumb Down"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"Select Thumb Down"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"Repeat None"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"Repeat All"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"Repeat One"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"Enable Shuffle"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"Disable Shuffle"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"Enable High Quality"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Disable High Quality"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Enable Closed Captioning"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Disable Closed Captioning"</string>
 </resources>
diff --git a/v17/leanback/res/values-es-rUS/strings.xml b/v17/leanback/res/values-es-rUS/strings.xml
index 896535a..ab05f83 100644
--- a/v17/leanback/res/values-es-rUS/strings.xml
+++ b/v17/leanback/res/values-es-rUS/strings.xml
@@ -21,5 +21,29 @@
     <string name="lb_search_bar_hint" msgid="8325490927970116252">"Búsqueda"</string>
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"Habla para buscar"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"Buscar <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
-    <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Habla para buscar <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>."</string>
+    <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Habla para buscar en <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>."</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"Reproducir"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"Pausar"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"Avanzar"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"Avanzar rápidamente %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"Retroceder"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"Rebobinar %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"Ir al siguiente"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"Ir al anterior"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"Más acciones"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"Desmarcar \"Me gusta\""</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"Marcar \"Me gusta\""</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"Desmarcar \"No me gusta\""</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"Marcar \"No me gusta\""</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"No repetir"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"Repetir todo"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"Repetir uno"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"Habilitar reproducción aleatoria"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"Inhabilitar reproducción aleatoria"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"Habilitar calidad alta"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Inhabilitar calidad alta"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Habilitar subtítulos"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Inhabilitar subtítulos"</string>
 </resources>
diff --git a/v17/leanback/res/values-es/strings.xml b/v17/leanback/res/values-es/strings.xml
index 9990ae6..0cff1c9 100644
--- a/v17/leanback/res/values-es/strings.xml
+++ b/v17/leanback/res/values-es/strings.xml
@@ -19,7 +19,31 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="orb_search_action" msgid="5651268540267663887">"Buscar..."</string>
     <string name="lb_search_bar_hint" msgid="8325490927970116252">"Buscar"</string>
-    <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"Buscar por voz"</string>
+    <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"Habla para buscar"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"Buscar <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
-    <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Buscar por voz <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Habla para buscar <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"Reproducir"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"Pausar"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"Avance rápido"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"Avance rápido %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"Rebobinar"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"Rebobinar %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"Saltar siguiente"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"Saltar anterior"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"Más acciones"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"No seleccionar pulgar hacia arriba"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"Seleccionar pulgar hacia arriba"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"No seleccionar pulgar hacia abajo"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"Seleccionar pulgar hacia abajo"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"No repetir"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"Repetir todo"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"Repetir uno"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"Habilitar reproducción aleatoria"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"Inhabilitar reproducción aleatoria"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"Habilitar alta calidad"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Inhabilitar alta calidad"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Habilitar subtítulos"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Inhabilitar subtítulos"</string>
 </resources>
diff --git a/v17/leanback/res/values-et-rEE/strings.xml b/v17/leanback/res/values-et-rEE/strings.xml
index a097b5d..32fff96 100644
--- a/v17/leanback/res/values-et-rEE/strings.xml
+++ b/v17/leanback/res/values-et-rEE/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"Öelge otsimiseks"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"Otsige teenusest <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Kõnelge teenusest <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g> otsimiseks"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"Esita"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"Peata"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"Keri edasi"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"Edasikerimine %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"Keri tagasi"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"Tagasikerimine %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"Liigu järgmise üksuse juurde"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"Liigu eelmise üksuse juurde"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"Veel toiminguid"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"Tühista hinnang Meeldib"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"Vali hinnang Meeldib"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"Tühista hinnang Ei meeldi"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"Vali hinnang Ei meeldi"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"Ära korda midagi"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"Korda kõike"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"Korda ühte"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"Luba juhuslikus järjekorras esitamine"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"Keela juhuslikus järjekorras esitamine"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"Luba kõrgkvaliteetne taasesitus"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Keela kõrgkvaliteetne taasesitus"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Luba subtiitrid"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Keela subtiitrid"</string>
 </resources>
diff --git a/v17/leanback/res/values-eu-rES/strings.xml b/v17/leanback/res/values-eu-rES/strings.xml
index 2690a84..d9f9bf7 100644
--- a/v17/leanback/res/values-eu-rES/strings.xml
+++ b/v17/leanback/res/values-eu-rES/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"Esan bilatu nahi duzuna"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"Bilatu <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Esan bilatu nahi duzuna, bilaketa hemen egiteko: <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"Erreproduzitu"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"Pausatu"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"Aurreratu"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"Aurreratu %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"Atzeratu"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"Atzeratu %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"Saltatu hurrengora"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"Saltatu aurrekora"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"Ekintza gehiago"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"Desautatu \"erpurua gora\""</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"Hautatu \"erpurua gora\""</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"Desautatu \"erpurua behera\""</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"Hautatu \"erpurua behera\""</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"Ez errepikatu"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"Errepikatu guztiak"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"Errepikatu bat"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"Gaitu ausazko erreprodukzioa"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"Desgaitu ausazko erreprodukzioa"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"Gaitu kalitate handiko erreprodukzioa"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Desgaitu kalitate handiko erreprodukzioa"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Gaitu azpitituluak"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Desgaitu azpitituluak"</string>
 </resources>
diff --git a/v17/leanback/res/values-fa/strings.xml b/v17/leanback/res/values-fa/strings.xml
index fa4bb0c..bb615fc 100644
--- a/v17/leanback/res/values-fa/strings.xml
+++ b/v17/leanback/res/values-fa/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"برای جستجو صحبت کنید"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"جستجوی <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"جستجو با گفتن <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"پخش"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"توقف موقت"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"جلو بردن سریع"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"‏بازارسال سریع %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"عقب بردن"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"‏عقب بردن %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"رد شدن از بعدی"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"رد شدن از قبلی"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"عملکردهای بیشتر"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"لغو انتخاب رأی موافق"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"انتخاب رأی موافق"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"لغو انتخاب رأی مخالف"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"انتخاب رأی مخالف"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"تکرار هیچ‌کدام"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"تکرار همه"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"یک‌بار تکرار"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"فعال کردن پخش تصادفی"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"غیرفعال کردن پخش تصادفی"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"فعال کردن کیفیت بالا"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"غیرفعال کردن کیفیت بالا"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"فعال کردن زیرنویس"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"غیرفعال کردن زیرنویس"</string>
 </resources>
diff --git a/v17/leanback/res/values-fi/strings.xml b/v17/leanback/res/values-fi/strings.xml
index 3193006..9d38d3c 100644
--- a/v17/leanback/res/values-fi/strings.xml
+++ b/v17/leanback/res/values-fi/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"Tee haku puhumalla"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"Haku: <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Puhehaku: <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"Toista"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"Keskeytä"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"Kelaa eteenpäin"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"Kelaa eteenpäin %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"Kelaa taakse"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"Kelaa taaksepäin %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"Siirry seuraavaan"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"Siirry edelliseen"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"Lisää toimintoja"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"Poista Tykkään-valinta"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"Valitse Tykkään"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"Poista En tykkää -valinta"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"Valitse En tykkää"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"Ei uudelleentoistoa"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"Toista kaikki uudelleen"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"Toista yksi uudelleen"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"Ota satunnaistoisto käyttöön"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"Poista satunnaistoisto käytöstä"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"Ota korkea laatu käyttöön"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Poista korkea laatu käytöstä"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Ota tekstitys käyttöön"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Poista tekstitys käytöstä"</string>
 </resources>
diff --git a/v17/leanback/res/values-fr-rCA/strings.xml b/v17/leanback/res/values-fr-rCA/strings.xml
index 20595c3..bbd3eea 100644
--- a/v17/leanback/res/values-fr-rCA/strings.xml
+++ b/v17/leanback/res/values-fr-rCA/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"Énoncez votre recherche"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"Rechercher dans <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Énoncez votre recherche dans <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"Lecture"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"Pause"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"Avance rapide"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"Avance rapide à %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"Reculer"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"Retour rapide à %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"Passer à l\'élément suivant"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"Passer à l\'élément précédent"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"Autres actions"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"Désélectionner la mention « J\'aime »"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"Sélectionner la mention « J\'aime »"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"Désélectionner la mention « Je n\'aime pas »"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"Sélectionner la mention « Je n\'aime pas »"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"Aucune répétition"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"Tout lire en boucle"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"Répéter un élément"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"Activer la lecture aléatoire"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"Désactiver la lecture aléatoire"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"Activer la lecture haute qualité"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Désactiver la lecture haute qualité"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Activer le sous-titrage"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Désactiver le sous-titrage"</string>
 </resources>
diff --git a/v17/leanback/res/values-fr/strings.xml b/v17/leanback/res/values-fr/strings.xml
index 9a8d2c7..e9c051c 100644
--- a/v17/leanback/res/values-fr/strings.xml
+++ b/v17/leanback/res/values-fr/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"Énoncer la recherche"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"Rechercher \"<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>\""</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Énoncer la recherche \"<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>\""</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"Lecture"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"Interrompre"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"Avance rapide"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"Avance rapide de %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"Retour arrière"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"Retour arrière de %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"Ignorer l\'élément suivant"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"Ignorer l\'élément précédent"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"Autres actions"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"Désélectionner \"J\'aime\""</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"Sélectionner \"J\'aime\""</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"Désélectionner \"Je n\'aime pas\""</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"Sélectionner \"Je n\'aime pas\""</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"Ne rien lire en boucle"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"Tout lire en boucle"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"Lire en boucle un élément"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"Désactiver la lecture en mode aléatoire"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"Désactiver la lecture en mode aléatoire"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"Activer la haute qualité"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Désactiver la haute qualité"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Activer les sous-titres"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Désactiver les sous-titres"</string>
 </resources>
diff --git a/v17/leanback/res/values-gl-rES/strings.xml b/v17/leanback/res/values-gl-rES/strings.xml
index b85dcd1..717b994 100644
--- a/v17/leanback/res/values-gl-rES/strings.xml
+++ b/v17/leanback/res/values-gl-rES/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"Fala para efectuar a busca"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"Busca <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Fala para buscar <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"Reproducir"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"Pausar"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"Avance rápido"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"Avance rápido %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"Rebobinar"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"Rebobinado %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"Saltar seguinte"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"Saltar anterior"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"Máis accións"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"Anular \"Gústame\""</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"Seleccionar polgar cara arriba"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"Anular \"Non me gusta\""</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"Seleccionar polgar cara abaixo"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"Non repetir"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"Repetir todo"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"Repetir un"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"Activar reprodución aleatoria"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"Desactivar reprodución aleatoria"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"Activar alta calidade"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Desactivar alta calidade"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Activar subtítulos"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Desactivar subtítulos"</string>
 </resources>
diff --git a/v17/leanback/res/values-gu-rIN/strings.xml b/v17/leanback/res/values-gu-rIN/strings.xml
new file mode 100644
index 0000000..2e4f30f
--- /dev/null
+++ b/v17/leanback/res/values-gu-rIN/strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+Copyright (C) 2014 The Android Open Source Project
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="orb_search_action" msgid="5651268540267663887">"શોધ ક્રિયા"</string>
+    <string name="lb_search_bar_hint" msgid="8325490927970116252">"શોધો"</string>
+    <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"શોધવા માટે બોલો"</string>
+    <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g> શોધો"</string>
+    <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g> ને શોધવા માટે બોલો"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"ચલાવો"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"થોભો"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"ઝડપી ફોરવર્ડ"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"ફાસ્ટ ફોરવર્ડ કરો %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"રીવાઇન્ડ કરો"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"%1$dX ને રિવાઇન્ડ કરો"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"આગલા પર જાઓ"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"પહેલાનાને છોડો"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"વધુ ક્રિયાઓ"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"એકદમ સરસ નાપસંદ કરો"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"એકદમ સરસ પસંદ કરો"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"સારું નથી નાપસંદ કરો"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"સારું નથી પસંદ કરો"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"કોઈનું પુનરાવર્તન નહીં"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"બધાનું પુનરાવર્તન કરો"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"એક પુનરાવર્તિત કરો"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"શફલ કરોને સક્ષમ કરો"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"શફલ કરોને અક્ષમ કરો"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"ઉચ્ચ ગુણવત્તા સક્ષમ કરો"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"ઉચ્ચ ગુણવત્તા અક્ષમ કરો"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"ઉપશીર્ષક સક્ષમ કરો"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"વિગતવાર ઉપશીર્ષકોને અક્ષમ કરો"</string>
+</resources>
diff --git a/v17/leanback/res/values-hi/strings.xml b/v17/leanback/res/values-hi/strings.xml
index 0d3e72d..a926396 100644
--- a/v17/leanback/res/values-hi/strings.xml
+++ b/v17/leanback/res/values-hi/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"खोजने के लिए बोलें"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g> खोजें"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g> खोजने के लिए बोलें"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"चलाएं"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"रोकें"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"फ़ास्ट फ़ॉरवर्ड"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"फ़ास्‍ट फ़ॉरवर्ड %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"रिवाइंड करें"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"रिवाइंड %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"अगले पर जाएं"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"पिछले पर जाएं"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"अधिक विकल्प"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"पसंदीदा को ना चुनें"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"पसंदीदा चुनें"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"नापसंद को ना चुनें"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"नापसंद चुनें"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"कुछ भी न दोहराएं"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"सभी को दोहराएं"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"एक दोहराएं"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"फेर-बदल सक्षम करें"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"फेर-बदल अक्षम करें"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"उच्च गुणवत्ता सक्षम करें"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"उच्च गुणवत्ता अक्षम करें"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"उपशीर्षक सक्षम करें"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"उपशीर्षक अक्षम करें"</string>
 </resources>
diff --git a/v17/leanback/res/values-hr/strings.xml b/v17/leanback/res/values-hr/strings.xml
index 89d8053..166369f 100644
--- a/v17/leanback/res/values-hr/strings.xml
+++ b/v17/leanback/res/values-hr/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"Izgovorite upit za pretraživanje"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"Tražite <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Izgovorite upit za pretraživanje <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"Reproduciraj"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"Pauziraj"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"Brzo naprijed"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"Brzo unaprijed %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"Unatrag"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"Unatrag %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"Preskoči na sljedeće"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"Preskoči na prethodno"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"Više radnji"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"Poništi odabir palca gore"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"Odaberi palac gore"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"Poništi odabir palca dolje"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"Odaberi palac dolje"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"Bez ponavljanja"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"Ponovi sve"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"Ponovi jedno"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"Omogući nasumičnu reprodukciju"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"Onemogući nasumičnu reprodukciju"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"Omogući visoku kvalitetu"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Onemogući visoku kvalitetu"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Omogući titlove"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Onemogući titlove"</string>
 </resources>
diff --git a/v17/leanback/res/values-hu/strings.xml b/v17/leanback/res/values-hu/strings.xml
index e6eaacb..427f1cd 100644
--- a/v17/leanback/res/values-hu/strings.xml
+++ b/v17/leanback/res/values-hu/strings.xml
@@ -21,5 +21,29 @@
     <string name="lb_search_bar_hint" msgid="8325490927970116252">"Keresés"</string>
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"Beszéljen a keresés indításához"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"Keresés itt: <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
-    <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Mondjon valamit, hogy itt keressen: <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Mondj valamit a kereséshez: <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"Lejátszás"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"Szünet"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"Gyors előretekerés"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"Előretekerés %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"Visszatekerés"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"Visszatekerés %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"Ugrás a következőre"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"Ugrás az előzőre"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"További műveletek"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"„Tetszik” értékelés visszavonása"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"„Tetszik” értékelés kiválasztása"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"„Nem tetszik” értékelés visszavonása"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"„Nem tetszik” értékelés kiválasztása"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"Nincs ismétlés"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"Összes ismétlése"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"Egy ismétlése"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"Véletlenszerű lejátszás engedélyezése"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"Véletlenszerű lejátszás letiltása"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"Jó minőségű lejátszás engedélyezése"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Jó minőségű lejátszás letiltása"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Feliratok engedélyezése"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Feliratok letiltása"</string>
 </resources>
diff --git a/v17/leanback/res/values-hy-rAM/strings.xml b/v17/leanback/res/values-hy-rAM/strings.xml
index de8561f..7e8112e 100644
--- a/v17/leanback/res/values-hy-rAM/strings.xml
+++ b/v17/leanback/res/values-hy-rAM/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"Խոսեք՝ որոնելու համար"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"Որոնեք <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Խոսեք՝ <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g> որոնելու համար"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"Նվագարկել"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"Դադարեցնել"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"Արագ առաջ անցնել"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"Առագ առաջանցում %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"Հետ փաթաթել"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"Հետանցում %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"Անցնել հաջորդին"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"Անցնել նախորդին"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"Այլ գործողություններ"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"Ապանշել Հավանելու կոճակը"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"Նշել Հավանելու կոճակը"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"Ապանշել Չհավանելու կոճակը"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"Նշել Չհավանելու կոճակը"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"Չկրկնել"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"Կրկնել բոլորը"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"Կրկնել մեկը"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"Միացնել խառը նվագարկումը"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"Անջատել խառը նվագարկումը"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"Միացնել բարձր որակը"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Անջատել բարձր որակը"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Միացնել խորագրերը"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Անջատել խորագրերը"</string>
 </resources>
diff --git a/v17/leanback/res/values-in/strings.xml b/v17/leanback/res/values-in/strings.xml
index 9be0a01..2dca7d3 100644
--- a/v17/leanback/res/values-in/strings.xml
+++ b/v17/leanback/res/values-in/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"Ucapkan untuk menelusuri"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"Telusuri <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Ucapkan untuk menelusuri <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"Putar"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"Jeda"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"Maju Cepat"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"Maju %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"Putar Ulang"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"Mundur %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"Lewati ke Berikutnya"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"Lewati ke Sebelumnya"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"Tindakan Lainnya"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"Batal Pilih Yang Disukai"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"Pilih Yang Disukai"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"Batal Pilih Yang Tidak Disukai"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"Pilih Yang Tidak Disukai"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"Jangan Ulangi"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"Ulangi Semua"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"Ulangi Satu"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"Aktifkan Acak"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"Nonaktifkan Acak"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"Aktifkan Kualitas Tinggi"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Nonaktifkan Kualitas Tinggi"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Aktifkan Pembuatan Teks"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Nonaktifkan Pembuatan Teks"</string>
 </resources>
diff --git a/v17/leanback/res/values-is-rIS/strings.xml b/v17/leanback/res/values-is-rIS/strings.xml
index 29ccdc1..c84a4c6 100644
--- a/v17/leanback/res/values-is-rIS/strings.xml
+++ b/v17/leanback/res/values-is-rIS/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"Talaðu til að leita"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"Leita í <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Talaðu til að leita í <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"Spila"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"Hlé"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"Spóla áfram"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"Spóla áfram %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"Spóla til baka"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"Spóla til baka %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"Fara í næsta"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"Fara í fyrra"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"Fleiri aðgerðir"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"Hætta við þumal upp"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"Gefa þumal upp"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"Hætta við þumal niður"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"Gefa þumal niður"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"Endurtaka ekkert"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"Endurtaka allt"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"Endurtaka eitt"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"Kveikja á stokkun"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"Slökkva á stokkun"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"Kveikja á miklum gæðum"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Slökkva á miklum gæðum"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Kveikja á skjátextum"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Slökkva á skjátextum"</string>
 </resources>
diff --git a/v17/leanback/res/values-it/strings.xml b/v17/leanback/res/values-it/strings.xml
index fa11e9d..1b58e0c 100644
--- a/v17/leanback/res/values-it/strings.xml
+++ b/v17/leanback/res/values-it/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"Parla per cercare"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"Cerca in <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Parla per cercare in <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"Riproduci"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"Metti in pausa"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"Avanza velocemente"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"Avanti veloce: %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"Riavvolgi"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"Indietro: %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"Salta successivo"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"Salta precedente"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"Altre azioni"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"Deseleziona Mi piace"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"Seleziona Mi piace"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"Deseleziona pollice abbassato"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"Seleziona pollice abbassato"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"Non ripetere nessuno"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"Ripeti tutti"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"Ripeti uno"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"Attiva riproduzione casuale"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"Disattiva riproduzione casuale"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"Attiva alta qualità"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Disattiva alta qualità"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Attiva sottotitoli"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Disattiva sottotitoli"</string>
 </resources>
diff --git a/v17/leanback/res/values-iw/strings.xml b/v17/leanback/res/values-iw/strings.xml
index dacb052..f102498 100644
--- a/v17/leanback/res/values-iw/strings.xml
+++ b/v17/leanback/res/values-iw/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"דבר כדי לחפש"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"חפש את <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"דבר כדי לחפש את <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"‎%1$dX‎‎"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"‎%1$dX‎‎"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"הפעל"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"השהה"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"הרץ קדימה"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"‏העברה קדימה של %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"הרץ אחורה"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"‏העברה לאחור של %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"דלג אל הפריט הבא"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"דלג אל הפריט הקודם"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"עוד פעולות"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"בטל בחירה באגודל כלפי מעלה"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"בחר באגודל כלפי מעלה"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"בטל בחירה באגודל כלפי מטה"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"בחר באגודל כלפי מטה"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"אל תחזור על כלום"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"חזור על הכל"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"חזור על פריט אחד"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"הפעל ערבוב"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"השבת ערבוב"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"הפעל איכות גבוהה"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"השבת איכות גבוהה"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"הפעל כתוביות"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"השבת כתוביות"</string>
 </resources>
diff --git a/v17/leanback/res/values-ja/strings.xml b/v17/leanback/res/values-ja/strings.xml
index 62b08b5..802631c 100644
--- a/v17/leanback/res/values-ja/strings.xml
+++ b/v17/leanback/res/values-ja/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"音声検索"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>を検索"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>を音声検索"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"再生"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"一時停止"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"早送り"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"早送り%1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"巻き戻し"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"巻き戻し%1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"次の曲にスキップ"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"前の曲にスキップ"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"その他の操作"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"グッドの選択を解除"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"グッドを選択"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"イマイチの選択を解除"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"イマイチを選択"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"繰り返しなし"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"全曲を繰り返し"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"1曲を繰り返し"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"シャッフルを有効にする"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"シャッフルを無効にする"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"高品質を有効にする"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"高品質を無効にする"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"字幕を有効にする"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"字幕を無効にする"</string>
 </resources>
diff --git a/v17/leanback/res/values-ka-rGE/strings.xml b/v17/leanback/res/values-ka-rGE/strings.xml
index ab9492c..70aeada 100644
--- a/v17/leanback/res/values-ka-rGE/strings.xml
+++ b/v17/leanback/res/values-ka-rGE/strings.xml
@@ -22,4 +22,32 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"თქვით საძიებო ფრაზა"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>-ის ძიება"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"თქვით <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>-ის საძიებლად"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"დაკვრა"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"პაუზა"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"წინ გადახვევა"</string>
+    <!-- String.format failed for translation -->
+    <!-- no translation found for lb_playback_controls_fast_forward_multiplier (1058753672110224526) -->
+    <skip />
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"უკან გადახვევა"</string>
+    <!-- String.format failed for translation -->
+    <!-- no translation found for lb_playback_controls_rewind_multiplier (1640629531440849942) -->
+    <skip />
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"შემდეგის გამოტოვება"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"წინას გამოტოვება"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"დამატებითი ქმედებები"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"მაღალი შეფასების არჩევის გაუქმება"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"მაღალი შეფასების არჩევა"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"დაბალი შეფასების არჩევის გაუქმება"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"დაბალი შეფასების არჩევა"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"არცერთის გამეორება"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"ყველას გამეორება"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"ერთის გამეორება"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"არეულად დაკვრის ჩართვა"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"არეულად დაკვრის გამორთვა"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"მაღალი ხარისხის ჩართვა"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"მაღალი ხარისხის გამორთვა"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"დახურული წარწერების ჩართვა"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"დახურული წარწერების გაუქმება"</string>
 </resources>
diff --git a/v17/leanback/res/values-kk-rKZ/strings.xml b/v17/leanback/res/values-kk-rKZ/strings.xml
index 160a8e7..9ed6ce2 100644
--- a/v17/leanback/res/values-kk-rKZ/strings.xml
+++ b/v17/leanback/res/values-kk-rKZ/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"Іздеу үшін сөйлеу"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g> іздеу"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g> іздеу үшін сөйлеңіз"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"Ойнату"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"Кідірту"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"Алға айналдыру"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"%1$dX алға айналдыру"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"Кері айналдыру"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"%1$dX кері айналдыру"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"Келесіге өту"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"Алдыңғыға өту"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"Қосымша әрекеттер"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"Саусақты жоғары қаратудан таңдауды алу"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"Саусақты жоғары қаратуды таңдау"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"Саусақты төмен қаратудан таңдауды алу"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"Саусақты төмен қаратуды таңдау"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"Ешқайсысын қайталамау"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"Барлығын қайталау"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"Біреуін қайталау"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"Кездейсоқ ойнатуды қосу"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"Кездейсоқ ойнатуды өшіру"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"Жоғары сапаны қосу"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Жоғары сапаны өшіру"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Жасырын титрлерді қосу"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Жасырын титрлерді өшіру"</string>
 </resources>
diff --git a/v17/leanback/res/values-km-rKH/strings.xml b/v17/leanback/res/values-km-rKH/strings.xml
index 92245b7..7874af2 100644
--- a/v17/leanback/res/values-km-rKH/strings.xml
+++ b/v17/leanback/res/values-km-rKH/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"និយាយ​​ដើម្បី​ស្វែងរក"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"ស្វែងរក <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"និយាយ​ដើម្បី​ស្វែងរក <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"ចាក់"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"ផ្អាក"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"បញ្ជូន​បន្ត​រហ័ស"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"ខាទៅមុខ %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"ខា​ថយក្រោយ"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"ខាថយក្រោយ %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"រំលង​បន្ទាប់"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"រំលង​មុន"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"សកម្មភាព​ច្រើន​ទៀត"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"មិន​ជ្រើស​មេ​​ដៃ​ឡើង​វិញ"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"ជ្រើស​មេ​ដៃ​ឡើង​លើ"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"មិន​ជ្រើស​​មេដៃ​ចុះ​ក្រោម"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"ជ្រើស​​មេ​ដៃ​ចុះក្រោម"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"មិន​ធ្វើ​ឡើង​វិញ​"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"ធ្វើ​ម្ដង​ទៀត​ទាំងអស់"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"ធ្វើ​​ឡើងវិញ​ម្ដង"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"បើក​ការ​​ច្របល់"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"បិទ​ការ​ច្របល់"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"បើក​គុណភាព​ខ្ពស់"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"បិទ​គុណភាព​ខ្ពស់"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"បើក​ការ​ដាក់​ចំណង​ដែល​បាន​បិទ"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"បិទ​ការ​ដាក់​ចំណង​ដែល​បាន​បិទ"</string>
 </resources>
diff --git a/v17/leanback/res/values-kn-rIN/strings.xml b/v17/leanback/res/values-kn-rIN/strings.xml
index 6ca527f..196b154 100644
--- a/v17/leanback/res/values-kn-rIN/strings.xml
+++ b/v17/leanback/res/values-kn-rIN/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"ಹುಡುಕಲು ಮಾತನಾಡಿ"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g> ಹುಡುಕಿ"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g> ಮಾತನಾಡಿ ಹುಡುಕಾಟ ನಡೆಸಿ"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"ಪ್ಲೇ ಮಾಡು"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"ವಿರಾಮಗೊಳಿಸು"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"ಫಾಸ್ಟ್ ಫಾರ್ವರ್ಡ್"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"ಫಾಸ್ಟ್ ಫಾರ್ವರ್ಡ್ %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"ರೀವೈಂಡ್"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"ರಿವೈಂಡ್ %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"ಮುಂದೆ ಸ್ಕಿಪ್ ಮಾಡಿ"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"ಹಿಂದೆ ಸ್ಕಿಪ್ ಮಾಡಿ"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"ಹೆಚ್ಚು ಕ್ರಿಯೆಗಳು"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"ಥಂಬ್ ಅಪ್ ಆಯ್ಕೆರದ್ದುಮಾಡಿ"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"ಥಂಬ್ ಅಪ್ ಆಯ್ಕೆಮಾಡಿ"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"ಥಂಬ್ ಡೌನ್ ಆಯ್ಕೆರದ್ದುಮಾಡಿ"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"ಥಂಬ್ ಡೌನ್ ಆಯ್ಕೆಮಾಡಿ"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"ಯಾವುದನ್ನೂ ಪುನರಾವರ್ತಿಸಬೇಡಿ"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"ಎಲ್ಲವನ್ನು ಪುನರಾವರ್ತಿಸಿ"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"ಒಂದನ್ನು ಪುನರಾವರ್ತಿಸಿ"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"ಜೋಡಿಸುವುದನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"ಜೋಡಿಸುವುದನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"ಹೆಚ್ಚು ಗುಣಮಟ್ಟವನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"ಹೆಚ್ಚು ಗುಣಮಟ್ಟವನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"ಮುಚ್ಚಿದ ಶೀರ್ಷಿಕೆಯನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"ಮುಚ್ಚಿದ ಶೀರ್ಷಿಕೆಯನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ"</string>
 </resources>
diff --git a/v17/leanback/res/values-ko/strings.xml b/v17/leanback/res/values-ko/strings.xml
index af0130d..c244dbf 100644
--- a/v17/leanback/res/values-ko/strings.xml
+++ b/v17/leanback/res/values-ko/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"음성 검색"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g> 검색"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g> 음성 검색"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$d배속"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$d배속"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"재생"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"일시중지"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"빨리 감기"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"%1$d배속 빨리 감기"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"되감기"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"%1$d배속 되감기"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"다음으로 건너뛰기"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"이전으로 건너뛰기"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"추가 작업"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"추천 선택 해제"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"추천 선택"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"비추천 선택 해제"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"비추천 선택"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"반복 안함"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"전체 반복"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"한 항목 반복"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"셔플 사용 설정"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"셔플 사용 중지"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"고화질 사용 설정"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"고화질 사용 중지"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"자막 사용 설정"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"자막 사용 중지"</string>
 </resources>
diff --git a/v17/leanback/res/values-ky-rKG/strings.xml b/v17/leanback/res/values-ky-rKG/strings.xml
index 64a2e72..4ddb284 100644
--- a/v17/leanback/res/values-ky-rKG/strings.xml
+++ b/v17/leanback/res/values-ky-rKG/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"Издөө үчүн сүйлөңүз"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g> издөө"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g> издөө үчүн сүйлөңүз"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"Ойнотуу"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"Тындыруу"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"Алдыга түрүү"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"Алдыга түрүү %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"Артка түрүү"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"Артка түрүү %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"Кийинкини өткөрүп жиберүү"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"Мурункуну өткөрүп жиберүү"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"Дагы көнүгүүлөр"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"Жактырууну тандоодон чыгаруу"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"Жактырууну тандоо"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"Жактырбоону тандоодон чыгаруу"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"Жактырбоону тандоо"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"Эч бирин кайталабоо"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"Баарын кайталоо"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"Бирөөнү кайталоо"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"Аралаштырууну иштетүү"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"Аралаштырууну өчүрүү"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"Жогорку сапатты иштетүү"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Жогорку сапатты өчүрүү"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Жабык субтитрлерди иштетүү"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Жабык субтитрлерди өчүрүү"</string>
 </resources>
diff --git a/v17/leanback/res/values-lo-rLA/strings.xml b/v17/leanback/res/values-lo-rLA/strings.xml
index 107f989..35f519b 100644
--- a/v17/leanback/res/values-lo-rLA/strings.xml
+++ b/v17/leanback/res/values-lo-rLA/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"ເວົ້າ​ເພື່ອ​ຊອກ​ຫາ"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"ຊອກ​ຫາ <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"ເວົ້າ​ເພື່ອ​ຊອກ​ຫາ <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"ຫຼິ້ນ"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"ຢຸດຊົ່ວຄາວ"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"ເລື່ອນ​ໄປ​ໜ້າ"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"ໄປ​ໜ້າແບບໄວ %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"​ຣີ​ວາຍກັບ"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"​ກັບ​ຄືນ %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"​ຂ້າມ​ໄປ​ຕໍ່"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"​ຂ້າມ​ໄປ​ກ່ອນ​ໜ້າ"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"ຄຳສັ່ງ​ເພີ່ມເຕີມ"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"​ຢຸດ​ເລືອກ​ຍົກ​ໂປ້​ແລ້ວ"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"​ເລືອກ​ຍົກ​ໂປ້​ແລ້ວ"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"​ຢຸດ​ຊີ້​ໂປ້​ລົງ​ແລ້ວ"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"ເລືອກ​ຊີ້​ໂປ້​ລົງ​ແລ້ວ"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"​ບໍ່ຫຼິ້ນ​ຊ້ຳ"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"ຫຼິ້ນ​ຊ້ຳ​ທັງ​ໝົດ"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"ຫຼິ້ນ​ຊ້ຳ"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"​ເປີດ​ນຳ​ໃຊ້​ການ​ສະຫຼັບ"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"​ປິດ​ນຳ​ໃຊ້​ການ​ສະຫຼັບ"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"​ເປີດນຳ​ໃຊ້​ການຫຼິ້ນ​ດ້ວຍຄຸນ​ນະ​ພາບ​ສູງ"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"​ປິດ​ນຳ​ໃຊ້​ການຫຼິ້ນ​ດ້ວຍຄຸນ​ນະ​ພາບ​ສູງ"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"​ເປີດ​ນຳ​ໃຊ້​​ຄຳ​ບັນ​ຍາຍ​ແບບ​ປິດ"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"​ປິດ​ນຳ​ໃຊ້​ຄຳ​ບັນ​ຍາຍ​ແບບ​ປິດ"</string>
 </resources>
diff --git a/v17/leanback/res/values-lt/strings.xml b/v17/leanback/res/values-lt/strings.xml
index f765d04..6ca2bab 100644
--- a/v17/leanback/res/values-lt/strings.xml
+++ b/v17/leanback/res/values-lt/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"Pasakykite, kad ieškotumėte"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"Ieškoti „<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>“"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Kalbėkite, kad ieškotumėte „<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>“"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$d k."</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$d k."</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"Leisti"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"Pristabdyti"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"Sukti pirmyn"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"Sukti pirmyn %1$d k. greičiau"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"Sukti atgal"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"Sukti atgal %1$d k. greičiau"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"Praleisti kitą"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"Praleisti ankstesnį"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"Daugiau veiksmų"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"Panaikinti parinkties „Patinka“ pasirinkimą"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"Pasirinkti parinktį „Patinka“"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"Panaikinti parinkties „Nepatinka“ pasirinkimą"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"Pasirinkti parinktį „Nepatinka“"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"Nekartoti nieko"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"Kartoti viską"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"Kartoti vieną"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"Įgalinti maišymą"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"Išjungti maišymą"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"Įgalinti aukštą kokybę"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Išjungti aukštą kokybę"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Įgalinti subtitrus"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Išjungti subtitrus"</string>
 </resources>
diff --git a/v17/leanback/res/values-lv/strings.xml b/v17/leanback/res/values-lv/strings.xml
index 677ae6b..7d3bc2b 100644
--- a/v17/leanback/res/values-lv/strings.xml
+++ b/v17/leanback/res/values-lv/strings.xml
@@ -21,5 +21,29 @@
     <string name="lb_search_bar_hint" msgid="8325490927970116252">"Meklēt"</string>
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"Runāt, lai meklētu"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"Meklējiet <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
-    <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Runājiet, lai meklētu <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Runājiet, lai meklētu: <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"Atskaņot"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"Pauzēt"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"Pārtīt uz priekšu"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"Pārtīt uz priekšu %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"Attīt atpakaļ"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"Attīt atpakaļ %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"Izlaist nākamo"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"Izlaist iepriekšējo"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"Citas darbības"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"Atcelt “Patīk” atlasi"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"Atlasīt “Patīk”"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"Atcelt “Nepatīk” atlasi"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"Atlasīt “Nepatīk”"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"Neatkārtot nevienu"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"Atkārtot visu"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"Atkārtot vienu"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"Iespējot atskaņošanu jauktā secībā"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"Atspējot atskaņošanu jauktā secībā"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"Iespējot augstas kvalitātes vienumu atskaņošanu"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Atspējot augstas kvalitātes vienumu atskaņošanu"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Iespējot slēgtos parakstus"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Atspējot slēgtos parakstus"</string>
 </resources>
diff --git a/v17/leanback/res/values-mk-rMK/strings.xml b/v17/leanback/res/values-mk-rMK/strings.xml
index 8ab8384..75666e0 100644
--- a/v17/leanback/res/values-mk-rMK/strings.xml
+++ b/v17/leanback/res/values-mk-rMK/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"Зборувајте за да пребарувате"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"Пребарувај <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Кажете за да се пребарува <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"Пушти"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"Пауза"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"Брзо премотај напред"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"Премотај напред %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"Премотај назад"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"Премотај назад %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"Прескокни на следна"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"Прескокни на претходна"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"Повеќе дејства"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"Откажи палец нагоре"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"Избери палец нагоре"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"Откажи палец надолу"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"Избери палец надолу"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"Не повторувај ниту една"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"Повтори ги сите"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"Повтори една"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"Овозможи мешање"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"Оневозможи мешање"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"Овозможи висок квалитет"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Оневозможи висок квалитет"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Овозможи затворено објаснување"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Оневозможи затворено објаснување"</string>
 </resources>
diff --git a/v17/leanback/res/values-ml-rIN/strings.xml b/v17/leanback/res/values-ml-rIN/strings.xml
index e31770d..b900f09 100644
--- a/v17/leanback/res/values-ml-rIN/strings.xml
+++ b/v17/leanback/res/values-ml-rIN/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"ശബ്‌ദം ഉപയോഗിച്ച് തിരയുക"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g> തിരയുക"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g> തിരയുന്നതിന് സംസാരിക്കുക"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"പ്ലേ ചെയ്യുക"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"താൽക്കാലികമായി നിർത്തുക"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"ഫാസ്റ്റ് ഫോർവേഡ് ചെയ്യുക"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"%1$dX വേഗത്തിൽ ഫോർവേഡുചെയ്യുക"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"റിവൈൻഡുചെയ്യുക"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"%1$dX റിവൈൻഡുചെയ്യുക"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"അടുത്തതിലേക്ക് പോകുക"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"മുമ്പത്തേതിലേക്ക് പോകുക"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"കൂടുതൽ പ്രവർത്തനങ്ങൾ"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"തമ്പ് അപ്പ് തിരഞ്ഞെടുത്തത് മാറ്റുക"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"തമ്പ് അപ്പ് തിരഞ്ഞെടുക്കുക"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"തമ്പ് ഡൗൺ തിരഞ്ഞെടുത്തത് മാറ്റുക"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"തമ്പ് ഡൗൺ തിരഞ്ഞെടുക്കുക"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"ഒന്നും ആവർത്തിക്കരുത്"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"എല്ലാം ആവർത്തിക്കുക"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"ഒന്ന് ആവർത്തിക്കുക"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"ഷഫിൾ ചെയ്യുന്നത് പ്രവർത്തനക്ഷമമാക്കുക"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"ഷഫിൾ ചെയ്യുന്നത് പ്രവർത്തനരഹിതമാക്കുക"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"ഉയർന്ന നിലവാരം പ്രവർത്തനക്ഷമമാക്കുക"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"ഉയർന്ന നിലവാരം പ്രവർത്തനരഹിതമാക്കുക"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"അടച്ച അടിക്കുറിപ്പ് നൽകൽ പ്രവർത്തനക്ഷമമാക്കുക"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"അടച്ച അടിക്കുറിപ്പ് നൽകൽ പ്രവർത്തനരഹിതമാക്കുക"</string>
 </resources>
diff --git a/v17/leanback/res/values-mn-rMN/strings.xml b/v17/leanback/res/values-mn-rMN/strings.xml
index a58dfe9..e4a8fcd 100644
--- a/v17/leanback/res/values-mn-rMN/strings.xml
+++ b/v17/leanback/res/values-mn-rMN/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"Ярьж хайх"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g> Хайх"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g> хайхын тулд ярина уу"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"Тоглуулах"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"Түр зогсоох"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"Хурдан урагшлуулах"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"Түргэн Урагш Гүйлгэх %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"Буцааж хураах"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"Хойш Гүйлгэх %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"Дараагийнхийг алгасах"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"Өмнөхийг алгасах"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"Өөр үйлдлүүд"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"Дээш  эрхий хурууг цуцлах"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"Дээш эрхий хурууг сонгох"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"Доош эрхий хурууг цуцлах"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"Доош эрхий хурууг сонгох"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"Алийг нь ч давтахгүй"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"Бүгдийг давтах"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"Нэгийг давтах"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"Холихыг идэвхжүүлэх"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"Холихыг идэвхгүйжүүлэх"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"Өндөр чанарыг идэвхжүүлэх"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Өндөр чанарыг идэвхгүйжүүлэх"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Текст тайлбарыг идэвхжүүлэх"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Текст тайлбарыг идэвхгүйжүүлэх"</string>
 </resources>
diff --git a/v17/leanback/res/values-mr-rIN/strings.xml b/v17/leanback/res/values-mr-rIN/strings.xml
index 296b21c..11748ec 100644
--- a/v17/leanback/res/values-mr-rIN/strings.xml
+++ b/v17/leanback/res/values-mr-rIN/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"शोधण्यासाठी बोला"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g> शोधा"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g> शोधण्यासाठी बोला"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"प्ले करा"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"विराम द्या"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"फास्ट फॉरवर्ड करा"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"फास्ट फॉरवर्ड %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"रिवाईँड करा"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"रीवाईंड %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"पुढील वगळा"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"मागील वगळा"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"अधिक क्रिया"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"वर अंगठा निवड रद्द करा"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"वर अंगठा निवडा"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"खाली अंगठा निवड रद्द करा"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"खाली अंगठा निवडा"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"काहीही पुनरावृत्ती करू नका"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"सर्व पुनरावृत्ती करा"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"एक पुनरावृत्ती करा"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"शफल करा सक्षम करा"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"शफल करा अक्षम करा"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"उच्च गुणवत्ता सक्षम करा"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"उच्च गुणवत्ता अक्षम करा"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"उपशीर्षके सक्षम करा"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"उपशीर्षके अक्षम करा"</string>
 </resources>
diff --git a/v17/leanback/res/values-ms-rMY/strings.xml b/v17/leanback/res/values-ms-rMY/strings.xml
index d915409..c073e43 100644
--- a/v17/leanback/res/values-ms-rMY/strings.xml
+++ b/v17/leanback/res/values-ms-rMY/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"Tutur untuk membuat carian"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"Cari <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Sebut untuk mencari <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"Main"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"Jeda"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"Mara Laju"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"Lajukan %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"Gulung semula"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"Gulung semula %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"Langkau Seterusnya"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"Langkau Sebelumnya"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"Lagi Tindakan"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"Nyahpilih Bagus"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"Pilih Bagus"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"Nyahpilih Tidak Bagus"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"Pilih Tidak Bagus"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"Jangan Ulang"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"Ulang Semua"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"Ulang Satu"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"Dayakan Rombak"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"Lumpuhkan Rombak"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"Dayakan Kualiti Tinggi"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Lumpuhkan Kualiti Tinggi"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Dayakan Kapsyen Tertutup"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Lumpuhkan Kapsyen Tertutup"</string>
 </resources>
diff --git a/v17/leanback/res/values-my-rMM/strings.xml b/v17/leanback/res/values-my-rMM/strings.xml
index 76e70f2..2efaf7f 100644
--- a/v17/leanback/res/values-my-rMM/strings.xml
+++ b/v17/leanback/res/values-my-rMM/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"ရှာဖွေရန် ပြောပါ"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>ကို ရှာရန်"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g> ကို ရှာရန် ပြောပါ"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"ဖွင့်ရန်"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"ခဏရပ်ရန်"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"ရှေ့သို့ သွားရန်"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"ရှေ့သို့ ရစ်ရန် %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"ပြန်ရစ်ရန်"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"နောက်သို့ ရစ်ရန် %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"န​ောက်တစ်ပုဒ်သို့ ကျော်ရန်"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"ယခင်တစ်ပုဒ်သို့ သွားရန်"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"နောက်ထပ် လုပ်ဆောင်ချက်များ"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"နှစ်ခြိုက်သော သင်္က​ေတအား မရွေးရန်"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"နှစ်ခြိုက်သော သင်္က​ေတအား ရွေးရန်"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"မနှစ်ခြိုက်သော သင်္က​ေတအား မရွေးရန်"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"မနှစ်ခြိုက်သော သင်္က​ေတအား ရွေးရန်"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"ထပ်တလဲလဲမဖွင့်ရန်"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"အားလုံး ထပ်တလဲလဲဖွင့်ရန်"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"တစ်ခုအား ထပ်တလဲလဲဖွင့်ရန်"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"ရောသမမွှေခြင်း ပြုရန်"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"ရောသမမေွှခြင်း မပြုရန်"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"အရည်အသွေးကောင်းအား ဖွင့်ရန်"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"အရည်အသွေးကောင်းအား ပိတ်ထားရန်"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"စာတမ်းထိုး ဖွင့်ရန်"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"စာတမ်းထိုးအား ပိတ်ထားရန်"</string>
 </resources>
diff --git a/v17/leanback/res/values-nb/strings.xml b/v17/leanback/res/values-nb/strings.xml
index c1fe682..f5ab2e1 100644
--- a/v17/leanback/res/values-nb/strings.xml
+++ b/v17/leanback/res/values-nb/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"Snakk for å søke"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"Søk i <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Snakk for å søke i <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"Spill av"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"Sett på pause"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"Fremoverspoling"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"Fremoverspoling %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"Tilbakespoling"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"Tilbakespoling %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"Hopp til neste"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"Hopp til forrige"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"Flere handlinger"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"Fjern valg av tommel opp"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"Velg tommel opp"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"Fjern valg av tommel ned"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"Velg tommel ned"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"Ikke gjenta noen"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"Gjenta alle"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"Gjenta én"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"Aktivér avspilling i tilfeldig rekkefølge"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"Deaktiver avspilling i tilfeldig rekkefølge"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"Aktivér høy kvalitet"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Deaktiver høy kvalitet"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Aktivér teksting"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Deaktiver teksting"</string>
 </resources>
diff --git a/v17/leanback/res/values-ne-rNP/strings.xml b/v17/leanback/res/values-ne-rNP/strings.xml
index 81ce461..c399985 100644
--- a/v17/leanback/res/values-ne-rNP/strings.xml
+++ b/v17/leanback/res/values-ne-rNP/strings.xml
@@ -22,4 +22,30 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"खोजी गर्न बोल्नुहोस्"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g> खोज्नुहोस्"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g> खोजी गर्न बोल्नुहोस्"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"प्ले गर्नुहोस्"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"रोक्नुहोस्"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"फास्ट फर्वार्ड"</string>
+    <!-- String.format failed for translation -->
+    <!-- no translation found for lb_playback_controls_fast_forward_multiplier (1058753672110224526) -->
+    <skip />
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"दोहोर्याउनुहोस्"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"पुन: वाइन्ड गर्नुहोस् %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"अर्को छोड्नुहोस्"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"अघिल्लो छोड्नुहोस्"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"थप कार्यहरू"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"औंठा माथि चयन नगर्नुहोस्"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"औंठा माथि चयन गर्नुहोस्"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"औंठा तल चयन नगर्नुहोस्"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"औंठा तल चयन गर्नुहोस्"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"कुनै पनि नदोहोर्याउनुहोस्"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"सबै दोहोर्याउनुहोस्"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"एउटा दोहोर्याउनुहोस्"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"सफ्फल सक्षम"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"सफ्फल असक्षम"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"उच्च गुणस्तर सक्षम"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"उच्च गुणस्तर असक्षम"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"बन्द क्याप्सनहरु सक्षम"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"बन्द क्याप्सनहरु असक्षम"</string>
 </resources>
diff --git a/v17/leanback/res/values-nl/strings.xml b/v17/leanback/res/values-nl/strings.xml
index 5c0ba2e..fe73141 100644
--- a/v17/leanback/res/values-nl/strings.xml
+++ b/v17/leanback/res/values-nl/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"Spreek om te zoeken"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g> zoeken"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Spreek om <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g> te zoeken"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"Afspelen"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"Onderbreken"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"Vooruitspoelen"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"Vooruitspoelen %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"Terugspoelen"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"Terugspoelen %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"Naar volgende"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"Naar vorige"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"Meer acties"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"Selectie van \'Leuk\' ongedaan maken"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"\'Leuk\' selecteren"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"Selectie van \'Niet leuk\' ongedaan maken"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"\'Niet leuk\' selecteren"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"Niet herhalen"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"Alles herhalen"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"Eén herhalen"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"Shuffle inschakelen"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"Shuffle uitschakelen"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"Hoge kwaliteit inschakelen"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Hoge kwaliteit uitschakelen"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Ondertiteling inschakelen"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Ondertiteling uitschakelen"</string>
 </resources>
diff --git a/v17/leanback/res/values-pa-rIN/strings.xml b/v17/leanback/res/values-pa-rIN/strings.xml
new file mode 100644
index 0000000..f9c7c4b
--- /dev/null
+++ b/v17/leanback/res/values-pa-rIN/strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+Copyright (C) 2014 The Android Open Source Project
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="orb_search_action" msgid="5651268540267663887">"ਖੋਜ ਕਿਰਿਆ"</string>
+    <string name="lb_search_bar_hint" msgid="8325490927970116252">"ਖੋਜੋ"</string>
+    <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"ਖੋਜਣ ਲਈ ਬੋਲੋ"</string>
+    <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g> ਖੋਜੋ"</string>
+    <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g> ਖੋਜਣ ਲਈ ਬੋਲੋ"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"ਪਲੇ ਕਰੋ"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"ਰੋਕੋ"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"ਅੱਗੇ ਭੇਜੋ"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"%1$dX ਨੂੰ ਅੱਗੇ ਭੇਜੋ"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"ਰੀਵਾਈਂਡ"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"%1$dX ਨੂੰ ਰੀਵਾਈਂਡ ਕਰੋ"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"ਅਗਲਾ ਨੂੰ ਛੱਡੋ"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"ਪਿਛਲਾ ਨੂੰ ਛੱਡੋ"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"ਹੋਰ ਕਿਰਿਆਵਾਂ"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"ਥੰਬ ਅਪ ਨੂੰ ਅਚੋਣਵਾਂ ਕਰੋ"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"ਥੰਬ ਅਪ ਨੂੰ ਚੁਣੋ"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"ਥੰਬ ਡਾਊਨ ਨੂੰ ਅਚੋਣਵਾਂ ਕਰੋ"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"ਥੰਬ ਡਾਊਨ ਨੂੰ ਚੁਣੋ"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"ਕੋਈ ਵੀ ਨਾ ਦੁਹਰਾਓ"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"ਸਾਰਿਆਂ ਨੂੰ ਦੁਹਰਾਓ"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"ਇੱਕ ਦੁਹਰਾਓ"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"ਸ਼ਫਲ ਨੂੰ ਸਮਰੱਥ ਬਣਾਓ"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"ਸ਼ਫਲ ਨੂੰ ਅਸਮਰੱਥ ਬਣਾਓ"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"ਉੱਚ ਗੁਣਵੱਤਾ ਨੂੰ ਸਮਰੱਥ ਬਣਾਓ"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"ਉੱਚ ਗੁਣਵੱਤਾ ਨੂੰ ਅਸਮਰੱਥ ਬਣਾਓ"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"ਬੰਦ ਕੈਪਸ਼ਨਿੰਗ ਸਮਰੱਥ ਬਣਾਓ"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"ਬੰਦ ਕੈਪਸ਼ਨਿੰਗ ਅਸਮਰੱਥ ਬਣਾਓ"</string>
+</resources>
diff --git a/v17/leanback/res/values-pl/strings.xml b/v17/leanback/res/values-pl/strings.xml
index 9942bc7..f6280a3 100644
--- a/v17/leanback/res/values-pl/strings.xml
+++ b/v17/leanback/res/values-pl/strings.xml
@@ -21,5 +21,29 @@
     <string name="lb_search_bar_hint" msgid="8325490927970116252">"Szukaj"</string>
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"Powiedz, aby wyszukać"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"Szukaj <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
-    <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Powiedz, by wyszukać <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Powiedz, by wyszukać w aplikacji <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"Odtwórz"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"Wstrzymaj"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"Przewiń do przodu"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"Przewiń do przodu %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"Przewiń do tyłu"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"Przewiń do tyłu %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"Pomiń następny"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"Pomiń poprzedni"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"Więcej czynności"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"Odznacz Lubię"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"Zaznacz Lubię"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"Odznacz Nie lubię"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"Zaznacz Nie lubię"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"Nie powtarzaj"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"Powtórz wszystkie"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"Powtórz jeden"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"Włącz odtwarzanie losowe"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"Wyłącz odtwarzanie losowe"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"Włącz wysoką jakość"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Wyłącz wysoką jakość"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Włącz napisy"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Wyłącz napisy"</string>
 </resources>
diff --git a/v17/leanback/res/values-pt-rPT/strings.xml b/v17/leanback/res/values-pt-rPT/strings.xml
index 0f15262..f3bf4aa 100644
--- a/v17/leanback/res/values-pt-rPT/strings.xml
+++ b/v17/leanback/res/values-pt-rPT/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"Fale para pesquisar"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"Pesquisar <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Fale para pesquisar <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"Reproduzir"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"Interromper"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"Avançar"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"Avançar %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"Recuar"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"Recuar %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"Avançar para o seguinte"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"Avançar para o anterior"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"Mais ações"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"Desselecionar Gosto"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"Selecionar Gosto"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"Desselecionar Não gosto"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"Selecionar Não gosto"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"Não repetir"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"Repetir tudo"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"Repetir um"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"Ativar reprodução aleatória"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"Desativar reprodução aleatória"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"Ativar alta qualidade"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Desativar alta qualidade"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Ativar legendas"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Desativar legendas"</string>
 </resources>
diff --git a/v17/leanback/res/values-pt/strings.xml b/v17/leanback/res/values-pt/strings.xml
index 0f15262..13d01a5 100644
--- a/v17/leanback/res/values-pt/strings.xml
+++ b/v17/leanback/res/values-pt/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"Fale para pesquisar"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"Pesquisar <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Fale para pesquisar <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"Reproduzir"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"Pausar"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"Avançar"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"Avançar %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"Retroceder"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"Retroceder %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"Pular próxima"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"Pular anterior"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"Mais ações"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"Desmarcar gostei"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"Marcar gostei"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"Desmarcar não gostei"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"Marcar não gostei"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"Não repetir"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"Repetir tudo"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"Repetir uma"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"Ativar reprodução aleatória"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"Desativar reprodução aleatória"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"Ativar alta qualidade"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Desativar alta qualidade"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Ativar closed captioning"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Desativar closed captioning"</string>
 </resources>
diff --git a/v17/leanback/res/values-ro/strings.xml b/v17/leanback/res/values-ro/strings.xml
index fd354372..cb6aa4a 100644
--- a/v17/leanback/res/values-ro/strings.xml
+++ b/v17/leanback/res/values-ro/strings.xml
@@ -21,5 +21,29 @@
     <string name="lb_search_bar_hint" msgid="8325490927970116252">"Căutați"</string>
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"Rostiți pentru a căuta"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"Căutați <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
-    <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Vorbiți pentru a căuta <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Vorbiți pentru a căuta în <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"Redă"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"Întrerupe"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"Derulează rapid înainte"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"Derulați rapid înainte cu %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"Derulează"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"Derulați înapoi cu %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"Ignoră articolul următor"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"Ignoră articolul anterior"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"Mai multe acţiuni"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"Deselectează „Îmi place”"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"Selectează „Îmi place”"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"Deselectează „Nu-mi place”"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"Selectează „Nu-mi place”"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"Nu repetă"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"Repetă toate"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"Repetă unul"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"Activează redarea în mod aleatoriu"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"Dezactivează redarea în mod aleatoriu"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"Activează calitatea înaltă"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Dezactivează calitatea înaltă"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Activează subtitrările"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Dezactivează subtitrările"</string>
 </resources>
diff --git a/v17/leanback/res/values-ru/strings.xml b/v17/leanback/res/values-ru/strings.xml
index a06ebbc..fb03f9d 100644
--- a/v17/leanback/res/values-ru/strings.xml
+++ b/v17/leanback/res/values-ru/strings.xml
@@ -21,5 +21,29 @@
     <string name="lb_search_bar_hint" msgid="8325490927970116252">"Поиск"</string>
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"Произнесите запрос"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"Поиск здесь: <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
-    <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Произнесите запрос для поиска здесь: <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Произнесите запрос, чтобы найти <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"Воспроизвести."</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"Приостановить."</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"Перемотка вперед."</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"Перемотка вперед %1$dX."</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"Перемотать назад."</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"Перемотка назад %1$dX."</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"Перейти к следующему элементу."</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"Перейти к предыдущему элементу."</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"Другие действия."</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"Убрать отметку Нравится."</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"Поставить отметку Нравится."</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"Убрать отметку Не нравится."</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"Поставить отметку Не нравится."</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"Не повторять."</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"Повторять все."</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"Повторять один элемент."</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"Включить перемешивание."</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"Отключить перемешивание."</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"Включить высокое качество."</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Отключить высокое качество."</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Включить субтитры."</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Отключить субтитры."</string>
 </resources>
diff --git a/v17/leanback/res/values-si-rLK/strings.xml b/v17/leanback/res/values-si-rLK/strings.xml
index 77742b5..e5c0cf4 100644
--- a/v17/leanback/res/values-si-rLK/strings.xml
+++ b/v17/leanback/res/values-si-rLK/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"සෙවීමට කථා කරන්න"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g> සොයන්න"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g> සොයන්න කථා කරන්න"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"ධාවනය කරන්න"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"විරාමය"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"වේගයෙන් ඉදිරියට යන"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"%1$dX වේගයෙන් ඉදිරියට යවන්න"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"නැවත ඔතන්න"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"%1$dX ආපස්සට යවන්න"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"ඊළඟ එක මග අරින්න"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"කළින් එක මග අරින්න"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"තව ක්‍රියාකාරකම්"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"මහපටැඟිල්ල ඉහළට තිබීම තේරීම නොකරන්න"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"මහපටැඟිල්ල ඉහළට තිබීම තේරීම කරන්න"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"මහපටැඟිල්ල පහළට තිබීම තේරීම නොකරන්න"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"මහපටැඟිල්ල පහළට තිබීම තේරීම කරන්න"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"නැවත කරන්න කිසිවක් නැත"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"සියල්ල නැවත කරන්න"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"එකක් නැවත කරන්න"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"ඇනීම සබල කරන්න"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"ඇනීම අබල කරන්න"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"උපරිම ගුණත්වය සබල කරන ලදි"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"උපරිම ගුණත්වය අබල කරන ලදි"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"වැසුණු ශිර්ෂ කිරීම සබල කරන ලදි"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"වැසුණු ශිර්ෂ කිරීම අබල කරන ලදි"</string>
 </resources>
diff --git a/v17/leanback/res/values-sk/strings.xml b/v17/leanback/res/values-sk/strings.xml
index 8af51d8..74a9044 100644
--- a/v17/leanback/res/values-sk/strings.xml
+++ b/v17/leanback/res/values-sk/strings.xml
@@ -21,5 +21,29 @@
     <string name="lb_search_bar_hint" msgid="8325490927970116252">"Hľadať"</string>
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"Hovorením spustíte vyhľadávanie"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"Vyhľadať výraz <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
-    <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Vyslovením výrazu <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g> spustíte jeho vyhľad."</string>
+    <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Hovorte na vyhľadávanie v kontexte <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"Prehrať"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"Pozastaviť"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"Pretočiť dopredu"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"Pretočiť dopredu %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"Pretočiť späť"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"Pretočiť späť %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"Prejsť na ďalšiu položku"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"Prejsť na predchádzajúcu položku"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"Viac akcií"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"Zrušiť Páči sa mi"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"Vybrať Páči sa mi"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"Zrušiť Nepáči sa mi"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"Vybrať Nepáči sa mi"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"Neopakovať"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"Opakovať všetko"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"Opakovať jednu položku"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"Zapnúť náhodné prehrávanie"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"Vypnúť náhodné prehrávanie"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"Povoliť médiá vo vysokej kvalite"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Zakázať médiá vo vysokej kvalite"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Zapnúť skryté titulky"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Vypnúť skryté titulky"</string>
 </resources>
diff --git a/v17/leanback/res/values-sl/strings.xml b/v17/leanback/res/values-sl/strings.xml
index d367572..1af639b 100644
--- a/v17/leanback/res/values-sl/strings.xml
+++ b/v17/leanback/res/values-sl/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"Izgovorite, če želite iskati"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"Iskanje: <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Govorite, če želite iskati: <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$d-kratno"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$d-kratno"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"Predvajaj"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"Zaustavi"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"Previj naprej"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"Hitro previjanje naprej – %1$d-kratno"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"Previj nazaj"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"Previjanje nazaj – %1$d-kratno"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"Preskoči naslednje"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"Preskoči prejšnje"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"Več dejanj"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"Prekliči izbor palca gor"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"Izberi palec gor"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"Prekliči izbor palca dol"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"Izberi palec dol"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"Ne ponovi"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"Ponovi vse"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"Ponovi eno"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"Omogoči naključno predvajanje"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"Onemogoči naključno predvajanje"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"Omogoči visoko kakovost"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Onemogoči visoko kakovost"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Omogoči podnapise"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Onemogoči podnapise"</string>
 </resources>
diff --git a/v17/leanback/res/values-sq-rAL/strings.xml b/v17/leanback/res/values-sq-rAL/strings.xml
new file mode 100644
index 0000000..28c313f
--- /dev/null
+++ b/v17/leanback/res/values-sq-rAL/strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+Copyright (C) 2014 The Android Open Source Project
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="orb_search_action" msgid="5651268540267663887">"Veprim i kërkimit"</string>
+    <string name="lb_search_bar_hint" msgid="8325490927970116252">"Kërko"</string>
+    <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"Fol për të kërkuar"</string>
+    <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"Kërko për <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Fol për të kërkuar <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"Luaj"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"Pauzë"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"Përparo me shpejtësi"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"Përparo me shpejtësi %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"Kthe në fillim"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"Kthe në fillim %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"Kapërce për te tjetra"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"Kapërce të mëparshmin"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"Veprime të tjera"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"Hiq nga përzgjedhja \"Gishti lart\""</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"Përzgjidh \"Gishtin sipër\""</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"Hiq nga përzgjedhja \"Gishti poshtë\""</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"Përzgjidh \"Gishtin poshtë\""</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"Mos përsërit asnjë"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"Përsërit të gjitha"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"Përsërit një"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"Aktivizo përzierjen"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"Çaktivizo përzierjen"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"Aktivizo \"Cilësinë e lartë\""</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Çaktivizo \"Cilësinë e lartë\""</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Aktivizo titrat"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Çaktivizo titrat me sekuencë kohore"</string>
+</resources>
diff --git a/v17/leanback/res/values-sr/strings.xml b/v17/leanback/res/values-sr/strings.xml
index 771067c..bb5c32d 100644
--- a/v17/leanback/res/values-sr/strings.xml
+++ b/v17/leanback/res/values-sr/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"Говорите да бисте претраживали"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"Претражите <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Изговорите да бисте претражили <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"Пусти"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"Паузирај"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"Премотај унапред"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"Премотај унапред %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"Премотај уназад"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"Премотај уназад %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"Прескочи следећу"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"Прескочи претходну"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"Још радњи"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"Опозови избор палца нагоре"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"Изабери палац нагоре"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"Опозови избор палца надоле"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"Изабери палац надоле"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"Не понављај ниједну"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"Понови све"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"Понови једну"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"Омогући насумичну репродукцију"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"Онемогући насумичну репродукцију"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"Омогући висок квалитет"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Онемогући висок квалитет"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Омогући титлове"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Онемогући титлове"</string>
 </resources>
diff --git a/v17/leanback/res/values-sv/strings.xml b/v17/leanback/res/values-sv/strings.xml
index 8b64837..1a8e757 100644
--- a/v17/leanback/res/values-sv/strings.xml
+++ b/v17/leanback/res/values-sv/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"Säg det du söker efter"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"Sök i <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Tala för att söka i <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"Spela upp"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"Pausa"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"Snabbspola framåt"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"Spola framåt %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"Spola tillbaka"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"Spola tillbaka %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"Hoppa till nästa"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"Hoppa till föregående"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"Fler åtgärder"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"Avmarkera tummen upp"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"Markera tummen upp"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"Avmarkera tummen ned"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"Markera tummen ned"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"Upprepa inga"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"Upprepa alla"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"Upprepa en"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"Blanda spår"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"Blanda inte spår"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"Aktivera hög kvalitet"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Inaktivera hög kvalitet"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Aktivera textning"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Inaktivera textning"</string>
 </resources>
diff --git a/v17/leanback/res/values-sw/strings.xml b/v17/leanback/res/values-sw/strings.xml
index 23d2641..17c7480 100644
--- a/v17/leanback/res/values-sw/strings.xml
+++ b/v17/leanback/res/values-sw/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"Tamka ili utafute"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"Tafuta <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Tamka ili utafute <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"Google Play"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"Sitisha"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"Peleka mbele Haraka"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"Peleka Mbele %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"Rudisha nyuma"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"Peleka nyuma %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"Ruka Inayofuata"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"Ruka Iliyotangulia"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"Vitendo zaidi"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"Ondoa Uteuzi wa Bomba"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"Teua Bomba"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"Ondoa Uteuzi wa Si Bomba"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"Teua Si Bomba"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"Usirudie Yoyote"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"Rudia zote"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"Rudia Moja"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"Washa Kuchanganya"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"Zima Kuchanganya"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"Washa Ubora wa Juu"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Zima Ubora wa Juu"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Washa manukuu"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Zima manukuu"</string>
 </resources>
diff --git a/v17/leanback/res/values-ta-rIN/strings.xml b/v17/leanback/res/values-ta-rIN/strings.xml
index 9533839..9472522 100644
--- a/v17/leanback/res/values-ta-rIN/strings.xml
+++ b/v17/leanback/res/values-ta-rIN/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"தேட, பேசவும்"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g> ஐத் தேடுக"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g> ஐத் தேட, பேசவும்"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"இயக்கு"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"இடைநிறுத்து"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"வேகமாக முன் நகர்த்து"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"%1$dX வேகத்தில் முன்செல்"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"வேகமாக பின் நகர்த்து"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"%1$dX வேகத்தில் பின்செல்"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"அடுத்ததைத் தவிர்"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"முந்தையதைத் தவிர்"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"மேலும் செயல்கள்"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"தரமேற்றத்தைத் திரும்பப் பெறு"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"தரமேற்றத்தைத் தேர்ந்தெடு"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"தரமிறக்கத்தைத் திரும்பப் பெறு"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"தரமிறக்கத்தைத் தேர்ந்தெடு"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"எதையும் மீண்டும் இயக்காதே"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"அனைத்தையும் மீண்டும் இயக்கு"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"ஒன்றை மட்டும் மீண்டும் இயக்கு"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"கலைத்து இயக்கு"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"கலைக்காமல் இயக்கு"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"உயர் தரத்தை இயக்கு"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"உயர் தரத்தை முடக்கு"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"விரிவான வசனங்களை இயக்கு"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"விரிவான வசனங்களை முடக்கு"</string>
 </resources>
diff --git a/v17/leanback/res/values-te-rIN/strings.xml b/v17/leanback/res/values-te-rIN/strings.xml
index 2715f97..f71e8cb 100644
--- a/v17/leanback/res/values-te-rIN/strings.xml
+++ b/v17/leanback/res/values-te-rIN/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"శోధించడానికి చదివి వినిపించండి"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>ని శోధించండి"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>ని శోధించడానికి చదివి వినిపించండి"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"ప్లే చేయి"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"పాజ్ చేయి"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"వేగంగా ఫార్వార్డ్ చేయి"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"%1$dX ఫాస్ట్ ఫార్వార్డ్ చేయి"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"రివైండ్ చేయి"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"%1$dX రివైండ్ చేయి"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"తదుపరి దానికి దాటవేయి"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"మునుపటి దానికి దాటవేయి"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"మరిన్ని చర్యలు"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"విజయ సంకేతం ఎంపికను తీసివేయి"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"విజయ సంకేతాన్ని ఎంచుకోండి"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"ఓటమి సంకేతం ఎంపికను తీసివేయి"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"ఓటమి సంకేతాన్ని ఎంచుకోండి"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"ఏదీ పునరావృతం చేయవద్దు"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"అన్నీ పునరావృతం చేయి"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"ఒకదాన్ని పునరావృతం చేయి"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"షఫుల్‌ను ప్రారంభించు"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"షఫుల్‌ను నిలిపివేయి"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"అధిక నాణ్యతను ప్రారంభించు"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"అధిక నాణ్యతను నిలిపివేయి"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"సంవృత శీర్షికలను ప్రారంభించు"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"సంవృత శీర్షికలను నిలిపివేయి"</string>
 </resources>
diff --git a/v17/leanback/res/values-th/strings.xml b/v17/leanback/res/values-th/strings.xml
index 09922aa..581bac0 100644
--- a/v17/leanback/res/values-th/strings.xml
+++ b/v17/leanback/res/values-th/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"พูดเพื่อค้นหา"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"ค้นหา <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"พูดเพื่อค้นหา <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"เล่น"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"หยุดชั่วคราว"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"กรอไปข้างหน้า"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"กรอไปข้างหน้า %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"กรอกลับ"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"กรอกลับ %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"ข้ามไปรายการถัดไป"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"ข้ามไปรายการก่อนหน้า"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"การทำงานเพิ่มเติม"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"ยกเลิกการเลือกว่าชอบ"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"เลือกว่าชอบ"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"ยกเลิกการเลือกว่าไม่ชอบ"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"เลือกว่าไม่ชอบ"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"ไม่เล่นซ้ำ"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"เล่นซ้ำทั้งหมด"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"เล่นซ้ำรายการเดียว"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"เปิดใช้การสุ่มเพลง"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"ปิดใช้การสุ่มเพลง"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"เปิดใช้คุณภาพสูง"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"ปิดใช้คุณภาพสูง"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"เปิดใช้คำบรรยาย"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"ปิดใช้คำบรรยาย"</string>
 </resources>
diff --git a/v17/leanback/res/values-tl/strings.xml b/v17/leanback/res/values-tl/strings.xml
index 43eaad2..c4e15ec 100644
--- a/v17/leanback/res/values-tl/strings.xml
+++ b/v17/leanback/res/values-tl/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"Magsalita upang maghanap"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"Hanapin ang <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Magsalita upang hanapin ang <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"I-play"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"I-pause"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"I-fast Forward"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"I-fast Forward %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"I-rewind"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"I-rewind %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"Laktawan ang Susunod"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"Laktawan ang Nakaraan"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"Higit Pang Mga Pagkilos"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"Alisin sa Pagkakapili ang Thumb Up"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"Piliin ang Thumb Up"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"Alisin sa Pagkakapili ang Thumb Down"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"Piliin ang Thumb Down"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"Walang Uulitin"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"Ulitin Lahat"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"Ulitin ang Isa"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"I-enable ang Shuffle"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"I-disable ang Shuffle"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"I-enable ang Mataas na Kalidad"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"I-disable ang Mataas na Kalidad"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"I-enable ang Paglalagay ng Subtitle"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"I-disable ang Paglalagay ng Subtitle"</string>
 </resources>
diff --git a/v17/leanback/res/values-tr/strings.xml b/v17/leanback/res/values-tr/strings.xml
index cfa5167..4671058 100644
--- a/v17/leanback/res/values-tr/strings.xml
+++ b/v17/leanback/res/values-tr/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"Arama yapmak için konuşun"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"Ara: <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Aramak için konuşun: <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"Oynat"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"Duraklat"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"İleri Sar"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"%1$dX İleri Sar"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"Geri Sar"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"%1$dX Geri Sar"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"Sonrakine Atla"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"Öncekine Atla"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"Diğer İşlemler"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"Beğenme Seçimini Kaldır"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"Beğenmeyi Seç"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"Beğenmeme Seçimini Kaldır"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"Beğenmemeyi Seç"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"Hiçbirini Tekrarlama"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"Tümünü Tekrarla"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"Birini Tekrarla"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"Karıştırmayı Etkinleştir"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"Karıştırmayı Devre Dışı Bırak"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"Yüksek Kalitede Oynatmayı Etkinleştir"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Yüksek Kalitede Oynatmayı Devre Dışı Bırak"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Altyazıları Etkinleştir"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Altyazıları Devre Dışı Bırak"</string>
 </resources>
diff --git a/v17/leanback/res/values-uk/strings.xml b/v17/leanback/res/values-uk/strings.xml
index c67bc8b..79b2782 100644
--- a/v17/leanback/res/values-uk/strings.xml
+++ b/v17/leanback/res/values-uk/strings.xml
@@ -21,5 +21,29 @@
     <string name="lb_search_bar_hint" msgid="8325490927970116252">"Пошук"</string>
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"Продиктуйте пошуковий запит"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"Шукати: <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
-    <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Продиктуйте, щоб шукати: <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Продиктуйте запит для пошуку: <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"Відтворити"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"Призупинити"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"Перемотати вперед"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"Перемотати вперед %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"Перемотати назад"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"Перемотати назад %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"Пропустити наступний елемент"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"Пропустити попередній елемент"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"Інші дії"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"Скасувати оцінку \"Подобається\""</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"Вибрати оцінку \"Подобається\""</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"Скасувати оцінку \"Не подобається\""</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"Вибрати оцінку \"Не подобається\""</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"Не повторювати"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"Повторити все"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"Повторити один елемент"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"Увімкнути перемішування"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"Вимкнути перемішування"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"Увімкнути високу якість"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Вимкнути високу якість"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Увімкнути субтитри"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Вимкнути субтитри"</string>
 </resources>
diff --git a/v17/leanback/res/values-ur-rPK/strings.xml b/v17/leanback/res/values-ur-rPK/strings.xml
index bcc9fde..b670251 100644
--- a/v17/leanback/res/values-ur-rPK/strings.xml
+++ b/v17/leanback/res/values-ur-rPK/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"تلاش کرنے کیلئے بولیں"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g> تلاش کریں"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g> تلاش کرنے کیلئے بولیں"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"چلائیں"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"موقوف کریں"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"تیزی سے فارورڈ کریں"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"‏تیزی سے فارورڈ کریں ‎%1$dX‎"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"ریوائینڈ کریں"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"‏ریوائنڈ کریں ‎%1$dX‎"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"اگلے پر جائیں"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"پچھلے پر جائیں"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"مزید کارروائیاں"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"اوپر کی طرف والے انگوٹھے کے نشان کو غیر منتخب کریں"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"اوپر کی طرف والے انگوٹھے کے نشان کو منتخب کریں"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"نیچے کی طرف والے انگوٹھے کے نشان کو غیر منتخب کریں"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"نیچے کی طرف والے انگوٹھے کے نشان کو منتخب کریں"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"کسی کو نہ دہرائیں"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"سبھی کو دہرائیں"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"ایک کو دہرائیں"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"شفل کو فعال کریں"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"شفل کو غیر فعال کریں"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"اعلی معیار کو فعال کریں"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"اعلی معیار کو غیر فعال کریں"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"سب ٹائٹلز کو فعال کریں"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"سب ٹائٹلز کو غیر فعال کریں"</string>
 </resources>
diff --git a/v17/leanback/res/values-uz-rUZ/strings.xml b/v17/leanback/res/values-uz-rUZ/strings.xml
index 95ae803..235d88f 100644
--- a/v17/leanback/res/values-uz-rUZ/strings.xml
+++ b/v17/leanback/res/values-uz-rUZ/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"Qidirish uchun gapiring"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"Qidirish: <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Qidirish uchun ayting: <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"Ijro qilish"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"To‘xtatib turish"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"Oldinga o‘tkazish"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"%1$dX tezlikda oldinga o‘tkazish"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"Orqaga qaytarish"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"%1$dX tezlikda orqaga qaytarish"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"Keyingisiga o‘tish"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"Avvalgisiga qaytish"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"Boshqa amallar"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"Ijobiy baho tanlovini bekor qilish"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"Ijobiy bahoni tanlash"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"Salbiy baho tanlovini bekor qilish"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"Salbiy bahoni tanlash"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"Takrorlamaslik"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"Barchasini takrorlash"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"Bir marta takrorlash"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"Aralashtirish funksiyasini yoqish"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"Aralashtirish funksiyasini o‘chirish"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"Yuqori sifatni yoqish"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Yuqori sifatni o‘chirib qo‘yish"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Taglavhalarni yoqish"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Taglavhalarni o‘chirib qo‘yish"</string>
 </resources>
diff --git a/v17/leanback/res/values-vi/strings.xml b/v17/leanback/res/values-vi/strings.xml
index 2da6873..201d137 100644
--- a/v17/leanback/res/values-vi/strings.xml
+++ b/v17/leanback/res/values-vi/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"Nói để tìm kiếm"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"Tìm kiếm <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Nói để tìm kiếm <xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"Phát"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"Tạm dừng"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"Tua nhanh"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"Tua đi %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"Tua lại"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"Tua lại %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"Chuyển đến mục tiếp theo"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"Chuyển về mục trước"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"Tác vụ khác"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"Bỏ chọn thích"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"Chọn thích"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"Bỏ chọn không thích"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"Chọn không thích"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"Không lặp lại"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"Lặp lại tất cả"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"Lặp lại một mục"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"Bật phát ngẫu nhiên"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"Tắt phát ngẫu nhiên"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"Bật chế độ chất lượng cao"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Tắt chế độ chất lượng cao"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Bật phụ đề"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Tắt phụ đề"</string>
 </resources>
diff --git a/v17/leanback/res/values-zh-rCN/strings.xml b/v17/leanback/res/values-zh-rCN/strings.xml
index 7f91918..276e7bb 100644
--- a/v17/leanback/res/values-zh-rCN/strings.xml
+++ b/v17/leanback/res/values-zh-rCN/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"说话即可开始搜索"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"搜索<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"说话即可在<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>中搜索"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$d 倍速"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$d 倍速"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"播放"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"暂停"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"快进"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"%1$d 倍速快进"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"快退"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"%1$d 倍速快退"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"跳至下一个"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"跳至上一个"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"更多操作"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"取消选择顶操作"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"选择顶操作"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"取消选择踩操作"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"选择踩操作"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"不重复播放"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"重复播放全部"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"重复播放一项"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"开启随机播放"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"关闭随机播放"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"开启高画质模式"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"关闭高画质模式"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"开启字幕"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"关闭字幕"</string>
 </resources>
diff --git a/v17/leanback/res/values-zh-rHK/strings.xml b/v17/leanback/res/values-zh-rHK/strings.xml
index 6e32bf5..5e87989 100644
--- a/v17/leanback/res/values-zh-rHK/strings.xml
+++ b/v17/leanback/res/values-zh-rHK/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"使用語音搜尋"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"搜尋「<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>」"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"使用語音搜尋「<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>」"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"播放"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"暫停"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"向前快轉"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"快轉 %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"向後倒轉"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"倒帶 %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"移至下一個媒體項目"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"移至上一個媒體項目"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"更多動作"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"取消選取喜歡"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"選取喜歡"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"取消選取不喜歡"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"選取不喜歡"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"不重複播放"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"重複播放所有媒體項目"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"重複播放一個媒體項目"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"啟用隨機播放"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"停用隨機播放"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"啟用高畫質"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"停用高畫質"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"啟用字幕"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"停用字幕"</string>
 </resources>
diff --git a/v17/leanback/res/values-zh-rTW/strings.xml b/v17/leanback/res/values-zh-rTW/strings.xml
index 6e32bf5..67efc40 100644
--- a/v17/leanback/res/values-zh-rTW/strings.xml
+++ b/v17/leanback/res/values-zh-rTW/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"使用語音搜尋"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"搜尋「<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>」"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"使用語音搜尋「<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>」"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"播放"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"暫停"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"向前快轉"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"快轉 %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"倒轉"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"倒轉 %1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"跳至下一個項目"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"跳至上一個項目"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"更多動作"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"取消選取喜歡"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"選取喜歡"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"取消選取不喜歡"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"選取不喜歡"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"不重複播放"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"重複播放所有項目"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"重複播放單一項目"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"啟用隨機播放"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"停用隨機播放"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"啟用高品質播放"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"停用高品質播放"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"啟用字幕"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"停用字幕"</string>
 </resources>
diff --git a/v17/leanback/res/values-zu/strings.xml b/v17/leanback/res/values-zu/strings.xml
index 4168b19..f17455d 100644
--- a/v17/leanback/res/values-zu/strings.xml
+++ b/v17/leanback/res/values-zu/strings.xml
@@ -22,4 +22,28 @@
     <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"Khuluma ukuze useshe"</string>
     <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"Sesha i-<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
     <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"Khuluma ukuze useshe i-<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"%1$dX"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"Dlala"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"Misa isikhashana"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"Iya phambili ngokushesha"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"Mikisa phambili ngokushesha i-%1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"Buyisela emuva"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"Mikisa emuva i-%1$dX"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"Yeqa okulandelayo"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"Yeqa kwangaphambilini"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"Izenzo eziningi"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"Susa ukukhetha isithupha saphezulu"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"Khetha isithupha saphezulu"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"Susa ukukhetha isithupha saphansi"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"Khetha isithupha saphansi"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"Ungaphindi lutho"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"Phinda konke"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"Phida okukodwa"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"Nika amandla ukushova"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"Khubaza ukushova"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"Nika amandla ikhwalithi ephezulu"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"Khubaza ikhwalithi ephezulu"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"Nika amandla imibhalo engezansi"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"Khubaza imihbalo engezansi"</string>
 </resources>
diff --git a/v17/leanback/res/values/attrs.xml b/v17/leanback/res/values/attrs.xml
index 1b77694..656e38e 100644
--- a/v17/leanback/res/values/attrs.xml
+++ b/v17/leanback/res/values/attrs.xml
@@ -431,5 +431,27 @@
 
     </declare-styleable>
 
+    <attr name="cardGravity">
+        <!-- Push child views to the left of the container. -->
+        <flag name="left" value="0x03" />
+        <!-- Push child views to the right of the container. -->
+        <flag name="right" value="0x05" />
+        <!-- Push child views to the beginning of the container. -->
+        <flag name="start" value="0x00800003" />
+        <!-- Push child views to the end of the container. -->
+        <flag name="end" value="0x00800005" />
+    </attr>
+
+    <declare-styleable name="StackedLayout">
+        <!-- Defines the width of child views in this layout -->
+        <attr name="cardWidth" format="dimension" />
+        <!-- Defines the distance to shift child views away from the edge when another child
+             is added -->
+        <attr name="stackShift" format="dimension" />
+        <!-- Defines the amount to increment the elevation of each added child -->
+        <attr name="elevationIncrement" format="dimension" />
+        <!-- Defines which edge child views are laid out on -->
+        <attr name="cardGravity" />
+    </declare-styleable>
 
 </resources>
diff --git a/v17/leanback/src/android/support/v17/leanback/app/BackgroundManager.java b/v17/leanback/src/android/support/v17/leanback/app/BackgroundManager.java
index 4eec366..1b10741 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/BackgroundManager.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/BackgroundManager.java
@@ -15,6 +15,7 @@
 
 import java.lang.ref.WeakReference;
 
+import android.support.annotation.ColorInt;
 import android.graphics.PixelFormat;
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffColorFilter;
@@ -964,7 +965,7 @@
      * Sets the background to the given color. The timing for when this becomes
      * visible in the app is undefined and may take place after a small delay.
      */
-    public void setColor(int color) {
+    public void setColor(@ColorInt int color) {
         if (DEBUG) Log.v(TAG, "setColor " + Integer.toHexString(color));
 
         mBackgroundColor = color;
@@ -1116,6 +1117,7 @@
     /**
      * Returns the current background color.
      */
+    @ColorInt
     public final int getColor() {
         return mBackgroundColor;
     }
diff --git a/v17/leanback/src/android/support/v17/leanback/app/BrowseFragment.java b/v17/leanback/src/android/support/v17/leanback/app/BrowseFragment.java
index 4860018..5f8cd51 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/BrowseFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/BrowseFragment.java
@@ -13,6 +13,7 @@
  */
 package android.support.v17.leanback.app;
 
+import android.support.annotation.ColorInt;
 import android.support.v17.leanback.R;
 import android.support.v17.leanback.transition.LeanbackTransitionHelper;
 import android.support.v17.leanback.transition.TransitionHelper;
@@ -276,7 +277,7 @@
      *
      * @param color The color to use as the brand color of the fragment.
      */
-    public void setBrandColor(int color) {
+    public void setBrandColor(@ColorInt int color) {
         mBrandColor = color;
         mBrandColorSet = true;
 
@@ -289,6 +290,7 @@
      * Returns the brand color for the browse fragment.
      * The default is transparent.
      */
+    @ColorInt
     public int getBrandColor() {
         return mBrandColor;
     }
diff --git a/v17/leanback/src/android/support/v17/leanback/app/BrowseSupportFragment.java b/v17/leanback/src/android/support/v17/leanback/app/BrowseSupportFragment.java
index bfa83e8..a98e1ea 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/BrowseSupportFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/BrowseSupportFragment.java
@@ -15,6 +15,7 @@
  */
 package android.support.v17.leanback.app;
 
+import android.support.annotation.ColorInt;
 import android.support.v17.leanback.R;
 import android.support.v17.leanback.transition.LeanbackTransitionHelper;
 import android.support.v17.leanback.transition.TransitionHelper;
@@ -278,7 +279,7 @@
      *
      * @param color The color to use as the brand color of the fragment.
      */
-    public void setBrandColor(int color) {
+    public void setBrandColor(@ColorInt int color) {
         mBrandColor = color;
         mBrandColorSet = true;
 
@@ -291,6 +292,7 @@
      * Returns the brand color for the browse fragment.
      * The default is transparent.
      */
+    @ColorInt
     public int getBrandColor() {
         return mBrandColor;
     }
diff --git a/v17/leanback/src/android/support/v17/leanback/app/VerticalGridFragment.java b/v17/leanback/src/android/support/v17/leanback/app/VerticalGridFragment.java
index d02ef97..6b6cc2e 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/VerticalGridFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/VerticalGridFragment.java
@@ -13,6 +13,7 @@
  */
 package android.support.v17.leanback.app;
 
+import android.support.annotation.ColorInt;
 import android.support.v17.leanback.R;
 import android.support.v17.leanback.widget.BrowseFrameLayout;
 import android.support.v17.leanback.widget.OnChildLaidOutListener;
diff --git a/v17/leanback/src/android/support/v17/leanback/app/VerticalGridSupportFragment.java b/v17/leanback/src/android/support/v17/leanback/app/VerticalGridSupportFragment.java
index 73d299c..0770761 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/VerticalGridSupportFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/VerticalGridSupportFragment.java
@@ -15,6 +15,7 @@
  */
 package android.support.v17.leanback.app;
 
+import android.support.annotation.ColorInt;
 import android.support.v17.leanback.R;
 import android.support.v17.leanback.widget.BrowseFrameLayout;
 import android.support.v17.leanback.widget.OnChildLaidOutListener;
diff --git a/v17/leanback/src/android/support/v17/leanback/view/StackedLayout.java b/v17/leanback/src/android/support/v17/leanback/view/StackedLayout.java
new file mode 100644
index 0000000..56c4bad
--- /dev/null
+++ b/v17/leanback/src/android/support/v17/leanback/view/StackedLayout.java
@@ -0,0 +1,410 @@
+/*
+ * 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.view;
+
+import android.animation.Animator;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Rect;
+import android.support.v17.leanback.R;
+import android.support.v4.view.GravityCompat;
+import android.support.v4.view.ViewCompat;
+import android.util.AttributeSet;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewGroup;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A ViewGroup which arranges its children in an overlapping stack with the most
+ * recently added view displayed at the top. Adding and removing views is animated.
+ *
+ * @attr ref R.styleable#StackedLayout_cardWidth
+ * @attr ref R.styleable#StackedLayout_stackShift
+ * @attr ref R.styleable#StackedLayout_elevationIncrement
+ * @attr ref R.styleable#StackedLayout_cardGravity
+ *
+ * @hide
+ */
+public class StackedLayout extends ViewGroup {
+
+    private int mCardWidth;
+    private int mStackShift;
+    private float mElevationIncrement;
+    private int mCardGravity;
+
+    private int mAddedViews = 0;
+    private int mRemovedViews = 0;
+    private List<View> mQueuedRemovedViews;
+    private Animator mCurrentAnimator;
+
+    private OnHierarchyChangeListener mHierarchyChangeListener;
+    private final OnHierarchyChangeListener mHierarchyChangeListenerInternal =
+            new OnHierarchyChangeInternalListener();
+
+    public StackedLayout(Context context) {
+        this(context, null);
+    }
+
+    public StackedLayout(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public StackedLayout(Context context, AttributeSet attrs,
+            int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+
+        final TypedArray a = context.obtainStyledAttributes(
+                attrs, R.styleable.StackedLayout, defStyleAttr, 0);
+        mCardWidth = Math.round(a.getDimension(R.styleable.StackedLayout_cardWidth, 0));
+        mStackShift = Math.round(a.getDimension(R.styleable.StackedLayout_stackShift, 0));
+        mElevationIncrement = a.getDimension(R.styleable.StackedLayout_elevationIncrement, 0);
+        mCardGravity = a.getInt(R.styleable.StackedLayout_cardGravity, GravityCompat.END);
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        super.setOnHierarchyChangeListener(mHierarchyChangeListenerInternal);
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        super.setOnHierarchyChangeListener(null);
+    }
+
+    @Override
+    public void setOnHierarchyChangeListener(OnHierarchyChangeListener listener) {
+        mHierarchyChangeListener = listener;
+    }
+
+    @Override
+    protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
+        final int childCount = getChildCount();
+        if (childCount == 0) {
+            return false;
+        }
+        final View lastChild = getChildAt(childCount - 1);
+        return lastChild.requestFocus(direction, previouslyFocusedRect);
+    }
+
+    @Override
+    public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
+        // We only want to be able to focus the [child views of] the last child
+        if (getChildCount() == 0) {
+            return;
+        }
+
+        final View lastChild = getChildAt(getChildCount() - 1);
+        lastChild.addFocusables(views, direction, focusableMode);
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
+        final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
+        final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
+        final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
+
+        final int width;
+        final int height;
+
+        switch (widthMode) {
+            case MeasureSpec.EXACTLY:
+            case MeasureSpec.AT_MOST:
+                width = widthSize;
+                break;
+            case MeasureSpec.UNSPECIFIED:
+            default:
+                width = ViewCompat.getMinimumWidth(this);
+                break;
+        }
+
+        switch (heightMode) {
+            case MeasureSpec.EXACTLY:
+            case MeasureSpec.AT_MOST:
+                height = heightSize;
+                break;
+            case MeasureSpec.UNSPECIFIED:
+            default:
+                height = ViewCompat.getMinimumHeight(this);
+                break;
+        }
+
+        setMeasuredDimension(width, height);
+
+        final int childWidthMeasureSpec =
+                MeasureSpec.makeMeasureSpec(mCardWidth, MeasureSpec.EXACTLY);
+        final int childHeightMeasureSpec =
+                MeasureSpec.makeMeasureSpec(height - getPaddingTop() - getPaddingBottom(),
+                        MeasureSpec.AT_MOST);
+
+        measureChildren(childWidthMeasureSpec, childHeightMeasureSpec);
+    }
+
+    /**
+     *
+     * {@inheritDoc}
+     */
+    @Override
+    public LayoutParams generateLayoutParams(AttributeSet attrs) {
+        return new LayoutParams(getContext(), attrs);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
+        return p instanceof LayoutParams;
+    }
+
+    @Override
+    protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
+        return new LayoutParams(p);
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int l, int t, int r, int b) {
+        final boolean rightEdge =
+                (GravityCompat.getAbsoluteGravity(mCardGravity, ViewCompat.getLayoutDirection(this))
+                & Gravity.RIGHT) == Gravity.RIGHT;
+
+        layoutInternal(l, t, r, b, rightEdge);
+        if (mAddedViews != 0 || mRemovedViews != 0) {
+            if (mCurrentAnimator != null) {
+                mCurrentAnimator.cancel();
+                mCurrentAnimator = null;
+            }
+
+            final int initialPositions[] = getChildLeftPositions();
+
+            mAddedViews = 0;
+            mRemovedViews = 0;
+            layoutInternal(l, t, r, b, rightEdge);
+
+            final int finalPositions[] = getChildLeftPositions();
+
+
+            final int childCount = getChildCount();
+            final List<Animator> animators = new ArrayList<>(childCount);
+
+            for (int childIndex = 0; childIndex < childCount; childIndex++) {
+                final View child = getChildAt(childIndex);
+                // Want: initialPos = finalPos + translationX
+                // Thus: initialPos - finalPos = translationX
+                // Plus any current translation in case we interrupted an animation in progress
+
+                final int newTranslationX = initialPositions[childIndex]
+                        - finalPositions[childIndex] + Math.round(child.getTranslationX());
+
+                child.setTranslationX(newTranslationX);
+
+                if (newTranslationX != 0) {
+                    // Animate to zero
+                    animators.add(ObjectAnimator.ofFloat(child, "translationX", 0));
+                }
+            }
+
+            if (mQueuedRemovedViews != null) {
+                for (final View child : mQueuedRemovedViews) {
+                    // Want: initialPos = finalPos + translationX
+                    // Thus: initialPos - finalPos = translationX
+                    // Plus any current translation in case we interrupted an animation in progress
+
+                    final int newTranslationX;
+
+                    if (rightEdge) {
+                        newTranslationX = child.getLeft() - getRight()
+                                + Math.round(child.getTranslationX());
+                        // Move the child to the new position and set the translation
+                        child.offsetLeftAndRight(getRight() - child.getLeft());
+                    } else {
+                        newTranslationX = child.getLeft() - getLeft() + child.getWidth()
+                                + Math.round(child.getTranslationX());
+                        // Move the child to the new position and set the translation
+                        child.offsetLeftAndRight(getLeft() - child.getWidth() - child.getLeft());
+                    }
+
+                    child.setTranslationX(newTranslationX);
+
+                    // Animate to zero
+                    final Animator animator = ObjectAnimator.ofFloat(child, "translationX", 0);
+                    animator.addListener(new RemovalAnimationListener(child));
+                    animators.add(animator);
+                }
+                mQueuedRemovedViews = null;
+            }
+
+            final AnimatorSet animatorSet = new AnimatorSet();
+            animatorSet.playTogether(animators);
+            mCurrentAnimator = animatorSet;
+            mCurrentAnimator.start();
+        }
+
+    }
+
+    private int[] getChildLeftPositions() {
+        final int childCount = getChildCount();
+        final int positions[] = new int[childCount];
+        for (int childIndex = 0; childIndex < childCount; childIndex++) {
+            positions[childIndex] = getChildAt(childIndex).getLeft();
+        }
+        return positions;
+    }
+
+    private void layoutInternal(int l, int t, int r, int b, boolean rightEdge) {
+        final int parentLeft = getPaddingLeft();
+        final int parentRight = r - l - getPaddingRight();
+
+        final int parentTop = getPaddingTop();
+        final int parentBottom = b - t - getPaddingBottom();
+
+        final float baseElevation = ViewCompat.getElevation(this);
+
+        final int childCount = getChildCount();
+        for (int childIndex = 0; childIndex < childCount; childIndex++) {
+            final View child = getChildAt(childIndex);
+            if (child.getVisibility() != GONE) {
+                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+
+                final int width = Math.round(mCardWidth);
+                final int height = child.getMeasuredHeight();
+
+                final int childLeft;
+                if (childIndex >= childCount - mAddedViews) {
+                    // This is a freshly added view, start it off the edge of the container.
+                    if (rightEdge) {
+                        childLeft = parentRight;
+                    } else {
+                        childLeft = parentLeft - width;
+                    }
+                } else {
+                    // This is an existing view, just place it normally. If there are added/removed
+                    // views, then place it as if those views have not yet been added/removed.
+                    if (rightEdge) {
+                        childLeft = parentRight - width - lp.rightMargin -
+                                (childCount - childIndex - (1 + mAddedViews - mRemovedViews))
+                                        * mStackShift;
+                    } else {
+                        childLeft = parentLeft + lp.leftMargin +
+                                (childCount - childIndex - (1 + mAddedViews - mRemovedViews))
+                                        * mStackShift;
+                    }
+                }
+                final int childTop = parentTop + lp.topMargin;
+
+                child.layout(childLeft, childTop, childLeft + width, childTop + height);
+
+                ViewCompat.setElevation(child,
+                        baseElevation + (childIndex + 1) * mElevationIncrement);
+            }
+        }
+    }
+
+    public class LayoutParams extends MarginLayoutParams {
+
+        public LayoutParams(Context c, AttributeSet attrs) {
+            super(c, attrs);
+        }
+
+        public LayoutParams(int width, int height) {
+            super(width, height);
+        }
+
+        public LayoutParams(MarginLayoutParams source) {
+            super(source);
+        }
+
+        public LayoutParams(ViewGroup.LayoutParams source) {
+            super(source);
+        }
+    }
+
+    private class OnHierarchyChangeInternalListener implements OnHierarchyChangeListener {
+
+        @Override
+        public void onChildViewAdded(View parent, View child) {
+            final int childCount = getChildCount();
+            for (int i = 0; i < childCount - 1; i++) {
+                final View oldChild = getChildAt(i);
+                oldChild.clearFocus();
+            }
+            mAddedViews++;
+            if (mHierarchyChangeListener != null) {
+                mHierarchyChangeListener.onChildViewAdded(parent, child);
+            }
+        }
+
+        @Override
+        public void onChildViewRemoved(View parent, final View child) {
+            if (mHierarchyChangeListener != null) {
+                mHierarchyChangeListener.onChildViewRemoved(parent, child);
+            }
+            mRemovedViews++;
+            if (ViewGroupOverlayHelper.supportsOverlay()) {
+                ViewGroupOverlayHelper.addChildToOverlay(StackedLayout.this, child);
+                if (mQueuedRemovedViews == null) {
+                    mQueuedRemovedViews = new ArrayList<>(1);
+                }
+                mQueuedRemovedViews.add(child);
+            }
+        }
+    }
+
+    private class RemovalAnimationListener implements Animator.AnimatorListener {
+        private final View mView;
+
+        public RemovalAnimationListener(View view) {
+            mView = view;
+        }
+
+        @Override
+        public void onAnimationStart(Animator animation) {}
+
+        @Override
+        public void onAnimationEnd(Animator animation) {
+            ViewGroupOverlayHelper.removeChildFromOverlay(StackedLayout.this, mView);
+            animation.removeListener(this);
+        }
+
+        @Override
+        public void onAnimationCancel(Animator animation) {
+            // Re-add the view to the queued list so that the next animation continues
+            // animating it away
+            if (mQueuedRemovedViews == null) {
+                mQueuedRemovedViews = new ArrayList<>(1);
+            }
+            mQueuedRemovedViews.add(mView);
+            animation.removeListener(this);
+        }
+
+        @Override
+        public void onAnimationRepeat(Animator animation) {}
+
+        @Override
+        public String toString() {
+            return getClass().getName() + " [" + mView.toString() + "]";
+        }
+    }
+
+}
diff --git a/v17/leanback/src/android/support/v17/leanback/view/ViewGroupOverlayHelper.java b/v17/leanback/src/android/support/v17/leanback/view/ViewGroupOverlayHelper.java
new file mode 100644
index 0000000..18e3534
--- /dev/null
+++ b/v17/leanback/src/android/support/v17/leanback/view/ViewGroupOverlayHelper.java
@@ -0,0 +1,76 @@
+/*
+ * 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.view;
+
+import android.os.Build;
+import android.view.View;
+import android.view.ViewGroup;
+
+public class ViewGroupOverlayHelper {
+
+    public interface Impl {
+        void addChildToOverlay(ViewGroup parent, View child);
+        void removeChildFromOverlay(ViewGroup parent, View child);
+    }
+
+    private static class ImplStub implements Impl {
+
+        @Override
+        public void addChildToOverlay(ViewGroup parent, View child) {}
+
+        @Override
+        public void removeChildFromOverlay(ViewGroup parent, View child) {}
+    }
+
+    private static class ImplJbmr2 implements Impl {
+
+        @Override
+        public void addChildToOverlay(ViewGroup parent, View child) {
+            ViewGroupOverlayHelperJbmr2.addChildToOverlay(parent, child);
+        }
+
+        @Override
+        public void removeChildFromOverlay(ViewGroup parent, View child) {
+            ViewGroupOverlayHelperJbmr2.removeChildFromOverlay(parent, child);
+        }
+    }
+
+    private static Impl sInstance;
+
+    private static Impl getInstance() {
+        if (sInstance == null) {
+            if (Build.VERSION.SDK_INT >= 18) {
+                sInstance = new ImplJbmr2();
+            } else {
+                sInstance = new ImplStub();
+            }
+        }
+        return sInstance;
+    }
+
+    public static boolean supportsOverlay() {
+        return Build.VERSION.SDK_INT >= 18;
+    }
+
+    public static void addChildToOverlay(ViewGroup parent, View child) {
+        getInstance().addChildToOverlay(parent, child);
+    }
+
+    public static void removeChildFromOverlay(ViewGroup parent, View child) {
+        getInstance().removeChildFromOverlay(parent, child);
+    }
+}
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/DetailsOverviewRowPresenter.java b/v17/leanback/src/android/support/v17/leanback/widget/DetailsOverviewRowPresenter.java
index be9a263..34c2004 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/DetailsOverviewRowPresenter.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/DetailsOverviewRowPresenter.java
@@ -21,6 +21,7 @@
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.ColorDrawable;
 import android.os.Handler;
+import android.support.annotation.ColorInt;
 import android.support.v17.leanback.R;
 import android.support.v7.widget.RecyclerView;
 import android.util.Log;
@@ -326,7 +327,7 @@
     /**
      * Sets the background color.  If not set, a default from the theme will be used.
      */
-    public void setBackgroundColor(int color) {
+    public void setBackgroundColor(@ColorInt int color) {
         mBackgroundColor = color;
         mBackgroundColorSet = true;
     }
@@ -335,6 +336,7 @@
      * Returns the background color.  If no background color was set, transparent
      * is returned.
      */
+    @ColorInt
     public int getBackgroundColor() {
         return mBackgroundColor;
     }
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 48e491b..15943b4 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/GuidedActionsStylist.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/GuidedActionsStylist.java
@@ -529,6 +529,8 @@
             Context context = iconView.getContext();
             icon = action.getIcon();
             if (icon != null) {
+                // setImageDrawable resets the drawable's level unless we set the view level first.
+                iconView.setImageLevel(icon.getLevel());
                 iconView.setImageDrawable(icon);
                 iconView.setVisibility(View.VISIBLE);
             } else {
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/ImageCardView.java b/v17/leanback/src/android/support/v17/leanback/widget/ImageCardView.java
index eaab7c0..2c1c7e0 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/ImageCardView.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/ImageCardView.java
@@ -16,6 +16,7 @@
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.drawable.Drawable;
+import android.support.annotation.ColorInt;
 import android.support.v17.leanback.R;
 import android.text.TextUtils;
 import android.util.AttributeSet;
@@ -169,8 +170,8 @@
 
     /**
      * Sets the info area background color.
-     */
-    public void setInfoAreaBackgroundColor(int color) {
+     */    
+    public void setInfoAreaBackgroundColor(@ColorInt int color) {
         if (mInfoArea != null) {
             mInfoArea.setBackgroundColor(color);
         }
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/PlaybackControlsPresenter.java b/v17/leanback/src/android/support/v17/leanback/widget/PlaybackControlsPresenter.java
index 72352f9..f1db00b 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/PlaybackControlsPresenter.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/PlaybackControlsPresenter.java
@@ -20,6 +20,7 @@
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.LayerDrawable;
+import android.support.annotation.ColorInt;
 import android.support.v17.leanback.R;
 import android.view.Gravity;
 import android.view.LayoutInflater;
@@ -227,7 +228,7 @@
         return mMoreActionsEnabled;
     }
 
-    public void setProgressColor(ViewHolder vh, int color) {
+    public void setProgressColor(ViewHolder vh, @ColorInt int color) {
         Drawable drawable = new ClipDrawable(new ColorDrawable(color),
                 Gravity.LEFT, ClipDrawable.HORIZONTAL);
         ((LayerDrawable) vh.mProgressBar.getProgressDrawable())
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/PlaybackControlsRowPresenter.java b/v17/leanback/src/android/support/v17/leanback/widget/PlaybackControlsRowPresenter.java
index f6ceacb..b43fdb7 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/PlaybackControlsRowPresenter.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/PlaybackControlsRowPresenter.java
@@ -14,6 +14,7 @@
 package android.support.v17.leanback.widget;
 
 import android.graphics.drawable.Drawable;
+import android.support.annotation.ColorInt;
 import android.support.v17.leanback.R;
 import android.support.v17.leanback.widget.ControlBarPresenter.OnControlClickedListener;
 import android.support.v17.leanback.widget.ControlBarPresenter.OnControlSelectedListener;
@@ -231,7 +232,7 @@
     /**
      * Sets the background color.  If not set, a default from the theme will be used.
      */
-    public void setBackgroundColor(int color) {
+    public void setBackgroundColor(@ColorInt int color) {
         mBackgroundColor = color;
         mBackgroundColorSet = true;
     }
@@ -240,6 +241,7 @@
      * Returns the background color.  If no background color was set, transparent
      * is returned.
      */
+    @ColorInt
     public int getBackgroundColor() {
         return mBackgroundColor;
     }
@@ -248,7 +250,7 @@
      * Sets the primary color for the progress bar.  If not set, a default from
      * the theme will be used.
      */
-    public void setProgressColor(int color) {
+    public void setProgressColor(@ColorInt int color) {
         mProgressColor = color;
         mProgressColorSet = true;
     }
@@ -257,6 +259,7 @@
      * Returns the primary color for the progress bar.  If no color was set, transparent
      * is returned.
      */
+    @ColorInt
     public int getProgressColor() {
         return mProgressColor;
     }
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/RowContainerView.java b/v17/leanback/src/android/support/v17/leanback/widget/RowContainerView.java
index 4de58ea..a8ea24c 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/RowContainerView.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/RowContainerView.java
@@ -17,6 +17,7 @@
 import android.graphics.Canvas;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
+import android.support.annotation.ColorInt;
 import android.support.v17.leanback.R;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
@@ -77,7 +78,7 @@
         invalidate();
     }
 
-    public void setForegroundColor(int color) {
+    public void setForegroundColor(@ColorInt int color) {
         if (mForeground instanceof ColorDrawable) {
             ((ColorDrawable) mForeground.mutate()).setColor(color);
             invalidate();
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/SearchOrbView.java b/v17/leanback/src/android/support/v17/leanback/widget/SearchOrbView.java
index 46293ea..a060ec0 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/SearchOrbView.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/SearchOrbView.java
@@ -25,6 +25,7 @@
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.GradientDrawable;
+import android.support.annotation.ColorInt;
 import android.support.v17.leanback.R;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
@@ -63,7 +64,7 @@
          *
          * @param color The main search orb color.
          */
-        public Colors(int color) {
+        public Colors(@ColorInt int color) {
             this(color, color);
         }
 
@@ -74,7 +75,7 @@
          * @param color The main search orb color.
          * @param brightColor A brighter version of the search orb used for animation.
          */
-        public Colors(int color, int brightColor) {
+        public Colors(@ColorInt int color, @ColorInt int brightColor) {
             this(color, brightColor, Color.TRANSPARENT);
         }
 
@@ -85,7 +86,7 @@
          * @param brightColor A brighter version of the search orb used for animation.
          * @param iconColor A color used to tint the search orb icon.
          */
-        public Colors(int color, int brightColor, int iconColor) {
+        public Colors(@ColorInt int color, @ColorInt int brightColor, @ColorInt int iconColor) {
             this.color = color;
             this.brightColor = brightColor == color ? getBrightColor(color) : brightColor;
             this.iconColor = iconColor;
@@ -94,16 +95,19 @@
         /**
          * The main color of the search orb.
          */
+        @ColorInt
         public int color;
 
         /**
          * A brighter version of the search orb used for animation.
          */
+        @ColorInt
         public int brightColor;
 
         /**
          * A color used to tint the search orb icon.
          */
+        @ColorInt
         public int iconColor;
 
         /**
@@ -294,7 +298,7 @@
      * @deprecated Use {@link #setOrbColors(Colors)} instead.
      */
     @Deprecated
-    public void setOrbColor(int color, int brightColor) {
+    public void setOrbColor(@ColorInt int color, @ColorInt int brightColor) {
         setOrbColors(new Colors(color, brightColor, Color.TRANSPARENT));
     }
 
@@ -302,6 +306,7 @@
      * Returns the orb color
      * @return the RGBA color
      */
+    @ColorInt
     public int getOrbColor() {
         return mColors.color;
     }
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/ShadowOverlayContainer.java b/v17/leanback/src/android/support/v17/leanback/widget/ShadowOverlayContainer.java
index 2244f5e..ad82fd2 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/ShadowOverlayContainer.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/ShadowOverlayContainer.java
@@ -14,6 +14,7 @@
 package android.support.v17.leanback.widget;
 
 import android.content.Context;
+import android.support.annotation.ColorInt;
 import android.support.v17.leanback.R;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
@@ -216,7 +217,7 @@
     /**
      * Set color (with alpha) of the overlay.
      */
-    public void setOverlayColor(int overlayColor) {
+    public void setOverlayColor(@ColorInt int overlayColor) {
         if (mColorDimOverlay != null) {
             mColorDimOverlay.setBackgroundColor(overlayColor);
         }
diff --git a/v17/preference-leanback/Android.mk b/v17/preference-leanback/Android.mk
new file mode 100644
index 0000000..05a7a54
--- /dev/null
+++ b/v17/preference-leanback/Android.mk
@@ -0,0 +1,64 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+# Build the resources using the current SDK version.
+# We do this here because the final static library must be compiled with an older
+# SDK version than the resources.  The resources library and the R class that it
+# contains will not be linked into the final static library.
+include $(CLEAR_VARS)
+LOCAL_MODULE := android-support-v17-preference-leanback-res
+LOCAL_SDK_VERSION := current
+LOCAL_SRC_FILES := $(call all-java-files-under, dummy)
+LOCAL_RESOURCE_DIR := \
+        frameworks/support/v7/appcompat/res \
+        frameworks/support/v7/recyclerview/res \
+        frameworks/support/v7/preference/res \
+        frameworks/support/v14/preference/res \
+        frameworks/support/v17/leanback/res \
+        $(LOCAL_PATH)/res
+LOCAL_AAPT_FLAGS := \
+	--auto-add-overlay
+LOCAL_JAR_EXCLUDE_FILES := none
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+# Here is the final static library that apps can link against.
+# The R class is automatically excluded from the generated library.
+# Applications that use this library must specify LOCAL_RESOURCE_DIR
+# in their makefiles to include the resources in their package.
+include $(CLEAR_VARS)
+LOCAL_MODULE := android-support-v17-preference-leanback
+LOCAL_SDK_VERSION := 17
+LOCAL_SRC_FILES := $(call all-java-files-under,src)
+# LOCAL_STATIC_JAVA_LIBRARIES :=
+LOCAL_JAVA_LIBRARIES := \
+        android-support-v4 \
+        android-support-v7-appcompat \
+        android-support-v7-recyclerview \
+        android-support-v7-preference \
+        android-support-v14-preference \
+        android-support-v17-leanback \
+        android-support-annotations \
+        android-support-v17-preference-leanback-res
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+# API Check
+# ---------------------------------------------
+support_module := $(LOCAL_MODULE)
+support_module_api_dir := $(LOCAL_PATH)/api
+support_module_src_files := $(LOCAL_SRC_FILES)
+support_module_java_libraries := $(LOCAL_JAVA_LIBRARIES)
+support_module_java_packages := android.support.v17.preference
+include $(SUPPORT_API_CHECK)
diff --git a/v17/preference-leanback/AndroidManifest.xml b/v17/preference-leanback/AndroidManifest.xml
new file mode 100644
index 0000000..e2cfe35
--- /dev/null
+++ b/v17/preference-leanback/AndroidManifest.xml
@@ -0,0 +1,24 @@
+<?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
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.support.v17.preference"
+    android:versionCode="1"
+    android:versionName="1.0">
+    <uses-sdk android:minSdkVersion="17" />
+    <application />
+</manifest>
diff --git a/v17/preference-leanback/api/current.txt b/v17/preference-leanback/api/current.txt
new file mode 100644
index 0000000..b31306c
--- /dev/null
+++ b/v17/preference-leanback/api/current.txt
@@ -0,0 +1,68 @@
+package android.support.v17.preference {
+
+  public abstract class BaseLeanbackPreferenceFragment extends android.support.v14.preference.PreferenceFragment {
+    ctor public BaseLeanbackPreferenceFragment();
+  }
+
+  public class LeanbackListPreferenceDialogFragment extends android.support.v17.preference.LeanbackPreferenceDialogFragment {
+    ctor public LeanbackListPreferenceDialogFragment();
+    method public static android.support.v17.preference.LeanbackListPreferenceDialogFragment newInstanceMulti(java.lang.String);
+    method public static android.support.v17.preference.LeanbackListPreferenceDialogFragment newInstanceSingle(java.lang.String);
+    method public android.support.v7.widget.RecyclerView.Adapter onCreateAdapter();
+  }
+
+  public class LeanbackListPreferenceDialogFragment.AdapterMulti extends android.support.v7.widget.RecyclerView.Adapter implements android.support.v17.preference.LeanbackListPreferenceDialogFragment.ViewHolder.OnItemClickListener {
+    ctor public LeanbackListPreferenceDialogFragment.AdapterMulti(java.lang.CharSequence[], java.lang.CharSequence[], java.util.Set<java.lang.String>);
+    method public int getItemCount();
+    method public void onBindViewHolder(android.support.v17.preference.LeanbackListPreferenceDialogFragment.ViewHolder, int);
+    method public android.support.v17.preference.LeanbackListPreferenceDialogFragment.ViewHolder onCreateViewHolder(android.view.ViewGroup, int);
+    method public void onItemClick(android.support.v17.preference.LeanbackListPreferenceDialogFragment.ViewHolder);
+  }
+
+  public class LeanbackListPreferenceDialogFragment.AdapterSingle extends android.support.v7.widget.RecyclerView.Adapter implements android.support.v17.preference.LeanbackListPreferenceDialogFragment.ViewHolder.OnItemClickListener {
+    ctor public LeanbackListPreferenceDialogFragment.AdapterSingle(java.lang.CharSequence[], java.lang.CharSequence[], java.lang.CharSequence);
+    method public int getItemCount();
+    method public void onBindViewHolder(android.support.v17.preference.LeanbackListPreferenceDialogFragment.ViewHolder, int);
+    method public android.support.v17.preference.LeanbackListPreferenceDialogFragment.ViewHolder onCreateViewHolder(android.view.ViewGroup, int);
+    method public void onItemClick(android.support.v17.preference.LeanbackListPreferenceDialogFragment.ViewHolder);
+  }
+
+  public static class LeanbackListPreferenceDialogFragment.ViewHolder extends android.support.v7.widget.RecyclerView.ViewHolder implements android.view.View.OnClickListener {
+    ctor public LeanbackListPreferenceDialogFragment.ViewHolder(android.view.View, android.support.v17.preference.LeanbackListPreferenceDialogFragment.ViewHolder.OnItemClickListener);
+    method public android.view.ViewGroup getContainer();
+    method public android.widget.TextView getTitleView();
+    method public android.widget.Checkable getWidgetView();
+    method public void onClick(android.view.View);
+  }
+
+  public static abstract interface LeanbackListPreferenceDialogFragment.ViewHolder.OnItemClickListener {
+    method public abstract void onItemClick(android.support.v17.preference.LeanbackListPreferenceDialogFragment.ViewHolder);
+  }
+
+  public class LeanbackPreferenceDialogFragment extends android.app.Fragment {
+    ctor public LeanbackPreferenceDialogFragment();
+    method public android.support.v7.preference.DialogPreference getPreference();
+    method public android.support.v14.preference.PreferenceFragment getPreferenceFragment();
+    method public android.support.v17.preference.LeanbackSettingsFragment getSettingsFragment();
+    field public static final java.lang.String ARG_KEY = "key";
+  }
+
+  public static abstract interface LeanbackPreferenceDialogFragment.TargetFragment {
+    method public abstract android.support.v14.preference.PreferenceFragment getPreferenceFragment();
+    method public abstract android.support.v17.preference.LeanbackSettingsFragment getSettingsFragment();
+  }
+
+  public abstract class LeanbackPreferenceFragment extends android.support.v17.preference.BaseLeanbackPreferenceFragment {
+    ctor public LeanbackPreferenceFragment();
+  }
+
+  public abstract class LeanbackSettingsFragment extends android.app.Fragment {
+    ctor public LeanbackSettingsFragment();
+    method public boolean onPreferenceDisplayDialog(android.support.v14.preference.PreferenceFragment, android.support.v7.preference.Preference);
+    method public abstract void onPreferenceStartInitialScreen();
+    method public void startImmersiveFragment(android.app.Fragment, java.lang.String);
+    method public void startPreferenceFragment(android.app.Fragment, java.lang.String);
+  }
+
+}
+
diff --git a/v17/preference-leanback/api/removed.txt b/v17/preference-leanback/api/removed.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/v17/preference-leanback/api/removed.txt
diff --git a/v17/preference-leanback/build.gradle b/v17/preference-leanback/build.gradle
new file mode 100644
index 0000000..e8195da
--- /dev/null
+++ b/v17/preference-leanback/build.gradle
@@ -0,0 +1,58 @@
+/*
+ * 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
+ */
+
+
+
+apply plugin: 'android-library'
+
+archivesBaseName = 'preference-leanback-v17'
+
+dependencies {
+    compile project(':support-v4')
+    compile project(':support-appcompat-v7')
+    compile project(':support-recyclerview-v7')
+    compile project(':support-preference-v7')
+    compile project(':support-preference-v14')
+    compile project(':support-leanback-v17')
+}
+
+android {
+    compileSdkVersion 'current'
+
+    sourceSets {
+        main.manifest.srcFile 'AndroidManifest.xml'
+        main.java.srcDir 'src'
+        main.res.srcDir 'res'
+        main.assets.srcDir 'assets'
+        main.resources.srcDir 'src'
+
+        // this moves src/instrumentTest to tests so all folders follow:
+        // tests/java, tests/res, tests/assets, ...
+        // This is a *reset* so it replaces the default paths
+        androidTest.setRoot('tests')
+        androidTest.java.srcDir 'tests/src'
+    }
+
+    compileOptions {
+        sourceCompatibility JavaVersion.VERSION_1_7
+        targetCompatibility JavaVersion.VERSION_1_7
+    }
+
+    lintOptions {
+        // TODO: fix errors and reenable.
+        abortOnError false
+    }
+}
diff --git a/v17/preference-leanback/res/layout/leanback_list_preference_fragment.xml b/v17/preference-leanback/res/layout/leanback_list_preference_fragment.xml
new file mode 100644
index 0000000..ba8254b
--- /dev/null
+++ b/v17/preference-leanback/res/layout/leanback_list_preference_fragment.xml
@@ -0,0 +1,54 @@
+<?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
+  -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/main_frame"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@color/lb_preference_decor_list_background"
+    android:orientation="vertical"
+    >
+
+    <TextView android:id="@+id/decor_title"
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/lb_preference_decor_title_text_height"
+        android:background="?attr/defaultBrandColor"
+        android:fontFamily="sans-serif-condensed"
+        android:gravity="center_vertical"
+        android:paddingTop="@dimen/lb_preference_decor_title_padding_top"
+        android:paddingStart="@dimen/lb_preference_decor_title_padding_start"
+        android:paddingEnd="@dimen/lb_preference_decor_title_padding_end"
+        android:singleLine="true"
+        android:textSize="@dimen/lb_preference_decor_title_text_size"
+        android:textColor="?android:attr/textColorPrimary"
+        />
+
+    <TextView
+        android:id="@android:id/message"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingTop="14dp"
+        android:paddingBottom="14dp"
+        android:paddingStart="24dp"
+        android:paddingEnd="56dp"
+        android:visibility="gone" />
+
+    <android.support.v17.leanback.widget.VerticalGridView android:id="@android:id/list"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
+
+</LinearLayout>
diff --git a/v17/preference-leanback/res/layout/leanback_list_preference_item_multi.xml b/v17/preference-leanback/res/layout/leanback_list_preference_item_multi.xml
new file mode 100644
index 0000000..3b1345c
--- /dev/null
+++ b/v17/preference-leanback/res/layout/leanback_list_preference_item_multi.xml
@@ -0,0 +1,37 @@
+<?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
+  -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/container"
+    android:layout_width="match_parent"
+    android:layout_height="?android:attr/listPreferredItemHeight"
+    android:background="?android:attr/selectableItemBackground"
+    android:clickable="true"
+    android:focusable="true"
+    android:descendantFocusability="blocksDescendants"
+    android:orientation="horizontal">
+    <CheckBox
+        android:id="@+id/button"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+    <TextView
+        android:id="@android:id/title"
+        android:layout_width="0dp"
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:gravity="center_vertical" />
+</LinearLayout>
diff --git a/v17/preference-leanback/res/layout/leanback_list_preference_item_single.xml b/v17/preference-leanback/res/layout/leanback_list_preference_item_single.xml
new file mode 100644
index 0000000..eaf42a4
--- /dev/null
+++ b/v17/preference-leanback/res/layout/leanback_list_preference_item_single.xml
@@ -0,0 +1,37 @@
+<?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
+  -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/container"
+    android:layout_width="match_parent"
+    android:layout_height="?android:attr/listPreferredItemHeight"
+    android:background="?android:attr/selectableItemBackground"
+    android:clickable="true"
+    android:focusable="true"
+    android:descendantFocusability="blocksDescendants"
+    android:orientation="horizontal">
+    <RadioButton
+        android:id="@+id/button"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+    <TextView
+        android:id="@android:id/title"
+        android:layout_width="0dp"
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:gravity="center_vertical" />
+</LinearLayout>
diff --git a/v17/preference-leanback/res/layout/leanback_preference_fragment.xml b/v17/preference-leanback/res/layout/leanback_preference_fragment.xml
new file mode 100644
index 0000000..3279a42
--- /dev/null
+++ b/v17/preference-leanback/res/layout/leanback_preference_fragment.xml
@@ -0,0 +1,40 @@
+<?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
+  -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/main_frame"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@color/lb_preference_decor_list_background"
+    android:orientation="vertical"
+    >
+
+    <TextView android:id="@+id/decor_title"
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/lb_preference_decor_title_text_height"
+        android:background="?attr/defaultBrandColor"
+        android:fontFamily="sans-serif-condensed"
+        android:gravity="center_vertical"
+        android:paddingTop="@dimen/lb_preference_decor_title_padding_top"
+        android:paddingStart="@dimen/lb_preference_decor_title_padding_start"
+        android:paddingEnd="@dimen/lb_preference_decor_title_padding_end"
+        android:singleLine="true"
+        android:textSize="@dimen/lb_preference_decor_title_text_size"
+        android:textColor="?android:attr/textColorPrimary"
+        />
+
+</LinearLayout>
diff --git a/v17/preference-leanback/res/layout/leanback_preferences_list.xml b/v17/preference-leanback/res/layout/leanback_preferences_list.xml
new file mode 100644
index 0000000..15ecebc
--- /dev/null
+++ b/v17/preference-leanback/res/layout/leanback_preferences_list.xml
@@ -0,0 +1,22 @@
+<?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
+  -->
+
+<android.support.v17.leanback.widget.VerticalGridView
+    android:id="@+id/list"
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent" />
diff --git a/v17/preference-leanback/res/layout/leanback_settings_fragment.xml b/v17/preference-leanback/res/layout/leanback_settings_fragment.xml
new file mode 100644
index 0000000..5cf3e51
--- /dev/null
+++ b/v17/preference-leanback/res/layout/leanback_settings_fragment.xml
@@ -0,0 +1,20 @@
+<?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
+  -->
+<android.support.v17.preference.LeanbackSettingsRootView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/settings_fragment_container"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"/>
diff --git a/v17/preference-leanback/res/layout/leanback_settings_fragment_stack.xml b/v17/preference-leanback/res/layout/leanback_settings_fragment_stack.xml
new file mode 100644
index 0000000..568c41e
--- /dev/null
+++ b/v17/preference-leanback/res/layout/leanback_settings_fragment_stack.xml
@@ -0,0 +1,26 @@
+<?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
+  -->
+<android.support.v17.leanback.view.StackedLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/settings_preference_stack"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    app:cardWidth="@dimen/lb_settings_card_width"
+    app:stackShift="@dimen/lb_settings_card_shift"
+    app:elevationIncrement="@dimen/lb_settings_card_elevation"
+    />
diff --git a/v17/preference-leanback/res/values/colors.xml b/v17/preference-leanback/res/values/colors.xml
new file mode 100644
index 0000000..de6c888
--- /dev/null
+++ b/v17/preference-leanback/res/values/colors.xml
@@ -0,0 +1,19 @@
+<?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
+  -->
+<resources>
+    <color name="lb_preference_decor_list_background">#263238</color>
+</resources>
diff --git a/v17/preference-leanback/res/values/dimens.xml b/v17/preference-leanback/res/values/dimens.xml
new file mode 100644
index 0000000..c3e519f
--- /dev/null
+++ b/v17/preference-leanback/res/values/dimens.xml
@@ -0,0 +1,27 @@
+<?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
+  -->
+<resources>
+  <dimen name="lb_preference_decor_title_text_height">64dp</dimen>
+  <dimen name="lb_preference_decor_title_padding_top">27dp</dimen>
+  <dimen name="lb_preference_decor_title_padding_start">24dp</dimen>
+  <dimen name="lb_preference_decor_title_padding_end">56dp</dimen>
+  <dimen name="lb_preference_decor_title_text_size">20sp</dimen>
+
+  <dimen name="lb_settings_card_width">360dp</dimen>
+  <dimen name="lb_settings_card_shift">72dp</dimen>
+  <dimen name="lb_settings_card_elevation">12dp</dimen>
+</resources>
diff --git a/v17/preference-leanback/src/android/support/v17/preference/BaseLeanbackPreferenceFragment.java b/v17/preference-leanback/src/android/support/v17/preference/BaseLeanbackPreferenceFragment.java
new file mode 100644
index 0000000..40d9607
--- /dev/null
+++ b/v17/preference-leanback/src/android/support/v17/preference/BaseLeanbackPreferenceFragment.java
@@ -0,0 +1,41 @@
+/*
+ * 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.preference;
+
+import android.os.Bundle;
+import android.support.v14.preference.PreferenceFragment;
+import android.support.v17.leanback.widget.VerticalGridView;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.ViewGroup;
+
+/**
+ * This fragment provides a preference fragment with leanback-style behavior, suitable for
+ * embedding into broader UI elements.
+ */
+public abstract class BaseLeanbackPreferenceFragment extends PreferenceFragment {
+
+    @Override
+    public RecyclerView onCreateRecyclerView(LayoutInflater inflater, ViewGroup parent,
+            Bundle savedInstanceState) {
+        VerticalGridView verticalGridView = (VerticalGridView) inflater
+                .inflate(R.layout.leanback_preferences_list, parent, false);
+        verticalGridView.setWindowAlignment(VerticalGridView.WINDOW_ALIGN_BOTH_EDGE);
+        verticalGridView.setFocusScrollStrategy(VerticalGridView.FOCUS_SCROLL_ALIGNED);
+        return verticalGridView;
+    }
+}
diff --git a/v17/preference-leanback/src/android/support/v17/preference/LeanbackListPreferenceDialogFragment.java b/v17/preference-leanback/src/android/support/v17/preference/LeanbackListPreferenceDialogFragment.java
new file mode 100644
index 0000000..17887e0
--- /dev/null
+++ b/v17/preference-leanback/src/android/support/v17/preference/LeanbackListPreferenceDialogFragment.java
@@ -0,0 +1,250 @@
+/*
+ * 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.preference;
+
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v14.preference.MultiSelectListPreference;
+import android.support.v17.leanback.widget.VerticalGridView;
+import android.support.v7.preference.DialogPreference;
+import android.support.v7.preference.ListPreference;
+import android.support.v7.widget.RecyclerView;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Checkable;
+import android.widget.TextView;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public class LeanbackListPreferenceDialogFragment extends LeanbackPreferenceDialogFragment {
+
+    public static LeanbackListPreferenceDialogFragment newInstanceSingle(String key) {
+        final Bundle args = new Bundle(5);
+        args.putString(ARG_KEY, key);
+
+        final LeanbackListPreferenceDialogFragment
+                fragment = new LeanbackListPreferenceDialogFragment();
+        fragment.setArguments(args);
+
+        return fragment;
+    }
+
+    public static LeanbackListPreferenceDialogFragment newInstanceMulti(String key) {
+        final Bundle args = new Bundle(5);
+        args.putString(ARG_KEY, key);
+
+        final LeanbackListPreferenceDialogFragment
+                fragment = new LeanbackListPreferenceDialogFragment();
+        fragment.setArguments(args);
+
+        return fragment;
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        final DialogPreference preference = getPreference();
+        if (!(preference instanceof ListPreference) &&
+                !(preference instanceof MultiSelectListPreference)) {
+            throw new IllegalArgumentException("Preference must be a ListPreference or " +
+                    "MultiSelectListPreference");
+        }
+    }
+
+    @Override
+    public @Nullable View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        final View view = inflater.inflate(R.layout.leanback_list_preference_fragment, container,
+                false);
+        final VerticalGridView verticalGridView =
+                (VerticalGridView) view.findViewById(android.R.id.list);
+
+        verticalGridView.setWindowAlignment(VerticalGridView.WINDOW_ALIGN_BOTH_EDGE);
+        verticalGridView.setFocusScrollStrategy(VerticalGridView.FOCUS_SCROLL_ALIGNED);
+        verticalGridView.setAdapter(onCreateAdapter());
+
+        final DialogPreference preference = getPreference();
+        final CharSequence title = preference.getDialogTitle();
+        if (!TextUtils.isEmpty(title)) {
+            final TextView titleView = (TextView) view.findViewById(R.id.decor_title);
+            titleView.setText(title);
+        }
+
+        final CharSequence message = preference.getDialogMessage();
+        if (!TextUtils.isEmpty(message)) {
+            final TextView messageView = (TextView) view.findViewById(android.R.id.message);
+            messageView.setVisibility(View.VISIBLE);
+            messageView.setText(message);
+        }
+
+        return view;
+    }
+
+    public RecyclerView.Adapter onCreateAdapter() {
+        final DialogPreference preference = getPreference();
+        if (preference instanceof MultiSelectListPreference) {
+            final MultiSelectListPreference pref = (MultiSelectListPreference) preference;
+            final CharSequence[] entries = pref.getEntries();
+            final CharSequence[] entryValues = pref.getEntryValues();
+            final Set<String> initialSelections = pref.getValues();
+            return new AdapterMulti(entries, entryValues, initialSelections);
+        } else if (preference instanceof ListPreference) {
+            final ListPreference pref = (ListPreference) preference;
+            final CharSequence[] entries = pref.getEntries();
+            final CharSequence[] entryValues = pref.getEntryValues();
+            final String initialSelection = pref.getValue();
+            return new AdapterSingle(entries, entryValues, initialSelection);
+        } else {
+            throw new IllegalStateException("Unknown preference type");
+        }
+    }
+
+    public class AdapterSingle extends RecyclerView.Adapter<ViewHolder>
+            implements ViewHolder.OnItemClickListener {
+
+        private final CharSequence[] mEntries;
+        private final CharSequence[] mEntryValues;
+        private CharSequence mSelectedValue;
+
+        public AdapterSingle(CharSequence[] entries, CharSequence[] entryValues,
+                CharSequence selectedValue) {
+            mEntries = entries;
+            mEntryValues = entryValues;
+            mSelectedValue = selectedValue;
+        }
+
+        @Override
+        public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+            final LayoutInflater inflater = LayoutInflater.from(parent.getContext());
+            final View view = inflater.inflate(R.layout.leanback_list_preference_item_single,
+                    parent, false);
+            return new ViewHolder(view, this);
+        }
+
+        @Override
+        public void onBindViewHolder(ViewHolder holder, int position) {
+            holder.getWidgetView().setChecked(mEntryValues[position].equals(mSelectedValue));
+            holder.getTitleView().setText(mEntries[position]);
+        }
+
+        @Override
+        public int getItemCount() {
+            return mEntries.length;
+        }
+
+        @Override
+        public void onItemClick(ViewHolder viewHolder) {
+            final int index = viewHolder.getAdapterPosition();
+            final CharSequence entry = mEntryValues[index];
+            mSelectedValue = entry;
+            ((ListPreference) getPreference()).setValue(entry.toString());
+            getFragmentManager().popBackStack();
+            notifyDataSetChanged();
+        }
+    }
+
+    public class AdapterMulti extends RecyclerView.Adapter<ViewHolder>
+            implements ViewHolder.OnItemClickListener {
+
+        private final CharSequence[] mEntries;
+        private final CharSequence[] mEntryValues;
+        private final Set<String> mSelections;
+
+        public AdapterMulti(CharSequence[] entries, CharSequence[] entryValues,
+                Set<String> initialSelections) {
+            mEntries = entries;
+            mEntryValues = entryValues;
+            mSelections = new HashSet<>(initialSelections);
+        }
+
+        @Override
+        public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+            final LayoutInflater inflater = LayoutInflater.from(parent.getContext());
+            final View view = inflater.inflate(R.layout.leanback_list_preference_item_multi, parent,
+                    false);
+            return new ViewHolder(view, this);
+        }
+
+        @Override
+        public void onBindViewHolder(ViewHolder holder, int position) {
+            holder.getWidgetView().setChecked(
+                    mSelections.contains(mEntryValues[position].toString()));
+            holder.getTitleView().setText(mEntries[position]);
+        }
+
+        @Override
+        public int getItemCount() {
+            return mEntries.length;
+        }
+
+        @Override
+        public void onItemClick(ViewHolder viewHolder) {
+            final int index = viewHolder.getAdapterPosition();
+            final String entry = mEntryValues[index].toString();
+            if (mSelections.contains(entry)) {
+                mSelections.remove(entry);
+            } else {
+                mSelections.add(entry);
+            }
+            ((MultiSelectListPreference) getPreference()).setValues(mSelections);
+            notifyDataSetChanged();
+        }
+    }
+
+    public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
+
+        public interface OnItemClickListener {
+            void onItemClick(ViewHolder viewHolder);
+        }
+
+        private final Checkable mWidgetView;
+        private final TextView mTitleView;
+        private final ViewGroup mContainer;
+        private final OnItemClickListener mListener;
+
+        public ViewHolder(@NonNull View view, @NonNull OnItemClickListener listener) {
+            super(view);
+            mWidgetView = (Checkable) view.findViewById(R.id.button);
+            mContainer = (ViewGroup) view.findViewById(R.id.container);
+            mTitleView = (TextView) view.findViewById(android.R.id.title);
+            mContainer.setOnClickListener(this);
+            mListener = listener;
+        }
+
+        public Checkable getWidgetView() {
+            return mWidgetView;
+        }
+
+        public TextView getTitleView() {
+            return mTitleView;
+        }
+
+        public ViewGroup getContainer() {
+            return mContainer;
+        }
+
+        @Override
+        public void onClick(View v) {
+            mListener.onItemClick(this);
+        }
+    }
+}
diff --git a/v17/preference-leanback/src/android/support/v17/preference/LeanbackPreferenceDialogFragment.java b/v17/preference-leanback/src/android/support/v17/preference/LeanbackPreferenceDialogFragment.java
new file mode 100644
index 0000000..e92ce81
--- /dev/null
+++ b/v17/preference-leanback/src/android/support/v17/preference/LeanbackPreferenceDialogFragment.java
@@ -0,0 +1,72 @@
+/*
+ * 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.preference;
+
+import android.app.Fragment;
+import android.os.Bundle;
+import android.support.v14.preference.MultiSelectListPreference;
+import android.support.v14.preference.PreferenceFragment;
+import android.support.v7.preference.DialogPreference;
+import android.support.v7.preference.ListPreference;
+
+public class LeanbackPreferenceDialogFragment extends Fragment {
+
+    public interface TargetFragment extends DialogPreference.TargetFragment {
+
+        PreferenceFragment getPreferenceFragment();
+
+        LeanbackSettingsFragment getSettingsFragment();
+    }
+
+    public static final String ARG_KEY = "key";
+
+    private DialogPreference mPreference;
+
+    private PreferenceFragment mPreferenceFragment;
+
+    private LeanbackSettingsFragment mSettingsFragment;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        final Fragment rawFragment = getParentFragment();
+        if (!(rawFragment instanceof TargetFragment)) {
+            throw new IllegalStateException("Target fragment must implement TargetFragment" +
+                    " interface");
+        }
+
+        final TargetFragment fragment = (TargetFragment) rawFragment;
+
+        final String key = getArguments().getString(LeanbackListPreferenceDialogFragment.ARG_KEY);
+        mPreference = (DialogPreference) fragment.findPreference(key);
+        mPreferenceFragment = fragment.getPreferenceFragment();
+        mSettingsFragment = fragment.getSettingsFragment();
+    }
+
+    public DialogPreference getPreference() {
+        return mPreference;
+    }
+
+    public PreferenceFragment getPreferenceFragment() {
+        return mPreferenceFragment;
+    }
+
+    public LeanbackSettingsFragment getSettingsFragment() {
+        return mSettingsFragment;
+    }
+}
diff --git a/v17/preference-leanback/src/android/support/v17/preference/LeanbackPreferenceFragment.java b/v17/preference-leanback/src/android/support/v17/preference/LeanbackPreferenceFragment.java
new file mode 100644
index 0000000..73ce174
--- /dev/null
+++ b/v17/preference-leanback/src/android/support/v17/preference/LeanbackPreferenceFragment.java
@@ -0,0 +1,49 @@
+/*
+ * 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.preference;
+
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+/**
+ * This fragment provides a fully decorated leanback-style preference fragment, including a
+ * list background and header.
+ */
+public abstract class LeanbackPreferenceFragment extends BaseLeanbackPreferenceFragment {
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        final View view = inflater.inflate(R.layout.leanback_preference_fragment, container, false);
+        final ViewGroup innerContainer = (ViewGroup) view.findViewById(R.id.main_frame);
+        final View innerView = super.onCreateView(inflater, innerContainer, savedInstanceState);
+        if (innerView != null) {
+            innerContainer.addView(innerView);
+        }
+        return view;
+    }
+
+    @Override
+    public void onViewCreated(View view, Bundle savedInstanceState) {
+        super.onViewCreated(view, savedInstanceState);
+        final TextView decorTitle = (TextView) view.findViewById(R.id.decor_title);
+        decorTitle.setText(getPreferenceScreen().getTitle());
+    }
+}
diff --git a/v17/preference-leanback/src/android/support/v17/preference/LeanbackSettingsFragment.java b/v17/preference-leanback/src/android/support/v17/preference/LeanbackSettingsFragment.java
new file mode 100644
index 0000000..38ef3d9
--- /dev/null
+++ b/v17/preference-leanback/src/android/support/v17/preference/LeanbackSettingsFragment.java
@@ -0,0 +1,274 @@
+/*
+ * 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.preference;
+
+import android.app.Fragment;
+import android.app.FragmentTransaction;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v14.preference.MultiSelectListPreference;
+import android.support.v14.preference.PreferenceFragment;
+import android.support.v7.preference.ListPreference;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+public abstract class LeanbackSettingsFragment extends Fragment
+        implements PreferenceFragment.OnPreferenceStartFragmentCallback,
+        PreferenceFragment.OnPreferenceStartScreenCallback,
+        PreferenceFragment.OnPreferenceDisplayDialogCallback {
+
+    private static final String SETTINGS_FRAGMENT_INNER_TAG =
+            "android.support.v17.preference.LeanbackSettingsFragment.INNER_FRAGMENT";
+
+    private boolean mInitialScreen;
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        final View v = inflater.inflate(R.layout.leanback_settings_fragment, container, false);
+
+        // Trap back button presses
+        ((LeanbackSettingsRootView) v).setOnBackKeyListener(new RootViewOnKeyListener());
+
+        return v;
+    }
+
+    @Override
+    public void onViewCreated(View view, Bundle savedInstanceState) {
+        super.onViewCreated(view, savedInstanceState);
+        if (savedInstanceState == null) {
+            final Fragment f = new LeanbackSettingsFragmentInner();
+            getChildFragmentManager().beginTransaction()
+                    .add(R.id.settings_fragment_container, f, SETTINGS_FRAGMENT_INNER_TAG)
+                    .commit();
+            getChildFragmentManager().executePendingTransactions();
+            mInitialScreen = true;
+            onPreferenceStartInitialScreen();
+            mInitialScreen = false;
+        }
+    }
+
+    @Override
+    public boolean onPreferenceDisplayDialog(PreferenceFragment caller, Preference pref) {
+        final Fragment f;
+        if (pref instanceof ListPreference) {
+            final ListPreference listPreference = (ListPreference) pref;
+            f = LeanbackListPreferenceDialogFragment.newInstanceSingle(listPreference.getKey());
+            getInnerFragment().startDialogFragment(f, caller, null);
+        } else if (pref instanceof MultiSelectListPreference) {
+            MultiSelectListPreference listPreference = (MultiSelectListPreference) pref;
+            f = LeanbackListPreferenceDialogFragment.newInstanceMulti(listPreference.getKey());
+            getInnerFragment().startDialogFragment(f, caller, null);
+        }
+        // TODO
+//        else if (pref instanceof EditTextPreference) {
+//
+//        }
+        else {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Called to instantiate the initial {@link android.support.v14.preference.PreferenceFragment}
+     * to be shown in this fragment. Implementations are expected to call
+     * {@link #startPreferenceFragment(android.app.Fragment, java.lang.String)}.
+     */
+    public abstract void onPreferenceStartInitialScreen();
+
+    /**
+     * Displays a preference fragment to the user. This method can also be used to display
+     * list-style fragments on top of the stack of preference fragments.
+     *
+     * @param fragment Fragment instance to be added.
+     * @param tag Fragment tag
+     */
+    public void startPreferenceFragment(@NonNull Fragment fragment, @Nullable String tag) {
+        getInnerFragment().startStackedFragment(fragment, tag, !mInitialScreen);
+    }
+
+    /**
+     * Displays a fragment to the user, temporarily replacing the contents of this fragment.
+     *
+     * @param fragment Fragment instance to be added.
+     * @param tag Fragment tag
+     */
+    public void startImmersiveFragment(@NonNull Fragment fragment, @Nullable String tag) {
+        getChildFragmentManager().beginTransaction()
+                .replace(R.id.settings_fragment_container, fragment, tag)
+                .addToBackStack(null)
+                .commit();
+    }
+
+    private LeanbackSettingsFragmentInner getInnerFragment() {
+        return (LeanbackSettingsFragmentInner)
+                getChildFragmentManager().findFragmentByTag(SETTINGS_FRAGMENT_INNER_TAG);
+    }
+
+    private boolean handleBackPress() {
+        final LeanbackSettingsFragmentInner inner = getInnerFragment();
+        boolean handled = false;
+        if (inner != null && inner.isVisible()) {
+            handled = inner.handleBackPress();
+        }
+        return handled || getChildFragmentManager().popBackStackImmediate();
+    }
+
+    /**
+     * @hide
+     */
+    public static class LeanbackSettingsFragmentInner extends Fragment
+            implements LeanbackPreferenceDialogFragment.TargetFragment {
+
+        private static final String SAVESTATE_TARGET_PREF_FRAG =
+                "android.support.v17.preference.LeanbackSettingsFragment.TARGET_PREF_FRAG";
+
+        private static final String TARGET_FRAGMENT_TAG =
+                "android.support.v17.preference.LeanbackSettingsFragment.TARGET";
+
+        // Preference fragment which last launched a dialog
+        private PreferenceFragment mTargetPreferenceFragment;
+
+        @Override
+        public void onCreate(Bundle savedInstanceState) {
+            super.onCreate(savedInstanceState);
+
+            if (savedInstanceState != null &&
+                    savedInstanceState.containsKey(SAVESTATE_TARGET_PREF_FRAG)) {
+                mTargetPreferenceFragment = (PreferenceFragment) getChildFragmentManager()
+                        .getFragment(savedInstanceState, SAVESTATE_TARGET_PREF_FRAG);
+            }
+        }
+
+        @Override
+        public @Nullable View onCreateView(LayoutInflater inflater, ViewGroup container,
+                Bundle savedInstanceState) {
+            return inflater.inflate(R.layout.leanback_settings_fragment_stack,
+                    container, false);
+        }
+
+        @Override
+        public void onSaveInstanceState(Bundle outState) {
+            super.onSaveInstanceState(outState);
+            if (mTargetPreferenceFragment != null) {
+                getChildFragmentManager().putFragment(outState, SAVESTATE_TARGET_PREF_FRAG,
+                        mTargetPreferenceFragment);
+            }
+        }
+
+        public void startDialogFragment(@NonNull Fragment dialogFragment,
+                @NonNull PreferenceFragment requestingFragment, @Nullable String tag) {
+            mTargetPreferenceFragment = requestingFragment;
+            startFragment(dialogFragment, tag, true);
+        }
+
+        public void startStackedFragment(@NonNull Fragment fragment, @Nullable String tag,
+                boolean addToBackstack) {
+            fragment.setTargetFragment(findTarget(), 0);
+            startFragment(fragment, tag, addToBackstack);
+        }
+
+        private void startFragment(@NonNull Fragment fragment, @Nullable String tag,
+                boolean addToBackstack) {
+            final FragmentTransaction transaction = getChildFragmentManager().beginTransaction()
+                    .add(R.id.settings_preference_stack, fragment, tag);
+            if (addToBackstack) {
+                transaction.addToBackStack(null);
+            }
+            transaction.commit();
+        }
+
+        private Fragment findTarget() {
+            Fragment target =
+                    getChildFragmentManager().findFragmentByTag(TARGET_FRAGMENT_TAG);
+            if (target == null) {
+                target = new Target();
+                getChildFragmentManager().beginTransaction()
+                        .add(target, TARGET_FRAGMENT_TAG)
+                        .commit();
+                getChildFragmentManager().executePendingTransactions();
+            }
+            return target;
+        }
+
+        public boolean handleBackPress() {
+            return getChildFragmentManager().popBackStackImmediate();
+        }
+
+        public Preference findPreference(CharSequence key) {
+            return mTargetPreferenceFragment.findPreference(key);
+        }
+
+        public PreferenceFragment getPreferenceFragment() {
+            return mTargetPreferenceFragment;
+        }
+
+        @Override
+        public LeanbackSettingsFragment getSettingsFragment() {
+            return (LeanbackSettingsFragment) getParentFragment();
+        }
+
+        // This looks terrible, and it is. We need this because the target fragment needs to be
+        // in the same FragmentManager as the fragment targeting it.
+        /**
+         * @hide
+         */
+        public static class Target extends Fragment
+                implements PreferenceFragment.OnPreferenceStartFragmentCallback,
+                PreferenceFragment.OnPreferenceStartScreenCallback,
+                PreferenceFragment.OnPreferenceDisplayDialogCallback {
+
+            private LeanbackSettingsFragment getOuterParent() {
+                return (LeanbackSettingsFragment) getParentFragment().getParentFragment();
+            }
+
+            @Override
+            public boolean onPreferenceStartFragment(PreferenceFragment caller, Preference pref) {
+                return getOuterParent().onPreferenceStartFragment(caller, pref);
+            }
+
+            @Override
+            public boolean onPreferenceStartScreen(PreferenceFragment caller,
+                    PreferenceScreen pref) {
+                return getOuterParent().onPreferenceStartScreen(caller, pref);
+            }
+
+            @Override
+            public boolean onPreferenceDisplayDialog(PreferenceFragment caller, Preference pref) {
+                return getOuterParent().onPreferenceDisplayDialog(caller, pref);
+            }
+        }
+    }
+
+    private class RootViewOnKeyListener implements View.OnKeyListener {
+
+        @Override
+        public boolean onKey(View v, int keyCode, KeyEvent event) {
+            if (keyCode == KeyEvent.KEYCODE_BACK) {
+                return handleBackPress();
+            } else {
+                return false;
+            }
+        }
+    }
+}
diff --git a/v17/preference-leanback/src/android/support/v17/preference/LeanbackSettingsRootView.java b/v17/preference-leanback/src/android/support/v17/preference/LeanbackSettingsRootView.java
new file mode 100644
index 0000000..6114f13
--- /dev/null
+++ b/v17/preference-leanback/src/android/support/v17/preference/LeanbackSettingsRootView.java
@@ -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
+ */
+
+package android.support.v17.preference;
+
+import android.content.Context;
+import android.support.annotation.NonNull;
+import android.util.AttributeSet;
+import android.view.KeyEvent;
+import android.widget.FrameLayout;
+
+/**
+ * @hide
+ */
+public class LeanbackSettingsRootView extends FrameLayout {
+
+    private OnKeyListener mOnBackKeyListener;
+
+    public LeanbackSettingsRootView(Context context) {
+        super(context);
+    }
+
+    public LeanbackSettingsRootView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public LeanbackSettingsRootView(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+    }
+
+    public void setOnBackKeyListener(OnKeyListener backKeyListener) {
+        mOnBackKeyListener = backKeyListener;
+    }
+
+    @Override
+    public boolean dispatchKeyEvent(@NonNull KeyEvent event) {
+        boolean handled = false;
+        if (event.getAction() == KeyEvent.ACTION_UP && event.getKeyCode() == KeyEvent.KEYCODE_BACK
+                && mOnBackKeyListener != null) {
+            handled = mOnBackKeyListener.onKey(this, event.getKeyCode(), event);
+        }
+        return handled || super.dispatchKeyEvent(event);
+    }
+}
diff --git a/v4/Android.mk b/v4/Android.mk
index 6e1187a..2050725 100644
--- a/v4/Android.mk
+++ b/v4/Android.mk
@@ -184,6 +184,16 @@
 
 # -----------------------------------------------------------------------
 
+# A helper sub-library that makes direct use of V23 APIs.
+include $(CLEAR_VARS)
+LOCAL_MODULE := android-support-v4-api23
+LOCAL_SDK_VERSION := current
+LOCAL_SRC_FILES := $(call all-java-files-under, api23)
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4-api22
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+# -----------------------------------------------------------------------
+
 # Here is the final static library that apps can link against.
 include $(CLEAR_VARS)
 LOCAL_MODULE := android-support-v4
@@ -191,8 +201,7 @@
 LOCAL_AIDL_INCLUDES := frameworks/support/v4/java
 LOCAL_SRC_FILES := $(call all-java-files-under, java) \
     $(call all-Iaidl-files-under, java)
-LOCAL_STATIC_JAVA_LIBRARIES += android-support-v4-api22
-
+LOCAL_STATIC_JAVA_LIBRARIES += android-support-v4-api23
 include $(BUILD_STATIC_JAVA_LIBRARY)
 
 # API Check
diff --git a/v4/AndroidManifest.xml b/v4/AndroidManifest.xml
index 08dbb61..a21d926 100644
--- a/v4/AndroidManifest.xml
+++ b/v4/AndroidManifest.xml
@@ -15,5 +15,6 @@
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
           package="android.support.v4">
+    <uses-sdk android:minSdkVersion="4"/>
     <application />
 </manifest>
diff --git a/v4/api/current.txt b/v4/api/current.txt
index ec5ae3e..17a1c4e 100644
--- a/v4/api/current.txt
+++ b/v4/api/current.txt
@@ -88,15 +88,22 @@
     ctor public ActivityCompat();
     method public static void finishAffinity(android.app.Activity);
     method public static void finishAfterTransition(android.app.Activity);
+    method public android.net.Uri getReferrer(android.app.Activity);
     method public static boolean invalidateOptionsMenu(android.app.Activity);
     method public static void postponeEnterTransition(android.app.Activity);
+    method public static void requestPermissions(android.app.Activity, java.lang.String[], int);
     method public static void setEnterSharedElementCallback(android.app.Activity, android.support.v4.app.SharedElementCallback);
     method public static void setExitSharedElementCallback(android.app.Activity, android.support.v4.app.SharedElementCallback);
+    method public static boolean shouldShowRequestPermissionRationale(android.app.Activity, java.lang.String);
     method public static void startActivity(android.app.Activity, android.content.Intent, android.os.Bundle);
     method public static void startActivityForResult(android.app.Activity, android.content.Intent, int, android.os.Bundle);
     method public static void startPostponedEnterTransition(android.app.Activity);
   }
 
+  public static abstract interface ActivityCompat.OnRequestPermissionsResultCallback {
+    method public abstract void onRequestPermissionsResult(int, java.lang.String[], int[]);
+  }
+
   public final class ActivityManagerCompat {
     method public static boolean isLowRamDevice(android.app.ActivityManager);
   }
@@ -112,6 +119,15 @@
     method public void update(android.support.v4.app.ActivityOptionsCompat);
   }
 
+  public class AppOpsManagerCompat {
+    ctor public AppOpsManagerCompat();
+    method public static int noteOp(android.content.Context, java.lang.String, int, java.lang.String);
+    method public static java.lang.String permissionToOp(java.lang.String);
+    field public static final int MODE_ALLOWED = 0; // 0x0
+    field public static final int MODE_DEFAULT = 3; // 0x3
+    field public static final int MODE_IGNORED = 1; // 0x1
+  }
+
    abstract class BaseFragmentActivityDonut extends android.app.Activity {
   }
 
@@ -149,9 +165,11 @@
     method public boolean getAllowReturnTransitionOverlap();
     method public final android.os.Bundle getArguments();
     method public final android.support.v4.app.FragmentManager getChildFragmentManager();
+    method public android.content.Context getContext();
     method public java.lang.Object getEnterTransition();
     method public java.lang.Object getExitTransition();
     method public final android.support.v4.app.FragmentManager getFragmentManager();
+    method public final java.lang.Object getHost();
     method public final int getId();
     method public android.support.v4.app.LoaderManager getLoaderManager();
     method public final android.support.v4.app.Fragment getParentFragment();
@@ -181,7 +199,8 @@
     method public final boolean isVisible();
     method public void onActivityCreated(android.os.Bundle);
     method public void onActivityResult(int, int, android.content.Intent);
-    method public void onAttach(android.app.Activity);
+    method public void onAttach(android.content.Context);
+    method public deprecated void onAttach(android.app.Activity);
     method public void onConfigurationChanged(android.content.res.Configuration);
     method public boolean onContextItemSelected(android.view.MenuItem);
     method public void onCreate(android.os.Bundle);
@@ -194,12 +213,14 @@
     method public void onDestroyView();
     method public void onDetach();
     method public void onHiddenChanged(boolean);
-    method public void onInflate(android.app.Activity, android.util.AttributeSet, android.os.Bundle);
+    method public void onInflate(android.content.Context, android.util.AttributeSet, android.os.Bundle);
+    method public deprecated void onInflate(android.app.Activity, android.util.AttributeSet, android.os.Bundle);
     method public void onLowMemory();
     method public boolean onOptionsItemSelected(android.view.MenuItem);
     method public void onOptionsMenuClosed(android.view.Menu);
     method public void onPause();
     method public void onPrepareOptionsMenu(android.view.Menu);
+    method public void onRequestPermissionsResult(int, java.lang.String[], int[]);
     method public void onResume();
     method public void onSaveInstanceState(android.os.Bundle);
     method public void onStart();
@@ -207,6 +228,7 @@
     method public void onViewCreated(android.view.View, android.os.Bundle);
     method public void onViewStateRestored(android.os.Bundle);
     method public void registerForContextMenu(android.view.View);
+    method public final void requestPermissions(java.lang.String[], int);
     method public void setAllowEnterTransitionOverlap(boolean);
     method public void setAllowReturnTransitionOverlap(boolean);
     method public void setArguments(android.os.Bundle);
@@ -224,6 +246,7 @@
     method public void setSharedElementReturnTransition(java.lang.Object);
     method public void setTargetFragment(android.support.v4.app.Fragment, int);
     method public void setUserVisibleHint(boolean);
+    method public boolean shouldShowRequestPermissionRationale(java.lang.String);
     method public void startActivity(android.content.Intent);
     method public void startActivityForResult(android.content.Intent, int);
     method public void unregisterForContextMenu(android.view.View);
@@ -239,7 +262,7 @@
     field public static final android.os.Parcelable.Creator<android.support.v4.app.Fragment.SavedState> CREATOR;
   }
 
-  public class FragmentActivity extends android.support.v4.app.BaseFragmentActivityHoneycomb {
+  public class FragmentActivity extends android.support.v4.app.BaseFragmentActivityHoneycomb implements android.support.v4.app.ActivityCompat.OnRequestPermissionsResultCallback {
     ctor public FragmentActivity();
     method public java.lang.Object getLastCustomNonConfigurationInstance();
     method public android.support.v4.app.FragmentManager getSupportFragmentManager();
@@ -255,6 +278,68 @@
     method public void supportInvalidateOptionsMenu();
     method public void supportPostponeEnterTransition();
     method public void supportStartPostponedEnterTransition();
+    method public final void validateRequestPermissionsRequestCode(int);
+  }
+
+  public abstract class FragmentContainer {
+    ctor public FragmentContainer();
+    method public abstract android.view.View onFindViewById(int);
+    method public abstract boolean onHasView();
+  }
+
+  public class FragmentController {
+    method public void attachHost(android.support.v4.app.Fragment);
+    method public static final android.support.v4.app.FragmentController createController(android.support.v4.app.FragmentHostCallback<?>);
+    method public void dispatchActivityCreated();
+    method public void dispatchConfigurationChanged(android.content.res.Configuration);
+    method public boolean dispatchContextItemSelected(android.view.MenuItem);
+    method public void dispatchCreate();
+    method public boolean dispatchCreateOptionsMenu(android.view.Menu, android.view.MenuInflater);
+    method public void dispatchDestroy();
+    method public void dispatchDestroyView();
+    method public void dispatchLowMemory();
+    method public boolean dispatchOptionsItemSelected(android.view.MenuItem);
+    method public void dispatchOptionsMenuClosed(android.view.Menu);
+    method public void dispatchPause();
+    method public boolean dispatchPrepareOptionsMenu(android.view.Menu);
+    method public void dispatchReallyStop();
+    method public void dispatchResume();
+    method public void dispatchStart();
+    method public void dispatchStop();
+    method public void doLoaderDestroy();
+    method public void doLoaderRetain();
+    method public void doLoaderStart();
+    method public void doLoaderStop(boolean);
+    method public void dumpLoaders(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
+    method public boolean execPendingActions();
+    method public java.util.List<android.support.v4.app.Fragment> getActiveFragments(java.util.List<android.support.v4.app.Fragment>);
+    method public int getActiveFragmentsCount();
+    method public android.support.v4.app.FragmentManager getSupportFragmentManager();
+    method public android.support.v4.app.LoaderManager getSupportLoaderManager();
+    method public void noteStateNotSaved();
+    method public android.view.View onCreateView(android.view.View, java.lang.String, android.content.Context, android.util.AttributeSet);
+    method public void reportLoaderStart();
+    method public void restoreAllState(android.os.Parcelable, java.util.List<android.support.v4.app.Fragment>);
+    method public void restoreLoaderNonConfig(android.support.v4.util.SimpleArrayMap<java.lang.String, android.support.v4.app.LoaderManager>);
+    method public android.support.v4.util.SimpleArrayMap<java.lang.String, android.support.v4.app.LoaderManager> retainLoaderNonConfig();
+    method public java.util.List<android.support.v4.app.Fragment> retainNonConfig();
+    method public android.os.Parcelable saveAllState();
+  }
+
+  public abstract class FragmentHostCallback extends android.support.v4.app.FragmentContainer {
+    ctor public FragmentHostCallback(android.content.Context, android.os.Handler, int);
+    method public void onDump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
+    method public android.view.View onFindViewById(int);
+    method public abstract E onGetHost();
+    method public android.view.LayoutInflater onGetLayoutInflater();
+    method public int onGetWindowAnimations();
+    method public boolean onHasView();
+    method public boolean onHasWindowAnimations();
+    method public void onRequestPermissionsFromFragment(android.support.v4.app.Fragment, java.lang.String[], int);
+    method public boolean onShouldSaveFragmentState(android.support.v4.app.Fragment);
+    method public boolean onShouldShowRequestPermissionRationale(java.lang.String);
+    method public void onStartActivityFromFragment(android.support.v4.app.Fragment, android.content.Intent, int);
+    method public void onSupportInvalidateOptionsMenu();
   }
 
   public abstract class FragmentManager {
@@ -857,16 +942,24 @@
 
   public abstract class AsyncTaskLoader extends android.support.v4.content.Loader {
     ctor public AsyncTaskLoader(android.content.Context);
-    method public boolean cancelLoad();
+    method public void cancelLoadInBackground();
+    method public boolean isLoadInBackgroundCanceled();
     method public abstract D loadInBackground();
     method public void onCanceled(D);
     method protected D onLoadInBackground();
     method public void setUpdateThrottle(long);
   }
 
+  public class ContentResolverCompat {
+    method public static android.database.Cursor query(android.content.ContentResolver, android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, android.support.v4.os.CancellationSignal);
+  }
+
   public class ContextCompat {
     ctor public ContextCompat();
+    method public static int checkSelfPermission(android.content.Context, java.lang.String);
     method public final java.io.File getCodeCacheDir(android.content.Context);
+    method public static final int getColor(android.content.Context, int);
+    method public static final android.content.res.ColorStateList getColorStateList(android.content.Context, int);
     method public static final android.graphics.drawable.Drawable getDrawable(android.content.Context, int);
     method public static java.io.File[] getExternalCacheDirs(android.content.Context);
     method public static java.io.File[] getExternalFilesDirs(android.content.Context, java.lang.String);
@@ -921,8 +1014,10 @@
   public class Loader {
     ctor public Loader(android.content.Context);
     method public void abandon();
+    method public boolean cancelLoad();
     method public void commitContentChanged();
     method public java.lang.String dataToString(D);
+    method public void deliverCancellation();
     method public void deliverResult(D);
     method public void dump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
     method public void forceLoad();
@@ -932,24 +1027,31 @@
     method public boolean isReset();
     method public boolean isStarted();
     method protected void onAbandon();
+    method protected boolean onCancelLoad();
     method public void onContentChanged();
     method protected void onForceLoad();
     method protected void onReset();
     method protected void onStartLoading();
     method protected void onStopLoading();
     method public void registerListener(int, android.support.v4.content.Loader.OnLoadCompleteListener<D>);
+    method public void registerOnLoadCanceledListener(android.support.v4.content.Loader.OnLoadCanceledListener<D>);
     method public void reset();
     method public void rollbackContentChanged();
     method public final void startLoading();
     method public void stopLoading();
     method public boolean takeContentChanged();
     method public void unregisterListener(android.support.v4.content.Loader.OnLoadCompleteListener<D>);
+    method public void unregisterOnLoadCanceledListener(android.support.v4.content.Loader.OnLoadCanceledListener<D>);
   }
 
   public final class Loader.ForceLoadContentObserver extends android.database.ContentObserver {
     ctor public Loader.ForceLoadContentObserver();
   }
 
+  public static abstract interface Loader.OnLoadCanceledListener {
+    method public abstract void onLoadCanceled(android.support.v4.content.Loader<D>);
+  }
+
   public static abstract interface Loader.OnLoadCompleteListener {
     method public abstract void onLoadComplete(android.support.v4.content.Loader<D>, D);
   }
@@ -962,6 +1064,28 @@
     method public void unregisterReceiver(android.content.BroadcastReceiver);
   }
 
+  public final class PermissionChecker {
+    method public static int checkCallingOrSelfPermission(android.content.Context, java.lang.String);
+    method public static int checkCallingPermission(android.content.Context, java.lang.String, java.lang.String);
+    method public static int checkPermission(android.content.Context, java.lang.String, int, int, java.lang.String);
+    method public static int checkSelfPermission(android.content.Context, java.lang.String);
+    field public static final int PERMISSION_DENIED = -1; // 0xffffffff
+    field public static final int PERMISSION_DENIED_APP_OP = -2; // 0xfffffffe
+    field public static final int PERMISSION_GRANTED = 0; // 0x0
+  }
+
+  public static abstract class PermissionChecker.PermissionResult implements java.lang.annotation.Annotation {
+  }
+
+  public class SharedPreferencesCompat {
+    ctor public SharedPreferencesCompat();
+  }
+
+  public static class SharedPreferencesCompat.EditorCompat {
+    method public void apply(android.content.SharedPreferences.Editor);
+    method public static android.support.v4.content.SharedPreferencesCompat.EditorCompat getInstance();
+  }
+
   public abstract class WakefulBroadcastReceiver extends android.content.BroadcastReceiver {
     ctor public WakefulBroadcastReceiver();
     method public static boolean completeWakefulIntent(android.content.Intent);
@@ -1023,11 +1147,13 @@
 
   public class DrawableCompat {
     ctor public DrawableCompat();
+    method public static int getLayoutDirection(android.graphics.drawable.Drawable);
     method public static boolean isAutoMirrored(android.graphics.drawable.Drawable);
     method public static void jumpToCurrentState(android.graphics.drawable.Drawable);
     method public static void setAutoMirrored(android.graphics.drawable.Drawable, boolean);
     method public static void setHotspot(android.graphics.drawable.Drawable, float, float);
     method public static void setHotspotBounds(android.graphics.drawable.Drawable, int, int, int, int);
+    method public static void setLayoutDirection(android.graphics.drawable.Drawable, int);
     method public static void setTint(android.graphics.drawable.Drawable, int);
     method public static void setTintList(android.graphics.drawable.Drawable, android.content.res.ColorStateList);
     method public static void setTintMode(android.graphics.drawable.Drawable, android.graphics.PorterDuff.Mode);
@@ -1076,6 +1202,37 @@
 
 }
 
+package android.support.v4.hardware.fingerprint {
+
+  public class FingerprintManagerCompat {
+    method public void authenticate(android.support.v4.hardware.fingerprint.FingerprintManagerCompat.CryptoObject, int, android.support.v4.os.CancellationSignal, android.support.v4.hardware.fingerprint.FingerprintManagerCompat.AuthenticationCallback, android.os.Handler);
+    method public static android.support.v4.hardware.fingerprint.FingerprintManagerCompat from(android.content.Context);
+    method public boolean hasEnrolledFingerprints();
+    method public boolean isHardwareDetected();
+  }
+
+  public static abstract class FingerprintManagerCompat.AuthenticationCallback {
+    ctor public FingerprintManagerCompat.AuthenticationCallback();
+    method public void onAuthenticationError(int, java.lang.CharSequence);
+    method public void onAuthenticationFailed();
+    method public void onAuthenticationHelp(int, java.lang.CharSequence);
+    method public void onAuthenticationSucceeded(android.support.v4.hardware.fingerprint.FingerprintManagerCompat.AuthenticationResult);
+  }
+
+  public static final class FingerprintManagerCompat.AuthenticationResult {
+    ctor public FingerprintManagerCompat.AuthenticationResult(android.support.v4.hardware.fingerprint.FingerprintManagerCompat.CryptoObject);
+    method public android.support.v4.hardware.fingerprint.FingerprintManagerCompat.CryptoObject getCryptoObject();
+  }
+
+  public static class FingerprintManagerCompat.CryptoObject {
+    ctor public FingerprintManagerCompat.CryptoObject(java.security.Signature);
+    ctor public FingerprintManagerCompat.CryptoObject(javax.crypto.Cipher);
+    method public javax.crypto.Cipher getCipher();
+    method public java.security.Signature getSignature();
+  }
+
+}
+
 package android.support.v4.media {
 
   public final class MediaDescriptionCompat implements android.os.Parcelable {
@@ -1537,12 +1694,30 @@
     method public static android.os.AsyncTask<Params, Progress, Result> executeParallel(android.os.AsyncTask<Params, Progress, Result>, Params...);
   }
 
+  public final class CancellationSignal {
+    ctor public CancellationSignal();
+    method public void cancel();
+    method public java.lang.Object getCancellationSignalObject();
+    method public boolean isCanceled();
+    method public void setOnCancelListener(android.support.v4.os.CancellationSignal.OnCancelListener);
+    method public void throwIfCanceled();
+  }
+
+  public static abstract interface CancellationSignal.OnCancelListener {
+    method public abstract void onCancel();
+  }
+
   public class EnvironmentCompat {
     ctor public EnvironmentCompat();
     method public static java.lang.String getStorageState(java.io.File);
     field public static final java.lang.String MEDIA_UNKNOWN = "unknown";
   }
 
+  public class OperationCanceledException extends java.lang.RuntimeException {
+    ctor public OperationCanceledException();
+    ctor public OperationCanceledException(java.lang.String);
+  }
+
   public class ParcelableCompat {
     ctor public ParcelableCompat();
     method public static android.os.Parcelable.Creator<T> newCreator(android.support.v4.os.ParcelableCompatCreatorCallbacks<T>);
@@ -1644,8 +1819,7 @@
 
   public class ICUCompat {
     ctor public ICUCompat();
-    method public static java.lang.String addLikelySubtags(java.lang.String);
-    method public static java.lang.String getScript(java.lang.String);
+    method public static java.lang.String maximizeAndGetScript(java.util.Locale);
   }
 
   public abstract interface TextDirectionHeuristicCompat {
@@ -2216,6 +2390,7 @@
     method public static float getZ(android.view.View);
     method public static boolean hasAccessibilityDelegate(android.view.View);
     method public static boolean hasNestedScrollingParent(android.view.View);
+    method public static boolean hasOverlappingRendering(android.view.View);
     method public static boolean hasTransientState(android.view.View);
     method public static boolean isAttachedToWindow(android.view.View);
     method public static boolean isLaidOut(android.view.View);
@@ -2529,7 +2704,9 @@
     method public void addAction(android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat);
     method public void addChild(android.view.View);
     method public void addChild(android.view.View, int);
+    method public boolean canOpenPopup();
     method public java.util.List<android.support.v4.view.accessibility.AccessibilityNodeInfoCompat> findAccessibilityNodeInfosByText(java.lang.String);
+    method public java.util.List<android.support.v4.view.accessibility.AccessibilityNodeInfoCompat> findAccessibilityNodeInfosByViewId(java.lang.String);
     method public android.support.v4.view.accessibility.AccessibilityNodeInfoCompat findFocus(int);
     method public android.support.v4.view.accessibility.AccessibilityNodeInfoCompat focusSearch(int);
     method public java.util.List<android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat> getActionList();
@@ -2543,24 +2720,37 @@
     method public android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.CollectionItemInfoCompat getCollectionItemInfo();
     method public java.lang.CharSequence getContentDescription();
     method public java.lang.CharSequence getError();
+    method public android.os.Bundle getExtras();
     method public java.lang.Object getInfo();
+    method public int getInputType();
+    method public android.support.v4.view.accessibility.AccessibilityNodeInfoCompat getLabelFor();
+    method public android.support.v4.view.accessibility.AccessibilityNodeInfoCompat getLabeledBy();
     method public int getLiveRegion();
+    method public int getMaxTextLength();
     method public int getMovementGranularities();
     method public java.lang.CharSequence getPackageName();
     method public android.support.v4.view.accessibility.AccessibilityNodeInfoCompat getParent();
     method public android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.RangeInfoCompat getRangeInfo();
     method public java.lang.CharSequence getText();
+    method public int getTextSelectionEnd();
+    method public int getTextSelectionStart();
+    method public android.support.v4.view.accessibility.AccessibilityNodeInfoCompat getTraversalAfter();
+    method public android.support.v4.view.accessibility.AccessibilityNodeInfoCompat getTraversalBefore();
     method public java.lang.String getViewIdResourceName();
+    method public android.support.v4.view.accessibility.AccessibilityWindowInfoCompat getWindow();
     method public int getWindowId();
     method public boolean isAccessibilityFocused();
     method public boolean isCheckable();
     method public boolean isChecked();
     method public boolean isClickable();
     method public boolean isContentInvalid();
+    method public boolean isDismissable();
+    method public boolean isEditable();
     method public boolean isEnabled();
     method public boolean isFocusable();
     method public boolean isFocused();
     method public boolean isLongClickable();
+    method public boolean isMultiLine();
     method public boolean isPassword();
     method public boolean isScrollable();
     method public boolean isSelected();
@@ -2572,9 +2762,14 @@
     method public boolean performAction(int);
     method public boolean performAction(int, android.os.Bundle);
     method public void recycle();
+    method public boolean refresh();
+    method public boolean removeAction(android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat);
+    method public boolean removeChild(android.view.View);
+    method public boolean removeChild(android.view.View, int);
     method public void setAccessibilityFocused(boolean);
     method public void setBoundsInParent(android.graphics.Rect);
     method public void setBoundsInScreen(android.graphics.Rect);
+    method public void setCanOpenPopup(boolean);
     method public void setCheckable(boolean);
     method public void setChecked(boolean);
     method public void setClassName(java.lang.CharSequence);
@@ -2583,24 +2778,37 @@
     method public void setCollectionItemInfo(java.lang.Object);
     method public void setContentDescription(java.lang.CharSequence);
     method public void setContentInvalid(boolean);
+    method public void setDismissable(boolean);
+    method public void setEditable(boolean);
     method public void setEnabled(boolean);
     method public void setError(java.lang.CharSequence);
     method public void setFocusable(boolean);
     method public void setFocused(boolean);
+    method public void setInputType(int);
     method public void setLabelFor(android.view.View);
     method public void setLabelFor(android.view.View, int);
+    method public void setLabeledBy(android.view.View);
+    method public void setLabeledBy(android.view.View, int);
     method public void setLiveRegion(int);
     method public void setLongClickable(boolean);
+    method public void setMaxTextLength(int);
     method public void setMovementGranularities(int);
+    method public void setMultiLine(boolean);
     method public void setPackageName(java.lang.CharSequence);
     method public void setParent(android.view.View);
     method public void setParent(android.view.View, int);
     method public void setPassword(boolean);
+    method public void setRangeInfo(android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.RangeInfoCompat);
     method public void setScrollable(boolean);
     method public void setSelected(boolean);
     method public void setSource(android.view.View);
     method public void setSource(android.view.View, int);
     method public void setText(java.lang.CharSequence);
+    method public void setTextSelection(int, int);
+    method public void setTraversalAfter(android.view.View);
+    method public void setTraversalAfter(android.view.View, int);
+    method public void setTraversalBefore(android.view.View);
+    method public void setTraversalBefore(android.view.View, int);
     method public void setViewIdResourceName(java.lang.String);
     method public void setVisibleToUser(boolean);
     field public static final int ACTION_ACCESSIBILITY_FOCUS = 64; // 0x40
@@ -2734,6 +2942,27 @@
     method public void setToIndex(int);
   }
 
+  public class AccessibilityWindowInfoCompat {
+    method public void getBoundsInScreen(android.graphics.Rect);
+    method public android.support.v4.view.accessibility.AccessibilityWindowInfoCompat getChild(int);
+    method public int getChildCount();
+    method public int getId();
+    method public int getLayer();
+    method public android.support.v4.view.accessibility.AccessibilityWindowInfoCompat getParent();
+    method public android.support.v4.view.accessibility.AccessibilityNodeInfoCompat getRoot();
+    method public int getType();
+    method public boolean isAccessibilityFocused();
+    method public boolean isActive();
+    method public boolean isFocused();
+    method public static android.support.v4.view.accessibility.AccessibilityWindowInfoCompat obtain();
+    method public static android.support.v4.view.accessibility.AccessibilityWindowInfoCompat obtain(android.support.v4.view.accessibility.AccessibilityWindowInfoCompat);
+    method public void recycle();
+    field public static final int TYPE_ACCESSIBILITY_OVERLAY = 4; // 0x4
+    field public static final int TYPE_APPLICATION = 1; // 0x1
+    field public static final int TYPE_INPUT_METHOD = 2; // 0x2
+    field public static final int TYPE_SYSTEM = 3; // 0x3
+  }
+
 }
 
 package android.support.v4.view.animation {
@@ -2792,6 +3021,14 @@
     field public static final float RELATIVE_UNSPECIFIED = 0.0f;
   }
 
+  public final class CompoundButtonCompat {
+    method public static android.graphics.drawable.Drawable getButtonDrawable(android.widget.CompoundButton);
+    method public static android.content.res.ColorStateList getButtonTintList(android.widget.CompoundButton);
+    method public static android.graphics.PorterDuff.Mode getButtonTintMode(android.widget.CompoundButton);
+    method public static void setButtonTintList(android.widget.CompoundButton, android.content.res.ColorStateList);
+    method public static void setButtonTintMode(android.widget.CompoundButton, android.graphics.PorterDuff.Mode);
+  }
+
   public class ContentLoadingProgressBar extends android.widget.ProgressBar {
     ctor public ContentLoadingProgressBar(android.content.Context);
     ctor public ContentLoadingProgressBar(android.content.Context, android.util.AttributeSet);
@@ -2833,6 +3070,7 @@
     method public void closeDrawer(android.view.View);
     method public void closeDrawer(int);
     method public void closeDrawers();
+    method public float getDrawerElevation();
     method public int getDrawerLockMode(int);
     method public int getDrawerLockMode(android.view.View);
     method public java.lang.CharSequence getDrawerTitle(int);
@@ -2845,6 +3083,7 @@
     method protected void onLayout(boolean, int, int, int, int);
     method public void openDrawer(android.view.View);
     method public void openDrawer(int);
+    method public void setDrawerElevation(float);
     method public void setDrawerListener(android.support.v4.widget.DrawerLayout.DrawerListener);
     method public void setDrawerLockMode(int);
     method public void setDrawerLockMode(int, int);
@@ -2917,8 +3156,10 @@
     method public void invalidateVirtualView(int);
     method protected abstract boolean onPerformActionForVirtualView(int, int, android.os.Bundle);
     method protected abstract void onPopulateEventForVirtualView(int, android.view.accessibility.AccessibilityEvent);
+    method public void onPopulateNodeForHost(android.support.v4.view.accessibility.AccessibilityNodeInfoCompat);
     method protected abstract void onPopulateNodeForVirtualView(int, android.support.v4.view.accessibility.AccessibilityNodeInfoCompat);
     method public boolean sendEventForVirtualView(int, int);
+    field public static final int HOST_ID = -1; // 0xffffffff
     field public static final int INVALID_ID = -2147483648; // 0x80000000
   }
 
@@ -2958,6 +3199,10 @@
   }
 
   public class PopupWindowCompat {
+    method public static boolean getOverlapAnchor(android.widget.PopupWindow);
+    method public static int getWindowLayoutType(android.widget.PopupWindow);
+    method public static void setOverlapAnchor(android.widget.PopupWindow, boolean);
+    method public static void setWindowLayoutType(android.widget.PopupWindow, int);
     method public static void showAsDropDown(android.widget.PopupWindow, android.view.View, int, int, int);
   }
 
diff --git a/v4/api21/android/support/v4/app/FragmentTransitionCompat21.java b/v4/api21/android/support/v4/app/FragmentTransitionCompat21.java
index ef41045..45f67a2 100644
--- a/v4/api21/android/support/v4/app/FragmentTransitionCompat21.java
+++ b/v4/api21/android/support/v4/app/FragmentTransitionCompat21.java
@@ -16,14 +16,10 @@
 
 package android.support.v4.app;
 
-import android.content.Context;
-import android.content.res.TypedArray;
 import android.graphics.Rect;
 import android.transition.Transition;
-import android.transition.TransitionInflater;
 import android.transition.TransitionManager;
 import android.transition.TransitionSet;
-import android.util.ArrayMap;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewTreeObserver;
@@ -83,6 +79,19 @@
         });
     }
 
+    public static Object wrapSharedElementTransition(Object transitionObj) {
+        if (transitionObj == null) {
+            return null;
+        }
+        Transition transition = (Transition) transitionObj;
+        if (transition == null) {
+            return null;
+        }
+        TransitionSet transitionSet = new TransitionSet();
+        transitionSet.addTransition(transition);
+        return transitionSet;
+    }
+
     /**
      * Prepares the enter transition by adding a non-existent view to the transition's target list
      * and setting it epicenter callback. By adding a non-existent view to the target list,
@@ -106,8 +115,8 @@
                 enterTransition.addTarget(nonExistentView);
             }
             if (sharedElementTransitionObject != null) {
-                Transition sharedElementTransition = (Transition) sharedElementTransitionObject;
-                addTargets(sharedElementTransition, sharedElementTargets);
+                setSharedElementTargets(sharedElementTransitionObject, nonExistentView,
+                        renamedViews, sharedElementTargets);
             }
 
             if (inFragment != null) {
@@ -115,6 +124,9 @@
                         new ViewTreeObserver.OnPreDrawListener() {
                             public boolean onPreDraw() {
                                 container.getViewTreeObserver().removeOnPreDrawListener(this);
+                                if (enterTransition != null) {
+                                    enterTransition.removeTarget(nonExistentView);
+                                }
                                 View fragmentView = inFragment.getView();
                                 if (fragmentView != null) {
                                     if (!nameOverrides.isEmpty()) {
@@ -133,7 +145,6 @@
                                         captureTransitioningViews(enteringViews, fragmentView);
                                         enteringViews.removeAll(renamedViews.values());
                                         enteringViews.add(nonExistentView);
-                                        enterTransition.removeTarget(nonExistentView);
                                         addTargets(enterTransition, enteringViews);
                                     }
                                 }
@@ -203,7 +214,67 @@
         return transition;
     }
 
+    /**
+     * Finds all children of the shared elements and sets the wrapping TransitionSet
+     * targets to point to those. It also limits transitions that have no targets to the
+     * specific shared elements. This allows developers to target child views of the
+     * shared elements specifically, but this doesn't happen by default.
+     */
+    public static void setSharedElementTargets(Object transitionObj,
+            View nonExistentView, Map<String, View> namedViews,
+            ArrayList<View> sharedElementTargets) {
+        TransitionSet transition = (TransitionSet) transitionObj;
+        sharedElementTargets.clear();
+        sharedElementTargets.addAll(namedViews.values());
 
+        final List<View> views = transition.getTargets();
+        views.clear();
+        final int count = sharedElementTargets.size();
+        for (int i = 0; i < count; i++) {
+            final View view = sharedElementTargets.get(i);
+            bfsAddViewChildren(views, view);
+        }
+        sharedElementTargets.add(nonExistentView);
+        addTargets(transition, sharedElementTargets);
+    }
+
+    /**
+     * Uses a breadth-first scheme to add startView and all of its children to views.
+     * It won't add a child if it is already in views.
+     */
+    private static void bfsAddViewChildren(final List<View> views, final View startView) {
+        final int startIndex = views.size();
+        if (containedBeforeIndex(views, startView, startIndex)) {
+            return; // This child is already in the list, so all its children are also.
+        }
+        views.add(startView);
+        for (int index = startIndex; index < views.size(); index++) {
+            final View view = views.get(index);
+            if (view instanceof ViewGroup) {
+                ViewGroup viewGroup = (ViewGroup) view;
+                final int childCount =  viewGroup.getChildCount();
+                for (int childIndex = 0; childIndex < childCount; childIndex++) {
+                    final View child = viewGroup.getChildAt(childIndex);
+                    if (!containedBeforeIndex(views, child, startIndex)) {
+                        views.add(child);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Does a linear search through views for view, limited to maxIndex.
+     */
+    private static boolean containedBeforeIndex(final List<View> views, final View view,
+            final int maxIndex) {
+        for (int i = 0; i < maxIndex; i++) {
+            if (views.get(i) == view) {
+                return true;
+            }
+        }
+        return false;
+    }
 
     private static void setSharedElementEpicenter(Transition transition,
             final EpicenterView epicenterView) {
@@ -283,7 +354,6 @@
                 public boolean onPreDraw() {
                     sceneRoot.getViewTreeObserver().removeOnPreDrawListener(this);
                     if (enterTransition != null) {
-                        enterTransition.removeTarget(nonExistentView);
                         removeTargets(enterTransition, enteringViews);
                     }
                     if (exitTransition != null) {
diff --git a/v4/api21/android/support/v4/view/accessibility/AccessibilityNodeInfoCompatApi21.java b/v4/api21/android/support/v4/view/accessibility/AccessibilityNodeInfoCompatApi21.java
index ce6abf3..8939fee 100644
--- a/v4/api21/android/support/v4/view/accessibility/AccessibilityNodeInfoCompatApi21.java
+++ b/v4/api21/android/support/v4/view/accessibility/AccessibilityNodeInfoCompatApi21.java
@@ -35,6 +35,10 @@
         ((AccessibilityNodeInfo) info).addAction((AccessibilityAction) action);
     }
 
+    public static boolean removeAction(Object info, Object action) {
+        return ((AccessibilityNodeInfo) info).removeAction((AccessibilityAction) action);
+    }
+
     public static Object obtainCollectionInfo(int rowCount, int columnCount,
             boolean hierarchical, int selectionMode) {
         return AccessibilityNodeInfo.CollectionInfo.obtain(rowCount, columnCount, hierarchical,
@@ -55,12 +59,24 @@
         ((AccessibilityNodeInfo) info).setError(error);
     }
 
-    public static void setLabelFor(Object info, View labeled) {
-        ((AccessibilityNodeInfo) info).setLabelFor(labeled);
+    public static void setMaxTextLength(Object info, int max) {
+        ((AccessibilityNodeInfo) info).setMaxTextLength(max);
     }
 
-    public static void setLabelFor(Object info, View root, int virtualDescendantId) {
-        ((AccessibilityNodeInfo) info).setLabelFor(root, virtualDescendantId);
+    public static int getMaxTextLength(Object info) {
+        return ((AccessibilityNodeInfo) info).getMaxTextLength();
+    }
+
+    public static Object getWindow(Object info) {
+        return ((AccessibilityNodeInfo) info).getWindow();
+    }
+
+    public static boolean removeChild(Object info, View child) {
+        return ((AccessibilityNodeInfo) info).removeChild(child);
+    }
+
+    public static boolean removeChild(Object info, View root, int virtualDescendantId) {
+        return ((AccessibilityNodeInfo) info).removeChild(root, virtualDescendantId);
     }
 
     static class CollectionItemInfo {
diff --git a/v4/api21/android/support/v4/view/accessibility/AccessibilityWindowInfoCompatApi21.java b/v4/api21/android/support/v4/view/accessibility/AccessibilityWindowInfoCompatApi21.java
new file mode 100644
index 0000000..c166530
--- /dev/null
+++ b/v4/api21/android/support/v4/view/accessibility/AccessibilityWindowInfoCompatApi21.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.support.v4.view.accessibility;
+
+import android.graphics.Rect;
+import android.view.accessibility.AccessibilityWindowInfo;
+
+/**
+ * Api21-specific AccessibilityWindowInfo API implementation.
+ */
+class AccessibilityWindowInfoCompatApi21 {
+
+    public static Object obtain() {
+        return AccessibilityWindowInfo.obtain();
+    }
+
+    public static Object obtain(Object info) {
+        return AccessibilityWindowInfo.obtain((AccessibilityWindowInfo) info);
+
+    }
+
+    public static int getType(Object info) {
+        return ((AccessibilityWindowInfo) info).getType();
+    }
+
+    public static int getLayer(Object info) {
+        return ((AccessibilityWindowInfo) info).getLayer();
+    }
+
+    public static Object getRoot(Object info) {
+        return ((AccessibilityWindowInfo) info).getRoot();
+    }
+
+    public static Object getParent(Object info) {
+        return ((AccessibilityWindowInfo) info).getParent();
+    }
+
+    public static int getId(Object info) {
+        return ((AccessibilityWindowInfo) info).getId();
+    }
+
+    public static void getBoundsInScreen(Object info, Rect outBounds) {
+        ((AccessibilityWindowInfo) info).getBoundsInScreen(outBounds);
+    }
+
+    public static boolean isActive(Object info) {
+        return ((AccessibilityWindowInfo) info).isActive();
+    }
+
+    public static boolean isFocused(Object info) {
+        return ((AccessibilityWindowInfo) info).isFocused();
+    }
+
+    public static boolean isAccessibilityFocused(Object info) {
+        return ((AccessibilityWindowInfo) info).isAccessibilityFocused();
+    }
+
+    public static int getChildCount(Object info) {
+        return ((AccessibilityWindowInfo) info).getChildCount();
+    }
+
+    public static Object getChild(Object info, int index) {
+        return ((AccessibilityWindowInfo) info).getChild(index);
+    }
+
+    public static void recycle(Object info) {
+        ((AccessibilityWindowInfo) info).recycle();
+    }
+}
diff --git a/v4/api21/android/support/v4/widget/CompoundButtonCompatLollipop.java b/v4/api21/android/support/v4/widget/CompoundButtonCompatLollipop.java
new file mode 100644
index 0000000..17f4fdb
--- /dev/null
+++ b/v4/api21/android/support/v4/widget/CompoundButtonCompatLollipop.java
@@ -0,0 +1,40 @@
+/*
+ * 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.v4.widget;
+
+import android.content.res.ColorStateList;
+import android.graphics.PorterDuff;
+import android.widget.CompoundButton;
+
+class CompoundButtonCompatLollipop {
+
+    static void setButtonTintList(CompoundButton button, ColorStateList tint) {
+        button.setButtonTintList(tint);
+    }
+
+    static ColorStateList getButtonTintList(CompoundButton button) {
+        return button.getButtonTintList();
+    }
+
+    static void setButtonTintMode(CompoundButton button, PorterDuff.Mode tintMode) {
+        button.setButtonTintMode(tintMode);
+    }
+
+    static PorterDuff.Mode getButtonTintMode(CompoundButton button) {
+        return button.getButtonTintMode();
+    }
+}
diff --git a/v4/api21/android/support/v4/widget/PopupWindowCompatApi21.java b/v4/api21/android/support/v4/widget/PopupWindowCompatApi21.java
new file mode 100644
index 0000000..3440f3c
--- /dev/null
+++ b/v4/api21/android/support/v4/widget/PopupWindowCompatApi21.java
@@ -0,0 +1,60 @@
+/*
+ * 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.v4.widget;
+
+import android.util.Log;
+import android.widget.PopupWindow;
+
+import java.lang.reflect.Field;
+
+class PopupWindowCompatApi21 {
+
+    private static final String TAG = "PopupWindowCompatApi21";
+
+    private static Field sOverlapAnchorField;
+
+    static {
+        try {
+            sOverlapAnchorField = PopupWindow.class.getDeclaredField("mOverlapAnchor");
+            sOverlapAnchorField.setAccessible(true);
+        } catch (NoSuchFieldException e) {
+            Log.i(TAG, "Could not fetch mOverlapAnchor field from PopupWindow", e);
+        }
+    }
+
+    static void setOverlapAnchor(PopupWindow popupWindow, boolean overlapAnchor) {
+        if (sOverlapAnchorField != null) {
+            try {
+                sOverlapAnchorField.set(popupWindow, overlapAnchor);
+            } catch (IllegalAccessException e) {
+                Log.i(TAG, "Could not set overlap anchor field in PopupWindow", e);
+            }
+        }
+    }
+
+    static boolean getOverlapAnchor(PopupWindow popupWindow) {
+        if (sOverlapAnchorField != null) {
+            try {
+                return (Boolean) sOverlapAnchorField.get(popupWindow);
+            } catch (IllegalAccessException e) {
+                Log.i(TAG, "Could not get overlap anchor field in PopupWindow", e);
+            }
+        }
+        return false;
+    }
+
+}
diff --git a/v4/api22/android/support/v4/app/ActivityCompat22.java b/v4/api22/android/support/v4/app/ActivityCompat22.java
new file mode 100644
index 0000000..3946f1d
--- /dev/null
+++ b/v4/api22/android/support/v4/app/ActivityCompat22.java
@@ -0,0 +1,26 @@
+/*
+ * 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.v4.app;
+
+import android.app.Activity;
+import android.net.Uri;
+
+class ActivityCompat22 {
+    public static Uri getReferrer(Activity activity) {
+        return activity.getReferrer();
+    }
+}
diff --git a/v4/api23/android/support/v4/app/ActivityCompat23.java b/v4/api23/android/support/v4/app/ActivityCompat23.java
new file mode 100644
index 0000000..40df982
--- /dev/null
+++ b/v4/api23/android/support/v4/app/ActivityCompat23.java
@@ -0,0 +1,39 @@
+/*
+ * 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.v4.app;
+
+import android.app.Activity;
+
+class ActivityCompatApi23 {
+    public interface RequestPermissionsRequestCodeValidator {
+        public void validateRequestPermissionsRequestCode(int requestCode);
+    }
+
+    public static void requestPermissions(Activity activity, String[] permissions,
+            int requestCode) {
+        if (activity instanceof RequestPermissionsRequestCodeValidator) {
+            ((RequestPermissionsRequestCodeValidator) activity)
+                    .validateRequestPermissionsRequestCode(requestCode);
+        }
+        activity.requestPermissions(permissions, requestCode);
+    }
+
+    public static boolean shouldShowRequestPermissionRationale(Activity activity,
+            String permission) {
+        return activity.shouldShowRequestPermissionRationale(permission);
+    }
+}
diff --git a/v4/api23/android/support/v4/app/AppOpsManagerCompat23.java b/v4/api23/android/support/v4/app/AppOpsManagerCompat23.java
new file mode 100644
index 0000000..94034ac
--- /dev/null
+++ b/v4/api23/android/support/v4/app/AppOpsManagerCompat23.java
@@ -0,0 +1,34 @@
+/*
+ * 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.v4.app;
+
+import android.app.AppOpsManager;
+import android.content.Context;
+
+/**
+ * AppOpsManager implementations for API 23.
+ */
+public class AppOpsManagerCompat23 {
+    public static String permissionToOp(String permission) {
+        return AppOpsManager.permissionToOp(permission);
+    }
+
+    public static int noteOp(Context context, String op, int uid, String packageName) {
+        AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class);
+        return appOpsManager.noteOp(op, uid, packageName);
+    }
+}
diff --git a/v4/api23/android/support/v4/content/ContextCompatApi23.java b/v4/api23/android/support/v4/content/ContextCompatApi23.java
new file mode 100644
index 0000000..64f1c15
--- /dev/null
+++ b/v4/api23/android/support/v4/content/ContextCompatApi23.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.support.v4.content;
+
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.graphics.drawable.Drawable;
+
+import java.io.File;
+
+class ContextCompatApi23 {
+    public static ColorStateList getColorStateList(Context context, int id) {
+        return context.getColorStateList(id);
+    }
+
+    public static int getColor(Context context, int id) {
+        return context.getColor(id);
+    }
+}
diff --git a/v4/api23/android/support/v4/graphics/drawable/DrawableCompatApi23.java b/v4/api23/android/support/v4/graphics/drawable/DrawableCompatApi23.java
new file mode 100644
index 0000000..975d501
--- /dev/null
+++ b/v4/api23/android/support/v4/graphics/drawable/DrawableCompatApi23.java
@@ -0,0 +1,32 @@
+/*
+ * 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.v4.graphics.drawable;
+
+import android.graphics.drawable.Drawable;
+
+/**
+ * Implementation of drawable compatibility that can call M APIs.
+ */
+class DrawableCompatApi23 {
+    public static void setLayoutDirection(Drawable drawable, int layoutDirection) {
+        drawable.setLayoutDirection(layoutDirection);
+    }
+
+    public static int getLayoutDirection(Drawable drawable) {
+        return drawable.getLayoutDirection();
+    }
+}
diff --git a/v4/api23/android/support/v4/hardware/fingerprint/FingerprintManagerCompatApi23.java b/v4/api23/android/support/v4/hardware/fingerprint/FingerprintManagerCompatApi23.java
new file mode 100644
index 0000000..e7dec1e
--- /dev/null
+++ b/v4/api23/android/support/v4/hardware/fingerprint/FingerprintManagerCompatApi23.java
@@ -0,0 +1,133 @@
+/*
+ * 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.v4.hardware.fingerprint;
+
+import android.content.Context;
+import android.hardware.fingerprint.FingerprintManager;
+import android.os.Handler;
+
+import java.security.Signature;
+
+import javax.crypto.Cipher;
+
+/**
+ * Actual FingerprintManagerCompat implementation for API level 23 and later.
+ */
+public final class FingerprintManagerCompatApi23 {
+
+    private static FingerprintManager getFingerprintManager(Context ctx) {
+        return ctx.getSystemService(FingerprintManager.class);
+    }
+
+    public static boolean hasEnrolledFingerprints(Context context) {
+        return getFingerprintManager(context).hasEnrolledFingerprints();
+    }
+
+    public static boolean isHardwareDetected(Context context) {
+        return getFingerprintManager(context).isHardwareDetected();
+    }
+
+    public static void authenticate(Context context, CryptoObject crypto, int flags, Object cancel,
+            AuthenticationCallback callback, Handler handler) {
+        getFingerprintManager(context).authenticate(wrapCryptoObject(crypto),
+                (android.os.CancellationSignal) cancel, flags,
+                wrapCallback(callback), handler);
+    }
+
+    private static FingerprintManager.CryptoObject wrapCryptoObject(CryptoObject cryptoObject) {
+        if (cryptoObject == null) {
+            return null;
+        } else if (cryptoObject.getCipher() != null) {
+            return new FingerprintManager.CryptoObject(cryptoObject.getCipher());
+        } else {
+            return new FingerprintManager.CryptoObject(cryptoObject.getSignature());
+        }
+    }
+
+    private static CryptoObject unwrapCryptoObject(FingerprintManager.CryptoObject cryptoObject) {
+        if (cryptoObject == null) {
+            return null;
+        } else if (cryptoObject.getCipher() != null) {
+            return new CryptoObject(cryptoObject.getCipher());
+        } else {
+            return new CryptoObject(cryptoObject.getSignature());
+        }
+    }
+
+    private static FingerprintManager.AuthenticationCallback wrapCallback(
+            final AuthenticationCallback callback) {
+        return new FingerprintManager.AuthenticationCallback() {
+            @Override
+            public void onAuthenticationError(int errMsgId, CharSequence errString) {
+                callback.onAuthenticationError(errMsgId, errString);
+            }
+
+            @Override
+            public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) {
+                callback.onAuthenticationHelp(helpMsgId, helpString);
+            }
+
+            @Override
+            public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) {
+                callback.onAuthenticationSucceeded(new AuthenticationResultInternal(
+                        unwrapCryptoObject(result.getCryptoObject())));
+            }
+
+            @Override
+            public void onAuthenticationFailed() {
+                callback.onAuthenticationFailed();
+            }
+        };
+    }
+
+    public static class CryptoObject {
+
+        private final Signature mSignature;
+        private final Cipher mCipher;
+
+        public CryptoObject(Signature signature) {
+            mSignature = signature;
+            mCipher = null;
+        }
+
+        public CryptoObject(Cipher cipher) {
+            mCipher = cipher;
+            mSignature = null;
+        }
+
+        public Signature getSignature() { return mSignature; }
+        public Cipher getCipher() { return mCipher; }
+    }
+
+    public static final class AuthenticationResultInternal {
+        private CryptoObject mCryptoObject;
+
+        public AuthenticationResultInternal(CryptoObject crypto) {
+            mCryptoObject = crypto;
+        }
+
+        public CryptoObject getCryptoObject() { return mCryptoObject; }
+    }
+
+    public static abstract class AuthenticationCallback {
+
+        public void onAuthenticationError(int errMsgId, CharSequence errString) { }
+        public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) { }
+        public void onAuthenticationSucceeded(AuthenticationResultInternal result) { }
+        public void onAuthenticationFailed() { }
+    }
+}
diff --git a/v4/api23/android/support/v4/text/ICUCompatApi23.java b/v4/api23/android/support/v4/text/ICUCompatApi23.java
new file mode 100644
index 0000000..f013522
--- /dev/null
+++ b/v4/api23/android/support/v4/text/ICUCompatApi23.java
@@ -0,0 +1,55 @@
+/*
+ * 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.v4.text;
+
+import android.util.Log;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Locale;
+
+public class ICUCompatApi23 {
+
+    private static final String TAG = "ICUCompatIcs";
+
+    private static Method sAddLikelySubtagsMethod;
+
+    static {
+        try {
+            // This class should always exist on API-23 since it's CTS tested.
+            final Class<?> clazz = Class.forName("libcore.icu.ICU");
+            sAddLikelySubtagsMethod = clazz.getMethod("addLikelySubtags",
+                    new Class[]{ Locale.class });
+        } catch (Exception e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+
+    public static String maximizeAndGetScript(Locale locale) {
+        try {
+            final Object[] args = new Object[] { locale };
+            return ((Locale) sAddLikelySubtagsMethod.invoke(null, args)).getScript();
+        } catch (InvocationTargetException e) {
+            Log.w(TAG, e);
+        } catch (IllegalAccessException e) {
+            Log.w(TAG, e);
+        }
+
+        return locale.getScript();
+    }
+}
diff --git a/v4/api23/android/support/v4/widget/CompoundButtonCompatApi23.java b/v4/api23/android/support/v4/widget/CompoundButtonCompatApi23.java
new file mode 100644
index 0000000..0c55bbc
--- /dev/null
+++ b/v4/api23/android/support/v4/widget/CompoundButtonCompatApi23.java
@@ -0,0 +1,30 @@
+/*
+ * 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.v4.widget;
+
+import android.content.res.ColorStateList;
+import android.graphics.PorterDuff;
+import android.graphics.drawable.Drawable;
+import android.support.annotation.Nullable;
+import android.widget.CompoundButton;
+
+class CompoundButtonCompatApi23 {
+
+    static Drawable getButtonDrawable(CompoundButton button) {
+        return button.getButtonDrawable();
+    }
+}
diff --git a/v4/api23/android/support/v4/widget/PopupWindowCompatApi23.java b/v4/api23/android/support/v4/widget/PopupWindowCompatApi23.java
new file mode 100644
index 0000000..96bf8d9
--- /dev/null
+++ b/v4/api23/android/support/v4/widget/PopupWindowCompatApi23.java
@@ -0,0 +1,39 @@
+/*
+ * 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.v4.widget;
+
+import android.widget.PopupWindow;
+
+class PopupWindowCompatApi23 {
+
+    static void setOverlapAnchor(PopupWindow popupWindow, boolean overlapAnchor) {
+        popupWindow.setOverlapAnchor(overlapAnchor);
+    }
+
+    static boolean getOverlapAnchor(PopupWindow popupWindow) {
+        return popupWindow.getOverlapAnchor();
+    }
+
+    static void setWindowLayoutType(PopupWindow popupWindow, int layoutType) {
+        popupWindow.setWindowLayoutType(layoutType);
+    }
+
+    static int getWindowLayoutType(PopupWindow popupWindow) {
+        return popupWindow.getWindowLayoutType();
+    }
+
+}
diff --git a/v4/build.gradle b/v4/build.gradle
index e64c5ad..a056973 100644
--- a/v4/build.gradle
+++ b/v4/build.gradle
@@ -27,9 +27,10 @@
 def jbMr1SS        = createApiSourceset('jellybeanmr1', 'jellybean-mr1', '17',      jbSS)
 def jbMr2SS        = createApiSourceset('jellybeanmr2', 'jellybean-mr2', '18',      jbMr1SS)
 def kitkatSS       = createApiSourceset('kitkat',       'kitkat',        '19',      jbMr2SS)
-def api20SS        = createApiSourceset('api20',        'api20',         '20', kitkatSS)
-def api21SS        = createApiSourceset('api21',        'api21',         '21', api20SS)
-def api22SS        = createApiSourceset('api22',        'api22',         'current', api21SS)
+def api20SS        = createApiSourceset('api20',        'api20',         '20',      kitkatSS)
+def api21SS        = createApiSourceset('api21',        'api21',         '21',      api20SS)
+def api22SS        = createApiSourceset('api22',        'api22',         '22',      api21SS)
+def api23SS        = createApiSourceset('api23',        'api23',         'current', api22SS)
 
 
 def createApiSourceset(String name, String folder, String apiLevel, SourceSet previousSource) {
diff --git a/v4/donut/android/support/v4/graphics/drawable/DrawableWrapperDonut.java b/v4/donut/android/support/v4/graphics/drawable/DrawableWrapperDonut.java
index e3672c8..9293520 100644
--- a/v4/donut/android/support/v4/graphics/drawable/DrawableWrapperDonut.java
+++ b/v4/donut/android/support/v4/graphics/drawable/DrawableWrapperDonut.java
@@ -215,6 +215,9 @@
                 mColorFilterSet = true;
                 return true;
             }
+        } else {
+            mColorFilterSet = false;
+            clearColorFilter();
         }
         return false;
     }
diff --git a/v4/donut/android/support/v4/widget/CompoundButtonCompatDonut.java b/v4/donut/android/support/v4/widget/CompoundButtonCompatDonut.java
new file mode 100644
index 0000000..af9e19f
--- /dev/null
+++ b/v4/donut/android/support/v4/widget/CompoundButtonCompatDonut.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.v4.widget;
+
+import android.content.res.ColorStateList;
+import android.graphics.PorterDuff;
+import android.graphics.drawable.Drawable;
+import android.util.Log;
+import android.widget.CompoundButton;
+
+import java.lang.reflect.Field;
+
+class CompoundButtonCompatDonut {
+
+    private static final String TAG = "CompoundButtonCompatDonut";
+
+    private static Field sButtonDrawableField;
+    private static boolean sButtonDrawableFieldFetched;
+
+    static void setButtonTintList(CompoundButton button, ColorStateList tint) {
+        if (button instanceof TintableCompoundButton) {
+            ((TintableCompoundButton) button).setSupportButtonTintList(tint);
+        }
+    }
+
+    static ColorStateList getButtonTintList(CompoundButton button) {
+        if (button instanceof TintableCompoundButton) {
+             return((TintableCompoundButton) button).getSupportButtonTintList();
+        }
+        return null;
+    }
+
+    static void setButtonTintMode(CompoundButton button, PorterDuff.Mode tintMode) {
+        if (button instanceof TintableCompoundButton) {
+            ((TintableCompoundButton) button).setSupportButtonTintMode(tintMode);
+        }
+    }
+
+    static PorterDuff.Mode getButtonTintMode(CompoundButton button) {
+        if (button instanceof TintableCompoundButton) {
+            return ((TintableCompoundButton) button).getSupportButtonTintMode();
+        }
+        return null;
+    }
+
+    static Drawable getButtonDrawable(CompoundButton button) {
+        if (!sButtonDrawableFieldFetched) {
+            try {
+                sButtonDrawableField = CompoundButton.class.getDeclaredField("mButtonDrawable");
+                sButtonDrawableField.setAccessible(true);
+            } catch (NoSuchFieldException e) {
+                Log.i(TAG, "Failed to retrieve mButtonDrawable field", e);
+            }
+            sButtonDrawableFieldFetched = true;
+        }
+
+        if (sButtonDrawableField != null) {
+            try {
+                return (Drawable) sButtonDrawableField.get(button);
+            } catch (IllegalAccessException e) {
+                Log.i(TAG, "Failed to get button drawable via reflection", e);
+                sButtonDrawableField = null;
+            }
+        }
+        return null;
+    }
+
+}
diff --git a/v4/donut/android/support/v4/widget/TintableCompoundButton.java b/v4/donut/android/support/v4/widget/TintableCompoundButton.java
new file mode 100644
index 0000000..6bcfa30
--- /dev/null
+++ b/v4/donut/android/support/v4/widget/TintableCompoundButton.java
@@ -0,0 +1,70 @@
+/*
+ * 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.v4.widget;
+
+import android.content.res.ColorStateList;
+import android.graphics.PorterDuff;
+import android.graphics.drawable.Drawable;
+import android.support.annotation.Nullable;
+
+/**
+ * Interface which allows a {@link android.widget.CompoundButton} to receive tinting
+ * calls from {@code CompoundButtonCompat} when running on API v20 devices or lower.
+ */
+public interface TintableCompoundButton {
+
+    /**
+     * Applies a tint to the button drawable. Does not modify the current tint
+     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
+     * <p>
+     * Subsequent calls to
+     * {@link android.widget.CompoundButton#setButtonDrawable(Drawable) setButtonDrawable(Drawable)}
+     * should automatically mutate the drawable and apply the specified tint and tint mode.
+     *
+     * @param tint the tint to apply, may be {@code null} to clear tint
+     */
+    public void setSupportButtonTintList(@Nullable ColorStateList tint);
+
+    /**
+     * Returns the tint applied to the button drawable
+     *
+     * @see #setSupportButtonTintList(ColorStateList)
+     */
+    @Nullable
+    public ColorStateList getSupportButtonTintList();
+
+    /**
+     * Specifies the blending mode which should be used to apply the tint specified by
+     * {@link #setSupportButtonTintList(ColorStateList)} to the button drawable. The
+     * default mode is {@link PorterDuff.Mode#SRC_IN}.
+     *
+     * @param tintMode the blending mode used to apply the tint, may be
+     *                 {@code null} to clear tint
+     *
+     * @see #getSupportButtonTintMode()
+     * @see DrawableCompat#setTintMode(Drawable, PorterDuff.Mode)
+     */
+    public void setSupportButtonTintMode(@Nullable PorterDuff.Mode tintMode);
+
+    /**
+     * Returns the blending mode used to apply the tint to the button drawable
+     *
+     * @see #setSupportButtonTintMode(PorterDuff.Mode)
+     */
+    @Nullable
+    public PorterDuff.Mode getSupportButtonTintMode();
+}
diff --git a/v4/gingerbread/android/support/v4/content/EditorCompatGingerbread.java b/v4/gingerbread/android/support/v4/content/EditorCompatGingerbread.java
new file mode 100644
index 0000000..394964d
--- /dev/null
+++ b/v4/gingerbread/android/support/v4/content/EditorCompatGingerbread.java
@@ -0,0 +1,33 @@
+/*
+ * 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.v4.content;
+
+import android.content.SharedPreferences;
+import android.support.annotation.NonNull;
+
+class EditorCompatGingerbread {
+    public static void apply(@NonNull SharedPreferences.Editor editor) {
+        try {
+            editor.apply();
+        } catch (AbstractMethodError unused) {
+            // The app injected its own pre-Gingerbread
+            // SharedPreferences.Editor implementation without
+            // an apply method.
+            editor.commit();
+        }
+    }
+}
diff --git a/v4/gingerbread/android/support/v4/widget/PopupWindowCompatGingerbread.java b/v4/gingerbread/android/support/v4/widget/PopupWindowCompatGingerbread.java
new file mode 100644
index 0000000..b87db30
--- /dev/null
+++ b/v4/gingerbread/android/support/v4/widget/PopupWindowCompatGingerbread.java
@@ -0,0 +1,76 @@
+/*
+ * 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.v4.widget;
+
+import android.widget.PopupWindow;
+
+import java.lang.reflect.Method;
+
+/**
+ * Implementation of PopupWindow compatibility that can call Gingerbread APIs.
+ */
+class PopupWindowCompatGingerbread {
+
+    private static Method sSetWindowLayoutTypeMethod;
+    private static boolean sSetWindowLayoutTypeMethodAttempted;
+    private static Method sGetWindowLayoutTypeMethod;
+    private static boolean sGetWindowLayoutTypeMethodAttempted;
+
+    static void setWindowLayoutType(PopupWindow popupWindow, int layoutType) {
+        if (!sSetWindowLayoutTypeMethodAttempted) {
+            try {
+                sSetWindowLayoutTypeMethod = PopupWindow.class.getDeclaredMethod(
+                        "setWindowLayoutType", int.class);
+                sSetWindowLayoutTypeMethod.setAccessible(true);
+            } catch (Exception e) {
+                // Reflection method fetch failed. Oh well.
+            }
+            sSetWindowLayoutTypeMethodAttempted = true;
+        }
+
+        if (sSetWindowLayoutTypeMethod != null) {
+            try {
+                sSetWindowLayoutTypeMethod.invoke(popupWindow, layoutType);
+            } catch (Exception e) {
+                // Reflection call failed. Oh well.
+            }
+        }
+    }
+
+    static int getWindowLayoutType(PopupWindow popupWindow) {
+        if (!sGetWindowLayoutTypeMethodAttempted) {
+            try {
+                sGetWindowLayoutTypeMethod = PopupWindow.class.getDeclaredMethod(
+                        "getWindowLayoutType");
+                sGetWindowLayoutTypeMethod.setAccessible(true);
+            } catch (Exception e) {
+                // Reflection method fetch failed. Oh well.
+            }
+            sGetWindowLayoutTypeMethodAttempted = true;
+        }
+
+        if (sGetWindowLayoutTypeMethod != null) {
+            try {
+                return (Integer) sGetWindowLayoutTypeMethod.invoke(popupWindow);
+            } catch (Exception e) {
+                // Reflection call failed. Oh well.
+            }
+        }
+        return 0;
+    }
+
+}
diff --git a/v4/ics/android/support/v4/text/ICUCompatIcs.java b/v4/ics/android/support/v4/text/ICUCompatIcs.java
index 7dc5d3c..dfb9e7e 100644
--- a/v4/ics/android/support/v4/text/ICUCompatIcs.java
+++ b/v4/ics/android/support/v4/text/ICUCompatIcs.java
@@ -20,6 +20,7 @@
 
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.util.Locale;
 
 class ICUCompatIcs {
 
@@ -38,15 +39,27 @@
                         new Class[]{ String.class });
             }
         } catch (Exception e) {
+            sGetScriptMethod = null;
+            sAddLikelySubtagsMethod = null;
+
             // Nothing we can do here, we just log the exception
             Log.w(TAG, e);
         }
     }
 
-    public static String getScript(String locale) {
+    public static String maximizeAndGetScript(Locale locale) {
+        final String localeWithSubtags = addLikelySubtags(locale);
+        if (localeWithSubtags != null) {
+            return getScript(localeWithSubtags);
+        }
+
+        return null;
+    }
+
+    private static String getScript(String localeStr) {
         try {
             if (sGetScriptMethod != null) {
-                final Object[] args = new Object[] { locale };
+                final Object[] args = new Object[] { localeStr };
                 return (String) sGetScriptMethod.invoke(null, args);
             }
         } catch (IllegalAccessException e) {
@@ -60,10 +73,11 @@
         return null;
     }
 
-    public static String addLikelySubtags(String locale) {
+    private static String addLikelySubtags(Locale locale) {
+        final String localeStr = locale.toString();
         try {
             if (sAddLikelySubtagsMethod != null) {
-                final Object[] args = new Object[] { locale };
+                final Object[] args = new Object[] { localeStr };
                 return (String) sAddLikelySubtagsMethod.invoke(null, args);
             }
         } catch (IllegalAccessException e) {
@@ -74,6 +88,7 @@
             // Nothing we can do here, we just log the exception
             Log.w(TAG, e);
         }
-        return locale;
+
+        return localeStr;
     }
 }
diff --git a/v4/java/android/support/v4/app/ActivityCompat.java b/v4/java/android/support/v4/app/ActivityCompat.java
index 8d8bf04..58cc199 100644
--- a/v4/java/android/support/v4/app/ActivityCompat.java
+++ b/v4/java/android/support/v4/app/ActivityCompat.java
@@ -19,15 +19,21 @@
 import android.app.Activity;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.PackageManager;
 import android.graphics.Matrix;
 import android.graphics.RectF;
+import android.net.Uri;
 import android.os.Build;
 import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
 import android.os.Parcelable;
+import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.support.v4.content.ContextCompat;
 import android.view.View;
 
+import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
 
@@ -36,6 +42,30 @@
  * introduced after API level 4 in a backwards compatible fashion.
  */
 public class ActivityCompat extends ContextCompat {
+
+    /**
+     * This interface is the contract for receiving the results for permission requests.
+     */
+    public interface OnRequestPermissionsResultCallback {
+
+        /**
+         * Callback for the result from requesting permissions. This method
+         * is invoked for every call on {@link #requestPermissions(android.app.Activity,
+         * String[], int)}
+         *
+         * @param requestCode The request code passed in {@link #requestPermissions(
+         * android.app.Activity, String[], int)}
+         * @param permissions The requested permissions. Never null.
+         * @param grantResults The grant results for the corresponding permissions
+         *     which is either {@link android.content.pm.PackageManager#PERMISSION_GRANTED}
+         *     or {@link android.content.pm.PackageManager#PERMISSION_DENIED}. Never null.
+         *
+         * @see #requestPermissions(android.app.Activity, String[], int)
+         */
+        public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
+                @NonNull int[] grantResults);
+    }
+
     /**
      * Invalidate the activity's options menu, if able.
      *
@@ -163,6 +193,27 @@
     }
 
     /**
+     * Backwards compatible implementation of {@link android.app.Activity#getReferrer()
+     * Activity.getReferrer}.  Uses the platform's implementation if available, otherwise
+     * only falls back to digging any explicitly specified referrer from the activity's intent.
+     */
+    public Uri getReferrer(Activity activity) {
+        if (Build.VERSION.SDK_INT >= 22) {
+            return ActivityCompat22.getReferrer(activity);
+        }
+        Intent intent = activity.getIntent();
+        Uri referrer = intent.getParcelableExtra("android.intent.extra.REFERRER");
+        if (referrer != null) {
+            return referrer;
+        }
+        String referrerName = intent.getStringExtra("android.intent.extra.REFERRER_NAME");
+        if (referrerName != null) {
+            return Uri.parse(referrerName);
+        }
+        return null;
+    }
+
+    /**
      * When {@link android.app.ActivityOptions#makeSceneTransitionAnimation(Activity,
      * android.view.View, String)} was used to start an Activity, <var>callback</var>
      * will be called to handle shared elements on the <i>launched</i> Activity. This requires
@@ -205,6 +256,103 @@
         }
     }
 
+    /**
+     * Requests permissions to be granted to this application. These permissions
+     * must be requested in your manifest, they should not be granted to your app,
+     * and they should have protection level {@link android.content.pm.PermissionInfo
+     * #PROTECTION_DANGEROUS dangerous}, regardless whether they are declared by
+     * the platform or a third-party app.
+     * <p>
+     * Normal permissions {@link android.content.pm.PermissionInfo#PROTECTION_NORMAL}
+     * are granted at install time if requested in the manifest. Signature permissions
+     * {@link android.content.pm.PermissionInfo#PROTECTION_SIGNATURE} are granted at
+     * install time if requested in the manifest and the signature of your app matches
+     * the signature of the app declaring the permissions.
+     * </p>
+     * <p>
+     * If your app does not have the requested permissions the user will be presented
+     * with UI for accepting them. After the user has accepted or rejected the
+     * requested permissions you will receive a callback reporting whether the
+     * permissions were granted or not. Your activity has to implement {@link
+     * android.support.v4.app.ActivityCompat.OnRequestPermissionsResultCallback}
+     * and the results of permission requests will be delivered to its {@link
+     * android.support.v4.app.ActivityCompat.OnRequestPermissionsResultCallback#onRequestPermissionsResult(
+     * int, String[], int[])} method.
+     * </p>
+     * <p>
+     * Note that requesting a permission does not guarantee it will be granted and
+     * your app should be able to run without having this permission.
+     * </p>
+     * <p>
+     * This method may start an activity allowing the user to choose which permissions
+     * to grant and which to reject. Hence, you should be prepared that your activity
+     * may be paused and resumed. Further, granting some permissions may require
+     * a restart of you application. In such a case, the system will recreate the
+     * activity stack before delivering the result to your onRequestPermissionsResult(
+     * int, String[], int[]).
+     * </p>
+     * <p>
+     * When checking whether you have a permission you should use {@link
+     * #checkSelfPermission(android.content.Context, String)}.
+     * </p>
+     *
+     * @param activity The target activity.
+     * @param permissions The requested permissions.
+     * @param requestCode Application specific request code to match with a result
+     *    reported to {@link OnRequestPermissionsResultCallback#onRequestPermissionsResult(
+     *    int, String[], int[])}.
+     *
+     * @see #checkSelfPermission(android.content.Context, String)
+     * @see #shouldShowRequestPermissionRationale(android.app.Activity, String)
+     */
+    public static void requestPermissions(final @NonNull Activity activity,
+            final @NonNull String[] permissions, final int requestCode) {
+        // TODO: Change to comparison against API 23 once we have it defined.
+        if (Build.VERSION.CODENAME.equals("MNC") || Build.VERSION.SDK_INT > 22) {
+            ActivityCompatApi23.requestPermissions(activity, permissions, requestCode);
+        } else if (activity instanceof OnRequestPermissionsResultCallback) {
+            Handler handler = new Handler(Looper.getMainLooper());
+            handler.post(new Runnable() {
+                @Override
+                public void run() {
+                    final int[] grantResults = new int[permissions.length];
+                    Arrays.fill(grantResults, PackageManager.PERMISSION_GRANTED);
+                    ((OnRequestPermissionsResultCallback) activity).onRequestPermissionsResult(
+                            requestCode, permissions, grantResults);
+                }
+            });
+        }
+    }
+
+    /**
+     * Gets whether you should show UI with rationale for requesting a permission.
+     * You should do this only if you do not have the permission and the context in
+     * which the permission is requested does not clearly communicate to the user
+     * what would be the benefit from granting this permission.
+     * <p>
+     * For example, if you write a camera app, requesting the camera permission
+     * would be expected by the user and no rationale for why it is requested is
+     * needed. If however, the app needs location for tagging photos then a non-tech
+     * savvy user may wonder how location is related to taking photos. In this case
+     * you may choose to show UI with rationale of requesting this permission.
+     * </p>
+     *
+     * @param activity The target activity.
+     * @param permission A permission your app wants to request.
+     * @return Whether you can show permission rationale UI.
+     *
+     * @see #checkSelfPermission(android.content.Context, String)
+     * @see #requestPermissions(android.app.Activity, String[], int)
+     */
+    public static boolean shouldShowRequestPermissionRationale(@NonNull Activity activity,
+            @NonNull String permission) {
+        // TODO: Change to comparison against API 23 once we have it defined.
+        if (Build.VERSION.CODENAME.equals("MNC") || Build.VERSION.SDK_INT > 22) {
+            return ActivityCompatApi23.shouldShowRequestPermissionRationale(activity, permission);
+        }
+        return false;
+    }
+
     private static ActivityCompat21.SharedElementCallback21 createCallback(
             SharedElementCallback callback) {
         ActivityCompat21.SharedElementCallback21 newCallback = null;
diff --git a/v4/java/android/support/v4/app/AppOpsManagerCompat.java b/v4/java/android/support/v4/app/AppOpsManagerCompat.java
new file mode 100644
index 0000000..49d4940
--- /dev/null
+++ b/v4/java/android/support/v4/app/AppOpsManagerCompat.java
@@ -0,0 +1,110 @@
+/*
+ * 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.v4.app;
+
+import android.content.Context;
+import android.os.Build;
+import android.support.annotation.NonNull;
+
+/**
+ * Helper for accessing features in android.app.AppOpsManager
+ * introduced after API level 4 in a backwards compatible fashion.
+ */
+public class AppOpsManagerCompat {
+
+    /**
+     * Result from {@link #noteOp}: the given caller is allowed to
+     * perform the given operation.
+     */
+    public static final int MODE_ALLOWED = 0;
+
+    /**
+     * Result from {@link #noteOp}: the given caller is not allowed to perform
+     * the given operation, and this attempt should <em>silently fail</em> (it
+     * should not cause the app to crash).
+     */
+    public static final int MODE_IGNORED = 1;
+
+    /**
+     * Result from {@link #noteOp}: the given caller should use its default
+     * security check.  This mode is not normally used; it should only be used
+     * with appop permissions, and callers must explicitly check for it and
+     * deal with it.
+     */
+    public static final int MODE_DEFAULT = 3;
+
+    private static class AppOpsManagerImpl {
+        public String permissionToOp(String permission) {
+            return null;
+        }
+
+        public int noteOp(Context context, String op, int uid, String packageName) {
+            return MODE_IGNORED;
+        }
+    }
+
+    private static class AppOpsManager23 extends AppOpsManagerImpl {
+        @Override
+        public String permissionToOp(String permission) {
+            return AppOpsManagerCompat23.permissionToOp(permission);
+        }
+
+        @Override
+        public int noteOp(Context context, String op, int uid, String packageName) {
+            return AppOpsManagerCompat23.noteOp(context, op, uid, packageName);
+        }
+    }
+
+    private static final AppOpsManagerImpl IMPL;
+    static {
+        // TODO: Change to comparison against API 23 once we have it defined.
+        if (Build.VERSION.CODENAME.equals("MNC") || Build.VERSION.SDK_INT > 22) {
+            IMPL = new AppOpsManager23();
+        } else {
+            IMPL = new AppOpsManagerImpl();
+        }
+    }
+
+    /**
+     * Gets the app op name associated with a given permission.
+     *
+     * @param permission The permission.
+     * @return The app op associated with the permission or null.
+     */
+    public static String permissionToOp(@NonNull String permission) {
+        return IMPL.permissionToOp(permission);
+    }
+
+    /**
+     * Make note of an application performing an operation.  Note that you must pass
+     * in both the uid and name of the application to be checked; this function will verify
+     * that these two match, and if not, return {@link #MODE_IGNORED}.  If this call
+     * succeeds, the last execution time of the operation for this app will be updated to
+     * the current time.
+     * @param context Your context.
+     * @param op The operation to note.  One of the OPSTR_* constants.
+     * @param uid The user id of the application attempting to perform the operation.
+     * @param packageName The name of the application attempting to perform the operation.
+     * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
+     * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
+     * causing the app to crash).
+     * @throws SecurityException If the app has been configured to crash on this op.
+     */
+    public static int noteOp(@NonNull Context context, String op, int uid, String packageName) {
+        return IMPL.noteOp(context, op, uid, packageName);
+    }
+}
diff --git a/v4/java/android/support/v4/app/BackStackRecord.java b/v4/java/android/support/v4/app/BackStackRecord.java
index 25f3ebf..647cc38 100644
--- a/v4/java/android/support/v4/app/BackStackRecord.java
+++ b/v4/java/android/support/v4/app/BackStackRecord.java
@@ -16,12 +16,11 @@
 
 package android.support.v4.app;
 
-import android.graphics.Rect;
 import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.support.v4.app.FragmentTransitionCompat21;
 import android.support.v4.util.LogWriter;
-import android.support.v4.util.Pair;
 import android.support.v4.util.ArrayMap;
 import android.text.TextUtils;
 import android.util.Log;
@@ -33,7 +32,6 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
-import java.util.Collection;
 
 final class BackStackState implements Parcelable {
     final int[] mOps;
@@ -48,7 +46,7 @@
     final ArrayList<String> mSharedElementSourceNames;
     final ArrayList<String> mSharedElementTargetNames;
 
-    public BackStackState(FragmentManagerImpl fm, BackStackRecord bse) {
+    public BackStackState(BackStackRecord bse) {
         int numRemoved = 0;
         BackStackRecord.Op op = bse.mHead;
         while (op != null) {
@@ -371,14 +369,14 @@
 
     public CharSequence getBreadCrumbTitle() {
         if (mBreadCrumbTitleRes != 0) {
-            return mManager.mActivity.getText(mBreadCrumbTitleRes);
+            return mManager.mHost.getContext().getText(mBreadCrumbTitleRes);
         }
         return mBreadCrumbTitleText;
     }
 
     public CharSequence getBreadCrumbShortTitle() {
         if (mBreadCrumbShortTitleRes != 0) {
-            return mManager.mActivity.getText(mBreadCrumbShortTitleRes);
+            return mManager.mHost.getContext().getText(mBreadCrumbShortTitleRes);
         }
         return mBreadCrumbShortTitleText;
     }
@@ -774,7 +772,7 @@
      */
     private void calculateFragments(SparseArray<Fragment> firstOutFragments,
             SparseArray<Fragment> lastInFragments) {
-        if (!mManager.mContainer.hasView()) {
+        if (!mManager.mContainer.onHasView()) {
             return; // nothing to see, so no transitions
         }
         Op op = mHead;
@@ -832,7 +830,7 @@
      */
     public void calculateBackFragments(SparseArray<Fragment> firstOutFragments,
             SparseArray<Fragment> lastInFragments) {
-        if (!mManager.mContainer.hasView()) {
+        if (!mManager.mContainer.onHasView()) {
             return; // nothing to see, so no transitions
         }
         Op op = mHead;
@@ -1023,7 +1021,7 @@
         // Adding a non-existent target view makes sure that the transitions don't target
         // any views by default. They'll only target the views we tell add. If we don't
         // add any, then no views will be targeted.
-        state.nonExistentView = new View(mManager.mActivity);
+        state.nonExistentView = new View(mManager.mHost.getContext());
 
         boolean anyTransitionStarted = false;
         // Go over all leaving fragments.
@@ -1073,7 +1071,7 @@
         if (inFragment == null || outFragment == null) {
             return null;
         }
-        return FragmentTransitionCompat21.cloneTransition(isBack ?
+        return FragmentTransitionCompat21.wrapSharedElementTransition(isBack ?
                 outFragment.getSharedElementReturnTransition() :
                 inFragment.getSharedElementEnterTransition());
     }
@@ -1131,7 +1129,7 @@
      */
     private boolean configureTransitions(int containerId, TransitionState state, boolean isBack,
             SparseArray<Fragment> firstOutFragments, SparseArray<Fragment> lastInFragments) {
-        ViewGroup sceneRoot = (ViewGroup) mManager.mContainer.findViewById(containerId);
+        ViewGroup sceneRoot = (ViewGroup) mManager.mContainer.onFindViewById(containerId);
         if (sceneRoot == null) {
             return false;
         }
@@ -1142,27 +1140,31 @@
         Object sharedElementTransition = getSharedElementTransition(inFragment, outFragment,
                 isBack);
         Object exitTransition = getExitTransition(outFragment, isBack);
-        if (enterTransition == null && sharedElementTransition == null &&
-                exitTransition == null) {
-            return false; // no transitions!
-        }
         ArrayMap<String, View> namedViews = null;
         ArrayList<View> sharedElementTargets = new ArrayList<View>();
         if (sharedElementTransition != null) {
             namedViews = remapSharedElements(state, outFragment, isBack);
-            sharedElementTargets.add(state.nonExistentView);
-            sharedElementTargets.addAll(namedViews.values());
-
-            // Notify the start of the transition.
-            SharedElementCallback callback = isBack ?
-                    outFragment.mEnterTransitionCallback :
-                    inFragment.mEnterTransitionCallback;
-            if (callback != null) {
-                ArrayList<String> names = new ArrayList<String>(namedViews.keySet());
-                ArrayList<View> views = new ArrayList<View>(namedViews.values());
-                callback.onSharedElementStart(names, views, null);
+            if (namedViews.isEmpty()) {
+                sharedElementTransition = null;
+                namedViews = null;
+            } else {
+                // Notify the start of the transition.
+                SharedElementCallback callback = isBack ?
+                        outFragment.mEnterTransitionCallback :
+                        inFragment.mEnterTransitionCallback;
+                if (callback != null) {
+                    ArrayList<String> names = new ArrayList<String>(namedViews.keySet());
+                    ArrayList<View> views = new ArrayList<View>(namedViews.values());
+                    callback.onSharedElementStart(names, views, null);
+                }
+                prepareSharedElementTransition(state, sceneRoot, sharedElementTransition,
+                        inFragment, outFragment, isBack, sharedElementTargets);
             }
         }
+        if (enterTransition == null && sharedElementTransition == null &&
+                exitTransition == null) {
+            return false; // no transitions!
+        }
 
         ArrayList<View> exitingViews = new ArrayList<View>();
         exitTransition = captureExitingViews(exitTransition, outFragment, exitingViews,
@@ -1190,16 +1192,14 @@
                     }
                 };
 
-        if (sharedElementTransition != null) {
-            prepareSharedElementTransition(state, sceneRoot, sharedElementTransition,
-                    inFragment, outFragment, isBack, sharedElementTargets);
-        }
-
         ArrayList<View> enteringViews = new ArrayList<View>();
         ArrayMap<String, View> renamedViews = new ArrayMap<String, View>();
 
-        boolean allowOverlap = isBack ? inFragment.getAllowReturnTransitionOverlap() :
-                inFragment.getAllowEnterTransitionOverlap();
+        boolean allowOverlap = true;
+        if (inFragment != null) {
+            allowOverlap = isBack ? inFragment.getAllowReturnTransitionOverlap() :
+                    inFragment.getAllowEnterTransitionOverlap();
+        }
         Object transition = FragmentTransitionCompat21.mergeTransitions(enterTransition,
                 exitTransition, sharedElementTransition, allowOverlap);
 
@@ -1243,10 +1243,8 @@
 
                     ArrayMap<String, View> namedViews = mapSharedElementsIn(
                             state, isBack, inFragment);
-                    sharedElementTargets.add(state.nonExistentView);
-                    sharedElementTargets.addAll(namedViews.values());
-                    FragmentTransitionCompat21.addTargets(sharedElementTransition,
-                            sharedElementTargets);
+                    FragmentTransitionCompat21.setSharedElementTargets(sharedElementTransition,
+                            state.nonExistentView, namedViews, sharedElementTargets);
 
                     setEpicenterIn(namedViews, state);
 
@@ -1392,7 +1390,7 @@
 
     private static void setNameOverride(ArrayMap<String, String> overrides,
             String source, String target) {
-        if (source != null && target != null && !source.equals(target)) {
+        if (source != null && target != null) {
             for (int index = 0; index < overrides.size(); index++) {
                 if (source.equals(overrides.valueAt(index))) {
                     overrides.setValueAt(index, target);
diff --git a/v4/java/android/support/v4/app/DialogFragment.java b/v4/java/android/support/v4/app/DialogFragment.java
index 343c145..fa7ad7b 100644
--- a/v4/java/android/support/v4/app/DialogFragment.java
+++ b/v4/java/android/support/v4/app/DialogFragment.java
@@ -306,23 +306,30 @@
         }
 
         mDialog = onCreateDialog(savedInstanceState);
-        switch (mStyle) {
-            case STYLE_NO_INPUT:
-                mDialog.getWindow().addFlags(
-                        WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
-                        WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
-                // fall through...
-            case STYLE_NO_FRAME:
-            case STYLE_NO_TITLE:
-                mDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
-        }
+
         if (mDialog != null) {
+            setupDialog(mDialog, mStyle);
+
             return (LayoutInflater) mDialog.getContext().getSystemService(
                     Context.LAYOUT_INFLATER_SERVICE);
         }
-        return (LayoutInflater) mActivity.getSystemService(
+        return (LayoutInflater) mHost.getContext().getSystemService(
                 Context.LAYOUT_INFLATER_SERVICE);
     }
+
+    /** @hide */
+    public void setupDialog(Dialog dialog, int style) {
+        switch (style) {
+            case STYLE_NO_INPUT:
+                dialog.getWindow().addFlags(
+                        WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
+                                WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
+                // fall through...
+            case STYLE_NO_FRAME:
+            case STYLE_NO_TITLE:
+                dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
+        }
+    }
     
     /**
      * Override to build your own custom Dialog container.  This is typically
diff --git a/v4/java/android/support/v4/app/Fragment.java b/v4/java/android/support/v4/app/Fragment.java
index eb6ab0d..d61f900 100644
--- a/v4/java/android/support/v4/app/Fragment.java
+++ b/v4/java/android/support/v4/app/Fragment.java
@@ -22,11 +22,10 @@
 import android.content.Intent;
 import android.content.res.Configuration;
 import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.os.Build;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.support.annotation.StringRes;
 import android.support.v4.util.SimpleArrayMap;
@@ -89,20 +88,21 @@
         mArguments = in.readBundle();
         mSavedFragmentState = in.readBundle();
     }
-    
-    public Fragment instantiate(FragmentActivity activity, Fragment parent) {
+
+    public Fragment instantiate(FragmentHostCallback host, Fragment parent) {
         if (mInstance != null) {
             return mInstance;
         }
-        
+
+        final Context context = host.getContext();
         if (mArguments != null) {
-            mArguments.setClassLoader(activity.getClassLoader());
+            mArguments.setClassLoader(context.getClassLoader());
         }
-        
-        mInstance = Fragment.instantiate(activity, mClassName, mArguments);
-        
+
+        mInstance = Fragment.instantiate(context, mClassName, mArguments);
+
         if (mSavedFragmentState != null) {
-            mSavedFragmentState.setClassLoader(activity.getClassLoader());
+            mSavedFragmentState.setClassLoader(context.getClassLoader());
             mInstance.mSavedFragmentState = mSavedFragmentState;
         }
         mInstance.setIndex(mIndex, parent);
@@ -113,14 +113,14 @@
         mInstance.mTag = mTag;
         mInstance.mRetainInstance = mRetainInstance;
         mInstance.mDetached = mDetached;
-        mInstance.mFragmentManager = activity.mFragments;
+        mInstance.mFragmentManager = host.mFragmentManager;
 
         if (FragmentManagerImpl.DEBUG) Log.v(FragmentManagerImpl.TAG,
                 "Instantiated fragment " + mInstance);
 
         return mInstance;
     }
-    
+
     public int describeContents() {
         return 0;
     }
@@ -228,17 +228,17 @@
 
     // True if this fragment has been restored from previously saved state.
     boolean mRestored;
-    
+
     // Number of active back stack entries this fragment is in.
     int mBackStackNesting;
-    
+
     // The fragment manager we are associated with.  Set as soon as the
     // fragment is used in a transaction; cleared after it has been removed
     // from all transactions.
     FragmentManagerImpl mFragmentManager;
 
-    // Activity this fragment is attached to.
-    FragmentActivity mActivity;
+    // Host this fragment is attached to.
+    FragmentHostCallback mHost;
 
     // Private fragment manager for child fragments inside of this one.
     FragmentManagerImpl mChildFragmentManager;
@@ -348,10 +348,12 @@
 
         public static final Parcelable.Creator<SavedState> CREATOR
                 = new Parcelable.Creator<SavedState>() {
+            @Override
             public SavedState createFromParcel(Parcel in) {
                 return new SavedState(in, null);
             }
 
+            @Override
             public SavedState[] newArray(int size) {
                 return new SavedState[size];
             }
@@ -606,22 +608,39 @@
     }
 
     /**
-     * Return the Activity this fragment is currently associated with.
+     * Return the {@link Context} this fragment is currently associated with.
+     */
+    public Context getContext() {
+        return mHost == null ? null : mHost.getContext();
+    }
+
+    /**
+     * Return the {@link FragmentActivity} this fragment is currently associated with.
+     * May return {@code null} if the fragment is associated with a {@link Context}
+     * instead.
      */
     final public FragmentActivity getActivity() {
-        return mActivity;
+        return mHost == null ? null : (FragmentActivity) mHost.getActivity();
     }
-    
+
+    /**
+     * Return the host object of this fragment. May return {@code null} if the fragment
+     * isn't currently being hosted.
+     */
+    final public Object getHost() {
+        return mHost == null ? null : mHost.onGetHost();
+    }
+
     /**
      * Return <code>getActivity().getResources()</code>.
      */
     final public Resources getResources() {
-        if (mActivity == null) {
+        if (mHost == null) {
             throw new IllegalStateException("Fragment " + this + " not attached to Activity");
         }
-        return mActivity.getResources();
+        return mHost.getContext().getResources();
     }
-    
+
     /**
      * Return a localized, styled CharSequence from the application's package's
      * default string table.
@@ -701,7 +720,7 @@
      * Return true if the fragment is currently added to its activity.
      */
     final public boolean isAdded() {
-        return mActivity != null && mAdded;
+        return mHost != null && mAdded;
     }
 
     /**
@@ -812,14 +831,14 @@
      * Report that this fragment would like to participate in populating
      * the options menu by receiving a call to {@link #onCreateOptionsMenu}
      * and related methods.
-     * 
+     *
      * @param hasMenu If true, the fragment has menu items to contribute.
      */
     public void setHasOptionsMenu(boolean hasMenu) {
         if (mHasMenu != hasMenu) {
             mHasMenu = hasMenu;
             if (isAdded() && !isHidden()) {
-                mActivity.supportInvalidateOptionsMenu();
+                mHost.onSupportInvalidateOptionsMenu();
             }
         }
     }
@@ -837,7 +856,7 @@
         if (mMenuVisible != menuVisible) {
             mMenuVisible = menuVisible;
             if (mHasMenu && isAdded() && !isHidden()) {
-                mActivity.supportInvalidateOptionsMenu();
+                mHost.onSupportInvalidateOptionsMenu();
             }
         }
     }
@@ -878,42 +897,42 @@
         if (mLoaderManager != null) {
             return mLoaderManager;
         }
-        if (mActivity == null) {
+        if (mHost == null) {
             throw new IllegalStateException("Fragment " + this + " not attached to Activity");
         }
         mCheckedForLoaderManager = true;
-        mLoaderManager = mActivity.getLoaderManager(mWho, mLoadersStarted, true);
+        mLoaderManager = mHost.getLoaderManager(mWho, mLoadersStarted, true);
         return mLoaderManager;
     }
-    
+
     /**
-     * Call {@link Activity#startActivity(Intent)} on the fragment's
+     * Call {@link Activity#startActivity(Intent)} from the fragment's
      * containing Activity.
      */
     public void startActivity(Intent intent) {
-        if (mActivity == null) {
+        if (mHost == null) {
             throw new IllegalStateException("Fragment " + this + " not attached to Activity");
         }
-        mActivity.startActivityFromFragment(this, intent, -1);
+        mHost.onStartActivityFromFragment(this /*fragment*/, intent, -1);
     }
-    
+
     /**
-     * Call {@link Activity#startActivityForResult(Intent, int)} on the fragment's
+     * Call {@link Activity#startActivityForResult(Intent, int)} from the fragment's
      * containing Activity.
      */
     public void startActivityForResult(Intent intent, int requestCode) {
-        if (mActivity == null) {
+        if (mHost == null) {
             throw new IllegalStateException("Fragment " + this + " not attached to Activity");
         }
-        mActivity.startActivityFromFragment(this, intent, requestCode);
+        mHost.onStartActivityFromFragment(this /*fragment*/, intent, requestCode);
     }
-    
+
     /**
      * Receive the result from a previous call to
      * {@link #startActivityForResult(Intent, int)}.  This follows the
      * related Activity API as described there in
      * {@link Activity#onActivityResult(int, int, Intent)}.
-     * 
+     *
      * @param requestCode The integer request code originally supplied to
      *                    startActivityForResult(), allowing you to identify who this
      *                    result came from.
@@ -924,19 +943,137 @@
      */
     public void onActivityResult(int requestCode, int resultCode, Intent data) {
     }
-    
+
+    /**
+     * Requests permissions to be granted to this application. These permissions
+     * must be requested in your manifest, they should not be granted to your app,
+     * and they should have protection level {@link android.content.pm.PermissionInfo
+     * #PROTECTION_DANGEROUS dangerous}, regardless whether they are declared by
+     * the platform or a third-party app.
+     * <p>
+     * Normal permissions {@link android.content.pm.PermissionInfo#PROTECTION_NORMAL}
+     * are granted at install time if requested in the manifest. Signature permissions
+     * {@link android.content.pm.PermissionInfo#PROTECTION_SIGNATURE} are granted at
+     * install time if requested in the manifest and the signature of your app matches
+     * the signature of the app declaring the permissions.
+     * </p>
+     * <p>
+     * If your app does not have the requested permissions the user will be presented
+     * with UI for accepting them. After the user has accepted or rejected the
+     * requested permissions you will receive a callback on {@link
+     * #onRequestPermissionsResult(int, String[], int[])} reporting whether the
+     * permissions were granted or not.
+     * </p>
+     * <p>
+     * Note that requesting a permission does not guarantee it will be granted and
+     * your app should be able to run without having this permission.
+     * </p>
+     * <p>
+     * This method may start an activity allowing the user to choose which permissions
+     * to grant and which to reject. Hence, you should be prepared that your activity
+     * may be paused and resumed. Further, granting some permissions may require
+     * a restart of you application. In such a case, the system will recreate the
+     * activity stack before delivering the result to {@link
+     * #onRequestPermissionsResult(int, String[], int[])}.
+     * </p>
+     * <p>
+     * When checking whether you have a permission you should use {@link
+     * android.content.Context#checkSelfPermission(String)}.
+     * </p>
+     * <p>
+     * A sample permissions request looks like this:
+     * </p>
+     * <code><pre><p>
+     * private void showContacts() {
+     *     if (getActivity().checkSelfPermission(Manifest.permission.READ_CONTACTS)
+     *             != PackageManager.PERMISSION_GRANTED) {
+     *         requestPermissions(new String[]{Manifest.permission.READ_CONTACTS},
+     *                 PERMISSIONS_REQUEST_READ_CONTACTS);
+     *     } else {
+     *         doShowContacts();
+     *     }
+     * }
+     *
+     * {@literal @}Override
+     * public void onRequestPermissionsResult(int requestCode, String[] permissions,
+     *         int[] grantResults) {
+     *     if (requestCode == PERMISSIONS_REQUEST_READ_CONTACTS
+     *             && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+     *         doShowContacts();
+     *     }
+     * }
+     * </code></pre></p>
+     *
+     * @param permissions The requested permissions.
+     * @param requestCode Application specific request code to match with a result
+     *    reported to {@link #onRequestPermissionsResult(int, String[], int[])}.
+     *
+     * @see #onRequestPermissionsResult(int, String[], int[])
+     * @see android.content.Context#checkSelfPermission(String)
+     */
+    public final void requestPermissions(@NonNull String[] permissions, int requestCode) {
+        if (mHost == null) {
+            throw new IllegalStateException("Fragment " + this + " not attached to Activity");
+        }
+        mHost.onRequestPermissionsFromFragment(this, permissions,requestCode);
+    }
+
+    /**
+     * Callback for the result from requesting permissions. This method
+     * is invoked for every call on {@link #requestPermissions(String[], int)}.
+     *
+     * @param requestCode The request code passed in {@link #requestPermissions(String[], int)}.
+     * @param permissions The requested permissions. Never null.
+     * @param grantResults The grant results for the corresponding permissions
+     *     which is either {@link android.content.pm.PackageManager#PERMISSION_GRANTED}
+     *     or {@link android.content.pm.PackageManager#PERMISSION_DENIED}. Never null.
+     *
+     * @see #requestPermissions(String[], int)
+     */
+    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
+            @NonNull int[] grantResults) {
+        /* callback - do nothing */
+    }
+
+    /**
+     * Gets whether you should show UI with rationale for requesting a permission.
+     * You should do this only if you do not have the permission and the context in
+     * which the permission is requested does not clearly communicate to the user
+     * what would be the benefit from granting this permission.
+     * <p>
+     * For example, if you write a camera app, requesting the camera permission
+     * would be expected by the user and no rationale for why it is requested is
+     * needed. If however, the app needs location for tagging photos then a non-tech
+     * savvy user may wonder how location is related to taking photos. In this case
+     * you may choose to show UI with rationale of requesting this permission.
+     * </p>
+     *
+     * @param permission A permission your app wants to request.
+     * @return Whether you can show permission rationale UI.
+     *
+     * @see Context#checkSelfPermission(String)
+     * @see #requestPermissions(String[], int)
+     * @see #onRequestPermissionsResult(int, String[], int[])
+     */
+    public boolean shouldShowRequestPermissionRationale(@NonNull String permission) {
+        if (mHost != null) {
+            return mHost.onShouldShowRequestPermissionRationale(permission);
+        }
+        return false;
+    }
+
     /**
      * @hide Hack so that DialogFragment can make its Dialog before creating
      * its views, and the view construction can use the dialog's context for
      * inflation.  Maybe this should become a public API. Note sure.
      */
     public LayoutInflater getLayoutInflater(Bundle savedInstanceState) {
-        LayoutInflater result = mActivity.getLayoutInflater().cloneInContext(mActivity);
+        LayoutInflater result = mHost.onGetLayoutInflater();
         getChildFragmentManager(); // Init if needed; use raw implementation below.
         LayoutInflaterCompat.setFactory(result, mChildFragmentManager.getLayoutInflaterFactory());
         return result;
     }
-    
+
     /**
      * Called when a fragment is being created as part of a view layout
      * inflation, typically from setting the content view of an activity.  This
@@ -973,31 +1110,61 @@
      * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentArguments.java
      *      create}
      *
-     * @param activity The Activity that is inflating this fragment.
+     * @param context The Activity that is inflating this fragment.
      * @param attrs The attributes at the tag where the fragment is
      * being created.
      * @param savedInstanceState If the fragment is being re-created from
      * a previous saved state, this is the state.
      */
+    public void onInflate(Context context, AttributeSet attrs, Bundle savedInstanceState) {
+        mCalled = true;
+        final Activity hostActivity = mHost == null ? null : mHost.getActivity();
+        if (hostActivity != null) {
+            mCalled = false;
+            onInflate(hostActivity, attrs, savedInstanceState);
+        }
+    }
+
+    /**
+     * Called when a fragment is being created as part of a view layout
+     * inflation, typically from setting the content view of an activity.
+     * <p>Deprecated. See {@link #onInflate(Context, AttributeSet, Bundle)}.
+     */
+    @Deprecated
     public void onInflate(Activity activity, AttributeSet attrs, Bundle savedInstanceState) {
         mCalled = true;
     }
 
     /**
-     * Called when a fragment is first attached to its activity.
+     * Called when a fragment is first attached to its context.
      * {@link #onCreate(Bundle)} will be called after this.
      */
+    public void onAttach(Context context) {
+        mCalled = true;
+        final Activity hostActivity = mHost == null ? null : mHost.getActivity();
+        if (hostActivity != null) {
+            mCalled = false;
+            onAttach(hostActivity);
+        }
+    }
+
+    /**
+     * Called when a fragment is first attached to its activity.
+     * {@link #onCreate(Bundle)} will be called after this.
+     * <p>Deprecated. See {@link #onAttach(Context)}.
+     */
+    @Deprecated
     public void onAttach(Activity activity) {
         mCalled = true;
     }
-    
+
     /**
      * Called when a fragment loads an animation.
      */
     public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) {
         return null;
     }
-    
+
     /**
      * Called to do initial creation of a fragment.  This is called after
      * {@link #onAttach(Activity)} and before
@@ -1104,19 +1271,19 @@
      */
     public void onStart() {
         mCalled = true;
-        
+
         if (!mLoadersStarted) {
             mLoadersStarted = true;
             if (!mCheckedForLoaderManager) {
                 mCheckedForLoaderManager = true;
-                mLoaderManager = mActivity.getLoaderManager(mWho, mLoadersStarted, false);
+                mLoaderManager = mHost.getLoaderManager(mWho, mLoadersStarted, false);
             }
             if (mLoaderManager != null) {
                 mLoaderManager.doStart();
             }
         }
     }
-    
+
     /**
      * Called when the fragment is visible to the user and actively running.
      * This is generally
@@ -1198,7 +1365,7 @@
         //        + " mLoaderManager=" + mLoaderManager);
         if (!mCheckedForLoaderManager) {
             mCheckedForLoaderManager = true;
-            mLoaderManager = mActivity.getLoaderManager(mWho, mLoadersStarted, false);
+            mLoaderManager = mHost.getLoaderManager(mWho, mLoadersStarted, false);
         }
         if (mLoaderManager != null) {
             mLoaderManager.doDestroy();
@@ -1223,7 +1390,7 @@
         mBackStackNesting = 0;
         mFragmentManager = null;
         mChildFragmentManager = null;
-        mActivity = null;
+        mHost = null;
         mFragmentId = 0;
         mContainerId = 0;
         mTag = null;
@@ -1335,6 +1502,7 @@
      * It is not safe to hold onto the context menu after this method returns.
      * {@inheritDoc}
      */
+    @Override
     public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
         getActivity().onCreateContextMenu(menu, v, menuInfo);
     }
@@ -1678,9 +1846,9 @@
             writer.print(prefix); writer.print("mFragmentManager=");
                     writer.println(mFragmentManager);
         }
-        if (mActivity != null) {
-            writer.print(prefix); writer.print("mActivity=");
-                    writer.println(mActivity);
+        if (mHost != null) {
+            writer.print(prefix); writer.print("mHost=");
+                    writer.println(mHost);
         }
         if (mParentFragment != null) {
             writer.print(prefix); writer.print("mParentFragment=");
@@ -1741,10 +1909,10 @@
 
     void instantiateChildFragmentManager() {
         mChildFragmentManager = new FragmentManagerImpl();
-        mChildFragmentManager.attachActivity(mActivity, new FragmentContainer() {
+        mChildFragmentManager.attachController(mHost, new FragmentContainer() {
             @Override
             @Nullable
-            public View findViewById(int id) {
+            public View onFindViewById(int id) {
                 if (mView == null) {
                     throw new IllegalStateException("Fragment does not have a view");
                 }
@@ -1752,7 +1920,7 @@
             }
 
             @Override
-            public boolean hasView() {
+            public boolean onHasView() {
                 return (mView != null);
             }
         }, this);
@@ -1974,10 +2142,10 @@
             mLoadersStarted = false;
             if (!mCheckedForLoaderManager) {
                 mCheckedForLoaderManager = true;
-                mLoaderManager = mActivity.getLoaderManager(mWho, mLoadersStarted, false);
+                mLoaderManager = mHost.getLoaderManager(mWho, mLoadersStarted, false);
             }
             if (mLoaderManager != null) {
-                if (!mActivity.mRetaining) {
+                if (!mRetaining) {
                     mLoaderManager.doStop();
                 } else {
                     mLoaderManager.doRetain();
diff --git a/v4/java/android/support/v4/app/FragmentActivity.java b/v4/java/android/support/v4/app/FragmentActivity.java
index 29c6f56..9a0489c 100644
--- a/v4/java/android/support/v4/app/FragmentActivity.java
+++ b/v4/java/android/support/v4/app/FragmentActivity.java
@@ -31,6 +31,7 @@
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.KeyEvent;
+import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.View;
@@ -40,6 +41,7 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.List;
 
 /**
  * Base class for activities that want to use the support-based
@@ -73,11 +75,13 @@
  * state, this may be a snapshot slightly before what the user last saw.</p>
  * </ul>
  */
-public class FragmentActivity extends BaseFragmentActivityHoneycomb {
+public class FragmentActivity extends BaseFragmentActivityHoneycomb implements
+        ActivityCompat.OnRequestPermissionsResultCallback,
+        ActivityCompatApi23.RequestPermissionsRequestCodeValidator {
     private static final String TAG = "FragmentActivity";
-    
+
     static final String FRAGMENTS_TAG = "android:support:fragments";
-    
+
     // This is the SDK API version of Honeycomb (3.0).
     private static final int HONEYCOMB = 11;
 
@@ -103,21 +107,8 @@
         }
 
     };
-    final FragmentManagerImpl mFragments = new FragmentManagerImpl();
-    final FragmentContainer mContainer = new FragmentContainer() {
-        @Override
-        @Nullable
-        public View findViewById(int id) {
-            return FragmentActivity.this.findViewById(id);
-        }
+    final FragmentController mFragments = FragmentController.createController(new HostCallbacks());
 
-        @Override
-        public boolean hasView() {
-            Window window = FragmentActivity.this.getWindow();
-            return (window != null && window.peekDecorView() != null);
-        }
-    };
-    
     boolean mCreated;
     boolean mResumed;
     boolean mStopped;
@@ -125,24 +116,18 @@
     boolean mRetaining;
 
     boolean mOptionsMenuInvalidated;
-
-    boolean mCheckedForLoaderManager;
-    boolean mLoadersStarted;
-    SimpleArrayMap<String, LoaderManagerImpl> mAllLoaderManagers;
-    LoaderManagerImpl mLoaderManager;
+    boolean mRequestedPermissionsFromFragment;
 
     static final class NonConfigurationInstances {
-        Object activity;
         Object custom;
-        SimpleArrayMap<String, Object> children;
-        ArrayList<Fragment> fragments;
-        SimpleArrayMap<String, LoaderManagerImpl> loaders;
+        List<Fragment> fragments;
+        SimpleArrayMap<String, LoaderManager> loaders;
     }
-    
+
     // ------------------------------------------------------------------------
     // HOOKS INTO ACTIVITY
     // ------------------------------------------------------------------------
-    
+
     /**
      * Dispatch incoming result to the correct fragment.
      */
@@ -152,12 +137,15 @@
         int index = requestCode>>16;
         if (index != 0) {
             index--;
-            if (mFragments.mActive == null || index < 0 || index >= mFragments.mActive.size()) {
+            final int activeFragmentsCount = mFragments.getActiveFragmentsCount();
+            if (activeFragmentsCount == 0 || index < 0 || index >= activeFragmentsCount) {
                 Log.w(TAG, "Activity result fragment index out of range: 0x"
                         + Integer.toHexString(requestCode));
                 return;
             }
-            Fragment frag = mFragments.mActive.get(index);
+            final List<Fragment> activeFragments =
+                    mFragments.getActiveFragments(new ArrayList<Fragment>(activeFragmentsCount));
+            Fragment frag = activeFragments.get(index);
             if (frag == null) {
                 Log.w(TAG, "Activity result no fragment exists for index: 0x"
                         + Integer.toHexString(requestCode));
@@ -166,7 +154,7 @@
             }
             return;
         }
-        
+
         super.onActivityResult(requestCode, resultCode, data);
     }
 
@@ -175,7 +163,7 @@
      * as appropriate.
      */
     public void onBackPressed() {
-        if (!mFragments.popBackStackImmediate()) {
+        if (!mFragments.getSupportFragmentManager().popBackStackImmediate()) {
             supportFinishAfterTransition();
         }
     }
@@ -246,16 +234,17 @@
     /**
      * Perform initialization of all fragments and loaders.
      */
+    @SuppressWarnings("deprecation")
     @Override
     protected void onCreate(@Nullable Bundle savedInstanceState) {
-        mFragments.attachActivity(this, mContainer, null);
-        
+        mFragments.attachHost(null /*parent*/);
+
         super.onCreate(savedInstanceState);
-        
-        NonConfigurationInstances nc = (NonConfigurationInstances)
-                getLastNonConfigurationInstance();
+
+        NonConfigurationInstances nc =
+                (NonConfigurationInstances) getLastNonConfigurationInstance();
         if (nc != null) {
-            mAllLoaderManagers = nc.loaders;
+            mFragments.restoreLoaderNonConfig(nc.loaders);
         }
         if (savedInstanceState != null) {
             Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);
@@ -299,9 +288,7 @@
         doReallyStop(false);
 
         mFragments.dispatchDestroy();
-        if (mLoaderManager != null) {
-            mLoaderManager.doDestroy();
-        }
+        mFragments.doLoaderDestroy();
     }
 
     /**
@@ -470,36 +457,17 @@
 
         Object custom = onRetainCustomNonConfigurationInstance();
 
-        ArrayList<Fragment> fragments = mFragments.retainNonConfig();
-        boolean retainLoaders = false;
-        if (mAllLoaderManagers != null) {
-            // prune out any loader managers that were already stopped and so
-            // have nothing useful to retain.
-            final int N = mAllLoaderManagers.size();
-            LoaderManagerImpl loaders[] = new LoaderManagerImpl[N];
-            for (int i=N-1; i>=0; i--) {
-                loaders[i] = mAllLoaderManagers.valueAt(i);
-            }
-            for (int i=0; i<N; i++) {
-                LoaderManagerImpl lm = loaders[i];
-                if (lm.mRetaining) {
-                    retainLoaders = true;
-                } else {
-                    lm.doDestroy();
-                    mAllLoaderManagers.remove(lm.mWho);
-                }
-            }
-        }
-        if (fragments == null && !retainLoaders && custom == null) {
+        List<Fragment> fragments = mFragments.retainNonConfig();
+        SimpleArrayMap<String, LoaderManager> loaders = mFragments.retainLoaderNonConfig();
+
+        if (fragments == null && loaders == null && custom == null) {
             return null;
         }
-        
+
         NonConfigurationInstances nci = new NonConfigurationInstances();
-        nci.activity = null;
         nci.custom = custom;
-        nci.children = null;
         nci.fragments = fragments;
-        nci.loaders = mAllLoaderManagers;
+        nci.loaders = loaders;
         return nci;
     }
 
@@ -534,35 +502,13 @@
 
         mFragments.noteStateNotSaved();
         mFragments.execPendingActions();
-        
-        if (!mLoadersStarted) {
-            mLoadersStarted = true;
-            if (mLoaderManager != null) {
-                mLoaderManager.doStart();
-            } else if (!mCheckedForLoaderManager) {
-                mLoaderManager = getLoaderManager("(root)", mLoadersStarted, false);
-                // the returned loader manager may be a new one, so we have to start it
-                if ((mLoaderManager != null) && (!mLoaderManager.mStarted)) {
-                    mLoaderManager.doStart();
-                }
-            }
-            mCheckedForLoaderManager = true;
-        }
+
+        mFragments.doLoaderStart();
+
         // NOTE: HC onStart goes here.
-        
+
         mFragments.dispatchStart();
-        if (mAllLoaderManagers != null) {
-            final int N = mAllLoaderManagers.size();
-            LoaderManagerImpl loaders[] = new LoaderManagerImpl[N];
-            for (int i=N-1; i>=0; i--) {
-                loaders[i] = mAllLoaderManagers.valueAt(i);
-            }
-            for (int i=0; i<N; i++) {
-                LoaderManagerImpl lm = loaders[i];
-                lm.finishRetain();
-                lm.doReportStart();
-            }
-        }
+        mFragments.reportLoaderStart();
     }
 
     /**
@@ -574,14 +520,14 @@
 
         mStopped = true;
         mHandler.sendEmptyMessage(MSG_REALLY_STOPPED);
-        
+
         mFragments.dispatchStop();
     }
 
     // ------------------------------------------------------------------------
     // NEW METHODS
     // ------------------------------------------------------------------------
-    
+
     /**
      * Use this instead of {@link #onRetainNonConfigurationInstance()}.
      * Retrieve later with {@link #getLastCustomNonConfigurationInstance()}.
@@ -594,6 +540,7 @@
      * Return the value previously returned from
      * {@link #onRetainCustomNonConfigurationInstance()}.
      */
+    @SuppressWarnings("deprecation")
     public Object getLastCustomNonConfigurationInstance() {
         NonConfigurationInstances nc = (NonConfigurationInstances)
                 getLastNonConfigurationInstance();
@@ -644,15 +591,8 @@
                 writer.print(mResumed); writer.print(" mStopped=");
                 writer.print(mStopped); writer.print(" mReallyStopped=");
                 writer.println(mReallyStopped);
-        writer.print(innerPrefix); writer.print("mLoadersStarted=");
-                writer.println(mLoadersStarted);
-        if (mLoaderManager != null) {
-            writer.print(prefix); writer.print("Loader Manager ");
-                    writer.print(Integer.toHexString(System.identityHashCode(mLoaderManager)));
-                    writer.println(":");
-            mLoaderManager.dump(prefix + "  ", fd, writer, args);
-        }
-        mFragments.dump(prefix, fd, writer, args);
+        mFragments.dumpLoaders(innerPrefix, fd, writer, args);
+        mFragments.getSupportFragmentManager().dump(prefix, fd, writer, args);
         writer.print(prefix); writer.println("View Hierarchy:");
         dumpViewHierarchy(prefix + "  ", writer, getWindow().getDecorView());
     }
@@ -761,16 +701,7 @@
      * tell us what we need to know.
      */
     void onReallyStop() {
-        if (mLoadersStarted) {
-            mLoadersStarted = false;
-            if (mLoaderManager != null) {
-                if (!mRetaining) {
-                    mLoaderManager.doStop();
-                } else {
-                    mLoaderManager.doRetain();
-                }
-            }
-        }
+        mFragments.doLoaderStop(mRetaining);
 
         mFragments.dispatchReallyStop();
     }
@@ -778,19 +709,24 @@
     // ------------------------------------------------------------------------
     // FRAGMENT SUPPORT
     // ------------------------------------------------------------------------
-    
+
     /**
      * Called when a fragment is attached to the activity.
      */
+    @SuppressWarnings("unused")
     public void onAttachFragment(Fragment fragment) {
     }
-    
+
     /**
      * Return the FragmentManager for interacting with fragments associated
      * with this activity.
      */
     public FragmentManager getSupportFragmentManager() {
-        return mFragments;
+        return mFragments.getSupportFragmentManager();
+    }
+
+    public LoaderManager getSupportLoaderManager() {
+        return mFragments.getSupportLoaderManager();
     }
 
     /**
@@ -805,10 +741,61 @@
         super.startActivityForResult(intent, requestCode);
     }
 
+    @Override
+    public final void validateRequestPermissionsRequestCode(int requestCode) {
+        // We use 8 bits of the request code to encode the fragment id when
+        // requesting permissions from a fragment. Hence, requestPermissions()
+        // should validate the code against that but we cannot override it as
+        // we can not then call super and also the ActivityCompat would call
+        // back to this override. To handle this we use dependency inversion
+        // where we are the validator of request codes when requesting
+        // permissions in ActivityCompat.
+        if (mRequestedPermissionsFromFragment) {
+            mRequestedPermissionsFromFragment = false;
+        } else if ((requestCode & 0xffffff00) != 0) {
+            throw new IllegalArgumentException("Can only use lower 8 bits for requestCode");
+        }
+    }
+
+    /**
+     * Callback for the result from requesting permissions. This method
+     * is invoked for every call on {@link #requestPermissions(String[], int)}.
+     *
+     * @param requestCode The request code passed in {@link #requestPermissions(String[], int)}.
+     * @param permissions The requested permissions. Never null.
+     * @param grantResults The grant results for the corresponding permissions
+     *     which is either {@link android.content.pm.PackageManager#PERMISSION_GRANTED}
+     *     or {@link android.content.pm.PackageManager#PERMISSION_DENIED}. Never null.
+     *
+     * @see #requestPermissions(String[], int)
+     */
+    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
+            @NonNull int[] grantResults) {
+        int index = (requestCode>>8)&0xff;
+        if (index != 0) {
+            index--;
+            final int activeFragmentsCount = mFragments.getActiveFragmentsCount();
+            if (activeFragmentsCount == 0 || index < 0 || index >= activeFragmentsCount) {
+                Log.w(TAG, "Activity result fragment index out of range: 0x"
+                        + Integer.toHexString(requestCode));
+                return;
+            }
+            final List<Fragment> activeFragments =
+                    mFragments.getActiveFragments(new ArrayList<Fragment>(activeFragmentsCount));
+            Fragment frag = activeFragments.get(index);
+            if (frag == null) {
+                Log.w(TAG, "Activity result no fragment exists for index: 0x"
+                        + Integer.toHexString(requestCode));
+            } else {
+                frag.onRequestPermissionsResult(requestCode&0xff, permissions, grantResults);
+            }
+        }
+    }
+
     /**
      * Called by Fragment.startActivityForResult() to implement its behavior.
      */
-    public void startActivityFromFragment(Fragment fragment, Intent intent, 
+    public void startActivityFromFragment(Fragment fragment, Intent intent,
             int requestCode) {
         if (requestCode == -1) {
             super.startActivityForResult(intent, -1);
@@ -819,47 +806,98 @@
         }
         super.startActivityForResult(intent, ((fragment.mIndex+1)<<16) + (requestCode&0xffff));
     }
-    
-    void invalidateSupportFragment(String who) {
-        //Log.v(TAG, "invalidateSupportFragment: who=" + who);
-        if (mAllLoaderManagers != null) {
-            LoaderManagerImpl lm = mAllLoaderManagers.get(who);
-            if (lm != null && !lm.mRetaining) {
-                lm.doDestroy();
-                mAllLoaderManagers.remove(who);
-            }
-        }
-    }
-    
-    // ------------------------------------------------------------------------
-    // LOADER SUPPORT
-    // ------------------------------------------------------------------------
-    
+
     /**
-     * Return the LoaderManager for this fragment, creating it if needed.
+     * Called by Fragment.requestPermissions() to implement its behavior.
      */
-    public LoaderManager getSupportLoaderManager() {
-        if (mLoaderManager != null) {
-            return mLoaderManager;
+    private void requestPermissionsFromFragment(Fragment fragment, String[] permissions,
+            int requestCode) {
+        if (requestCode == -1) {
+            ActivityCompat.requestPermissions(this, permissions, requestCode);
+            return;
         }
-        mCheckedForLoaderManager = true;
-        mLoaderManager = getLoaderManager("(root)", mLoadersStarted, true);
-        return mLoaderManager;
+        if ((requestCode&0xffffff00) != 0) {
+            throw new IllegalArgumentException("Can only use lower 8 bits for requestCode");
+        }
+        mRequestedPermissionsFromFragment = true;
+        ActivityCompat.requestPermissions(this, permissions,
+                ((fragment.mIndex + 1) << 8) + (requestCode & 0xff));
     }
-    
-    LoaderManagerImpl getLoaderManager(String who, boolean started, boolean create) {
-        if (mAllLoaderManagers == null) {
-            mAllLoaderManagers = new SimpleArrayMap<String, LoaderManagerImpl>();
+
+    class HostCallbacks extends FragmentHostCallback<FragmentActivity> {
+        public HostCallbacks() {
+            super(FragmentActivity.this /*fragmentActivity*/);
         }
-        LoaderManagerImpl lm = mAllLoaderManagers.get(who);
-        if (lm == null) {
-            if (create) {
-                lm = new LoaderManagerImpl(who, this, started);
-                mAllLoaderManagers.put(who, lm);
-            }
-        } else {
-            lm.updateActivity(this);
+
+        @Override
+        public void onDump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
+            FragmentActivity.this.dump(prefix, fd, writer, args);
         }
-        return lm;
+
+        @Override
+        public boolean onShouldSaveFragmentState(Fragment fragment) {
+            return !isFinishing();
+        }
+
+        @Override
+        public LayoutInflater onGetLayoutInflater() {
+            return FragmentActivity.this.getLayoutInflater().cloneInContext(FragmentActivity.this);
+        }
+
+        @Override
+        public FragmentActivity onGetHost() {
+            return FragmentActivity.this;
+        }
+
+        @Override
+        public void onSupportInvalidateOptionsMenu() {
+            FragmentActivity.this.supportInvalidateOptionsMenu();
+        }
+
+        @Override
+        public void onStartActivityFromFragment(Fragment fragment, Intent intent, int requestCode) {
+            FragmentActivity.this.startActivityFromFragment(fragment, intent, requestCode);
+        }
+
+        @Override
+        public void onRequestPermissionsFromFragment(@NonNull Fragment fragment,
+                @NonNull String[] permissions, int requestCode) {
+            FragmentActivity.this.requestPermissionsFromFragment(fragment, permissions,
+                    requestCode);
+        }
+
+        @Override
+        public boolean onShouldShowRequestPermissionRationale(@NonNull String permission) {
+            return ActivityCompat.shouldShowRequestPermissionRationale(
+                    FragmentActivity.this, permission);
+        }
+
+        @Override
+        public boolean onHasWindowAnimations() {
+            return getWindow() != null;
+        }
+
+        @Override
+        public int onGetWindowAnimations() {
+            final Window w = getWindow();
+            return (w == null) ? 0 : w.getAttributes().windowAnimations;
+        }
+
+        @Override
+        public void onAttachFragment(Fragment fragment) {
+            FragmentActivity.this.onAttachFragment(fragment);
+        }
+
+        @Nullable
+        @Override
+        public View onFindViewById(int id) {
+            return FragmentActivity.this.findViewById(id);
+        }
+
+        @Override
+        public boolean onHasView() {
+            final Window w = getWindow();
+            return (w != null && w.peekDecorView() != null);
+        }
     }
 }
diff --git a/v4/java/android/support/v4/app/FragmentContainer.java b/v4/java/android/support/v4/app/FragmentContainer.java
new file mode 100644
index 0000000..1367540
--- /dev/null
+++ b/v4/java/android/support/v4/app/FragmentContainer.java
@@ -0,0 +1,23 @@
+package android.support.v4.app;
+
+import android.support.annotation.IdRes;
+import android.support.annotation.Nullable;
+import android.view.View;
+
+
+/**
+ * Callbacks to a {@link Fragment}'s container.
+ */
+public abstract class FragmentContainer {
+    /**
+     * Return the view with the given resource ID. May return {@code null} if the
+     * view is not a child of this container.
+     */
+    @Nullable
+    public abstract View onFindViewById(@IdRes int id);
+
+    /**
+     * Return {@code true} if the container holds any view.
+     */
+    public abstract boolean onHasView();
+}
diff --git a/v4/java/android/support/v4/app/FragmentController.java b/v4/java/android/support/v4/app/FragmentController.java
new file mode 100644
index 0000000..5d647b0
--- /dev/null
+++ b/v4/java/android/support/v4/app/FragmentController.java
@@ -0,0 +1,396 @@
+/*
+ * 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.v4.app;
+
+import android.content.Context;
+import android.content.res.Configuration;
+import android.os.Parcelable;
+import android.support.v4.util.SimpleArrayMap;
+import android.util.AttributeSet;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Provides integration points with a {@link FragmentManager} for a fragment host.
+ * <p>
+ * It is the responsibility of the host to take care of the Fragment's lifecycle.
+ * The methods provided by {@link FragmentController} are for that purpose.
+ */
+public class FragmentController {
+    private final FragmentHostCallback<?> mHost;
+
+    /**
+     * Returns a {@link FragmentController}.
+     */
+    public static final FragmentController createController(FragmentHostCallback<?> callbacks) {
+        return new FragmentController(callbacks);
+    }
+
+    private FragmentController(FragmentHostCallback<?> callbacks) {
+        mHost = callbacks;
+    }
+
+    /**
+     * Returns a {@link FragmentManager} for this controller.
+     */
+    public FragmentManager getSupportFragmentManager() {
+        return mHost.getFragmentManagerImpl();
+    }
+
+    /**
+     * Returns a {@link LoaderManager}.
+     */
+    public LoaderManager getSupportLoaderManager() {
+        return mHost.getLoaderManagerImpl();
+    }
+
+    /**
+     * Returns the number of active fragments. 
+     */
+    public int getActiveFragmentsCount() {
+        final List<Fragment> actives = mHost.mFragmentManager.mActive;
+        return actives == null ? 0 : actives.size();
+    }
+
+    /**
+     * Returns the list of active fragments.
+     */
+    public List<Fragment> getActiveFragments(List<Fragment> actives) {
+        if (mHost.mFragmentManager.mActive == null) {
+            return null;
+        }
+        if (actives == null) {
+            actives = new ArrayList<Fragment>(getActiveFragmentsCount());
+        }
+        actives.addAll(mHost.mFragmentManager.mActive);
+        return actives;
+    }
+
+    /**
+     * Attaches the host to the FragmentManager for this controller. The host must be
+     * attached before the FragmentManager can be used to manage Fragments.
+     */
+    public void attachHost(Fragment parent) {
+        mHost.mFragmentManager.attachController(
+                mHost, mHost /*container*/, parent);
+    }
+
+    /**
+     * Instantiates a Fragment's view.
+     *
+     * @param parent The parent that the created view will be placed
+     * in; <em>note that this may be null</em>.
+     * @param name Tag name to be inflated.
+     * @param context The context the view is being created in.
+     * @param attrs Inflation attributes as specified in XML file.
+     *
+     * @return view the newly created view
+     */
+    public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
+        return mHost.mFragmentManager.onCreateView(parent, name, context, attrs);
+    }
+
+    /**
+     * Marks the fragment state as unsaved. This allows for "state loss" detection.
+     */
+    public void noteStateNotSaved() {
+        mHost.mFragmentManager.noteStateNotSaved();
+    }
+
+    /**
+     * Saves the state for all Fragments.
+     */
+    public Parcelable saveAllState() {
+        return mHost.mFragmentManager.saveAllState();
+    }
+
+    /**
+     * Restores the saved state for all Fragments. The given Fragment list are Fragment
+     * instances retained across configuration changes.
+     *
+     * @see #retainNonConfig()
+     */
+    public void restoreAllState(Parcelable state, List<Fragment> nonConfigList) {
+        mHost.mFragmentManager.restoreAllState(state, nonConfigList);
+    }
+
+    /**
+     * Returns a list of Fragments that have opted to retain their instance across
+     * configuration changes.
+     */
+    public List<Fragment> retainNonConfig() {
+        return mHost.mFragmentManager.retainNonConfig();
+    }
+
+    /**
+     * Moves all Fragments managed by the controller's FragmentManager
+     * into the create state.
+     * <p>Call when Fragments should be created.
+     *
+     * @see Fragment#onCreate(Bundle)
+     */
+    public void dispatchCreate() {
+        mHost.mFragmentManager.dispatchCreate();
+    }
+
+    /**
+     * Moves all Fragments managed by the controller's FragmentManager
+     * into the activity created state.
+     * <p>Call when Fragments should be informed their host has been created.
+     *
+     * @see Fragment#onActivityCreated(Bundle)
+     */
+    public void dispatchActivityCreated() {
+        mHost.mFragmentManager.dispatchActivityCreated();
+    }
+
+    /**
+     * Moves all Fragments managed by the controller's FragmentManager
+     * into the start state.
+     * <p>Call when Fragments should be started.
+     *
+     * @see Fragment#onStart()
+     */
+    public void dispatchStart() {
+        mHost.mFragmentManager.dispatchStart();
+    }
+
+    /**
+     * Moves all Fragments managed by the controller's FragmentManager
+     * into the resume state.
+     * <p>Call when Fragments should be resumed.
+     *
+     * @see Fragment#onResume()
+     */
+    public void dispatchResume() {
+        mHost.mFragmentManager.dispatchResume();
+    }
+
+    /**
+     * Moves all Fragments managed by the controller's FragmentManager
+     * into the pause state.
+     * <p>Call when Fragments should be paused.
+     *
+     * @see Fragment#onPause()
+     */
+    public void dispatchPause() {
+        mHost.mFragmentManager.dispatchPause();
+    }
+
+    /**
+     * Moves all Fragments managed by the controller's FragmentManager
+     * into the stop state.
+     * <p>Call when Fragments should be stopped.
+     *
+     * @see Fragment#onStop()
+     */
+    public void dispatchStop() {
+        mHost.mFragmentManager.dispatchStop();
+    }
+
+    public void dispatchReallyStop() {
+        mHost.mFragmentManager.dispatchReallyStop();
+    }
+
+    /**
+     * Moves all Fragments managed by the controller's FragmentManager
+     * into the destroy view state.
+     * <p>Call when the Fragment's views should be destroyed.
+     *
+     * @see Fragment#onDestroyView()
+     */
+    public void dispatchDestroyView() {
+        mHost.mFragmentManager.dispatchDestroyView();
+    }
+
+    /**
+     * Moves all Fragments managed by the controller's FragmentManager
+     * into the destroy state.
+     * <p>Call when Fragments should be destroyed.
+     *
+     * @see Fragment#onDestroy()
+     */
+    public void dispatchDestroy() {
+        mHost.mFragmentManager.dispatchDestroy();
+    }
+
+    /**
+     * Lets all Fragments managed by the controller's FragmentManager
+     * know a configuration change occurred.
+     * <p>Call when there is a configuration change.
+     *
+     * @see Fragment#onConfigurationChanged(Configuration)
+     */
+    public void dispatchConfigurationChanged(Configuration newConfig) {
+        mHost.mFragmentManager.dispatchConfigurationChanged(newConfig);
+    }
+
+    /**
+     * Lets all Fragments managed by the controller's FragmentManager
+     * know the device is in a low memory condition.
+     * <p>Call when the device is low on memory and Fragment's should trim
+     * their memory usage.
+     *
+     * @see Fragment#onLowMemory()
+     */
+    public void dispatchLowMemory() {
+        mHost.mFragmentManager.dispatchLowMemory();
+    }
+
+    /**
+     * Lets all Fragments managed by the controller's FragmentManager
+     * know they should create an options menu.
+     * <p>Call when the Fragment should create an options menu.
+     *
+     * @return {@code true} if the options menu contains items to display
+     * @see Fragment#onCreateOptionsMenu(Menu, MenuInflater)
+     */
+    public boolean dispatchCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+        return mHost.mFragmentManager.dispatchCreateOptionsMenu(menu, inflater);
+    }
+
+    /**
+     * Lets all Fragments managed by the controller's FragmentManager
+     * know they should prepare their options menu for display.
+     * <p>Call immediately before displaying the Fragment's options menu.
+     *
+     * @return {@code true} if the options menu contains items to display
+     * @see Fragment#onPrepareOptionsMenu(Menu)
+     */
+    public boolean dispatchPrepareOptionsMenu(Menu menu) {
+        return mHost.mFragmentManager.dispatchPrepareOptionsMenu(menu);
+    }
+
+    /**
+     * Sends an option item selection event to the Fragments managed by the
+     * controller's FragmentManager. Once the event has been consumed,
+     * no additional handling will be performed.
+     * <p>Call immediately after an options menu item has been selected
+     *
+     * @return {@code true} if the options menu selection event was consumed
+     * @see Fragment#onOptionsItemSelected(MenuItem)
+     */
+    public boolean dispatchOptionsItemSelected(MenuItem item) {
+        return mHost.mFragmentManager.dispatchOptionsItemSelected(item);
+    }
+
+    /**
+     * Sends a context item selection event to the Fragments managed by the
+     * controller's FragmentManager. Once the event has been consumed,
+     * no additional handling will be performed.
+     * <p>Call immediately after an options menu item has been selected
+     *
+     * @return {@code true} if the context menu selection event was consumed
+     * @see Fragment#onContextItemSelected(MenuItem)
+     */
+    public boolean dispatchContextItemSelected(MenuItem item) {
+        return mHost.mFragmentManager.dispatchContextItemSelected(item);
+    }
+
+    /**
+     * Lets all Fragments managed by the controller's FragmentManager
+     * know their options menu has closed.
+     * <p>Call immediately after closing the Fragment's options menu.
+     *
+     * @see Fragment#onOptionsMenuClosed(Menu)
+     */
+    public void dispatchOptionsMenuClosed(Menu menu) {
+        mHost.mFragmentManager.dispatchOptionsMenuClosed(menu);
+    }
+
+    /**
+     * Execute any pending actions for the Fragments managed by the
+     * controller's FragmentManager.
+     * <p>Call when queued actions can be performed [eg when the
+     * Fragment moves into a start or resume state].
+     * @return {@code true} if queued actions were performed
+     */
+    public boolean execPendingActions() {
+        return mHost.mFragmentManager.execPendingActions();
+    }
+
+    /**
+     * Starts the loaders.
+     */
+    public void doLoaderStart() {
+        mHost.doLoaderStart();
+    }
+
+    /**
+     * Stops the loaders, optionally retaining their state. This is useful for keeping the
+     * loader state across configuration changes.
+     *
+     * @param retain When {@code true}, the loaders aren't stopped, but, their instances
+     * are retained in a started state
+     */
+    public void doLoaderStop(boolean retain) {
+        mHost.doLoaderStop(retain);
+    }
+
+    /**
+     * Retains the state of each of the loaders.
+     */
+    public void doLoaderRetain() {
+        mHost.doLoaderRetain();
+    }
+
+    /**
+     * Destroys the loaders and, if their state is not being retained, removes them.
+     */
+    public void doLoaderDestroy() {
+        mHost.doLoaderDestroy();
+    }
+
+    /**
+     * Lets the loaders know the host is ready to receive notifications.
+     */
+    public void reportLoaderStart() {
+        mHost.reportLoaderStart();
+    }
+
+    /**
+     * Returns a list of LoaderManagers that have opted to retain their instance across
+     * configuration changes.
+     */
+    public SimpleArrayMap<String, LoaderManager> retainLoaderNonConfig() {
+        return mHost.retainLoaderNonConfig();
+    }
+
+    /**
+     * Restores the saved state for all LoaderManagers. The given LoaderManager list are
+     * LoaderManager instances retained across configuration changes.
+     *
+     * @see #retainLoaderNonConfig()
+     */
+    public void restoreLoaderNonConfig(SimpleArrayMap<String, LoaderManager> loaderManagers) {
+        mHost.restoreLoaderNonConfig(loaderManagers);
+    }
+
+    /**
+     * Dumps the current state of the loaders.
+     */
+    public void dumpLoaders(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
+        mHost.dumpLoaders(prefix, fd, writer, args);
+    }
+}
diff --git a/v4/java/android/support/v4/app/FragmentHostCallback.java b/v4/java/android/support/v4/app/FragmentHostCallback.java
new file mode 100644
index 0000000..fb4410f
--- /dev/null
+++ b/v4/java/android/support/v4/app/FragmentHostCallback.java
@@ -0,0 +1,322 @@
+/*
+ * 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.v4.app;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Handler;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v4.util.SimpleArrayMap;
+import android.view.LayoutInflater;
+import android.view.View;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+/**
+ * Integration points with the Fragment host.
+ * <p>
+ * Fragments may be hosted by any object; such as an {@link Activity}. In order to
+ * host fragments, implement {@link FragmentHostCallback}, overriding the methods
+ * applicable to the host.
+ */
+public abstract class FragmentHostCallback<E> extends FragmentContainer {
+    private final Activity mActivity;
+    final Context mContext;
+    private final Handler mHandler;
+    final int mWindowAnimations;
+    final FragmentManagerImpl mFragmentManager = new FragmentManagerImpl();
+    private SimpleArrayMap<String, LoaderManager> mAllLoaderManagers;
+    private LoaderManagerImpl mLoaderManager;
+    private boolean mCheckedForLoaderManager;
+    private boolean mLoadersStarted;
+
+    public FragmentHostCallback(Context context, Handler handler, int windowAnimations) {
+        this(null /*activity*/, context, handler, windowAnimations);
+    }
+
+    FragmentHostCallback(FragmentActivity activity) {
+        this(activity, activity /*context*/, activity.mHandler, 0 /*windowAnimations*/);
+    }
+
+    FragmentHostCallback(Activity activity, Context context, Handler handler,
+            int windowAnimations) {
+        mActivity = activity;
+        mContext = context;
+        mHandler = handler;
+        mWindowAnimations = windowAnimations;
+    }
+
+    /**
+     * Print internal state into the given stream.
+     *
+     * @param prefix Desired prefix to prepend at each line of output.
+     * @param fd The raw file descriptor that the dump is being sent to.
+     * @param writer The PrintWriter to which you should dump your state. This will be closed
+     *                  for you after you return.
+     * @param args additional arguments to the dump request.
+     */
+    public void onDump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
+    }
+
+    /**
+     * Return {@code true} if the fragment's state needs to be saved.
+     */
+    public boolean onShouldSaveFragmentState(Fragment fragment) {
+        return true;
+    }
+
+    /**
+     * Return a {@link LayoutInflater}.
+     * See {@link Activity#getLayoutInflater()}.
+     */
+    public LayoutInflater onGetLayoutInflater() {
+        return (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+    }
+
+    /**
+     * Return the object that's currently hosting the fragment. If a {@link Fragment}
+     * is hosted by a {@link FragmentActivity}, the object returned here should be
+     * the same object returned from {@link Fragment#getActivity()}.
+     */
+    @Nullable
+    public abstract E onGetHost();
+
+    /**
+     * Invalidates the activity's options menu.
+     * See {@link FragmentActivity#supportInvalidateOptionsMenu()}
+     */
+    public void onSupportInvalidateOptionsMenu() {
+    }
+
+    /**
+     * Starts a new {@link Activity} from the given fragment.
+     * See {@link FragmentActivity#startActivityForResult(Intent, int)}.
+     */
+    public void onStartActivityFromFragment(Fragment fragment, Intent intent, int requestCode) {
+        if (requestCode != -1) {
+            throw new IllegalStateException(
+                    "Starting activity with a requestCode requires a FragmentActivity host");
+        }
+        mContext.startActivity(intent);
+    }
+
+    /**
+     * Requests permissions from the given fragment.
+     * See {@link FragmentActivity#requestPermissions(String[], int)}
+     */
+    public void onRequestPermissionsFromFragment(@NonNull Fragment fragment,
+            @NonNull String[] permissions, int requestCode) {
+    }
+
+    /**
+     * Checks wehter to show permission rationale UI from a fragment.
+     * See {@link FragmentActivity#shouldShowRequestPermissionRationale(String)}
+     */
+    public boolean onShouldShowRequestPermissionRationale(@NonNull String permission) {
+        return false;
+    }
+
+    /**
+     * Return {@code true} if there are window animations.
+     */
+    public boolean onHasWindowAnimations() {
+        return true;
+    }
+
+    /**
+     * Return the window animations.
+     */
+    public int onGetWindowAnimations() {
+        return mWindowAnimations;
+    }
+
+    @Nullable
+    @Override
+    public View onFindViewById(int id) {
+        return null;
+    }
+
+    @Override
+    public boolean onHasView() {
+        return true;
+    }
+
+    Activity getActivity() {
+        return mActivity;
+    }
+
+    Context getContext() {
+        return mContext;
+    }
+
+    Handler getHandler() {
+        return mHandler;
+    }
+
+    FragmentManagerImpl getFragmentManagerImpl() {
+        return mFragmentManager;
+    }
+
+    LoaderManagerImpl getLoaderManagerImpl() {
+        if (mLoaderManager != null) {
+            return mLoaderManager;
+        }
+        mCheckedForLoaderManager = true;
+        mLoaderManager = getLoaderManager("(root)", mLoadersStarted, true /*create*/);
+        return mLoaderManager;
+    }
+
+    void inactivateFragment(String who) {
+        //Log.v(TAG, "invalidateSupportFragment: who=" + who);
+        if (mAllLoaderManagers != null) {
+            LoaderManagerImpl lm = (LoaderManagerImpl) mAllLoaderManagers.get(who);
+            if (lm != null && !lm.mRetaining) {
+                lm.doDestroy();
+                mAllLoaderManagers.remove(who);
+            }
+        }
+    }
+
+    void onAttachFragment(Fragment fragment) {
+    }
+
+    void doLoaderStart() {
+        if (mLoadersStarted) {
+            return;
+        }
+        mLoadersStarted = true;
+
+        if (mLoaderManager != null) {
+            mLoaderManager.doStart();
+        } else if (!mCheckedForLoaderManager) {
+            mLoaderManager = getLoaderManager("(root)", mLoadersStarted, false);
+            // the returned loader manager may be a new one, so we have to start it
+            if ((mLoaderManager != null) && (!mLoaderManager.mStarted)) {
+                mLoaderManager.doStart();
+            }
+        }
+        mCheckedForLoaderManager = true;
+    }
+
+    // retain -- whether to stop the loader or retain it
+    void doLoaderStop(boolean retain) {
+        if (mLoaderManager == null) {
+            return;
+        }
+
+        if (!mLoadersStarted) {
+            return;
+        }
+        mLoadersStarted = false;
+
+        if (retain) {
+            mLoaderManager.doRetain();
+        } else {
+            mLoaderManager.doStop();
+        }
+    }
+
+    void doLoaderRetain() {
+        if (mLoaderManager == null) {
+            return;
+        }
+        mLoaderManager.doRetain();
+    }
+
+    void doLoaderDestroy() {
+        if (mLoaderManager == null) {
+            return;
+        }
+        mLoaderManager.doDestroy();
+    }
+
+    void reportLoaderStart() {
+        if (mAllLoaderManagers != null) {
+            final int N = mAllLoaderManagers.size();
+            LoaderManagerImpl loaders[] = new LoaderManagerImpl[N];
+            for (int i=N-1; i>=0; i--) {
+                loaders[i] = (LoaderManagerImpl) mAllLoaderManagers.valueAt(i);
+            }
+            for (int i=0; i<N; i++) {
+                LoaderManagerImpl lm = loaders[i];
+                lm.finishRetain();
+                lm.doReportStart();
+            }
+        }
+    }
+
+    LoaderManagerImpl getLoaderManager(String who, boolean started, boolean create) {
+        if (mAllLoaderManagers == null) {
+            mAllLoaderManagers = new SimpleArrayMap<String, LoaderManager>();
+        }
+        LoaderManagerImpl lm = (LoaderManagerImpl) mAllLoaderManagers.get(who);
+        if (lm == null) {
+            if (create) {
+                lm = new LoaderManagerImpl(who, this, started);
+                mAllLoaderManagers.put(who, lm);
+            }
+        } else {
+            lm.updateHostController(this);
+        }
+        return lm;
+    }
+
+    SimpleArrayMap<String, LoaderManager> retainLoaderNonConfig() {
+        boolean retainLoaders = false;
+        if (mAllLoaderManagers != null) {
+            // prune out any loader managers that were already stopped and so
+            // have nothing useful to retain.
+            final int N = mAllLoaderManagers.size();
+            LoaderManagerImpl loaders[] = new LoaderManagerImpl[N];
+            for (int i=N-1; i>=0; i--) {
+                loaders[i] = (LoaderManagerImpl) mAllLoaderManagers.valueAt(i);
+            }
+            for (int i=0; i<N; i++) {
+                LoaderManagerImpl lm = loaders[i];
+                if (lm.mRetaining) {
+                    retainLoaders = true;
+                } else {
+                    lm.doDestroy();
+                    mAllLoaderManagers.remove(lm.mWho);
+                }
+            }
+        }
+
+        if (retainLoaders) {
+            return mAllLoaderManagers;
+        }
+        return null;
+    }
+
+    void restoreLoaderNonConfig(SimpleArrayMap<String, LoaderManager> loaderManagers) {
+        mAllLoaderManagers = loaderManagers;
+    }
+
+    void dumpLoaders(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
+        writer.print(prefix); writer.print("mLoadersStarted=");
+        writer.println(mLoadersStarted);
+        if (mLoaderManager != null) {
+            writer.print(prefix); writer.print("Loader Manager ");
+            writer.print(Integer.toHexString(System.identityHashCode(mLoaderManager)));
+            writer.println(":");
+            mLoaderManager.dump(prefix + "  ", fd, writer, args);
+        }
+    }
+}
diff --git a/v4/java/android/support/v4/app/FragmentManager.java b/v4/java/android/support/v4/app/FragmentManager.java
index 6d41d45..94d8243 100644
--- a/v4/java/android/support/v4/app/FragmentManager.java
+++ b/v4/java/android/support/v4/app/FragmentManager.java
@@ -25,8 +25,8 @@
 import android.os.Looper;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.support.annotation.CallSuper;
 import android.support.annotation.IdRes;
-import android.support.annotation.Nullable;
 import android.support.annotation.StringRes;
 import android.support.v4.util.DebugUtils;
 import android.support.v4.util.LogWriter;
@@ -399,15 +399,6 @@
 }
 
 /**
- * Callbacks from FragmentManagerImpl to its container.
- */
-interface FragmentContainer {
-    @Nullable
-    public View findViewById(@IdRes int id);
-    public boolean hasView();
-}
-
-/**
  * Container for fragments associated with an activity.
  */
 final class FragmentManagerImpl extends FragmentManager implements LayoutInflaterFactory {
@@ -421,6 +412,39 @@
     static final String VIEW_STATE_TAG = "android:view_state";
     static final String USER_VISIBLE_HINT_TAG = "android:user_visible_hint";
 
+
+    static class AnimateOnHWLayerIfNeededListener implements AnimationListener {
+        private boolean mShouldRunOnHWLayer = false;
+        private View mView;
+        public AnimateOnHWLayerIfNeededListener(final View v, Animation anim) {
+            if (v == null || anim == null) {
+                return;
+            }
+            mView = v;
+        }
+
+        @Override
+        @CallSuper
+        public void onAnimationStart(Animation animation) {
+            mShouldRunOnHWLayer = shouldRunOnHWLayer(mView, animation);
+            if (mShouldRunOnHWLayer) {
+                ViewCompat.setLayerType(mView, ViewCompat.LAYER_TYPE_HARDWARE, null);
+            }
+        }
+
+        @Override
+        @CallSuper
+        public void onAnimationEnd(Animation animation) {
+            if (mShouldRunOnHWLayer) {
+                ViewCompat.setLayerType(mView, ViewCompat.LAYER_TYPE_NONE, null);
+            }
+        }
+
+        @Override
+        public void onAnimationRepeat(Animation animation) {
+        }
+    }
+
     ArrayList<Runnable> mPendingActions;
     Runnable[] mTmpActions;
     boolean mExecutingActions;
@@ -438,7 +462,8 @@
     ArrayList<OnBackStackChangedListener> mBackStackChangeListeners;
 
     int mCurState = Fragment.INITIALIZING;
-    FragmentActivity mActivity;
+    FragmentHostCallback mHost;
+    FragmentController mController;
     FragmentContainer mContainer;
     Fragment mParent;
     
@@ -459,14 +484,34 @@
         }
     };
 
+    static boolean modifiesAlpha(Animation anim) {
+        if (anim instanceof AlphaAnimation) {
+            return true;
+        } else if (anim instanceof AnimationSet) {
+            List<Animation> anims = ((AnimationSet) anim).getAnimations();
+            for (int i = 0; i < anims.size(); i++) {
+                if (anims.get(i) instanceof AlphaAnimation) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    static boolean shouldRunOnHWLayer(View v, Animation anim) {
+        return ViewCompat.getLayerType(v) == ViewCompat.LAYER_TYPE_NONE
+                && ViewCompat.hasOverlappingRendering(v)
+                && modifiesAlpha(anim);
+    }
+
     private void throwException(RuntimeException ex) {
         Log.e(TAG, ex.getMessage());
         Log.e(TAG, "Activity state:");
         LogWriter logw = new LogWriter(TAG);
         PrintWriter pw = new PrintWriter(logw);
-        if (mActivity != null) {
+        if (mHost != null) {
             try {
-                mActivity.dump("  ", null, pw, new String[] { });
+                mHost.onDump("  ", null, pw, new String[] { });
             } catch (Exception e) {
                 Log.e(TAG, "Failed dumping state", e);
             }
@@ -494,7 +539,7 @@
     public void popBackStack() {
         enqueueAction(new Runnable() {
             @Override public void run() {
-                popBackStackState(mActivity.mHandler, null, -1, 0);
+                popBackStackState(mHost.getHandler(), null, -1, 0);
             }
         }, false);
     }
@@ -503,14 +548,14 @@
     public boolean popBackStackImmediate() {
         checkStateLoss();
         executePendingTransactions();
-        return popBackStackState(mActivity.mHandler, null, -1, 0);
+        return popBackStackState(mHost.getHandler(), null, -1, 0);
     }
 
     @Override
     public void popBackStack(final String name, final int flags) {
         enqueueAction(new Runnable() {
             @Override public void run() {
-                popBackStackState(mActivity.mHandler, name, -1, flags);
+                popBackStackState(mHost.getHandler(), name, -1, flags);
             }
         }, false);
     }
@@ -519,7 +564,7 @@
     public boolean popBackStackImmediate(String name, int flags) {
         checkStateLoss();
         executePendingTransactions();
-        return popBackStackState(mActivity.mHandler, name, -1, flags);
+        return popBackStackState(mHost.getHandler(), name, -1, flags);
     }
 
     @Override
@@ -529,7 +574,7 @@
         }
         enqueueAction(new Runnable() {
             @Override public void run() {
-                popBackStackState(mActivity.mHandler, null, id, flags);
+                popBackStackState(mHost.getHandler(), null, id, flags);
             }
         }, false);
     }
@@ -541,7 +586,7 @@
         if (id < 0) {
             throw new IllegalArgumentException("Bad id: " + id);
         }
-        return popBackStackState(mActivity.mHandler, null, id, flags);
+        return popBackStackState(mHost.getHandler(), null, id, flags);
     }
 
     @Override
@@ -628,7 +673,7 @@
         if (mParent != null) {
             DebugUtils.buildShortClassTag(mParent, sb);
         } else {
-            DebugUtils.buildShortClassTag(mActivity, sb);
+            DebugUtils.buildShortClassTag(mHost, sb);
         }
         sb.append("}}");
         return sb.toString();
@@ -725,7 +770,7 @@
         }
 
         writer.print(prefix); writer.println("FragmentManager misc state:");
-        writer.print(prefix); writer.print("  mActivity="); writer.println(mActivity);
+        writer.print(prefix); writer.print("  mHost="); writer.println(mHost);
         writer.print(prefix); writer.print("  mContainer="); writer.println(mContainer);
         if (mParent != null) {
             writer.print(prefix); writer.print("  mParent="); writer.println(mParent);
@@ -775,7 +820,7 @@
         anim.setDuration(ANIM_DUR);
         return anim;
     }
-    
+
     Animation loadAnimation(Fragment fragment, int transit, boolean enter,
             int transitionStyle) {
         Animation animObj = fragment.onCreateAnimation(transit, enter,
@@ -785,7 +830,7 @@
         }
         
         if (fragment.mNextAnim != 0) {
-            Animation anim = AnimationUtils.loadAnimation(mActivity, fragment.mNextAnim);
+            Animation anim = AnimationUtils.loadAnimation(mHost.getContext(), fragment.mNextAnim);
             if (anim != null) {
                 return anim;
             }
@@ -799,24 +844,24 @@
         if (styleIndex < 0) {
             return null;
         }
-        
+
         switch (styleIndex) {
             case ANIM_STYLE_OPEN_ENTER:
-                return makeOpenCloseAnimation(mActivity, 1.125f, 1.0f, 0, 1);
+                return makeOpenCloseAnimation(mHost.getContext(), 1.125f, 1.0f, 0, 1);
             case ANIM_STYLE_OPEN_EXIT:
-                return makeOpenCloseAnimation(mActivity, 1.0f, .975f, 1, 0);
+                return makeOpenCloseAnimation(mHost.getContext(), 1.0f, .975f, 1, 0);
             case ANIM_STYLE_CLOSE_ENTER:
-                return makeOpenCloseAnimation(mActivity, .975f, 1.0f, 0, 1);
+                return makeOpenCloseAnimation(mHost.getContext(), .975f, 1.0f, 0, 1);
             case ANIM_STYLE_CLOSE_EXIT:
-                return makeOpenCloseAnimation(mActivity, 1.0f, 1.075f, 1, 0);
+                return makeOpenCloseAnimation(mHost.getContext(), 1.0f, 1.075f, 1, 0);
             case ANIM_STYLE_FADE_ENTER:
-                return makeFadeAnimation(mActivity, 0, 1);
+                return makeFadeAnimation(mHost.getContext(), 0, 1);
             case ANIM_STYLE_FADE_EXIT:
-                return makeFadeAnimation(mActivity, 1, 0);
+                return makeFadeAnimation(mHost.getContext(), 1, 0);
         }
         
-        if (transitionStyle == 0 && mActivity.getWindow() != null) {
-            transitionStyle = mActivity.getWindow().getAttributes().windowAnimations;
+        if (transitionStyle == 0 && mHost.onHasWindowAnimations()) {
+            transitionStyle = mHost.onGetWindowAnimations();
         }
         if (transitionStyle == 0) {
             return null;
@@ -847,6 +892,22 @@
         }
     }
 
+    /**
+     * Sets the to be animated view on hardware layer during the animation. Note
+     * that calling this will replace any existing animation listener on the animation
+     * with a new one, as animations do not support more than one listeners. Therefore,
+     * animations that already have listeners should do the layer change operations
+     * in their existing listeners, rather than calling this function.
+     */
+    private void setHWLayerAnimListenerIfAlpha(final View v, Animation anim) {
+        if (v == null || anim == null) {
+            return;
+        }
+        if (shouldRunOnHWLayer(v, anim)) {
+            anim.setAnimationListener(new AnimateOnHWLayerIfNeededListener(v, anim));
+        }
+    }
+
     void moveToState(Fragment f, int newState, int transit, int transitionStyle,
             boolean keepActive) {
         // Fragments that are not currently added will sit in the onCreate() state.
@@ -881,7 +942,7 @@
                 case Fragment.INITIALIZING:
                     if (DEBUG) Log.v(TAG, "moveto CREATED: " + f);
                     if (f.mSavedFragmentState != null) {
-                        f.mSavedFragmentState.setClassLoader(mActivity.getClassLoader());
+                        f.mSavedFragmentState.setClassLoader(mHost.getContext().getClassLoader());
                         f.mSavedViewState = f.mSavedFragmentState.getSparseParcelableArray(
                                 FragmentManagerImpl.VIEW_STATE_TAG);
                         f.mTarget = getFragment(f.mSavedFragmentState,
@@ -899,18 +960,18 @@
                             }
                         }
                     }
-                    f.mActivity = mActivity;
+                    f.mHost = mHost;
                     f.mParentFragment = mParent;
                     f.mFragmentManager = mParent != null
-                            ? mParent.mChildFragmentManager : mActivity.mFragments;
+                            ? mParent.mChildFragmentManager : mHost.getFragmentManagerImpl();
                     f.mCalled = false;
-                    f.onAttach(mActivity);
+                    f.onAttach(mHost.getContext());
                     if (!f.mCalled) {
                         throw new SuperNotCalledException("Fragment " + f
                                 + " did not call through to super.onAttach()");
                     }
                     if (f.mParentFragment == null) {
-                        mActivity.onAttachFragment(f);
+                        mHost.onAttachFragment(f);
                     }
 
                     if (!f.mRetaining) {
@@ -942,7 +1003,7 @@
                         if (!f.mFromLayout) {
                             ViewGroup container = null;
                             if (f.mContainerId != 0) {
-                                container = (ViewGroup)mContainer.findViewById(f.mContainerId);
+                                container = (ViewGroup)mContainer.onFindViewById(f.mContainerId);
                                 if (container == null && !f.mRestored) {
                                     throwException(new IllegalArgumentException(
                                             "No view found for id 0x"
@@ -965,6 +1026,7 @@
                                     Animation anim = loadAnimation(f, transit, true,
                                             transitionStyle);
                                     if (anim != null) {
+                                        setHWLayerAnimListenerIfAlpha(f.mView, anim);
                                         f.mView.startAnimation(anim);
                                     }
                                     container.addView(f.mView);
@@ -1021,7 +1083,7 @@
                         if (f.mView != null) {
                             // Need to save the current view state if not
                             // done already.
-                            if (!mActivity.isFinishing() && f.mSavedViewState == null) {
+                            if (mHost.onShouldSaveFragmentState(f) && f.mSavedViewState == null) {
                                 saveFragmentViewState(f);
                             }
                         }
@@ -1036,21 +1098,18 @@
                                 final Fragment fragment = f;
                                 f.mAnimatingAway = f.mView;
                                 f.mStateAfterAnimating = newState;
-                                anim.setAnimationListener(new AnimationListener() {
+                                final View viewToAnimate = f.mView;
+                                anim.setAnimationListener(new AnimateOnHWLayerIfNeededListener(
+                                        viewToAnimate, anim) {
                                     @Override
                                     public void onAnimationEnd(Animation animation) {
+                                        super.onAnimationEnd(animation);
                                         if (fragment.mAnimatingAway != null) {
                                             fragment.mAnimatingAway = null;
                                             moveToState(fragment, fragment.mStateAfterAnimating,
                                                     0, 0, false);
                                         }
                                     }
-                                    @Override
-                                    public void onAnimationRepeat(Animation animation) {
-                                    }
-                                    @Override
-                                    public void onAnimationStart(Animation animation) {
-                                    }
                                 });
                                 f.mView.startAnimation(anim);
                             }
@@ -1098,7 +1157,7 @@
                                 if (!f.mRetaining) {
                                     makeInactive(f);
                                 } else {
-                                    f.mActivity = null;
+                                    f.mHost = null;
                                     f.mParentFragment = null;
                                     f.mFragmentManager = null;
                                     f.mChildFragmentManager = null;
@@ -1121,8 +1180,8 @@
     }
     
     void moveToState(int newState, int transit, int transitStyle, boolean always) {
-        if (mActivity == null && newState != Fragment.INITIALIZING) {
-            throw new IllegalStateException("No activity");
+        if (mHost == null && newState != Fragment.INITIALIZING) {
+            throw new IllegalStateException("No host");
         }
 
         if (!always && mCurState == newState) {
@@ -1146,8 +1205,8 @@
                 startPendingDeferredFragments();
             }
 
-            if (mNeedMenuInvalidate && mActivity != null && mCurState == Fragment.RESUMED) {
-                mActivity.supportInvalidateOptionsMenu();
+            if (mNeedMenuInvalidate && mHost != null && mCurState == Fragment.RESUMED) {
+                mHost.onSupportInvalidateOptionsMenu();
                 mNeedMenuInvalidate = false;
             }
         }
@@ -1194,7 +1253,7 @@
             mAvailIndices = new ArrayList<Integer>();
         }
         mAvailIndices.add(f.mIndex);
-        mActivity.invalidateSupportFragment(f.mWho);
+        mHost.inactivateFragment(f.mWho);
         f.initState();
     }
     
@@ -1245,6 +1304,7 @@
                 Animation anim = loadAnimation(fragment, transition, false,
                         transitionStyle);
                 if (anim != null) {
+                    setHWLayerAnimListenerIfAlpha(fragment.mView, anim);
                     fragment.mView.startAnimation(anim);
                 }
                 fragment.mView.setVisibility(View.GONE);
@@ -1264,6 +1324,7 @@
                 Animation anim = loadAnimation(fragment, transition, true,
                         transitionStyle);
                 if (anim != null) {
+                    setHWLayerAnimListenerIfAlpha(fragment.mView, anim);
                     fragment.mView.startAnimation(anim);
                 }
                 fragment.mView.setVisibility(View.VISIBLE);
@@ -1395,7 +1456,7 @@
             checkStateLoss();
         }
         synchronized (this) {
-            if (mDestroyed || mActivity == null) {
+            if (mDestroyed || mHost == null) {
                 throw new IllegalStateException("Activity has been destroyed");
             }
             if (mPendingActions == null) {
@@ -1403,8 +1464,8 @@
             }
             mPendingActions.add(action);
             if (mPendingActions.size() == 1) {
-                mActivity.mHandler.removeCallbacks(mExecCommit);
-                mActivity.mHandler.post(mExecCommit);
+                mHost.getHandler().removeCallbacks(mExecCommit);
+                mHost.getHandler().post(mExecCommit);
             }
         }
     }
@@ -1473,7 +1534,7 @@
             throw new IllegalStateException("Recursive entry to executePendingTransactions");
         }
         
-        if (Looper.myLooper() != mActivity.mHandler.getLooper()) {
+        if (Looper.myLooper() != mHost.getHandler().getLooper()) {
             throw new IllegalStateException("Must be called from main thread of process");
         }
 
@@ -1493,7 +1554,7 @@
                 }
                 mPendingActions.toArray(mTmpActions);
                 mPendingActions.clear();
-                mActivity.mHandler.removeCallbacks(mExecCommit);
+                mHost.getHandler().removeCallbacks(mExecCommit);
             }
             
             mExecutingActions = true;
@@ -1537,6 +1598,7 @@
         reportBackStackChanged();
     }
     
+    @SuppressWarnings("unused")
     boolean popBackStackState(Handler handler, String name, int id, int flags) {
         if (mBackStack == null) {
             return false;
@@ -1780,7 +1842,7 @@
             if (N > 0) {
                 backStack = new BackStackState[N];
                 for (int i=0; i<N; i++) {
-                    backStack[i] = new BackStackState(this, mBackStack.get(i));
+                    backStack[i] = new BackStackState(mBackStack.get(i));
                     if (DEBUG) Log.v(TAG, "saveAllState: adding back stack #" + i
                             + ": " + mBackStack.get(i));
                 }
@@ -1794,7 +1856,7 @@
         return fms;
     }
     
-    void restoreAllState(Parcelable state, ArrayList<Fragment> nonConfig) {
+    void restoreAllState(Parcelable state, List<Fragment> nonConfig) {
         // If there is no saved state at all, then there can not be
         // any nonConfig fragments either, so that is that.
         if (state == null) return;
@@ -1815,7 +1877,7 @@
                 f.mAdded = false;
                 f.mTarget = null;
                 if (fs.mSavedFragmentState != null) {
-                    fs.mSavedFragmentState.setClassLoader(mActivity.getClassLoader());
+                    fs.mSavedFragmentState.setClassLoader(mHost.getContext().getClassLoader());
                     f.mSavedViewState = fs.mSavedFragmentState.getSparseParcelableArray(
                             FragmentManagerImpl.VIEW_STATE_TAG);
                     f.mSavedFragmentState = fs.mSavedFragmentState;
@@ -1832,7 +1894,7 @@
         for (int i=0; i<fms.mActive.length; i++) {
             FragmentState fs = fms.mActive[i];
             if (fs != null) {
-                Fragment f = fs.instantiate(mActivity, mParent);
+                Fragment f = fs.instantiate(mHost, mParent);
                 if (DEBUG) Log.v(TAG, "restoreAllState: active #" + i + ": " + f);
                 mActive.add(f);
                 // Now that the fragment is instantiated (or came from being
@@ -1906,11 +1968,11 @@
             mBackStack = null;
         }
     }
-    
-    public void attachActivity(FragmentActivity activity,
+
+    public void attachController(FragmentHostCallback host,
             FragmentContainer container, Fragment parent) {
-        if (mActivity != null) throw new IllegalStateException("Already attached");
-        mActivity = activity;
+        if (mHost != null) throw new IllegalStateException("Already attached");
+        mHost = host;
         mContainer = container;
         mParent = parent;
     }
@@ -1964,7 +2026,7 @@
         mDestroyed = true;
         execPendingActions();
         moveToState(Fragment.INITIALIZING, false);
-        mActivity = null;
+        mHost = null;
         mContainer = null;
         mParent = null;
     }
@@ -2132,7 +2194,7 @@
         String tag = a.getString(FragmentTag.Fragment_tag);
         a.recycle();
 
-        if (!Fragment.isSupportFragmentClass(mActivity, fname)) {
+        if (!Fragment.isSupportFragmentClass(mHost.getContext(), fname)) {
             // Invalid support lib fragment; let the device's framework handle it.
             // This will allow android.app.Fragments to do the right thing.
             return null;
@@ -2166,7 +2228,7 @@
             fragment.mTag = tag;
             fragment.mInLayout = true;
             fragment.mFragmentManager = this;
-            fragment.onInflate(mActivity, attrs, fragment.mSavedFragmentState);
+            fragment.onInflate(mHost.getContext(), attrs, fragment.mSavedFragmentState);
             addFragment(fragment, true);
 
         } else if (fragment.mInLayout) {
@@ -2184,7 +2246,7 @@
             // from last saved state), then give it the attributes to
             // initialize itself.
             if (!fragment.mRetaining) {
-                fragment.onInflate(mActivity, attrs, fragment.mSavedFragmentState);
+                fragment.onInflate(mHost.getContext(), attrs, fragment.mSavedFragmentState);
             }
         }
 
diff --git a/v4/java/android/support/v4/app/LoaderManager.java b/v4/java/android/support/v4/app/LoaderManager.java
index 57c0a30..fad56e0 100644
--- a/v4/java/android/support/v4/app/LoaderManager.java
+++ b/v4/java/android/support/v4/app/LoaderManager.java
@@ -184,6 +184,9 @@
     public boolean hasRunningLoaders() { return false; }
 }
 
+/**
+ * @hide
+ */
 class LoaderManagerImpl extends LoaderManager {
     static final String TAG = "LoaderManager";
     static boolean DEBUG = false;
@@ -201,14 +204,15 @@
 
     final String mWho;
 
-    FragmentActivity mActivity;
     boolean mStarted;
     boolean mRetaining;
     boolean mRetainingStarted;
     
     boolean mCreatingLoader;
+    private FragmentHostCallback mHost;
 
-    final class LoaderInfo implements Loader.OnLoadCompleteListener<Object> {
+    final class LoaderInfo implements Loader.OnLoadCompleteListener<Object>,
+            Loader.OnLoadCanceledListener<Object> {
         final int mId;
         final Bundle mArgs;
         LoaderManager.LoaderCallbacks<Object> mCallbacks;
@@ -216,8 +220,11 @@
         boolean mHaveData;
         boolean mDeliveredData;
         Object mData;
+        @SuppressWarnings("hiding")
         boolean mStarted;
+        @SuppressWarnings("hiding")
         boolean mRetaining;
+        @SuppressWarnings("hiding")
         boolean mRetainingStarted;
         boolean mReportNextStart;
         boolean mDestroyed;
@@ -260,6 +267,7 @@
                 }
                 if (!mListenerRegistered) {
                     mLoader.registerListener(mId, this);
+                    mLoader.registerOnLoadCanceledListener(this);
                     mListenerRegistered = true;
                 }
                 mLoader.startLoading();
@@ -318,11 +326,21 @@
                     // Let the loader know we're done with it
                     mListenerRegistered = false;
                     mLoader.unregisterListener(this);
+                    mLoader.unregisterOnLoadCanceledListener(this);
                     mLoader.stopLoading();
                 }
             }
         }
-        
+
+        void cancel() {
+            if (DEBUG) Log.v(TAG, "  Canceling: " + this);
+            if (mStarted && mLoader != null && mListenerRegistered) {
+                if (!mLoader.cancelLoad()) {
+                    onLoadCanceled(mLoader);
+                }
+            }
+        }
+
         void destroy() {
             if (DEBUG) Log.v(TAG, "  Destroying: " + this);
             mDestroyed = true;
@@ -331,15 +349,15 @@
             if (mCallbacks != null && mLoader != null && mHaveData && needReset) {
                 if (DEBUG) Log.v(TAG, "  Reseting: " + this);
                 String lastBecause = null;
-                if (mActivity != null) {
-                    lastBecause = mActivity.mFragments.mNoTransactionsBecause;
-                    mActivity.mFragments.mNoTransactionsBecause = "onLoaderReset";
+                if (mHost != null) {
+                    lastBecause = mHost.mFragmentManager.mNoTransactionsBecause;
+                    mHost.mFragmentManager.mNoTransactionsBecause = "onLoaderReset";
                 }
                 try {
                     mCallbacks.onLoaderReset(mLoader);
                 } finally {
-                    if (mActivity != null) {
-                        mActivity.mFragments.mNoTransactionsBecause = lastBecause;
+                    if (mHost != null) {
+                        mHost.mFragmentManager.mNoTransactionsBecause = lastBecause;
                     }
                 }
             }
@@ -350,6 +368,7 @@
                 if (mListenerRegistered) {
                     mListenerRegistered = false;
                     mLoader.unregisterListener(this);
+                    mLoader.unregisterOnLoadCanceledListener(this);
                 }
                 mLoader.reset();
             }
@@ -357,8 +376,38 @@
                 mPendingLoader.destroy();
             }
         }
-        
-        @Override public void onLoadComplete(Loader<Object> loader, Object data) {
+
+        @Override
+        public void onLoadCanceled(Loader<Object> loader) {
+            if (DEBUG) Log.v(TAG, "onLoadCanceled: " + this);
+
+            if (mDestroyed) {
+                if (DEBUG) Log.v(TAG, "  Ignoring load canceled -- destroyed");
+                return;
+            }
+
+            if (mLoaders.get(mId) != this) {
+                // This cancellation message is not coming from the current active loader.
+                // We don't care about it.
+                if (DEBUG) Log.v(TAG, "  Ignoring load canceled -- not active");
+                return;
+            }
+
+            LoaderInfo pending = mPendingLoader;
+            if (pending != null) {
+                // There is a new request pending and we were just
+                // waiting for the old one to cancel or complete before starting
+                // it.  So now it is time, switch over to the new loader.
+                if (DEBUG) Log.v(TAG, "  Switching to pending loader: " + pending);
+                mPendingLoader = null;
+                mLoaders.put(mId, null);
+                destroy();
+                installLoader(pending);
+            }
+        }
+
+        @Override
+        public void onLoadComplete(Loader<Object> loader, Object data) {
             if (DEBUG) Log.v(TAG, "onLoadComplete: " + this);
             
             if (mDestroyed) {
@@ -409,25 +458,25 @@
                 mInactiveLoaders.remove(mId);
             }
 
-            if (mActivity != null && !hasRunningLoaders()) {
-                mActivity.mFragments.startPendingDeferredFragments();
+            if (mHost != null && !hasRunningLoaders()) {
+                mHost.mFragmentManager.startPendingDeferredFragments();
             }
         }
 
         void callOnLoadFinished(Loader<Object> loader, Object data) {
             if (mCallbacks != null) {
                 String lastBecause = null;
-                if (mActivity != null) {
-                    lastBecause = mActivity.mFragments.mNoTransactionsBecause;
-                    mActivity.mFragments.mNoTransactionsBecause = "onLoadFinished";
+                if (mHost != null) {
+                    lastBecause = mHost.mFragmentManager.mNoTransactionsBecause;
+                    mHost.mFragmentManager.mNoTransactionsBecause = "onLoadFinished";
                 }
                 try {
                     if (DEBUG) Log.v(TAG, "  onLoadFinished in " + loader + ": "
                             + loader.dataToString(data));
                     mCallbacks.onLoadFinished(loader, data);
                 } finally {
-                    if (mActivity != null) {
-                        mActivity.mFragments.mNoTransactionsBecause = lastBecause;
+                    if (mHost != null) {
+                        mHost.mFragmentManager.mNoTransactionsBecause = lastBecause;
                     }
                 }
                 mDeliveredData = true;
@@ -474,21 +523,21 @@
         }
     }
     
-    LoaderManagerImpl(String who, FragmentActivity activity, boolean started) {
+    LoaderManagerImpl(String who, FragmentHostCallback host, boolean started) {
         mWho = who;
-        mActivity = activity;
+        mHost = host;
         mStarted = started;
     }
     
-    void updateActivity(FragmentActivity activity) {
-        mActivity = activity;
+    void updateHostController(FragmentHostCallback host) {
+        mHost = host;
     }
     
     private LoaderInfo createLoader(int id, Bundle args,
             LoaderManager.LoaderCallbacks<Object> callback) {
-        LoaderInfo info = new LoaderInfo(id, args,  (LoaderManager.LoaderCallbacks<Object>)callback);
+        LoaderInfo info = new LoaderInfo(id, args,  callback);
         Loader<Object> loader = callback.onCreateLoader(id, args);
-        info.mLoader = (Loader<Object>)loader;
+        info.mLoader = loader;
         return info;
     }
     
@@ -533,7 +582,7 @@
      * @param id A unique (to this LoaderManager instance) identifier under
      * which to manage the new Loader.
      * @param args Optional arguments that will be propagated to
-     * {@link LoaderCallbacks#onCreateLoader(int, Bundle) LoaderCallbacks.onCreateLoader()}.
+     * {@link android.support.v4.app.LoaderManager.LoaderCallbacks#onCreateLoader(int, Bundle) LoaderCallbacks.onCreateLoader()}.
      * @param callback Interface implementing management of this Loader.  Required.
      * Its onCreateLoader() method will be called while inside of the function to
      * instantiate the Loader object.
@@ -583,7 +632,7 @@
      * @param id A unique (to this LoaderManager instance) identifier under
      * which to manage the new Loader.
      * @param args Optional arguments that will be propagated to
-     * {@link LoaderCallbacks#onCreateLoader(int, Bundle) LoaderCallbacks.onCreateLoader()}.
+     * {@link android.support.v4.app.LoaderManager.LoaderCallbacks#onCreateLoader(int, Bundle) LoaderCallbacks.onCreateLoader()}.
      * @param callback Interface implementing management of this Loader.  Required.
      * Its onCreateLoader() method will be called while inside of the function to
      * instantiate the Loader object.
@@ -622,7 +671,9 @@
                     } else {
                         // Now we have three active loaders... we'll queue
                         // up this request to be processed once one of the other loaders
-                        // finishes.
+                        // finishes or is canceled.
+                        if (DEBUG) Log.v(TAG, "  Current loader is running; attempting to cancel");
+                        info.cancel();
                         if (info.mPendingLoader != null) {
                             if (DEBUG) Log.v(TAG, "  Removing pending loader: " + info.mPendingLoader);
                             info.mPendingLoader.destroy();
@@ -672,8 +723,8 @@
             mInactiveLoaders.removeAt(idx);
             info.destroy();
         }
-        if (mActivity != null && !hasRunningLoaders()) {
-            mActivity.mFragments.startPendingDeferredFragments();
+        if (mHost != null && !hasRunningLoaders()) {
+            mHost.mFragmentManager.startPendingDeferredFragments();
         }
     }
 
@@ -791,7 +842,7 @@
         sb.append("LoaderManager{");
         sb.append(Integer.toHexString(System.identityHashCode(this)));
         sb.append(" in ");
-        DebugUtils.buildShortClassTag(mActivity, sb);
+        DebugUtils.buildShortClassTag(mHost, sb);
         sb.append("}}");
         return sb.toString();
     }
diff --git a/v4/java/android/support/v4/app/NotificationCompat.java b/v4/java/android/support/v4/app/NotificationCompat.java
index 99c269e..b206e95 100644
--- a/v4/java/android/support/v4/app/NotificationCompat.java
+++ b/v4/java/android/support/v4/app/NotificationCompat.java
@@ -26,6 +26,7 @@
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Parcelable;
+import android.support.annotation.ColorInt;
 import android.support.v4.view.GravityCompat;
 import android.view.Gravity;
 import android.widget.RemoteViews;
@@ -342,6 +343,7 @@
      * telling the system not to decorate this notification with any special color but instead use
      * default colors when presenting this notification.
      */
+    @ColorInt
     public static final int COLOR_DEFAULT = Color.TRANSPARENT;
 
     /**
@@ -1198,7 +1200,7 @@
          * rate.  The rate is specified in terms of the number of milliseconds to be on
          * and then the number of milliseconds to be off.
          */
-        public Builder setLights(int argb, int onMs, int offMs) {
+        public Builder setLights(@ColorInt int argb, int onMs, int offMs) {
             mNotification.ledARGB = argb;
             mNotification.ledOnMS = onMs;
             mNotification.ledOffMS = offMs;
@@ -1504,7 +1506,7 @@
          *
          * @return The same Builder.
          */
-        public Builder setColor(int argb) {
+        public Builder setColor(@ColorInt int argb) {
             mColor = argb;
             return this;
         }
@@ -3012,7 +3014,7 @@
          * automotive setting. This method can be used to override the color provided in the
          * notification in such a situation.
          */
-        public CarExtender setColor(int color) {
+        public CarExtender setColor(@ColorInt int color) {
             mColor = color;
             return this;
         }
@@ -3022,6 +3024,7 @@
          *
          * @see setColor
          */
+        @ColorInt
         public int getColor() {
             return mColor;
         }
diff --git a/v4/java/android/support/v4/app/SharedElementCallback.java b/v4/java/android/support/v4/app/SharedElementCallback.java
index 7c0de86..8beb29d 100644
--- a/v4/java/android/support/v4/app/SharedElementCallback.java
+++ b/v4/java/android/support/v4/app/SharedElementCallback.java
@@ -48,9 +48,23 @@
     private static final String BUNDLE_SNAPSHOT_IMAGE_MATRIX = "sharedElement:snapshot:imageMatrix";
 
     /**
-     * Called immediately after the start state is set for the shared element.
-     * The shared element will start at the size and position of the shared element
-     * in the launching Activity or Fragment.
+     * In Activity Transitions, onSharedElementStart is called immediately before
+     * capturing the start of the shared element state on enter and reenter transitions and
+     * immediately before capturing the end of the shared element state for exit and return
+     * transitions.
+     * <p>
+     * In Fragment Transitions, onSharedElementStart is called immediately before capturing the
+     * start state of all shared element transitions.
+     * <p>
+     * This call can be used to adjust the transition start state by modifying the shared
+     * element Views. Note that no layout step will be executed between onSharedElementStart
+     * and the transition state capture.
+     * <p>
+     * For Activity Transitions, any changes made in {@link #onSharedElementEnd(List, List, List)}
+     * that are not updated during layout should be corrected in onSharedElementStart for exit and
+     * return transitions. For example, rotation or scale will not be affected by layout and
+     * if changed in {@link #onSharedElementEnd(List, List, List)}, it will also have to be reset
+     * in onSharedElementStart again to correct the end state.
      *
      * @param sharedElementNames The names of the shared elements that were accepted into
      *                           the View hierarchy.
@@ -65,17 +79,23 @@
             List<View> sharedElements, List<View> sharedElementSnapshots) {}
 
     /**
-     * Called after the end state is set for the shared element, but before the end state
-     * is captured by the shared element transition.
+     * In Activity Transitions, onSharedElementEnd is called immediately before
+     * capturing the end of the shared element state on enter and reenter transitions and
+     * immediately before capturing the start of the shared element state for exit and return
+     * transitions.
      * <p>
-     *     Any customization done in
-     *     {@link #onSharedElementStart(java.util.List, java.util.List, java.util.List)}
-     *     may need to be modified to the final state of the shared element if it is not
-     *     automatically corrected by layout. For example, rotation or scale will not
-     *     be affected by layout and if changed in {@link #onSharedElementStart(java.util.List,
-     *     java.util.List, java.util.List)}, it will also have to be set here again to correct
-     *     the end state.
-     * </p>
+     * In Fragment Transitions, onSharedElementEnd is called immediately before capturing the
+     * end state of all shared element transitions.
+     * <p>
+     * This call can be used to adjust the transition end state by modifying the shared
+     * element Views. Note that no layout step will be executed between onSharedElementEnd
+     * and the transition state capture.
+     * <p>
+     * Any changes made in {@link #onSharedElementStart(List, List, List)} that are not updated
+     * during layout should be corrected in onSharedElementEnd. For example, rotation or scale
+     * will not be affected by layout and if changed in
+     * {@link #onSharedElementStart(List, List, List)}, it will also have to be reset in
+     * onSharedElementEnd again to correct the end state.
      *
      * @param sharedElementNames The names of the shared elements that were accepted into
      *                           the View hierarchy.
diff --git a/v4/java/android/support/v4/content/AsyncTaskLoader.java b/v4/java/android/support/v4/content/AsyncTaskLoader.java
index 22fe3a2..17d7416 100644
--- a/v4/java/android/support/v4/content/AsyncTaskLoader.java
+++ b/v4/java/android/support/v4/content/AsyncTaskLoader.java
@@ -19,12 +19,14 @@
 import android.content.Context;
 import android.os.Handler;
 import android.os.SystemClock;
+import android.support.v4.os.OperationCanceledException;
 import android.support.v4.util.TimeUtils;
 import android.util.Log;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executor;
 
 /**
  * Static library support version of the framework's {@link android.content.AsyncTaskLoader}.
@@ -38,19 +40,33 @@
     static final boolean DEBUG = false;
 
     final class LoadTask extends ModernAsyncTask<Void, Void, D> implements Runnable {
+        private final CountDownLatch mDone = new CountDownLatch(1);
 
-        D result;
+        // Set to true to indicate that the task has been posted to a handler for
+        // execution at a later time.  Used to throttle updates.
         boolean waiting;
 
-        private CountDownLatch done = new CountDownLatch(1);
-
         /* Runs on a worker thread */
         @Override
         protected D doInBackground(Void... params) {
             if (DEBUG) Log.v(TAG, this + " >>> doInBackground");
-            result = AsyncTaskLoader.this.onLoadInBackground();
-            if (DEBUG) Log.v(TAG, this + "  <<< doInBackground");
-            return result;
+            try {
+                D data = AsyncTaskLoader.this.onLoadInBackground();
+                if (DEBUG) Log.v(TAG, this + "  <<< doInBackground");
+                return data;
+            } catch (OperationCanceledException ex) {
+                if (!isCancelled()) {
+                    // onLoadInBackground threw a canceled exception spuriously.
+                    // This is problematic because it means that the LoaderManager did not
+                    // cancel the Loader itself and still expects to receive a result.
+                    // Additionally, the Loader's own state will not have been updated to
+                    // reflect the fact that the task was being canceled.
+                    // So we treat this case as an unhandled exception.
+                    throw ex;
+                }
+                if (DEBUG) Log.v(TAG, this + "  <<< doInBackground (was canceled)", ex);
+                return null;
+            }
         }
 
         /* Runs on the UI thread */
@@ -60,27 +76,41 @@
             try {
                 AsyncTaskLoader.this.dispatchOnLoadComplete(this, data);
             } finally {
-                done.countDown();
+                mDone.countDown();
             }
         }
 
+        /* Runs on the UI thread */
         @Override
-        protected void onCancelled() {
+        protected void onCancelled(D data) {
             if (DEBUG) Log.v(TAG, this + " onCancelled");
             try {
-                AsyncTaskLoader.this.dispatchOnCancelled(this, result);
+                AsyncTaskLoader.this.dispatchOnCancelled(this, data);
             } finally {
-                done.countDown();
+                mDone.countDown();
             }
         }
 
+        /* Runs on the UI thread, when the waiting task is posted to a handler.
+         * This method is only executed when task execution was deferred (waiting was true). */
         @Override
         public void run() {
             waiting = false;
             AsyncTaskLoader.this.executePendingTask();
         }
+
+        /* Used for testing purposes to wait for the task to complete. */
+        public void waitForLoader() {
+            try {
+                mDone.await();
+            } catch (InterruptedException e) {
+                // Ignore
+            }
+        }
     }
 
+    private final Executor mExecutor;
+
     volatile LoadTask mTask;
     volatile LoadTask mCancellingTask;
 
@@ -89,12 +119,17 @@
     Handler mHandler;
 
     public AsyncTaskLoader(Context context) {
+        this(context, ModernAsyncTask.THREAD_POOL_EXECUTOR);
+    }
+
+    private AsyncTaskLoader(Context context, Executor executor) {
         super(context);
+        mExecutor = executor;
     }
 
     /**
      * Set amount to throttle updates by.  This is the minimum time from
-     * when the last {@link #onLoadInBackground()} call has completed until
+     * when the last {@link #loadInBackground()} call has completed until
      * a new load is scheduled.
      *
      * @param delayMS Amount of delay, in milliseconds.
@@ -115,24 +150,9 @@
         executePendingTask();
     }
 
-    /**
-     * Attempt to cancel the current load task. See {@link android.os.AsyncTask#cancel(boolean)}
-     * for more info.  Must be called on the main thread of the process.
-     *
-     * <p>Cancelling is not an immediate operation, since the load is performed
-     * in a background thread.  If there is currently a load in progress, this
-     * method requests that the load be cancelled, and notes this is the case;
-     * once the background thread has completed its work its remaining state
-     * will be cleared.  If another load request comes in during this time,
-     * it will be held until the cancelled load is complete.
-     *
-     * @return Returns <tt>false</tt> if the task could not be cancelled,
-     *         typically because it has already completed normally, or
-     *         because {@link #startLoading()} hasn't been called; returns
-     *         <tt>true</tt> otherwise.
-     */
-    public boolean cancelLoad() {
-        if (DEBUG) Log.v(TAG, "cancelLoad: mTask=" + mTask);
+    @Override
+    protected boolean onCancelLoad() {
+        if (DEBUG) Log.v(TAG, "onCancelLoad: mTask=" + mTask);
         if (mTask != null) {
             if (mCancellingTask != null) {
                 // There was a pending task already waiting for a previous
@@ -158,6 +178,7 @@
                 if (DEBUG) Log.v(TAG, "cancelLoad: cancelled=" + cancelled);
                 if (cancelled) {
                     mCancellingTask = mTask;
+                    cancelLoadInBackground();
                 }
                 mTask = null;
                 return cancelled;
@@ -168,7 +189,10 @@
 
     /**
      * Called if the task was canceled before it was completed.  Gives the class a chance
-     * to properly dispose of the result.
+     * to clean up post-cancellation and to properly dispose of the result.
+     *
+     * @param data The value that was returned by {@link #loadInBackground}, or null
+     * if the task threw {@link OperationCanceledException}.
      */
     public void onCanceled(D data) {
     }
@@ -192,7 +216,7 @@
                 }
             }
             if (DEBUG) Log.v(TAG, "Executing: " + mTask);
-            mTask.executeOnExecutor(ModernAsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null);
+            mTask.executeOnExecutor(mExecutor, (Void[]) null);
         }
     }
 
@@ -203,6 +227,8 @@
             rollbackContentChanged();
             mLastLoadCompleteTime = SystemClock.uptimeMillis();
             mCancellingTask = null;
+            if (DEBUG) Log.v(TAG, "Delivering cancellation");
+            deliverCancellation();
             executePendingTask();
         }
     }
@@ -226,23 +252,76 @@
     }
 
     /**
+     * Called on a worker thread to perform the actual load and to return
+     * the result of the load operation.
+     *
+     * Implementations should not deliver the result directly, but should return them
+     * from this method, which will eventually end up calling {@link #deliverResult} on
+     * the UI thread.  If implementations need to process the results on the UI thread
+     * they may override {@link #deliverResult} and do so there.
+     *
+     * To support cancellation, this method should periodically check the value of
+     * {@link #isLoadInBackgroundCanceled} and terminate when it returns true.
+     * Subclasses may also override {@link #cancelLoadInBackground} to interrupt the load
+     * directly instead of polling {@link #isLoadInBackgroundCanceled}.
+     *
+     * When the load is canceled, this method may either return normally or throw
+     * {@link OperationCanceledException}.  In either case, the {@link Loader} will
+     * call {@link #onCanceled} to perform post-cancellation cleanup and to dispose of the
+     * result object, if any.
+     *
+     * @return The result of the load operation.
+     *
+     * @throws OperationCanceledException if the load is canceled during execution.
+     *
+     * @see #isLoadInBackgroundCanceled
+     * @see #cancelLoadInBackground
+     * @see #onCanceled
      */
     public abstract D loadInBackground();
 
     /**
-     * Called on a worker thread to perform the actual load. Implementations should not deliver the
-     * result directly, but should return them from this method, which will eventually end up
-     * calling {@link #deliverResult} on the UI thread. If implementations need to process
-     * the results on the UI thread they may override {@link #deliverResult} and do so
-     * there.
+     * Calls {@link #loadInBackground()}.
      *
-     * @return Implementations must return the result of their load operation.
+     * This method is reserved for use by the loader framework.
+     * Subclasses should override {@link #loadInBackground} instead of this method.
+     *
+     * @return The result of the load operation.
+     *
+     * @throws OperationCanceledException if the load is canceled during execution.
+     *
+     * @see #loadInBackground
      */
     protected D onLoadInBackground() {
         return loadInBackground();
     }
 
     /**
+     * Called on the main thread to abort a load in progress.
+     *
+     * Override this method to abort the current invocation of {@link #loadInBackground}
+     * that is running in the background on a worker thread.
+     *
+     * This method should do nothing if {@link #loadInBackground} has not started
+     * running or if it has already finished.
+     *
+     * @see #loadInBackground
+     */
+    public void cancelLoadInBackground() {
+    }
+
+    /**
+     * Returns true if the current invocation of {@link #loadInBackground} is being canceled.
+     *
+     * @return True if the current invocation of {@link #loadInBackground} is being canceled.
+     *
+     * @see #loadInBackground
+     */
+    public boolean isLoadInBackgroundCanceled() {
+        return mCancellingTask != null;
+    }
+
+    /**
      * Locks the current thread until the loader completes the current load
      * operation. Returns immediately if there is no load operation running.
      * Should not be called from the UI thread: calling it from the UI
@@ -255,11 +334,7 @@
     public void waitForLoader() {
         LoadTask task = mTask;
         if (task != null) {
-            try {
-                task.done.await();
-            } catch (InterruptedException e) {
-                // Ignore
-            }
+            task.waitForLoader();
         }
     }
 
diff --git a/v4/java/android/support/v4/content/ContentResolverCompat.java b/v4/java/android/support/v4/content/ContentResolverCompat.java
new file mode 100644
index 0000000..3b5f01c
--- /dev/null
+++ b/v4/java/android/support/v4/content/ContentResolverCompat.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2013 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.v4.content;
+
+import android.content.ContentResolver;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Build;
+import android.support.v4.os.CancellationSignal;
+import android.support.v4.os.OperationCanceledException;
+
+/**
+ * Helper for accessing features in {@link android.content.ContentResolver}
+ * introduced after API level 4 in a backwards compatible fashion.
+ */
+public class ContentResolverCompat {
+    interface ContentResolverCompatImpl {
+        Cursor query(ContentResolver resolver,
+                Uri uri, String[] projection, String selection, String[] selectionArgs,
+                String sortOrder, CancellationSignal cancellationSignal);
+    }
+
+    static class ContentResolverCompatImplBase implements ContentResolverCompatImpl {
+        @Override
+        public Cursor query(ContentResolver resolver, Uri uri, String[] projection,
+                String selection, String[] selectionArgs, String sortOrder,
+                CancellationSignal cancellationSignal) {
+            // Note that the cancellation signal cannot cancel the query in progress
+            // prior to Jellybean so we cancel it preemptively here if needed.
+            if (cancellationSignal != null) {
+                cancellationSignal.throwIfCanceled();
+            }
+            return resolver.query(uri, projection, selection, selectionArgs, sortOrder);
+        }
+    }
+
+    static class ContentResolverCompatImplJB extends ContentResolverCompatImplBase {
+        @Override
+        public Cursor query(ContentResolver resolver, Uri uri, String[] projection,
+                String selection, String[] selectionArgs, String sortOrder,
+                CancellationSignal cancellationSignal) {
+            return ContentResolverCompatJellybean.query(resolver,
+                    uri, projection, selection, selectionArgs, sortOrder,
+                    cancellationSignal != null ?
+                            cancellationSignal.getCancellationSignalObject() : null);
+        }
+    }
+
+    private static final ContentResolverCompatImpl IMPL;
+    static {
+        final int version = Build.VERSION.SDK_INT;
+        if (version >= 16) {
+            IMPL = new ContentResolverCompatImplJB();
+        } else {
+            IMPL = new ContentResolverCompatImplBase();
+        }
+    }
+
+    private ContentResolverCompat() {
+        /* Hide constructor */
+    }
+
+    /**
+     * Query the given URI, returning a {@link Cursor} over the result set
+     * with optional support for cancellation.
+     * <p>
+     * For best performance, the caller should follow these guidelines:
+     * <ul>
+     * <li>Provide an explicit projection, to prevent
+     * reading data from storage that aren't going to be used.</li>
+     * <li>Use question mark parameter markers such as 'phone=?' instead of
+     * explicit values in the {@code selection} parameter, so that queries
+     * that differ only by those values will be recognized as the same
+     * for caching purposes.</li>
+     * </ul>
+     * </p>
+     *
+     * @param uri The URI, using the content:// scheme, for the content to
+     *         retrieve.
+     * @param projection A list of which columns to return. Passing null will
+     *         return all columns, which is inefficient.
+     * @param selection A filter declaring which rows to return, formatted as an
+     *         SQL WHERE clause (excluding the WHERE itself). Passing null will
+     *         return all rows for the given URI.
+     * @param selectionArgs You may include ?s in selection, which will be
+     *         replaced by the values from selectionArgs, in the order that they
+     *         appear in the selection. The values will be bound as Strings.
+     * @param sortOrder How to order the rows, formatted as an SQL ORDER BY
+     *         clause (excluding the ORDER BY itself). Passing null will use the
+     *         default sort order, which may be unordered.
+     * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
+     * If the operation is canceled, then {@link OperationCanceledException} will be thrown
+     * when the query is executed.
+     * @return A Cursor object, which is positioned before the first entry, or null
+     * @see Cursor
+     */
+    public static Cursor query(ContentResolver resolver,
+            Uri uri, String[] projection, String selection, String[] selectionArgs,
+            String sortOrder, CancellationSignal cancellationSignal) {
+        return IMPL.query(resolver, uri, projection, selection, selectionArgs,
+                sortOrder, cancellationSignal);
+    }
+}
diff --git a/v4/java/android/support/v4/content/ContextCompat.java b/v4/java/android/support/v4/content/ContextCompat.java
index 5c632dd..47baf8a 100644
--- a/v4/java/android/support/v4/content/ContextCompat.java
+++ b/v4/java/android/support/v4/content/ContextCompat.java
@@ -19,11 +19,13 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
+import android.content.res.ColorStateList;
 import android.graphics.drawable.Drawable;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Environment;
-import android.os.StatFs;
+import android.os.Process;
+import android.support.annotation.NonNull;
 import android.support.v4.os.EnvironmentCompat;
 import android.util.Log;
 
@@ -95,7 +97,7 @@
      * @param intents Array of intents defining the activities that will be started. The element
      *                length-1 will correspond to the top activity on the resulting task stack.
      * @param options Additional options for how the Activity should be started.
-     * See {@link android.content.Context#startActivity(Intent, Bundle)
+     * See {@link android.content.Context#startActivity(Intent, android.os.Bundle)
      * @return true if the underlying API was available and the call was successful, false otherwise
      */
     public static boolean startActivities(Context context, Intent[] intents,
@@ -133,7 +135,7 @@
      * <p>
      * An application may store data on any or all of the returned devices. For
      * example, an app may choose to store large files on the device with the
-     * most available space, as measured by {@link StatFs}.
+     * most available space, as measured by {@link android.os.StatFs}.
      * <p>
      * Starting in {@link android.os.Build.VERSION_CODES#KITKAT}, no permissions
      * are required to write to the returned paths; they're always accessible to
@@ -192,7 +194,7 @@
      * <p>
      * An application may store data on any or all of the returned devices. For
      * example, an app may choose to store large files on the device with the
-     * most available space, as measured by {@link StatFs}.
+     * most available space, as measured by {@link android.os.StatFs}.
      * <p>
      * Starting in {@link android.os.Build.VERSION_CODES#KITKAT}, no permissions
      * are required to write to the returned paths; they're always accessible to
@@ -252,7 +254,7 @@
      * <p>
      * An application may store data on any or all of the returned devices. For
      * example, an app may choose to store large files on the device with the
-     * most available space, as measured by {@link StatFs}.
+     * most available space, as measured by {@link android.os.StatFs}.
      * <p>
      * Starting in {@link android.os.Build.VERSION_CODES#KITKAT}, no permissions
      * are required to write to the returned paths; they're always accessible to
@@ -323,6 +325,69 @@
     }
 
     /**
+     * Returns a color state list associated with a particular resource ID.
+     * <p>
+     * Starting in {@link android.os.Build.VERSION_CODES#MNC}, the returned
+     * color state list will be styled for the specified Context's theme.
+     *
+     * @param id The desired resource identifier, as generated by the aapt
+     *           tool. This integer encodes the package, type, and resource
+     *           entry. The value 0 is an invalid identifier.
+     * @return A color state list, or {@code null} if the resource could not be
+     *         resolved.
+     * @throws android.content.res.Resources.NotFoundException if the given ID
+     *         does not exist.
+     */
+    public static final ColorStateList getColorStateList(Context context, int id) {
+        final int version = Build.VERSION.SDK_INT;
+        if (version >= 23) {
+            return ContextCompatApi23.getColorStateList(context, id);
+        } else {
+            return context.getResources().getColorStateList(id);
+        }
+    }
+
+    /**
+     * Returns a color associated with a particular resource ID
+     * <p>
+     * Starting in {@link android.os.Build.VERSION_CODES#MNC}, the returned
+     * color will be styled for the specified Context's theme.
+     *
+     * @param id The desired resource identifier, as generated by the aapt
+     *           tool. This integer encodes the package, type, and resource
+     *           entry. The value 0 is an invalid identifier.
+     * @return A single color value in the form 0xAARRGGBB.
+     * @throws android.content.res.Resources.NotFoundException if the given ID
+     *         does not exist.
+     */
+    public static final int getColor(Context context, int id) {
+        final int version = Build.VERSION.SDK_INT;
+        if (version >= 23) {
+            return ContextCompatApi23.getColor(context, id);
+        } else {
+            return context.getResources().getColor(id);
+        }
+    }
+
+    /**
+     * Determine whether <em>you</em> have been granted a particular permission.
+     *
+     * @param permission The name of the permission being checked.
+     *
+     * @return {@link android.content.pm.PackageManager#PERMISSION_GRANTED} if you have the
+     * permission, or {@link android.content.pm.PackageManager#PERMISSION_DENIED} if not.
+     *
+     * @see android.content.pm.PackageManager#checkPermission(String, String)
+     */
+    public static int checkSelfPermission(@NonNull Context context, @NonNull String permission) {
+        if (permission == null) {
+            throw new IllegalArgumentException("permission is null");
+        }
+
+        return context.checkPermission(permission, android.os.Process.myPid(), Process.myUid());
+    }
+
+    /**
      * Returns the absolute path to the directory on the filesystem similar to
      * {@link Context#getFilesDir()}.  The difference is that files placed under this
      * directory will be excluded from automatic backup to remote storage on
diff --git a/v4/java/android/support/v4/content/CursorLoader.java b/v4/java/android/support/v4/content/CursorLoader.java
index 980e7d9..503bb9c 100644
--- a/v4/java/android/support/v4/content/CursorLoader.java
+++ b/v4/java/android/support/v4/content/CursorLoader.java
@@ -16,10 +16,12 @@
 
 package android.support.v4.content;
 
+import android.content.ContentResolver;
 import android.content.Context;
-import android.database.ContentObserver;
 import android.database.Cursor;
 import android.net.Uri;
+import android.support.v4.os.CancellationSignal;
+import android.support.v4.os.OperationCanceledException;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -42,18 +44,48 @@
     String mSortOrder;
 
     Cursor mCursor;
+    CancellationSignal mCancellationSignal;
 
     /* Runs on a worker thread */
     @Override
     public Cursor loadInBackground() {
-        Cursor cursor = getContext().getContentResolver().query(mUri, mProjection, mSelection,
-                mSelectionArgs, mSortOrder);
-        if (cursor != null) {
-            // Ensure the cursor window is filled
-            cursor.getCount();
-            cursor.registerContentObserver(mObserver);
+        synchronized (this) {
+            if (isLoadInBackgroundCanceled()) {
+                throw new OperationCanceledException();
+            }
+            mCancellationSignal = new CancellationSignal();
         }
-        return cursor;
+        try {
+            Cursor cursor = ContentResolverCompat.query(getContext().getContentResolver(),
+                    mUri, mProjection, mSelection, mSelectionArgs, mSortOrder,
+                    mCancellationSignal);
+            if (cursor != null) {
+                try {
+                    // Ensure the cursor window is filled.
+                    cursor.getCount();
+                    cursor.registerContentObserver(mObserver);
+                } catch (RuntimeException ex) {
+                    cursor.close();
+                    throw ex;
+                }
+            }
+            return cursor;
+        } finally {
+            synchronized (this) {
+                mCancellationSignal = null;
+            }
+        }
+    }
+
+    @Override
+    public void cancelLoadInBackground() {
+        super.cancelLoadInBackground();
+
+        synchronized (this) {
+            if (mCancellationSignal != null) {
+                mCancellationSignal.cancel();
+            }
+        }
     }
 
     /* Runs on the UI thread */
@@ -90,7 +122,7 @@
 
     /**
      * Creates a fully-specified CursorLoader.  See
-     * {@link android.content.ContentResolver#query(Uri, String[], String, String[], String)
+     * {@link ContentResolver#query(Uri, String[], String, String[], String)
      * ContentResolver.query()} for documentation on the meaning of the
      * parameters.  These will be passed as-is to that call.
      */
diff --git a/v4/java/android/support/v4/content/Loader.java b/v4/java/android/support/v4/content/Loader.java
index bd01b0a..cf6cc99 100644
--- a/v4/java/android/support/v4/content/Loader.java
+++ b/v4/java/android/support/v4/content/Loader.java
@@ -34,6 +34,7 @@
 public class Loader<D> {
     int mId;
     OnLoadCompleteListener<D> mListener;
+    OnLoadCanceledListener<D> mOnLoadCanceledListener;
     Context mContext;
     boolean mStarted = false;
     boolean mAbandoned = false;
@@ -45,8 +46,8 @@
      * An implementation of a ContentObserver that takes care of connecting
      * it to the Loader to have the loader re-load its data when the observer
      * is told it has changed.  You do not normally need to use this yourself;
-     * it is used for you by {@link android.support.v4.content.CursorLoader}
-     * to take care of executing an update when the cursor's backing data changes.
+     * it is used for you by {@link CursorLoader} to take care of executing
+     * an update when the cursor's backing data changes.
      */
     public final class ForceLoadContentObserver extends ContentObserver {
         public ForceLoadContentObserver() {
@@ -83,8 +84,29 @@
     }
 
     /**
-     * Stores away the application context associated with context. Since Loaders can be used
-     * across multiple activities it's dangerous to store the context directly.
+     * Interface that is implemented to discover when a Loader has been canceled
+     * before it finished loading its data.  You do not normally need to implement
+     * this yourself; it is used in the implementation of {@link android.support.v4.app.LoaderManager}
+     * to find out when a Loader it is managing has been canceled so that it
+     * can schedule the next Loader.  This interface should only be used if a
+     * Loader is not being used in conjunction with LoaderManager.
+     */
+    public interface OnLoadCanceledListener<D> {
+        /**
+         * Called on the thread that created the Loader when the load is canceled.
+         *
+         * @param loader the loader that canceled the load
+         */
+        public void onLoadCanceled(Loader<D> loader);
+    }
+
+    /**
+     * Stores away the application context associated with context.
+     * Since Loaders can be used across multiple activities it's dangerous to
+     * store the context directly; always use {@link #getContext()} to retrieve
+     * the Loader's Context, don't use the constructor argument directly.
+     * The Context returned by {@link #getContext} is safe to use across
+     * Activity instances.
      *
      * @param context used to retrieve the application context.
      */
@@ -106,6 +128,18 @@
     }
 
     /**
+     * Informs the registered {@link OnLoadCanceledListener} that the load has been canceled.
+     * Should only be called by subclasses.
+     *
+     * Must be called from the process's main thread.
+     */
+    public void deliverCancellation() {
+        if (mOnLoadCanceledListener != null) {
+            mOnLoadCanceledListener.onLoadCanceled(this);
+        }
+    }
+
+    /**
      * @return an application context retrieved from the Context passed to the constructor.
      */
     public Context getContext() {
@@ -150,6 +184,40 @@
     }
 
     /**
+     * Registers a listener that will receive callbacks when a load is canceled.
+     * The callback will be called on the process's main thread so it's safe to
+     * pass the results to widgets.
+     *
+     * Must be called from the process's main thread.
+     *
+     * @param listener The listener to register.
+     */
+    public void registerOnLoadCanceledListener(OnLoadCanceledListener<D> listener) {
+        if (mOnLoadCanceledListener != null) {
+            throw new IllegalStateException("There is already a listener registered");
+        }
+        mOnLoadCanceledListener = listener;
+    }
+
+    /**
+     * Unregisters a listener that was previously added with
+     * {@link #registerOnLoadCanceledListener}.
+     *
+     * Must be called from the process's main thread.
+     *
+     * @param listener The listener to unregister.
+     */
+    public void unregisterOnLoadCanceledListener(OnLoadCanceledListener<D> listener) {
+        if (mOnLoadCanceledListener == null) {
+            throw new IllegalStateException("No listener register");
+        }
+        if (mOnLoadCanceledListener != listener) {
+            throw new IllegalArgumentException("Attempting to unregister the wrong listener");
+        }
+        mOnLoadCanceledListener = null;
+    }
+
+    /**
      * Return whether this load has been started.  That is, its {@link #startLoading()}
      * has been called and no calls to {@link #stopLoading()} or
      * {@link #reset()} have yet been made.
@@ -177,6 +245,12 @@
     }
 
     /**
+     * This function will normally be called for you automatically by
+     * {@link android.support.v4.app.LoaderManager} when the associated fragment/activity
+     * is being started.  When using a Loader with {@link android.support.v4.app.LoaderManager},
+     * you <em>must not</em> call this method yourself, or you will conflict
+     * with its management of the Loader.
+     *
      * Starts an asynchronous load of the Loader's data. When the result
      * is ready the callbacks will be called on the process's main thread.
      * If a previous load has been completed and is still valid
@@ -207,6 +281,43 @@
     }
 
     /**
+     * Attempt to cancel the current load task.
+     * Must be called on the main thread of the process.
+     *
+     * <p>Cancellation is not an immediate operation, since the load is performed
+     * in a background thread.  If there is currently a load in progress, this
+     * method requests that the load be canceled, and notes this is the case;
+     * once the background thread has completed its work its remaining state
+     * will be cleared.  If another load request comes in during this time,
+     * it will be held until the canceled load is complete.
+     *
+     * @return Returns <tt>false</tt> if the task could not be canceled,
+     * typically because it has already completed normally, or
+     * because {@link #startLoading()} hasn't been called; returns
+     * <tt>true</tt> otherwise.  When <tt>true</tt> is returned, the task
+     * is still running and the {@link OnLoadCanceledListener} will be called
+     * when the task completes.
+     */
+    public boolean cancelLoad() {
+        return onCancelLoad();
+    }
+
+    /**
+     * Subclasses must implement this to take care of requests to {@link #cancelLoad()}.
+     * This will always be called from the process's main thread.
+     *
+     * @return Returns <tt>false</tt> if the task could not be canceled,
+     * typically because it has already completed normally, or
+     * because {@link #startLoading()} hasn't been called; returns
+     * <tt>true</tt> otherwise.  When <tt>true</tt> is returned, the task
+     * is still running and the {@link OnLoadCanceledListener} will be called
+     * when the task completes.
+     */
+    protected boolean onCancelLoad() {
+        return false;
+    }
+
+    /**
      * Force an asynchronous load. Unlike {@link #startLoading()} this will ignore a previously
      * loaded data set and load a new one.  This simply calls through to the
      * implementation's {@link #onForceLoad()}.  You generally should only call this
@@ -226,7 +337,13 @@
     }
 
     /**
-     * Stops delivery of updates until the next time {@link #startLoading()} is called.
+     * This function will normally be called for you automatically by
+     * {@link android.support.v4.app.LoaderManager} when the associated fragment/activity
+     * is being stopped.  When using a Loader with {@link android.support.v4.app.LoaderManager},
+     * you <em>must not</em> call this method yourself, or you will conflict
+     * with its management of the Loader.
+     *
+     * <p>Stops delivery of updates until the next time {@link #startLoading()} is called.
      * Implementations should <em>not</em> invalidate their data at this point --
      * clients are still free to use the last data the loader reported.  They will,
      * however, typically stop reporting new data if the data changes; they can
@@ -254,6 +371,12 @@
     }
 
     /**
+     * This function will normally be called for you automatically by
+     * {@link android.support.v4.app.LoaderManager} when restarting a Loader.  When using
+     * a Loader with {@link android.support.v4.app.LoaderManager},
+     * you <em>must not</em> call this method yourself, or you will conflict
+     * with its management of the Loader.
+     *
      * Tell the Loader that it is being abandoned.  This is called prior
      * to {@link #reset} to have it retain its current data but not report
      * any new data.
@@ -272,10 +395,16 @@
      * {@link #onReset()} happens.  You can retrieve the current abandoned
      * state with {@link #isAbandoned}.
      */
-    protected void onAbandon() {        
+    protected void onAbandon() {
     }
     
     /**
+     * This function will normally be called for you automatically by
+     * {@link android.support.v4.app.LoaderManager} when destroying a Loader.  When using
+     * a Loader with {@link android.support.v4.app.LoaderManager},
+     * you <em>must not</em> call this method yourself, or you will conflict
+     * with its management of the Loader.
+     *
      * Resets the state of the Loader.  The Loader should at this point free
      * all of its resources, since it may never be called again; however, its
      * {@link #startLoading()} may later be called at which point it must be
diff --git a/v4/java/android/support/v4/content/ModernAsyncTask.java b/v4/java/android/support/v4/content/ModernAsyncTask.java
index 43b17f4..6744aa8 100644
--- a/v4/java/android/support/v4/content/ModernAsyncTask.java
+++ b/v4/java/android/support/v4/content/ModernAsyncTask.java
@@ -30,7 +30,9 @@
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
 
+import android.os.AsyncTask;
 import android.os.Handler;
+import android.os.Looper;
 import android.os.Message;
 import android.os.Process;
 
@@ -72,7 +74,7 @@
     private static final int MESSAGE_POST_RESULT = 0x1;
     private static final int MESSAGE_POST_PROGRESS = 0x2;
 
-    private static final InternalHandler sHandler = new InternalHandler();
+    private static InternalHandler sHandler;
 
     private static volatile Executor sDefaultExecutor = THREAD_POOL_EXECUTOR;
     private final WorkerRunnable<Params, Result> mWorker;
@@ -101,9 +103,13 @@
         FINISHED,
     }
 
-    /** @hide Used to force static handler to be created. */
-    public static void init() {
-        sHandler.getLooper();
+    private static Handler getHandler() {
+        synchronized (AsyncTask.class) {
+            if (sHandler == null) {
+                sHandler = new InternalHandler();
+            }
+            return sHandler;
+        }
     }
 
     /** @hide */
@@ -134,13 +140,13 @@
                 } catch (InterruptedException e) {
                     android.util.Log.w(LOG_TAG, e);
                 } catch (ExecutionException e) {
-                    throw new RuntimeException("An error occured while executing doInBackground()",
-                            e.getCause());
+                    throw new RuntimeException(
+                            "An error occurred while executing doInBackground()", e.getCause());
                 } catch (CancellationException e) {
                     postResultIfNotInvoked(null);
                 } catch (Throwable t) {
-                    throw new RuntimeException("An error occured while executing "
-                            + "doInBackground()", t);
+                    throw new RuntimeException(
+                            "An error occurred while executing doInBackground()", t);
                 }
             }
         };
@@ -154,7 +160,7 @@
     }
 
     private Result postResult(Result result) {
-        Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT,
+        Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
                 new AsyncTaskResult<Result>(this, result));
         message.sendToTarget();
         return result;
@@ -449,7 +455,7 @@
      */
     protected final void publishProgress(Progress... values) {
         if (!isCancelled()) {
-            sHandler.obtainMessage(MESSAGE_POST_PROGRESS,
+            getHandler().obtainMessage(MESSAGE_POST_PROGRESS,
                     new AsyncTaskResult<Progress>(this, values)).sendToTarget();
         }
     }
@@ -464,6 +470,10 @@
     }
 
     private static class InternalHandler extends Handler {
+        public InternalHandler() {
+            super(Looper.getMainLooper());
+        }
+
         @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
         @Override
         public void handleMessage(Message msg) {
diff --git a/v4/java/android/support/v4/content/PermissionChecker.java b/v4/java/android/support/v4/content/PermissionChecker.java
new file mode 100644
index 0000000..1c864c4
--- /dev/null
+++ b/v4/java/android/support/v4/content/PermissionChecker.java
@@ -0,0 +1,165 @@
+/*
+ * 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.v4.content;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.Binder;
+import android.os.Process;
+import android.support.annotation.IntDef;
+import android.support.annotation.NonNull;
+import android.support.v4.app.AppOpsManagerCompat;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * This class provides permission check APIs that verify both the
+ * permission and the associated app op for this permission if
+ * such is defined.
+ * <p>
+ * In the new permission model permissions with protection level
+ * dangerous are runtime permissions. For apps targeting API MNC
+ * and above the user may not grant such permissions or revoke
+ * them at any time. For apps targeting API lower than MNC these
+ * permissions are always granted as such apps do not expect
+ * permission revocations and would crash. Therefore, when the
+ * user disables a permission for a legacy app in the UI the
+ * platform disables the APIs guarded by this permission making
+ * them a no-op which is doing nothing or returning an empty
+ * result or default error.
+ * </p>
+ * <p>
+ * It is important that when you perform an operation on behalf of
+ * another app you use these APIs to check for permissions as the
+ * app may be a legacy app that does not participate in the new
+ * permission model for which the user had disabled the "permission"
+ * which is achieved by disallowing the corresponding app op.
+ * </p>
+ */
+public final class PermissionChecker {
+    /** Permission result: The permission is granted. */
+    public static final int PERMISSION_GRANTED =  PackageManager.PERMISSION_GRANTED;
+
+    /** Permission result: The permission is denied. */
+    public static final int PERMISSION_DENIED =  PackageManager.PERMISSION_DENIED;
+
+    /** Permission result: The permission is denied because the app op is not allowed. */
+    public static final int PERMISSION_DENIED_APP_OP =  PackageManager.PERMISSION_DENIED  - 1;
+
+    @IntDef({PERMISSION_GRANTED,
+            PERMISSION_DENIED,
+            PERMISSION_DENIED_APP_OP})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface PermissionResult {}
+
+    private PermissionChecker() {
+        /* do nothing */
+    }
+
+    /**
+     * Checks whether a given package in a UID and PID has a given permission
+     * and whether the app op that corresponds to this permission is allowed.
+     *
+     * @param context Context for accessing resources.
+     * @param permission The permission to check.
+     * @param pid The process id for which to check.
+     * @param uid The uid for which to check.
+     * @param packageName The package name for which to check. If null the
+     *     the first package for the calling UID will be used.
+     * @return The permission check result which is either {@link #PERMISSION_GRANTED}
+     *     or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}.
+     */
+    public static int checkPermission(@NonNull Context context, @NonNull String permission,
+            int pid, int uid, String packageName) {
+        if (context.checkPermission(permission, pid, uid) == PackageManager.PERMISSION_DENIED) {
+            return PERMISSION_DENIED;
+        }
+
+        String op = AppOpsManagerCompat.permissionToOp(permission);
+        if (op == null) {
+            return PERMISSION_GRANTED;
+        }
+
+        if (packageName == null) {
+            String[] packageNames = context.getPackageManager().getPackagesForUid(uid);
+            if (packageNames == null || packageNames.length <= 0) {
+                return PERMISSION_DENIED;
+            }
+            packageName = packageNames[0];
+        }
+
+        if (AppOpsManagerCompat.noteOp(context, op, uid, packageName)
+                != AppOpsManagerCompat.MODE_ALLOWED) {
+            return PERMISSION_DENIED_APP_OP;
+        }
+
+        return PERMISSION_GRANTED;
+    }
+
+    /**
+     * Checks whether your app has a given permission and whether the app op
+     * that corresponds to this permission is allowed.
+     *
+     * @param context Context for accessing resources.
+     * @param permission The permission to check.
+     * @return The permission check result which is either {@link #PERMISSION_GRANTED}
+     *     or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}.
+     */
+    public static int checkSelfPermission(@NonNull Context context,
+            @NonNull String permission) {
+        return checkPermission(context, permission, android.os.Process.myPid(),
+                android.os.Process.myUid(), context.getPackageName());
+    }
+
+    /**
+     * Checks whether the IPC you are handling has a given permission and whether
+     * the app op that corresponds to this permission is allowed.
+     *
+     * @param context Context for accessing resources.
+     * @param permission The permission to check.
+     * @param packageName The package name making the IPC. If null the
+     *     the first package for the calling UID will be used.
+     * @return The permission check result which is either {@link #PERMISSION_GRANTED}
+     *     or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}.
+     */
+    public static int checkCallingPermission(@NonNull Context context,
+            @NonNull String permission, String packageName) {
+        if (Binder.getCallingPid() == Process.myPid()) {
+            return PackageManager.PERMISSION_DENIED;
+        }
+        return checkPermission(context, permission, android.os.Process.myPid(),
+                android.os.Process.myUid(), packageName);
+    }
+
+    /**
+     * Checks whether the IPC you are handling or your app has a given permission
+     * and whether the app op that corresponds to this permission is allowed.
+     *
+     * @param context Context for accessing resources.
+     * @param permission The permission to check.
+     * @return The permission check result which is either {@link #PERMISSION_GRANTED}
+     *     or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}.
+     */
+    public static int checkCallingOrSelfPermission(@NonNull Context context,
+            @NonNull String permission) {
+        String packageName = (Binder.getCallingPid() == Process.myPid())
+                ? context.getPackageName() : null;
+        return checkPermission(context, permission, Binder.getCallingPid(),
+                Binder.getCallingUid(), packageName);
+    }
+}
diff --git a/v4/java/android/support/v4/content/SharedPreferencesCompat.java b/v4/java/android/support/v4/content/SharedPreferencesCompat.java
new file mode 100644
index 0000000..dca99a8
--- /dev/null
+++ b/v4/java/android/support/v4/content/SharedPreferencesCompat.java
@@ -0,0 +1,71 @@
+/*
+ * 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.v4.content;
+
+import android.content.SharedPreferences;
+import android.os.Build;
+import android.support.annotation.NonNull;
+
+public class SharedPreferencesCompat {
+
+    public static class EditorCompat {
+
+        private static EditorCompat sInstance;
+
+        private interface Helper {
+            void apply(@NonNull SharedPreferences.Editor editor);
+        }
+
+        private static class EditorHelperBaseImpl implements Helper {
+
+            @Override
+            public void apply(@NonNull SharedPreferences.Editor editor) {
+                editor.commit();
+            }
+        }
+
+        private static class EditorHelperApi9Impl implements Helper {
+
+            @Override
+            public void apply(@NonNull SharedPreferences.Editor editor) {
+                EditorCompatGingerbread.apply(editor);
+            }
+        }
+
+        private final Helper mHelper;
+
+        private EditorCompat() {
+            if (Build.VERSION.SDK_INT >= 9) {
+                mHelper = new EditorHelperApi9Impl();
+            } else {
+                mHelper = new EditorHelperBaseImpl();
+            }
+        }
+
+        public static EditorCompat getInstance() {
+            if (sInstance == null) {
+                sInstance = new EditorCompat();
+            }
+            return sInstance;
+        }
+
+        public void apply(@NonNull SharedPreferences.Editor editor) {
+            mHelper.apply(editor);
+        }
+    }
+
+}
diff --git a/v4/java/android/support/v4/content/res/TypedArrayUtils.java b/v4/java/android/support/v4/content/res/TypedArrayUtils.java
new file mode 100644
index 0000000..79e4ac8
--- /dev/null
+++ b/v4/java/android/support/v4/content/res/TypedArrayUtils.java
@@ -0,0 +1,73 @@
+/*
+ * 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.v4.content.res;
+
+import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
+import android.support.annotation.AnyRes;
+import android.support.annotation.StyleableRes;
+
+/**
+ * Compat methods for accessing TypedArray values.
+ *
+ * @hide
+ */
+public class TypedArrayUtils {
+    public static boolean getBoolean(TypedArray a, @StyleableRes int index,
+            @StyleableRes int fallbackIndex, boolean defaultValue) {
+        boolean val = a.getBoolean(fallbackIndex, defaultValue);
+        return a.getBoolean(index, val);
+    }
+
+    public static Drawable getDrawable(TypedArray a, @StyleableRes int index,
+            @StyleableRes int fallbackIndex) {
+        Drawable val = a.getDrawable(index);
+        if (val == null) {
+            val = a.getDrawable(fallbackIndex);
+        }
+        return val;
+    }
+
+    public static int getInt(TypedArray a, @StyleableRes int index,
+            @StyleableRes int fallbackIndex, int defaultValue) {
+        int val = a.getInt(fallbackIndex, defaultValue);
+        return a.getInt(index, val);
+    }
+
+    public static @AnyRes int getResourceId(TypedArray a, @StyleableRes int index,
+            @StyleableRes int fallbackIndex, @AnyRes int defaultValue) {
+        int val = a.getResourceId(fallbackIndex, defaultValue);
+        return a.getResourceId(index, val);
+    }
+
+    public static String getString(TypedArray a, @StyleableRes int index,
+            @StyleableRes int fallbackIndex) {
+        String val = a.getString(index);
+        if (val == null) {
+            val = a.getString(fallbackIndex);
+        }
+        return val;
+    }
+
+    public static CharSequence[] getTextArray(TypedArray a, @StyleableRes int index,
+            @StyleableRes int fallbackIndex) {
+        CharSequence[] val = a.getTextArray(index);
+        if (val == null) {
+            val = a.getTextArray(fallbackIndex);
+        }
+        return val;
+    }
+}
diff --git a/v4/java/android/support/v4/graphics/drawable/DrawableCompat.java b/v4/java/android/support/v4/graphics/drawable/DrawableCompat.java
index 99c762f..7d868b4 100644
--- a/v4/java/android/support/v4/graphics/drawable/DrawableCompat.java
+++ b/v4/java/android/support/v4/graphics/drawable/DrawableCompat.java
@@ -19,6 +19,7 @@
 import android.content.res.ColorStateList;
 import android.graphics.PorterDuff;
 import android.graphics.drawable.Drawable;
+import android.support.v4.view.ViewCompat;
 
 /**
  * Helper for accessing features in {@link android.graphics.drawable.Drawable}
@@ -38,6 +39,8 @@
         void setTintList(Drawable drawable, ColorStateList tint);
         void setTintMode(Drawable drawable, PorterDuff.Mode tintMode);
         Drawable wrap(Drawable drawable);
+        void setLayoutDirection(Drawable drawable, int layoutDirection);
+        int getLayoutDirection(Drawable drawable);
     }
 
     /**
@@ -84,6 +87,16 @@
         public Drawable wrap(Drawable drawable) {
             return DrawableCompatBase.wrapForTinting(drawable);
         }
+
+        @Override
+        public void setLayoutDirection(Drawable drawable, int layoutDirection) {
+            // No op for API < 23
+        }
+
+        @Override
+        public int getLayoutDirection(Drawable drawable) {
+            return ViewCompat.LAYOUT_DIRECTION_LTR;
+        }
     }
 
     /**
@@ -167,12 +180,29 @@
     }
 
     /**
+     * Interface implementation for devices with at least M APIs.
+     */
+    static class MDrawableImpl extends LollipopMr1DrawableImpl {
+        @Override
+        public void setLayoutDirection(Drawable drawable, int layoutDirection) {
+            DrawableCompatApi23.setLayoutDirection(drawable, layoutDirection);
+        }
+
+        @Override
+        public int getLayoutDirection(Drawable drawable) {
+            return DrawableCompatApi23.getLayoutDirection(drawable);
+        }
+    }
+
+    /**
      * Select the correct implementation to use for the current platform.
      */
     static final DrawableImpl IMPL;
     static {
         final int version = android.os.Build.VERSION.SDK_INT;
-        if (version >= 22) {
+        if (version >= 23) {
+            IMPL = new MDrawableImpl();
+        } else if (version >= 22) {
             IMPL = new LollipopMr1DrawableImpl();
         } else if (version >= 21) {
             IMPL = new LollipopDrawableImpl();
@@ -315,4 +345,29 @@
         }
         return (T) drawable;
     }
+
+    /**
+     * Set the layout direction for this drawable. Should be a resolved
+     * layout direction, as the Drawable has no capacity to do the resolution on
+     * its own.
+     *
+     * @param layoutDirection the resolved layout direction for the drawable,
+     *                        either {@link ViewCompat#LAYOUT_DIRECTION_LTR}
+     *                        or {@link ViewCompat#LAYOUT_DIRECTION_RTL}
+     * @see #getLayoutDirection(Drawable)
+     */
+    public static void setLayoutDirection(Drawable drawable, int layoutDirection) {
+        IMPL.setLayoutDirection(drawable, layoutDirection);
+    }
+
+    /**
+     * Returns the resolved layout direction for this Drawable.
+     *
+     * @return One of {@link ViewCompat#LAYOUT_DIRECTION_LTR},
+     *         {@link ViewCompat#LAYOUT_DIRECTION_RTL}
+     * @see #setLayoutDirection(Drawable, int)
+     */
+    public static int getLayoutDirection(Drawable drawable) {
+        return IMPL.getLayoutDirection(drawable);
+    }
 }
diff --git a/v4/java/android/support/v4/hardware/fingerprint/FingerprintManagerCompat.java b/v4/java/android/support/v4/hardware/fingerprint/FingerprintManagerCompat.java
new file mode 100644
index 0000000..0384f16
--- /dev/null
+++ b/v4/java/android/support/v4/hardware/fingerprint/FingerprintManagerCompat.java
@@ -0,0 +1,287 @@
+/*
+ * 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.v4.hardware.fingerprint;
+
+import android.content.Context;
+import android.os.Build;
+import android.os.Handler;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v4.os.CancellationSignal;
+
+import java.security.Signature;
+
+import javax.crypto.Cipher;
+
+/**
+ * A class that coordinates access to the fingerprint hardware.
+ * <p>
+ * On platforms before MNC, this class behaves as there would be no fingerprint hardware available.
+ */
+public class FingerprintManagerCompat {
+
+    private Context mContext;
+
+    /** Get a {@link FingerprintManagerCompat} instance for a provided context. */
+    public static FingerprintManagerCompat from(Context context) {
+        return new FingerprintManagerCompat(context);
+    }
+
+    private FingerprintManagerCompat(Context context) {
+        mContext = context;
+    }
+
+    static final FingerprintManagerCompatImpl IMPL;
+    static {
+        final int version = Build.VERSION.SDK_INT;
+        // STOPSHIP: Remove "MNC" check once the API's are final for MNC
+        if (version >= 23 || "MNC".equals(Build.VERSION.CODENAME)) {
+            IMPL = new Api23FingerprintManagerCompatImpl();
+        } else {
+            IMPL = new LegacyFingerprintManagerCompatImpl();
+        }
+    }
+
+    /**
+     * Determine if there is at least one fingerprint enrolled.
+     *
+     * @return true if at least one fingerprint is enrolled, false otherwise
+     */
+    public boolean hasEnrolledFingerprints() {
+        return IMPL.hasEnrolledFingerprints(mContext);
+    }
+
+    /**
+     * Determine if fingerprint hardware is present and functional.
+     *
+     * @return true if hardware is present and functional, false otherwise.
+     */
+    public boolean isHardwareDetected() {
+        return IMPL.isHardwareDetected(mContext);
+    }
+
+    /**
+     * Request authentication of a crypto object. This call warms up the fingerprint hardware
+     * and starts scanning for a fingerprint. It terminates when
+     * {@link AuthenticationCallback#onAuthenticationError(int, CharSequence)} or
+     * {@link AuthenticationCallback#onAuthenticationSucceeded(AuthenticationResult) is called, at
+     * which point the object is no longer valid. The operation can be canceled by using the
+     * provided cancel object.
+     *
+     * @param crypto object associated with the call or null if none required.
+     * @param flags optional flags; should be 0
+     * @param cancel an object that can be used to cancel authentication
+     * @param callback an object to receive authentication events
+     * @param handler an optional handler for events
+     */
+    public void authenticate(@Nullable CryptoObject crypto, int flags,
+            @Nullable CancellationSignal cancel, @NonNull AuthenticationCallback callback,
+            @Nullable Handler handler) {
+        IMPL.authenticate(mContext, crypto, flags, cancel, callback, handler);
+    }
+
+    /**
+     * A wrapper class for the crypto objects supported by FingerprintManager. Currently the
+     * framework supports {@link Signature} and {@link Cipher} objects.
+     */
+    public static class CryptoObject {
+
+        private final Signature mSignature;
+        private final Cipher mCipher;
+
+        public CryptoObject(Signature signature) {
+            mSignature = signature;
+            mCipher = null;
+        }
+
+        public CryptoObject(Cipher cipher) {
+            mCipher = cipher;
+            mSignature = null;
+        }
+
+        /**
+         * Get {@link Signature} object.
+         * @return {@link Signature} object or null if this doesn't contain one.
+         */
+        public Signature getSignature() { return mSignature; }
+
+        /**
+         * Get {@link Cipher} object.
+         * @return {@link Cipher} object or null if this doesn't contain one.
+         */
+        public Cipher getCipher() { return mCipher; }
+    }
+
+    /**
+     * Container for callback data from {@link FingerprintManagerCompat#authenticate(CryptoObject,
+     *     int, CancellationSignal, AuthenticationCallback, Handler)}.
+     */
+    public static final class AuthenticationResult {
+        private CryptoObject mCryptoObject;
+
+        public AuthenticationResult(CryptoObject crypto) {
+            mCryptoObject = crypto;
+        }
+
+        /**
+         * Obtain the crypto object associated with this transaction
+         * @return crypto object provided to {@link FingerprintManagerCompat#authenticate(
+         *         CryptoObject, int, CancellationSignal, AuthenticationCallback, Handler)}.
+         */
+        public CryptoObject getCryptoObject() { return mCryptoObject; }
+    }
+
+    /**
+     * Callback structure provided to {@link FingerprintManagerCompat#authenticate(CryptoObject,
+     * int, CancellationSignal, AuthenticationCallback, Handler)}. Users of {@link
+     * FingerprintManagerCompat#authenticate(CryptoObject, int, CancellationSignal,
+     * AuthenticationCallback, Handler) } must provide an implementation of this for listening to
+     * fingerprint events.
+     */
+    public static abstract class AuthenticationCallback {
+        /**
+         * Called when an unrecoverable error has been encountered and the operation is complete.
+         * No further callbacks will be made on this object.
+         * @param errMsgId An integer identifying the error message
+         * @param errString A human-readable error string that can be shown in UI
+         */
+        public void onAuthenticationError(int errMsgId, CharSequence errString) { }
+
+        /**
+         * Called when a recoverable error has been encountered during authentication. The help
+         * string is provided to give the user guidance for what went wrong, such as
+         * "Sensor dirty, please clean it."
+         * @param helpMsgId An integer identifying the error message
+         * @param helpString A human-readable string that can be shown in UI
+         */
+        public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) { }
+
+        /**
+         * Called when a fingerprint is recognized.
+         * @param result An object containing authentication-related data
+         */
+        public void onAuthenticationSucceeded(AuthenticationResult result) { }
+
+        /**
+         * Called when a fingerprint is valid but not recognized.
+         */
+        public void onAuthenticationFailed() { }
+    }
+
+    private interface FingerprintManagerCompatImpl {
+        boolean hasEnrolledFingerprints(Context context);
+        boolean isHardwareDetected(Context context);
+        void authenticate(Context context, CryptoObject crypto, int flags,
+                CancellationSignal cancel, AuthenticationCallback callback, Handler handler);
+    }
+
+    private static class LegacyFingerprintManagerCompatImpl
+            implements FingerprintManagerCompatImpl {
+
+        public LegacyFingerprintManagerCompatImpl() {
+        }
+
+        @Override
+        public boolean hasEnrolledFingerprints(Context context) {
+            return false;
+        }
+
+        @Override
+        public boolean isHardwareDetected(Context context) {
+            return false;
+        }
+
+        @Override
+        public void authenticate(Context context, CryptoObject crypto, int flags,
+                CancellationSignal cancel, AuthenticationCallback callback, Handler handler) {
+            // TODO: Figure out behavior when there is no fingerprint hardware available
+        }
+    }
+
+    private static class Api23FingerprintManagerCompatImpl implements FingerprintManagerCompatImpl {
+
+        public Api23FingerprintManagerCompatImpl() {
+        }
+
+        @Override
+        public boolean hasEnrolledFingerprints(Context context) {
+            return FingerprintManagerCompatApi23.hasEnrolledFingerprints(context);
+        }
+
+        @Override
+        public boolean isHardwareDetected(Context context) {
+            return FingerprintManagerCompatApi23.isHardwareDetected(context);
+        }
+
+        @Override
+        public void authenticate(Context context, CryptoObject crypto, int flags,
+                CancellationSignal cancel, AuthenticationCallback callback, Handler handler) {
+            FingerprintManagerCompatApi23.authenticate(context, wrapCryptoObject(crypto), flags,
+                    cancel != null ? cancel.getCancellationSignalObject() : null,
+                    wrapCallback(callback), handler);
+        }
+
+        private static FingerprintManagerCompatApi23.CryptoObject wrapCryptoObject(
+                CryptoObject cryptoObject) {
+            if (cryptoObject == null) {
+                return null;
+            } else if (cryptoObject.getCipher() != null) {
+                return new FingerprintManagerCompatApi23.CryptoObject(cryptoObject.getCipher());
+            } else {
+                return new FingerprintManagerCompatApi23.CryptoObject(cryptoObject.getSignature());
+            }
+        }
+
+        private static CryptoObject unwrapCryptoObject(
+                FingerprintManagerCompatApi23.CryptoObject cryptoObject) {
+            if (cryptoObject == null) {
+                return null;
+            } else if (cryptoObject.getCipher() != null) {
+                return new CryptoObject(cryptoObject.getCipher());
+            } else {
+                return new CryptoObject(cryptoObject.getSignature());
+            }
+        }
+
+        private static FingerprintManagerCompatApi23.AuthenticationCallback wrapCallback(
+                final AuthenticationCallback callback) {
+            return new FingerprintManagerCompatApi23.AuthenticationCallback() {
+                @Override
+                public void onAuthenticationError(int errMsgId, CharSequence errString) {
+                    callback.onAuthenticationError(errMsgId, errString);
+                }
+
+                @Override
+                public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) {
+                    callback.onAuthenticationHelp(helpMsgId, helpString);
+                }
+
+                @Override
+                public void onAuthenticationSucceeded(
+                        FingerprintManagerCompatApi23.AuthenticationResultInternal result) {
+                    callback.onAuthenticationSucceeded(new AuthenticationResult(
+                            unwrapCryptoObject(result.getCryptoObject())));
+                }
+
+                @Override
+                public void onAuthenticationFailed() {
+                    callback.onAuthenticationFailed();
+                }
+            };
+        }
+    }
+}
diff --git a/v4/java/android/support/v4/media/session/MediaSessionCompat.java b/v4/java/android/support/v4/media/session/MediaSessionCompat.java
index fafb8e7..e6e2824 100644
--- a/v4/java/android/support/v4/media/session/MediaSessionCompat.java
+++ b/v4/java/android/support/v4/media/session/MediaSessionCompat.java
@@ -1786,10 +1786,10 @@
                         mCallback.onCommand(cmd.command, cmd.extras, cmd.stub);
                         break;
                     case MSG_ADJUST_VOLUME:
-                        adjustVolume((Integer) msg.obj, 0);
+                        adjustVolume((int) msg.obj, 0);
                         break;
                     case MSG_SET_VOLUME:
-                        setVolumeTo((Integer) msg.obj, 0);
+                        setVolumeTo((int) msg.obj, 0);
                         break;
                 }
             }
diff --git a/v4/java/android/support/v4/os/CancellationSignal.java b/v4/java/android/support/v4/os/CancellationSignal.java
new file mode 100644
index 0000000..41bdfe6
--- /dev/null
+++ b/v4/java/android/support/v4/os/CancellationSignal.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.support.v4.os;
+
+import android.os.Build;
+
+/**
+ * Static library support version of the framework's {@link android.os.CancellationSignal}.
+ * Used to write apps that run on platforms prior to Android 4.1.  See the framework SDK
+ * documentation for a class overview.
+ */
+public final class CancellationSignal {
+    private boolean mIsCanceled;
+    private OnCancelListener mOnCancelListener;
+    private Object mCancellationSignalObj;
+    private boolean mCancelInProgress;
+
+    /**
+     * Creates a cancellation signal, initially not canceled.
+     */
+    public CancellationSignal() {
+    }
+
+    /**
+     * Returns true if the operation has been canceled.
+     *
+     * @return True if the operation has been canceled.
+     */
+    public boolean isCanceled() {
+        synchronized (this) {
+            return mIsCanceled;
+        }
+    }
+
+    /**
+     * Throws {@link OperationCanceledException} if the operation has been canceled.
+     *
+     * @throws OperationCanceledException if the operation has been canceled.
+     */
+    public void throwIfCanceled() {
+        if (isCanceled()) {
+            throw new OperationCanceledException();
+        }
+    }
+
+    /**
+     * Cancels the operation and signals the cancellation listener.
+     * If the operation has not yet started, then it will be canceled as soon as it does.
+     */
+    public void cancel() {
+        final OnCancelListener listener;
+        final Object obj;
+        synchronized (this) {
+            if (mIsCanceled) {
+                return;
+            }
+            mIsCanceled = true;
+            mCancelInProgress = true;
+            listener = mOnCancelListener;
+            obj = mCancellationSignalObj;
+        }
+
+        try {
+            if (listener != null) {
+                listener.onCancel();
+            }
+            if (obj != null) {
+                CancellationSignalCompatJellybean.cancel(obj);
+            }
+        } finally {
+            synchronized (this) {
+                mCancelInProgress = false;
+                notifyAll();
+            }
+        }
+    }
+
+    /**
+     * Sets the cancellation listener to be called when canceled.
+     *
+     * This method is intended to be used by the recipient of a cancellation signal
+     * such as a database or a content provider to handle cancellation requests
+     * while performing a long-running operation.  This method is not intended to be
+     * used by applications themselves.
+     *
+     * If {@link CancellationSignal#cancel} has already been called, then the provided
+     * listener is invoked immediately.
+     *
+     * This method is guaranteed that the listener will not be called after it
+     * has been removed.
+     *
+     * @param listener The cancellation listener, or null to remove the current listener.
+     */
+    public void setOnCancelListener(OnCancelListener listener) {
+        synchronized (this) {
+            waitForCancelFinishedLocked();
+
+            if (mOnCancelListener == listener) {
+                return;
+            }
+            mOnCancelListener = listener;
+            if (!mIsCanceled || listener == null) {
+                return;
+            }
+        }
+        listener.onCancel();
+    }
+
+    /**
+     * Gets the framework {@link android.os.CancellationSignal} associated with this object.
+     * <p>
+     * Framework support for cancellation signals was added in
+     * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} so this method will always
+     * return null on older versions of the platform.
+     * </p>
+     *
+     * @return A framework cancellation signal object, or null on platform versions
+     * prior to Jellybean.
+     */
+    public Object getCancellationSignalObject() {
+        if (Build.VERSION.SDK_INT < 16) {
+            return null;
+        }
+        synchronized (this) {
+            if (mCancellationSignalObj == null) {
+                mCancellationSignalObj = CancellationSignalCompatJellybean.create();
+                if (mIsCanceled) {
+                    CancellationSignalCompatJellybean.cancel(mCancellationSignalObj);
+                }
+            }
+            return mCancellationSignalObj;
+        }
+    }
+
+    private void waitForCancelFinishedLocked() {
+        while (mCancelInProgress) {
+            try {
+                wait();
+            } catch (InterruptedException ex) {
+            }
+        }
+    }
+
+     /**
+     * Listens for cancellation.
+     */
+    public interface OnCancelListener {
+        /**
+         * Called when {@link CancellationSignal#cancel} is invoked.
+         */
+        void onCancel();
+    }
+}
diff --git a/v4/java/android/support/v4/os/OperationCanceledException.java b/v4/java/android/support/v4/os/OperationCanceledException.java
new file mode 100644
index 0000000..9b28030
--- /dev/null
+++ b/v4/java/android/support/v4/os/OperationCanceledException.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2013 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.v4.os;
+
+
+/**
+ * An exception type that is thrown when an operation in progress is canceled.
+ */
+public class OperationCanceledException extends RuntimeException {
+    public OperationCanceledException() {
+        this(null);
+    }
+
+    public OperationCanceledException(String message) {
+        super(message != null ? message : "The operation has been canceled.");
+    }
+}
diff --git a/v4/java/android/support/v4/text/ICUCompat.java b/v4/java/android/support/v4/text/ICUCompat.java
index 6df35ff..43ada52 100644
--- a/v4/java/android/support/v4/text/ICUCompat.java
+++ b/v4/java/android/support/v4/text/ICUCompat.java
@@ -18,34 +18,32 @@
 
 import android.os.Build;
 
+import java.util.Locale;
+
 public class ICUCompat {
 
     interface ICUCompatImpl {
-        public String getScript(String locale);
-        public String addLikelySubtags(String locale);
+        public String maximizeAndGetScript(Locale locale);
     }
 
     static class ICUCompatImplBase implements ICUCompatImpl {
         @Override
-        public String getScript(String locale) {
+        public String maximizeAndGetScript(Locale locale) {
             return null;
         }
-
-        @Override
-        public String addLikelySubtags(String locale) {
-            return locale;
-        }
     }
 
     static class ICUCompatImplIcs implements ICUCompatImpl {
         @Override
-        public String getScript(String locale) {
-            return ICUCompatIcs.getScript(locale);
+        public String maximizeAndGetScript(Locale locale) {
+            return ICUCompatIcs.maximizeAndGetScript(locale);
         }
+    }
 
+    static class ICUCompatImplLollipop implements ICUCompatImpl {
         @Override
-        public String addLikelySubtags(String locale) {
-            return ICUCompatIcs.addLikelySubtags(locale);
+        public String maximizeAndGetScript(Locale locale) {
+            return ICUCompatApi23.maximizeAndGetScript(locale);
         }
     }
 
@@ -53,7 +51,9 @@
 
     static {
         final int version = Build.VERSION.SDK_INT;
-        if (version >= 14) {
+        if (version >= 21) {
+            IMPL = new ICUCompatImplLollipop();
+        } else if (version >= 14) {
             IMPL = new ICUCompatImplIcs();
         } else {
             IMPL = new ICUCompatImplBase();
@@ -61,18 +61,11 @@
     }
 
     /**
-     * Returns the script (language code) of a script.
+     * Returns the script for a given Locale.
      *
-     * @param locale The locale.
-     * @return a String representing the script (language code) of the locale.
-     */
-    public static String getScript(String locale) {
-        return IMPL.getScript(locale);
-    }
-
-    /**
-     * Add the likely subtags for a provided locale ID, per the algorithm described in the following
-     * CLDR technical report:
+     * If the locale isn't already in its maximal form, likely subtags for the provided locale
+     * ID are added before we determine the script. For further details, see the following CLDR
+     * technical report :
      *
      * http://www.unicode.org/reports/tr35/#Likely_Subtags
      *
@@ -87,12 +80,10 @@
      * "sr" maximizes to "sr_Cyrl_RS"
      * "sh" maximizes to "sr_Latn_RS" (Note this will not reverse.)
      * "zh_Hani" maximizes to "zh_Hans_CN" (Note this will not reverse.)
-
-     * @param locale The locale to maximize
      *
-     * @return the maximized locale
+     * @return
      */
-    public static String addLikelySubtags(String locale) {
-        return IMPL.addLikelySubtags(locale);
+    public static String maximizeAndGetScript(Locale locale) {
+        return IMPL.maximizeAndGetScript(locale);
     }
 }
diff --git a/v4/java/android/support/v4/text/TextUtilsCompat.java b/v4/java/android/support/v4/text/TextUtilsCompat.java
index 436d72f..507a006 100644
--- a/v4/java/android/support/v4/text/TextUtilsCompat.java
+++ b/v4/java/android/support/v4/text/TextUtilsCompat.java
@@ -74,8 +74,7 @@
      */
     public static int getLayoutDirectionFromLocale(@Nullable Locale locale) {
         if (locale != null && !locale.equals(ROOT)) {
-            final String scriptSubtag = ICUCompat.getScript(
-                    ICUCompat.addLikelySubtags(locale.toString()));
+            final String scriptSubtag = ICUCompat.maximizeAndGetScript(locale);
             if (scriptSubtag == null) return getLayoutDirectionFromFirstChar(locale);
 
             if (scriptSubtag.equalsIgnoreCase(ARAB_SCRIPT_SUBTAG) ||
diff --git a/v4/java/android/support/v4/util/CircularArray.java b/v4/java/android/support/v4/util/CircularArray.java
index 760c986..e2ac26b 100644
--- a/v4/java/android/support/v4/util/CircularArray.java
+++ b/v4/java/android/support/v4/util/CircularArray.java
@@ -93,7 +93,7 @@
     /**
      * Remove first element from front of the CircularArray and return it.
      * @return  The element removed.
-     * @throws {@link ArrayIndexOutOfBoundsException} if CircularArray is empty.
+     * @throws ArrayIndexOutOfBoundsException if CircularArray is empty.
      */
     public E popFirst() {
         if (mHead == mTail) {
@@ -108,7 +108,7 @@
     /**
      * Remove last element from end of the CircularArray and return it.
      * @return  The element removed.
-     * @throws {@link ArrayIndexOutOfBoundsException} if CircularArray is empty.
+     * @throws ArrayIndexOutOfBoundsException if CircularArray is empty.
      */
     public E popLast() {
         if (mHead == mTail) {
@@ -132,7 +132,7 @@
      * Remove multiple elements from front of the CircularArray, ignore when numOfElements
      * is less than or equals to 0.
      * @param numOfElements  Number of elements to remove.
-     * @throws {@link ArrayIndexOutOfBoundsException} if numOfElements is larger than
+     * @throws ArrayIndexOutOfBoundsException if numOfElements is larger than
      *         {@link #size()}
      */
     public void removeFromStart(int numOfElements) {
@@ -165,7 +165,7 @@
      * Remove multiple elements from end of the CircularArray, ignore when numOfElements
      * is less than or equals to 0.
      * @param numOfElements  Number of elements to remove.
-     * @throws {@link ArrayIndexOutOfBoundsException} if numOfElements is larger than
+     * @throws ArrayIndexOutOfBoundsException if numOfElements is larger than
      *         {@link #size()}
      */
     public void removeFromEnd(int numOfElements) {
diff --git a/v4/java/android/support/v4/util/CircularIntArray.java b/v4/java/android/support/v4/util/CircularIntArray.java
index 2389436..706d73b 100644
--- a/v4/java/android/support/v4/util/CircularIntArray.java
+++ b/v4/java/android/support/v4/util/CircularIntArray.java
@@ -94,7 +94,7 @@
     /**
      * Remove first integer from front of the CircularIntArray and return it.
      * @return  The integer removed.
-     * @throws {@link ArrayIndexOutOfBoundsException} if CircularIntArray is empty.
+     * @throws ArrayIndexOutOfBoundsException if CircularIntArray is empty.
      */
     public int popFirst() {
         if (mHead == mTail) throw new ArrayIndexOutOfBoundsException();
@@ -106,7 +106,7 @@
     /**
      * Remove last integer from end of the CircularIntArray and return it.
      * @return  The integer removed.
-     * @throws {@link ArrayIndexOutOfBoundsException} if CircularIntArray is empty.
+     * @throws ArrayIndexOutOfBoundsException if CircularIntArray is empty.
      */
     public int popLast() {
         if (mHead == mTail) throw new ArrayIndexOutOfBoundsException();
@@ -127,7 +127,7 @@
      * Remove multiple integers from front of the CircularIntArray, ignore when numOfElements
      * is less than or equals to 0.
      * @param numOfElements  Number of integers to remove.
-     * @throws {@link ArrayIndexOutOfBoundsException} if numOfElements is larger than
+     * @throws ArrayIndexOutOfBoundsException if numOfElements is larger than
      *         {@link #size()}
      */
     public void removeFromStart(int numOfElements) {
@@ -144,7 +144,7 @@
      * Remove multiple elements from end of the CircularIntArray, ignore when numOfElements
      * is less than or equals to 0.
      * @param numOfElements  Number of integers to remove.
-     * @throws {@link ArrayIndexOutOfBoundsException} if numOfElements is larger than
+     * @throws ArrayIndexOutOfBoundsException if numOfElements is larger than
      *         {@link #size()}
      */
     public void removeFromEnd(int numOfElements) {
diff --git a/v4/java/android/support/v4/view/PagerTabStrip.java b/v4/java/android/support/v4/view/PagerTabStrip.java
index 834035c..cd0206b 100644
--- a/v4/java/android/support/v4/view/PagerTabStrip.java
+++ b/v4/java/android/support/v4/view/PagerTabStrip.java
@@ -21,6 +21,7 @@
 import android.graphics.Paint;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
+import android.support.annotation.ColorInt;
 import android.support.annotation.ColorRes;
 import android.support.annotation.DrawableRes;
 import android.util.AttributeSet;
@@ -127,7 +128,7 @@
      *
      * @param color Color to set as an 0xRRGGBB value. The high byte (alpha) is ignored.
      */
-    public void setTabIndicatorColor(int color) {
+    public void setTabIndicatorColor(@ColorInt int color) {
         mIndicatorColor = color;
         mTabPaint.setColor(mIndicatorColor);
         invalidate();
@@ -145,6 +146,7 @@
     /**
      * @return The current tab indicator color as an 0xRRGGBB value.
      */
+    @ColorInt
     public int getTabIndicatorColor() {
         return mIndicatorColor;
     }
@@ -174,7 +176,7 @@
     }
 
     @Override
-    public void setBackgroundColor(int color) {
+    public void setBackgroundColor(@ColorInt int color) {
         super.setBackgroundColor(color);
         if (!mDrawFullUnderlineSet) {
             mDrawFullUnderline = (color & 0xFF000000) == 0;
diff --git a/v4/java/android/support/v4/view/PagerTitleStrip.java b/v4/java/android/support/v4/view/PagerTitleStrip.java
index 79c771f..cb9cd75 100644
--- a/v4/java/android/support/v4/view/PagerTitleStrip.java
+++ b/v4/java/android/support/v4/view/PagerTitleStrip.java
@@ -20,6 +20,8 @@
 import android.content.res.TypedArray;
 import android.database.DataSetObserver;
 import android.graphics.drawable.Drawable;
+import android.support.annotation.ColorInt;
+import android.support.annotation.FloatRange;
 import android.text.TextUtils.TruncateAt;
 import android.util.AttributeSet;
 import android.util.TypedValue;
@@ -189,7 +191,7 @@
      *
      * @param alpha Opacity value in the range 0-1f
      */
-    public void setNonPrimaryAlpha(float alpha) {
+    public void setNonPrimaryAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
         mNonPrimaryAlpha = (int) (alpha * 255) & 0xFF;
         final int transparentColor = (mNonPrimaryAlpha << 24) | (mTextColor & 0xFFFFFF);
         mPrevText.setTextColor(transparentColor);
@@ -202,7 +204,7 @@
      *
      * @param color Color hex code in 0xAARRGGBB format
      */
-    public void setTextColor(int color) {
+    public void setTextColor(@ColorInt int color) {
         mTextColor = color;
         mCurrText.setTextColor(color);
         final int transparentColor = (mNonPrimaryAlpha << 24) | (mTextColor & 0xFFFFFF);
diff --git a/v4/java/android/support/v4/view/ViewCompat.java b/v4/java/android/support/v4/view/ViewCompat.java
index 57ac229..d3dce89 100644
--- a/v4/java/android/support/v4/view/ViewCompat.java
+++ b/v4/java/android/support/v4/view/ViewCompat.java
@@ -24,6 +24,7 @@
 import android.graphics.drawable.Drawable;
 import android.os.Build;
 import android.os.Bundle;
+import android.support.annotation.FloatRange;
 import android.support.annotation.IdRes;
 import android.support.annotation.IntDef;
 import android.support.annotation.Nullable;
@@ -355,6 +356,7 @@
         public void requestApplyInsets(View view);
         public void setChildrenDrawingOrderEnabled(ViewGroup viewGroup, boolean enabled);
         public boolean getFitsSystemWindows(View view);
+        public boolean hasOverlappingRendering(View view);
         void setFitsSystemWindows(View view, boolean fitSystemWindows);
         void jumpDrawablesToCurrentState(View v);
         void setOnApplyWindowInsetsListener(View view, OnApplyWindowInsetsListener listener);
@@ -581,6 +583,11 @@
             }
         }
 
+        @Override
+        public boolean hasOverlappingRendering(View view) {
+            return true;
+        }
+
         private void bindTempDetach() {
             try {
                 mDispatchStartTemporaryDetach = View.class.getDeclaredMethod(
@@ -1291,6 +1298,11 @@
         public boolean getFitsSystemWindows(View view) {
             return ViewCompatJB.getFitsSystemWindows(view);
         }
+
+        @Override
+        public boolean hasOverlappingRendering(View view) {
+            return ViewCompatJB.hasOverlappingRendering(view);
+        }
     }
 
     static class JbMr1ViewCompatImpl extends JBViewCompatImpl {
@@ -2357,7 +2369,7 @@
      *
      * @param value The opacity of the view.
      */
-    public static void setAlpha(View view, float value) {
+    public static void setAlpha(View view, @FloatRange(from=0.0, to=1.0) float value) {
         IMPL.setAlpha(view, value);
     }
 
@@ -2713,6 +2725,24 @@
     }
 
     /**
+     * Returns whether this View has content which overlaps.
+     *
+     * <p>This function, intended to be overridden by specific View types, is an optimization when
+     * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
+     * an offscreen buffer and then composited into place, which can be expensive. If the view has
+     * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
+     * directly. An example of overlapping rendering is a TextView with a background image, such as
+     * a Button. An example of non-overlapping rendering is a TextView with no background, or an
+     * ImageView with only the foreground image. The default implementation returns true; subclasses
+     * should override if they have cases which can be optimized.</p>
+     *
+     * @return true if the content in this view might overlap, false otherwise.
+     */
+    public static boolean hasOverlappingRendering(View view) {
+        return IMPL.hasOverlappingRendering(view);
+    }
+
+    /**
      * Return if the padding as been set through relative values
      * {@code View.setPaddingRelative(int, int, int, int)} or thru
      *
diff --git a/v4/java/android/support/v4/view/ViewPager.java b/v4/java/android/support/v4/view/ViewPager.java
index 57152c2..f19104a 100644
--- a/v4/java/android/support/v4/view/ViewPager.java
+++ b/v4/java/android/support/v4/view/ViewPager.java
@@ -28,6 +28,7 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.SystemClock;
+import android.support.annotation.CallSuper;
 import android.support.annotation.DrawableRes;
 import android.support.v4.os.ParcelableCompat;
 import android.support.v4.os.ParcelableCompatCreatorCallbacks;
@@ -1704,6 +1705,7 @@
      * @param offset Value from [0, 1) indicating the offset from the page at position.
      * @param offsetPixels Value in pixels indicating the offset from position.
      */
+    @CallSuper
     protected void onPageScrolled(int position, float offset, int offsetPixels) {
         // Offset any decor views if needed - keep them on-screen at all times.
         if (mDecorChildCount > 0) {
diff --git a/v4/java/android/support/v4/view/accessibility/AccessibilityNodeInfoCompat.java b/v4/java/android/support/v4/view/accessibility/AccessibilityNodeInfoCompat.java
index 1b239a7..cc6a8f7 100644
--- a/v4/java/android/support/v4/view/accessibility/AccessibilityNodeInfoCompat.java
+++ b/v4/java/android/support/v4/view/accessibility/AccessibilityNodeInfoCompat.java
@@ -21,6 +21,7 @@
 import android.os.Bundle;
 import android.support.v4.accessibilityservice.AccessibilityServiceInfoCompat;
 import android.support.v4.view.ViewCompat;
+import android.text.InputType;
 import android.view.View;
 
 import java.util.ArrayList;
@@ -200,9 +201,12 @@
         public Object getChild(Object info, int index);
         public void addChild(Object info, View child);
         public void addChild(Object info, View child, int virtualDescendantId);
+        public boolean removeChild(Object info, View child);
+        public boolean removeChild(Object info, View root, int virtualDescendantId);
         public int getActions(Object info);
         public void addAction(Object info, int action);
         public void addAction(Object info, Object action);
+        public boolean removeAction(Object info, Object action);
         public int getAccessibilityActionId(Object action);
         public CharSequence getAccessibilityActionLabel(Object action);
         public boolean performAction(Object info, int action);
@@ -259,6 +263,7 @@
         public Object getCollectionItemInfo(Object info);
         public void setCollectionItemInfo(Object info, Object collectionItemInfo);
         public Object getRangeInfo(Object info);
+        public void setRangeInfo(Object info, Object rangeInfo);
         public List<Object> getActionList(Object info);
         public Object obtainCollectionInfo(int rowCount, int columnCount, boolean hierarchical,
                 int selectionMode);
@@ -273,10 +278,10 @@
         public int getCollectionItemRowSpan(Object info);
         public boolean isCollectionItemHeading(Object info);
         public boolean isCollectionItemSelected(Object info);
-        public AccessibilityNodeInfoCompat getTraversalBefore(Object info);
+        public Object getTraversalBefore(Object info);
         public void setTraversalBefore(Object info, View view);
         public void setTraversalBefore(Object info, View root, int virtualDescendantId);
-        public AccessibilityNodeInfoCompat getTraversalAfter(Object info);
+        public Object getTraversalAfter(Object info);
         public void setTraversalAfter(Object info, View view);
         public void setTraversalAfter(Object info, View root, int virtualDescendantId);
         public void setContentInvalid(Object info, boolean contentInvalid);
@@ -285,6 +290,29 @@
         public CharSequence getError(Object info);
         public void setLabelFor(Object info, View labeled);
         public void setLabelFor(Object info, View root, int virtualDescendantId);
+        public Object getLabelFor(Object info);
+        public void setLabeledBy(Object info, View labeled);
+        public void setLabeledBy(Object info, View root, int virtualDescendantId);
+        public Object getLabeledBy(Object info);
+        public boolean canOpenPopup(Object info);
+        public void setCanOpenPopup(Object info, boolean opensPopup);
+        public List<Object> findAccessibilityNodeInfosByViewId(Object info, String viewId);
+        public Bundle getExtras(Object info);
+        public int getInputType(Object info);
+        public void setInputType(Object info, int inputType);
+        public void setMaxTextLength(Object info, int max);
+        public int getMaxTextLength(Object info);
+        public void setTextSelection(Object info, int start, int end);
+        public int getTextSelectionStart(Object info);
+        public int getTextSelectionEnd(Object info);
+        public Object getWindow(Object info);
+        public boolean isDismissable(Object info);
+        public void setDismissable(Object info, boolean dismissable);
+        public boolean isEditable(Object info);
+        public void setEditable(Object info, boolean editable);
+        public boolean isMultiLine(Object info);
+        public void setMultiLine(Object info, boolean multiLine);
+        public boolean refresh(Object info);
     }
 
     static class AccessibilityNodeInfoStubImpl implements AccessibilityNodeInfoImpl {
@@ -324,6 +352,11 @@
         }
 
         @Override
+        public boolean removeAction(Object info, Object action) {
+            return false;
+        }
+
+        @Override
         public int getAccessibilityActionId(Object action) {
             return 0;
         }
@@ -344,6 +377,16 @@
         }
 
         @Override
+        public boolean removeChild(Object info, View child) {
+            return false;
+        }
+
+        @Override
+        public boolean removeChild(Object info, View root, int virtualDescendantId) {
+            return false;
+        }
+
+        @Override
         public List<Object> findAccessibilityNodeInfosByText(Object info, String text) {
             return Collections.emptyList();
         }
@@ -652,6 +695,10 @@
         }
 
         @Override
+        public void setRangeInfo(Object info, Object rangeInfo) {
+        }
+
+        @Override
         public List<Object> getActionList(Object info) {
             return null;
         }
@@ -714,7 +761,7 @@
         }
 
         @Override
-        public AccessibilityNodeInfoCompat getTraversalBefore(Object info) {
+        public Object getTraversalBefore(Object info) {
             return null;
         }
 
@@ -727,7 +774,7 @@
         }
 
         @Override
-        public AccessibilityNodeInfoCompat getTraversalAfter(Object info) {
+        public Object getTraversalAfter(Object info) {
             return null;
         }
 
@@ -764,6 +811,112 @@
         @Override
         public void setLabelFor(Object info, View root, int virtualDescendantId) {
         }
+
+        @Override
+        public Object getLabelFor(Object info) {
+            return null;
+        }
+
+        @Override
+        public void setLabeledBy(Object info, View labeled) {
+        }
+
+        @Override
+        public void setLabeledBy(Object info, View root, int virtualDescendantId) {
+        }
+
+        @Override
+        public Object getLabeledBy(Object info){
+            return null;
+        }
+
+        @Override
+        public boolean canOpenPopup(Object info) {
+            return false;
+        }
+
+        @Override
+        public void setCanOpenPopup(Object info, boolean opensPopup) {
+        }
+
+        @Override
+        public List<Object> findAccessibilityNodeInfosByViewId(Object info, String viewId) {
+            return  Collections.emptyList();
+        }
+
+        @Override
+        public Bundle getExtras(Object info) {
+            return new Bundle();
+        }
+
+        @Override
+        public int getInputType(Object info) {
+            return InputType.TYPE_NULL;
+        }
+
+        @Override
+        public void setInputType(Object info, int inputType) {
+        }
+
+        @Override
+        public void setMaxTextLength(Object info, int max) {
+        }
+
+        @Override
+        public int getMaxTextLength(Object info) {
+            return -1;
+        }
+
+        @Override
+        public void setTextSelection(Object info, int start, int end) {
+        }
+
+        @Override
+        public int getTextSelectionStart(Object info) {
+            return -1;
+        }
+
+        @Override
+        public int getTextSelectionEnd(Object info) {
+            return -1;
+        }
+
+        @Override
+        public Object getWindow(Object info) {
+            return null;
+        }
+
+        @Override
+        public boolean isDismissable(Object info) {
+            return false;
+        }
+
+        @Override
+        public void setDismissable(Object info, boolean dismissable) {
+        }
+
+        @Override
+        public boolean isEditable(Object info) {
+            return false;
+        }
+
+        @Override
+        public void setEditable(Object info, boolean editable) {
+        }
+
+        @Override
+        public boolean isMultiLine(Object info) {
+            return false;
+        }
+
+        @Override
+        public void setMultiLine(Object info, boolean multiLine) {
+        }
+
+        @Override
+        public boolean refresh(Object info) {
+            return false;
+        }
     }
 
     static class AccessibilityNodeInfoIcsImpl extends AccessibilityNodeInfoStubImpl {
@@ -1070,7 +1223,41 @@
         }
     }
 
-    static class AccessibilityNodeInfoJellybeanMr2Impl extends AccessibilityNodeInfoJellybeanImpl {
+    static class AccessibilityNodeInfoJellybeanMr1Impl extends AccessibilityNodeInfoJellybeanImpl {
+
+        @Override
+        public void setLabelFor(Object info, View labeled) {
+            AccessibilityNodeInfoCompatJellybeanMr1.setLabelFor(info, labeled);
+        }
+
+        @Override
+        public void setLabelFor(Object info, View root, int virtualDescendantId) {
+            AccessibilityNodeInfoCompatJellybeanMr1.setLabelFor(info, root, virtualDescendantId);
+        }
+
+        @Override
+        public Object getLabelFor(Object info) {
+            return AccessibilityNodeInfoCompatJellybeanMr1.getLabelFor(info);
+        }
+
+        @Override
+        public void setLabeledBy(Object info, View labeled) {
+            AccessibilityNodeInfoCompatJellybeanMr1.setLabeledBy(info, labeled);
+        }
+
+        @Override
+        public void setLabeledBy(Object info, View root, int virtualDescendantId) {
+            AccessibilityNodeInfoCompatJellybeanMr1.setLabeledBy(info, root, virtualDescendantId);
+        }
+
+        @Override
+        public Object getLabeledBy(Object info) {
+            return AccessibilityNodeInfoCompatJellybeanMr1.getLabeledBy(info);
+        }
+    }
+
+    static class AccessibilityNodeInfoJellybeanMr2Impl extends
+            AccessibilityNodeInfoJellybeanMr1Impl {
 
         @Override
         public String getViewIdResourceName(Object info) {
@@ -1081,6 +1268,42 @@
         public void setViewIdResourceName(Object info, String viewId) {
             AccessibilityNodeInfoCompatJellybeanMr2.setViewIdResourceName(info, viewId);
         }
+
+        @Override
+        public List<Object> findAccessibilityNodeInfosByViewId(Object info, String viewId) {
+            return AccessibilityNodeInfoCompatJellybeanMr2.findAccessibilityNodeInfosByViewId(info,
+                    viewId);
+        }
+
+        @Override
+        public void setTextSelection(Object info, int start, int end) {
+            AccessibilityNodeInfoCompatJellybeanMr2.setTextSelection(info, start, end);
+        }
+
+        @Override
+        public int getTextSelectionStart(Object info) {
+            return AccessibilityNodeInfoCompatJellybeanMr2.getTextSelectionStart(info);
+        }
+
+        @Override
+        public int getTextSelectionEnd(Object info) {
+            return AccessibilityNodeInfoCompatJellybeanMr2.getTextSelectionEnd(info);
+        }
+
+        @Override
+        public boolean isEditable(Object info) {
+            return AccessibilityNodeInfoCompatJellybeanMr2.isEditable(info);
+        }
+
+        @Override
+        public void setEditable(Object info, boolean editable) {
+            AccessibilityNodeInfoCompatJellybeanMr2.setEditable(info, editable);
+        }
+
+        @Override
+        public boolean refresh(Object info) {
+            return AccessibilityNodeInfoCompatJellybeanMr2.refresh(info);
+        }
     }
 
     static class AccessibilityNodeInfoKitKatImpl extends AccessibilityNodeInfoJellybeanMr2Impl {
@@ -1144,6 +1367,11 @@
         }
 
         @Override
+        public void setRangeInfo(Object info, Object rangeInfo) {
+            AccessibilityNodeInfoCompatKitKat.setRangeInfo(info, rangeInfo);
+        }
+
+        @Override
         public int getCollectionItemColumnIndex(Object info) {
             return AccessibilityNodeInfoCompatKitKat.CollectionItemInfo.getColumnIndex(info);
         }
@@ -1182,6 +1410,51 @@
         public boolean isContentInvalid(Object info) {
             return AccessibilityNodeInfoCompatKitKat.isContentInvalid(info);
         }
+
+        @Override
+        public boolean canOpenPopup(Object info) {
+            return AccessibilityNodeInfoCompatKitKat.canOpenPopup(info);
+        }
+
+        @Override
+        public void setCanOpenPopup(Object info, boolean opensPopup) {
+            AccessibilityNodeInfoCompatKitKat.setCanOpenPopup(info, opensPopup);
+        }
+
+        @Override
+        public Bundle getExtras(Object info) {
+            return AccessibilityNodeInfoCompatKitKat.getExtras(info);
+        }
+
+        @Override
+        public int getInputType(Object info) {
+            return AccessibilityNodeInfoCompatKitKat.getInputType(info);
+        }
+
+        @Override
+        public void setInputType(Object info, int inputType) {
+            AccessibilityNodeInfoCompatKitKat.setInputType(info, inputType);
+        }
+
+        @Override
+        public boolean isDismissable(Object info) {
+            return AccessibilityNodeInfoCompatKitKat.isDismissable(info);
+        }
+
+        @Override
+        public void setDismissable(Object info, boolean dismissable) {
+            AccessibilityNodeInfoCompatKitKat.setDismissable(info, dismissable);
+        }
+
+        @Override
+        public boolean isMultiLine(Object info) {
+            return AccessibilityNodeInfoCompatKitKat.isMultiLine(info);
+        }
+
+        @Override
+        public void setMultiLine(Object info, boolean multiLine) {
+            AccessibilityNodeInfoCompatKitKat.setMultiLine(info, multiLine);
+        }
     }
 
     static class AccessibilityNodeInfoApi21Impl extends AccessibilityNodeInfoKitKatImpl {
@@ -1208,6 +1481,11 @@
         }
 
         @Override
+        public boolean removeAction(Object info, Object action) {
+            return AccessibilityNodeInfoCompatApi21.removeAction(info, action);
+        }
+
+        @Override
         public int getAccessibilityActionId(Object action) {
             return AccessibilityNodeInfoCompatApi21.getAccessibilityActionId(action);
         }
@@ -1240,25 +1518,35 @@
         }
 
         @Override
-        public void setLabelFor(Object info, View labeled) {
-            AccessibilityNodeInfoCompatApi21.setLabelFor(info, labeled);
+        public void setMaxTextLength(Object info, int max) {
+            AccessibilityNodeInfoCompatApi21.setMaxTextLength(info, max);
         }
 
         @Override
-        public void setLabelFor(Object info, View root, int virtualDescendantId) {
-            AccessibilityNodeInfoCompatApi21.setLabelFor(info, root, virtualDescendantId);
+        public int getMaxTextLength(Object info) {
+            return AccessibilityNodeInfoCompatApi21.getMaxTextLength(info);
+        }
+
+        @Override
+        public Object getWindow(Object info) {
+            return AccessibilityNodeInfoCompatApi21.getWindow(info);
+        }
+
+        @Override
+        public boolean removeChild(Object info, View child) {
+            return AccessibilityNodeInfoCompatApi21.removeChild(info, child);
+        }
+
+        @Override
+        public boolean removeChild(Object info, View root, int virtualDescendantId) {
+            return AccessibilityNodeInfoCompatApi21.removeChild(info, root, virtualDescendantId);
         }
     }
 
     static class AccessibilityNodeInfoApi22Impl extends AccessibilityNodeInfoApi21Impl {
         @Override
-        public AccessibilityNodeInfoCompat getTraversalBefore(Object info) {
-            Object nodeInfo = AccessibilityNodeInfoCompatApi22.getTraversalBefore(info);
-            if (nodeInfo == null) {
-                return null;
-            }
-
-            return new AccessibilityNodeInfoCompat(nodeInfo);
+        public Object getTraversalBefore(Object info) {
+            return AccessibilityNodeInfoCompatApi22.getTraversalBefore(info);
         }
 
         @Override
@@ -1272,13 +1560,8 @@
         }
 
         @Override
-        public AccessibilityNodeInfoCompat getTraversalAfter(Object info) {
-            Object nodeInfo = AccessibilityNodeInfoCompatApi22.getTraversalAfter(info);
-            if (nodeInfo == null) {
-                return null;
-            }
-
-            return new AccessibilityNodeInfoCompat(nodeInfo);
+        public Object getTraversalAfter(Object info) {
+            return AccessibilityNodeInfoCompatApi22.getTraversalAfter(info);
         }
 
         @Override
@@ -1301,6 +1584,8 @@
             IMPL = new AccessibilityNodeInfoKitKatImpl();
         } else if (Build.VERSION.SDK_INT >= 18) { // JellyBean MR2
             IMPL = new AccessibilityNodeInfoJellybeanMr2Impl();
+        } else if (Build.VERSION.SDK_INT >= 17) { // JellyBean MR1
+            IMPL = new AccessibilityNodeInfoJellybeanMr1Impl();
         } else if (Build.VERSION.SDK_INT >= 16) { // JellyBean
             IMPL = new AccessibilityNodeInfoJellybeanImpl();
         } else if (Build.VERSION.SDK_INT >= 14) { // ICS
@@ -1840,6 +2125,38 @@
     }
 
     /**
+     * Removes a child. If the child was not previously added to the node,
+     * calling this method has no effect.
+     * <p>
+     * <strong>Note:</strong> Cannot be called from an
+     * {@link android.accessibilityservice.AccessibilityService}.
+     * This class is made immutable before being delivered to an AccessibilityService.
+     * </p>
+     *
+     * @param child The child.
+     * @return true if the child was present
+     *
+     * @throws IllegalStateException If called from an AccessibilityService.
+     */
+    public boolean removeChild(View child) {
+        return IMPL.removeChild(mInfo, child);
+    }
+
+    /**
+     * Removes a virtual child which is a descendant of the given
+     * <code>root</code>. If the child was not previously added to the node,
+     * calling this method has no effect.
+     *
+     * @param root The root of the virtual subtree.
+     * @param virtualDescendantId The id of the virtual child.
+     * @return true if the child was present
+     * @see #addChild(View, int)
+     */
+    public boolean removeChild(View root, int virtualDescendantId) {
+        return IMPL.removeChild(mInfo, root, virtualDescendantId);
+    }
+
+    /**
      * Gets the actions that can be performed on the node.
      *
      * @return The bit mask of with actions.
@@ -1883,6 +2200,24 @@
     }
 
     /**
+     * Removes an action that can be performed on the node. If the action was
+     * not already added to the node, calling this method has no effect.
+     * <p>
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
+     *   This class is made immutable before being delivered to an AccessibilityService.
+     * </p>
+     *
+     * @param action The action to be removed.
+     * @return The action removed from the list of actions.
+     *
+     * @throws IllegalStateException If called from an AccessibilityService.
+     */
+    public boolean removeAction(AccessibilityActionCompat action) {
+        return IMPL.removeAction(mInfo, action.mAction);
+    }
+
+    /**
      * Performs an action on the node.
      * <p>
      * <strong>Note:</strong> An action can be performed only if the request is
@@ -2574,6 +2909,20 @@
     }
 
     /**
+     * Sets the range info if this node is a range.
+     * <p>
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
+     *   This class is made immutable before being delivered to an AccessibilityService.
+     * </p>
+     *
+     * @param rangeInfo The range info.
+     */
+    public void setRangeInfo(RangeInfoCompat rangeInfo) {
+        IMPL.setRangeInfo(mInfo, rangeInfo.mInfo);
+    }
+
+    /**
      * Gets the actions that can be performed on the node.
      *
      * @return A list of AccessibilityActions.
@@ -2671,6 +3020,441 @@
         IMPL.setLabelFor(mInfo, root, virtualDescendantId);
     }
 
+    /**
+     * Gets the node info for which the view represented by this info serves as
+     * a label for accessibility purposes.
+     * <p>
+     *   <strong>Note:</strong> It is a client responsibility to recycle the
+     *     received info by calling {@link AccessibilityNodeInfoCompat#recycle()}
+     *     to avoid creating of multiple instances.
+     * </p>
+     *
+     * @return The labeled info.
+     */
+    public AccessibilityNodeInfoCompat getLabelFor() {
+        return AccessibilityNodeInfoCompat.wrapNonNullInstance(IMPL.getLabelFor(mInfo));
+    }
+
+    /**
+     * Sets the view which serves as the label of the view represented by
+     * this info for accessibility purposes.
+     *
+     * @param label The view that labels this node's source.
+     */
+    public void setLabeledBy(View label) {
+        IMPL.setLabeledBy(mInfo, label);
+    }
+
+    /**
+     * Sets the view which serves as the label of the view represented by
+     * this info for accessibility purposes. If <code>virtualDescendantId</code>
+     * is {@link View#NO_ID} the root is set as the label.
+     * <p>
+     * A virtual descendant is an imaginary View that is reported as a part of the view
+     * hierarchy for accessibility purposes. This enables custom views that draw complex
+     * content to report themselves as a tree of virtual views, thus conveying their
+     * logical structure.
+     * </p>
+     * <p>
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
+     *   This class is made immutable before being delivered to an AccessibilityService.
+     * </p>
+     *
+     * @param root The root whose virtual descendant labels this node's source.
+     * @param virtualDescendantId The id of the virtual descendant.
+     */
+    public void setLabeledBy(View root, int virtualDescendantId) {
+        IMPL.setLabeledBy(mInfo, root, virtualDescendantId);
+    }
+
+    /**
+     * Gets the node info which serves as the label of the view represented by
+     * this info for accessibility purposes.
+     * <p>
+     *   <strong>Note:</strong> It is a client responsibility to recycle the
+     *     received info by calling {@link AccessibilityNodeInfoCompat#recycle()}
+     *     to avoid creating of multiple instances.
+     * </p>
+     *
+     * @return The label.
+     */
+    public AccessibilityNodeInfoCompat getLabeledBy() {
+        return AccessibilityNodeInfoCompat.wrapNonNullInstance(IMPL.getLabeledBy(mInfo));
+    }
+
+    /**
+     * Gets if this node opens a popup or a dialog.
+     *
+     * @return If the the node opens a popup.
+     */
+    public boolean canOpenPopup() {
+        return IMPL.canOpenPopup(mInfo);
+    }
+
+    /**
+     * Sets if this node opens a popup or a dialog.
+     * <p>
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
+     *   This class is made immutable before being delivered to an AccessibilityService.
+     * </p>
+     *
+     * @param opensPopup If the the node opens a popup.
+     */
+    public void setCanOpenPopup(boolean opensPopup) {
+        IMPL.setCanOpenPopup(mInfo, opensPopup);
+    }
+
+    /**
+     * Finds {@link AccessibilityNodeInfoCompat}s by the fully qualified view id's resource
+     * name where a fully qualified id is of the from "package:id/id_resource_name".
+     * For example, if the target application's package is "foo.bar" and the id
+     * resource name is "baz", the fully qualified resource id is "foo.bar:id/baz".
+     *
+     * <p>
+     *   <strong>Note:</strong> It is a client responsibility to recycle the
+     *     received info by calling {@link AccessibilityNodeInfoCompat#recycle()}
+     *     to avoid creating of multiple instances.
+     * </p>
+     * <p>
+     *   <strong>Note:</strong> The primary usage of this API is for UI test automation
+     *   and in order to report the fully qualified view id if an
+     *   {@link AccessibilityNodeInfoCompat} the client has to set the
+     *   {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_REPORT_VIEW_IDS}
+     *   flag when configuring his {@link android.accessibilityservice.AccessibilityService}.
+     * </p>
+     *
+     * @param viewId The fully qualified resource name of the view id to find.
+     * @return A list of node info.
+     */
+    public List<AccessibilityNodeInfoCompat> findAccessibilityNodeInfosByViewId(String viewId) {
+        List<Object> nodes = IMPL.findAccessibilityNodeInfosByViewId(mInfo, viewId);
+        if (nodes != null) {
+            List<AccessibilityNodeInfoCompat> result = new ArrayList<AccessibilityNodeInfoCompat>();
+            for (Object node : nodes) {
+                result.add(new AccessibilityNodeInfoCompat(node));
+            }
+            return result;
+        } else {
+            return Collections.emptyList();
+        }
+    }
+
+    /**
+     * Gets an optional bundle with extra data. The bundle
+     * is lazily created and never <code>null</code>.
+     * <p>
+     * <strong>Note:</strong> It is recommended to use the package
+     * name of your application as a prefix for the keys to avoid
+     * collisions which may confuse an accessibility service if the
+     * same key has different meaning when emitted from different
+     * applications.
+     * </p>
+     *
+     * @return The bundle.
+     */
+    public Bundle getExtras() {
+        return IMPL.getExtras(mInfo);
+    }
+
+    /**
+     * Gets the input type of the source as defined by {@link InputType}.
+     *
+     * @return The input type.
+     */
+    public int getInputType() {
+        return IMPL.getInputType(mInfo);
+    }
+
+    /**
+     * Sets the input type of the source as defined by {@link InputType}.
+     * <p>
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
+     *   This class is made immutable before being delivered to an
+     *   AccessibilityService.
+     * </p>
+     *
+     * @param inputType The input type.
+     *
+     * @throws IllegalStateException If called from an AccessibilityService.
+     */
+    public void setInputType(int inputType) {
+        IMPL.setInputType(mInfo, inputType);
+    }
+
+    /**
+     * Sets the maximum text length, or -1 for no limit.
+     * <p>
+     * Typically used to indicate that an editable text field has a limit on
+     * the number of characters entered.
+     * <p>
+     * <strong>Note:</strong> Cannot be called from an
+     * {@link android.accessibilityservice.AccessibilityService}.
+     * This class is made immutable before being delivered to an AccessibilityService.
+     *
+     * @param max The maximum text length.
+     * @see #getMaxTextLength()
+     *
+     * @throws IllegalStateException If called from an AccessibilityService.
+     */
+    public void setMaxTextLength(int max) {
+        IMPL.setMaxTextLength(mInfo, max);
+    }
+
+    /**
+     * Returns the maximum text length for this node.
+     *
+     * @return The maximum text length, or -1 for no limit.
+     * @see #setMaxTextLength(int)
+     */
+    public int getMaxTextLength() {
+        return IMPL.getMaxTextLength(mInfo);
+    }
+
+    /**
+     * Sets the text selection start and end.
+     * <p>
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
+     *   This class is made immutable before being delivered to an AccessibilityService.
+     * </p>
+     *
+     * @param start The text selection start.
+     * @param end The text selection end.
+     *
+     * @throws IllegalStateException If called from an AccessibilityService.
+     */
+    public void setTextSelection(int start, int end) {
+        IMPL.setTextSelection(mInfo, start, end);
+    }
+
+    /**
+     * Gets the text selection start.
+     *
+     * @return The text selection start if there is selection or -1.
+     */
+    public int getTextSelectionStart() {
+        return IMPL.getTextSelectionStart(mInfo);
+    }
+
+    /**
+     * Gets the text selection end.
+     *
+     * @return The text selection end if there is selection or -1.
+     */
+    public int getTextSelectionEnd() {
+        return IMPL.getTextSelectionEnd(mInfo);
+    }
+
+    /**
+     * Gets the node before which this one is visited during traversal. A screen-reader
+     * must visit the content of this node before the content of the one it precedes.
+     *
+     * @return The succeeding node if such or <code>null</code>.
+     *
+     * @see #setTraversalBefore(android.view.View)
+     * @see #setTraversalBefore(android.view.View, int)
+     */
+    public AccessibilityNodeInfoCompat getTraversalBefore() {
+        return AccessibilityNodeInfoCompat.wrapNonNullInstance(IMPL.getTraversalBefore(mInfo));
+    }
+
+    /**
+     * Sets the view before whose node this one should be visited during traversal. A
+     * screen-reader must visit the content of this node before the content of the one
+     * it precedes.
+     * <p>
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
+     *   This class is made immutable before being delivered to an AccessibilityService.
+     * </p>
+     *
+     * @param view The view providing the preceding node.
+     *
+     * @see #getTraversalBefore()
+     */
+    public void setTraversalBefore(View view) {
+        IMPL.setTraversalBefore(mInfo, view);
+    }
+
+    /**
+     * Sets the node before which this one is visited during traversal. A screen-reader
+     * must visit the content of this node before the content of the one it precedes.
+     * The successor is a virtual descendant of the given <code>root</code>. If
+     * <code>virtualDescendantId</code> equals to {@link View#NO_ID} the root is set
+     * as the successor.
+     * <p>
+     * A virtual descendant is an imaginary View that is reported as a part of the view
+     * hierarchy for accessibility purposes. This enables custom views that draw complex
+     * content to report them selves as a tree of virtual views, thus conveying their
+     * logical structure.
+     * </p>
+     * <p>
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
+     *   This class is made immutable before being delivered to an AccessibilityService.
+     * </p>
+     *
+     * @param root The root of the virtual subtree.
+     * @param virtualDescendantId The id of the virtual descendant.
+     */
+    public void setTraversalBefore(View root, int virtualDescendantId) {
+        IMPL.setTraversalBefore(mInfo, root, virtualDescendantId);
+    }
+
+    /**
+     * Gets the node after which this one is visited in accessibility traversal.
+     * A screen-reader must visit the content of the other node before the content
+     * of this one.
+     *
+     * @return The succeeding node if such or <code>null</code>.
+     *
+     * @see #setTraversalAfter(android.view.View)
+     * @see #setTraversalAfter(android.view.View, int)
+     */
+    public AccessibilityNodeInfoCompat getTraversalAfter() {
+        return AccessibilityNodeInfoCompat.wrapNonNullInstance(IMPL.getTraversalAfter(mInfo));
+    }
+
+    /**
+     * Sets the view whose node is visited after this one in accessibility traversal.
+     * A screen-reader must visit the content of the other node before the content
+     * of this one.
+     * <p>
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
+     *   This class is made immutable before being delivered to an AccessibilityService.
+     * </p>
+     *
+     * @param view The previous view.
+     *
+     * @see #getTraversalAfter()
+     */
+    public void setTraversalAfter(View view) {
+        IMPL.setTraversalAfter(mInfo, view);
+    }
+
+    /**
+     * Sets the node after which this one is visited in accessibility traversal.
+     * A screen-reader must visit the content of the other node before the content
+     * of this one. If <code>virtualDescendantId</code> equals to {@link View#NO_ID}
+     * the root is set as the predecessor.
+     * <p>
+     * A virtual descendant is an imaginary View that is reported as a part of the view
+     * hierarchy for accessibility purposes. This enables custom views that draw complex
+     * content to report them selves as a tree of virtual views, thus conveying their
+     * logical structure.
+     * </p>
+     * <p>
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
+     *   This class is made immutable before being delivered to an AccessibilityService.
+     * </p>
+     *
+     * @param root The root of the virtual subtree.
+     * @param virtualDescendantId The id of the virtual descendant.
+     */
+    public void setTraversalAfter(View root, int virtualDescendantId) {
+        IMPL.setTraversalAfter(mInfo, root, virtualDescendantId);
+    }
+
+    /**
+     * Gets the window to which this node belongs.
+     *
+     * @return The window.
+     *
+     * @see android.accessibilityservice.AccessibilityService#getWindows()
+     */
+    public AccessibilityWindowInfoCompat getWindow() {
+        return AccessibilityWindowInfoCompat.wrapNonNullInstance(IMPL.getWindow(mInfo));
+    }
+
+    /**
+     * Gets if the node can be dismissed.
+     *
+     * @return If the node can be dismissed.
+     */
+    public boolean isDismissable() {
+        return IMPL.isDismissable(mInfo);
+    }
+
+    /**
+     * Sets if the node can be dismissed.
+     * <p>
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
+     *   This class is made immutable before being delivered to an AccessibilityService.
+     * </p>
+     *
+     * @param dismissable If the node can be dismissed.
+     */
+    public void setDismissable(boolean dismissable) {
+        IMPL.setDismissable(mInfo, dismissable);
+    }
+
+    /**
+     * Gets if the node is editable.
+     *
+     * @return True if the node is editable, false otherwise.
+     */
+    public boolean isEditable() {
+        return IMPL.isEditable(mInfo);
+    }
+
+    /**
+     * Sets whether this node is editable.
+     * <p>
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
+     *   This class is made immutable before being delivered to an AccessibilityService.
+     * </p>
+     *
+     * @param editable True if the node is editable.
+     *
+     * @throws IllegalStateException If called from an AccessibilityService.
+     */
+    public void setEditable(boolean editable) {
+        IMPL.setEditable(mInfo, editable);
+    }
+
+    /**
+     * Gets if the node is a multi line editable text.
+     *
+     * @return True if the node is multi line.
+     */
+    public boolean isMultiLine() {
+        return IMPL.isMultiLine(mInfo);
+    }
+
+    /**
+     * Sets if the node is a multi line editable text.
+     * <p>
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
+     *   This class is made immutable before being delivered to an AccessibilityService.
+     * </p>
+     *
+     * @param multiLine True if the node is multi line.
+     */
+    public void setMultiLine(boolean multiLine) {
+        IMPL.setMultiLine(mInfo, multiLine);
+    }
+
+    /**
+     * Refreshes this info with the latest state of the view it represents.
+     * <p>
+     * <strong>Note:</strong> If this method returns false this info is obsolete
+     * since it represents a view that is no longer in the view tree and should
+     * be recycled.
+     * </p>
+     * @return Whether the refresh succeeded.
+     */
+    public boolean refresh() {
+        return IMPL.refresh(mInfo);
+    }
+
     @Override
     public int hashCode() {
         return (mInfo == null) ? 0 : mInfo.hashCode();
diff --git a/v4/java/android/support/v4/view/accessibility/AccessibilityWindowInfoCompat.java b/v4/java/android/support/v4/view/accessibility/AccessibilityWindowInfoCompat.java
new file mode 100644
index 0000000..3197bb1
--- /dev/null
+++ b/v4/java/android/support/v4/view/accessibility/AccessibilityWindowInfoCompat.java
@@ -0,0 +1,454 @@
+/*
+ * 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.v4.view.accessibility;
+
+import android.graphics.Rect;
+import android.os.Build;
+
+/**
+ * Helper for accessing {@link android.view.accessibility.AccessibilityWindowInfo}
+ * introduced after API level 4 in a backwards compatible fashion.
+ */
+public class AccessibilityWindowInfoCompat {
+
+    private static interface AccessibilityWindowInfoImpl {
+        public Object obtain();
+        public Object obtain(Object info);
+        public int getType(Object info);
+        public int getLayer(Object info);
+        public Object getRoot(Object info);
+        public Object getParent(Object info);
+        public int getId(Object info);
+        public void getBoundsInScreen(Object info, Rect outBounds);
+        public boolean isActive(Object info);
+        public boolean isFocused(Object info);
+        public boolean isAccessibilityFocused(Object info);
+        public int getChildCount(Object info);
+        public Object getChild(Object info, int index);
+        public void recycle(Object info);
+    }
+
+    private static class AccessibilityWindowInfoStubImpl implements  AccessibilityWindowInfoImpl {
+
+        @Override
+        public Object obtain() {
+            return null;
+        }
+
+        @Override
+        public Object obtain(Object info) {
+            return null;
+        }
+
+        @Override
+        public int getType(Object info) {
+            return UNDEFINED;
+        }
+
+        @Override
+        public int getLayer(Object info) {
+            return UNDEFINED;
+        }
+
+        @Override
+        public Object getRoot(Object info) {
+            return null;
+        }
+
+        @Override
+        public Object getParent(Object info) {
+            return null;
+        }
+
+        @Override
+        public int getId(Object info) {
+            return UNDEFINED;
+        }
+
+        @Override
+        public void getBoundsInScreen(Object info, Rect outBounds) {
+        }
+
+        @Override
+        public boolean isActive(Object info) {
+            return true;
+        }
+
+        @Override
+        public boolean isFocused(Object info) {
+            return true;
+        }
+
+        @Override
+        public boolean isAccessibilityFocused(Object info) {
+            return true;
+        }
+
+        @Override
+        public int getChildCount(Object info) {
+            return 0;
+        }
+
+        @Override
+        public Object getChild(Object info, int index) {
+            return null;
+        }
+
+        @Override
+        public void recycle(Object info) {
+        }
+    }
+
+    private static class AccessibilityWindowInfoApi21Impl extends AccessibilityWindowInfoStubImpl {
+        @Override
+        public Object obtain() {
+            return AccessibilityWindowInfoCompatApi21.obtain();
+        }
+
+        @Override
+        public Object obtain(Object info) {
+            return AccessibilityWindowInfoCompatApi21.obtain(info);
+        }
+
+        @Override
+        public int getType(Object info) {
+            return AccessibilityWindowInfoCompatApi21.getType(info);
+        }
+
+        @Override
+        public int getLayer(Object info) {
+            return AccessibilityWindowInfoCompatApi21.getLayer(info);
+        }
+
+        @Override
+        public Object getRoot(Object info) {
+            return AccessibilityWindowInfoCompatApi21.getRoot(info);
+        }
+
+        @Override
+        public Object getParent(Object info) {
+            return AccessibilityWindowInfoCompatApi21.getParent(info);
+        }
+
+        @Override
+        public int getId(Object info) {
+            return AccessibilityWindowInfoCompatApi21.getId(info);
+        }
+
+        @Override
+        public void getBoundsInScreen(Object info, Rect outBounds) {
+            AccessibilityWindowInfoCompatApi21.getBoundsInScreen(info, outBounds);
+        }
+
+        @Override
+        public boolean isActive(Object info) {
+            return AccessibilityWindowInfoCompatApi21.isActive(info);
+        }
+
+        @Override
+        public boolean isFocused(Object info) {
+            return AccessibilityWindowInfoCompatApi21.isFocused(info);
+        }
+
+        @Override
+        public boolean isAccessibilityFocused(Object info) {
+            return AccessibilityWindowInfoCompatApi21.isAccessibilityFocused(info);
+        }
+
+        @Override
+        public int getChildCount(Object info) {
+            return AccessibilityWindowInfoCompatApi21.getChildCount(info);
+        }
+
+        @Override
+        public Object getChild(Object info, int index) {
+            return AccessibilityWindowInfoCompatApi21.getChild(info, index);
+        }
+
+        @Override
+        public void recycle(Object info) {
+            AccessibilityWindowInfoCompatApi21.recycle(info);
+        }
+    }
+
+    static {
+        if (Build.VERSION.SDK_INT >= 21) {
+            IMPL = new AccessibilityWindowInfoApi21Impl();
+        } else {
+            IMPL = new AccessibilityWindowInfoStubImpl();
+        }
+    }
+
+    private static final AccessibilityWindowInfoImpl IMPL;
+    private Object mInfo;
+
+    private static final int UNDEFINED = -1;
+
+    /**
+     * Window type: This is an application window. Such a window shows UI for
+     * interacting with an application.
+     */
+    public static final int TYPE_APPLICATION = 1;
+
+    /**
+     * Window type: This is an input method window. Such a window shows UI for
+     * inputting text such as keyboard, suggestions, etc.
+     */
+    public static final int TYPE_INPUT_METHOD = 2;
+
+    /**
+     * Window type: This is an system window. Such a window shows UI for
+     * interacting with the system.
+     */
+    public static final int TYPE_SYSTEM = 3;
+
+    /**
+     * Window type: Windows that are overlaid <em>only</em> by an {@link
+     * android.accessibilityservice.AccessibilityService} for interception of
+     * user interactions without changing the windows an accessibility service
+     * can introspect. In particular, an accessibility service can introspect
+     * only windows that a sighted user can interact with which they can touch
+     * these windows or can type into these windows. For example, if there
+     * is a full screen accessibility overlay that is touchable, the windows
+     * below it will be introspectable by an accessibility service regardless
+     * they are covered by a touchable window.
+     */
+    public static final int TYPE_ACCESSIBILITY_OVERLAY = 4;
+
+    /**
+     * Creates a wrapper for info implementation.
+     *
+     * @param object The info to wrap.
+     * @return A wrapper for if the object is not null, null otherwise.
+     */
+    static AccessibilityWindowInfoCompat wrapNonNullInstance(Object object) {
+        if (object != null) {
+            return new AccessibilityWindowInfoCompat(object);
+        }
+        return null;
+    }
+
+    private AccessibilityWindowInfoCompat(Object info) {
+        mInfo = info;
+    }
+
+    /**
+     * Gets the type of the window.
+     *
+     * @return The type.
+     *
+     * @see #TYPE_APPLICATION
+     * @see #TYPE_INPUT_METHOD
+     * @see #TYPE_SYSTEM
+     * @see #TYPE_ACCESSIBILITY_OVERLAY
+     */
+    public int getType() {
+        return IMPL.getType(mInfo);
+    }
+
+    /**
+     * Gets the layer which determines the Z-order of the window. Windows
+     * with greater layer appear on top of windows with lesser layer.
+     *
+     * @return The window layer.
+     */
+    public int getLayer() {
+        return IMPL.getLayer(mInfo);
+    }
+
+    /**
+     * Gets the root node in the window's hierarchy.
+     *
+     * @return The root node.
+     */
+    public AccessibilityNodeInfoCompat getRoot() {
+        return AccessibilityNodeInfoCompat.wrapNonNullInstance(IMPL.getRoot(mInfo));
+    }
+
+    /**
+     * Gets the parent window if such.
+     *
+     * @return The parent window.
+     */
+    public AccessibilityWindowInfoCompat getParent() {
+        return wrapNonNullInstance(IMPL.getParent(mInfo));
+    }
+
+    /**
+     * Gets the unique window id.
+     *
+     * @return windowId The window id.
+     */
+    public int getId() {
+        return IMPL.getId(mInfo);
+    }
+
+    /**
+     * Gets the bounds of this window in the screen.
+     *
+     * @param outBounds The out window bounds.
+     */
+    public void getBoundsInScreen(Rect outBounds) {
+        IMPL.getBoundsInScreen(mInfo, outBounds);
+    }
+
+    /**
+     * Gets if this window is active. An active window is the one
+     * the user is currently touching or the window has input focus
+     * and the user is not touching any window.
+     *
+     * @return Whether this is the active window.
+     */
+    public boolean isActive() {
+        return IMPL.isActive(mInfo);
+    }
+
+    /**
+     * Gets if this window has input focus.
+     *
+     * @return Whether has input focus.
+     */
+    public boolean isFocused() {
+        return IMPL.isFocused(mInfo);
+    }
+
+    /**
+     * Gets if this window has accessibility focus.
+     *
+     * @return Whether has accessibility focus.
+     */
+    public boolean isAccessibilityFocused() {
+        return IMPL.isAccessibilityFocused(mInfo);
+    }
+
+    /**
+     * Gets the number of child windows.
+     *
+     * @return The child count.
+     */
+    public int getChildCount() {
+        return IMPL.getChildCount(mInfo);
+    }
+
+    /**
+     * Gets the child window at a given index.
+     *
+     * @param index The index.
+     * @return The child.
+     */
+    public AccessibilityWindowInfoCompat getChild(int index) {
+        return wrapNonNullInstance(IMPL.getChild(mInfo, index));
+    }
+
+    /**
+     * Returns a cached instance if such is available or a new one is
+     * created.
+     *
+     * @return An instance.
+     */
+    public static AccessibilityWindowInfoCompat obtain() {
+        return wrapNonNullInstance(IMPL.obtain());
+    }
+
+    /**
+     * Returns a cached instance if such is available or a new one is
+     * created. The returned instance is initialized from the given
+     * <code>info</code>.
+     *
+     * @param info The other info.
+     * @return An instance.
+     */
+    public static AccessibilityWindowInfoCompat obtain(AccessibilityWindowInfoCompat info) {
+        return wrapNonNullInstance(IMPL.obtain(info.mInfo));
+    }
+
+    /**
+     * Return an instance back to be reused.
+     * <p>
+     * <strong>Note:</strong> You must not touch the object after calling this function.
+     * </p>
+     *
+     * @throws IllegalStateException If the info is already recycled.
+     */
+    public void recycle() {
+        IMPL.recycle(mInfo);
+    }
+
+    @Override
+    public int hashCode() {
+        return (mInfo == null) ? 0 : mInfo.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        AccessibilityWindowInfoCompat other = (AccessibilityWindowInfoCompat) obj;
+        if (mInfo == null) {
+            if (other.mInfo != null) {
+                return false;
+            }
+        } else if (!mInfo.equals(other.mInfo)) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        Rect bounds = new Rect();
+        getBoundsInScreen(bounds);
+        builder.append("AccessibilityWindowInfo[");
+        builder.append("id=").append(getId());
+        builder.append(", type=").append(typeToString(getType()));
+        builder.append(", layer=").append(getLayer());
+        builder.append(", bounds=").append(bounds);
+        builder.append(", focused=").append(isFocused());
+        builder.append(", active=").append(isActive());
+        builder.append(", hasParent=").append(getParent() != null);
+        builder.append(", hasChildren=").append(getChildCount() > 0);
+        builder.append(']');
+        return builder.toString();
+    }
+
+    private static String typeToString(int type) {
+        switch (type) {
+            case TYPE_APPLICATION: {
+                return "TYPE_APPLICATION";
+            }
+            case TYPE_INPUT_METHOD: {
+                return "TYPE_INPUT_METHOD";
+            }
+            case TYPE_SYSTEM: {
+                return "TYPE_SYSTEM";
+            }
+            case TYPE_ACCESSIBILITY_OVERLAY: {
+                return "TYPE_ACCESSIBILITY_OVERLAY";
+            }
+            default:
+                return "<UNKNOWN>";
+        }
+    }
+}
diff --git a/v4/java/android/support/v4/widget/CompoundButtonCompat.java b/v4/java/android/support/v4/widget/CompoundButtonCompat.java
new file mode 100644
index 0000000..d08d1c0
--- /dev/null
+++ b/v4/java/android/support/v4/widget/CompoundButtonCompat.java
@@ -0,0 +1,176 @@
+/*
+ * 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.v4.widget;
+
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.graphics.Canvas;
+import android.graphics.PorterDuff;
+import android.graphics.drawable.Drawable;
+import android.os.Build;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v4.graphics.drawable.DrawableCompat;
+import android.widget.CompoundButton;
+
+/**
+ * Helper for accessing {@link android.widget.CompoundButton} methods introduced after
+ * API level 4 in a backwards compatible fashion.
+ */
+public final class CompoundButtonCompat {
+
+    private static final CompoundButtonCompatImpl IMPL;
+
+    static {
+        final int sdk = Build.VERSION.SDK_INT;
+        if (sdk >= 23 || "MNC".equals(Build.VERSION.CODENAME)) {
+            IMPL = new Api23CompoundButtonImpl();
+        } else if (sdk >= 21) {
+            IMPL = new LollipopCompoundButtonImpl();
+        } else {
+            IMPL = new BaseCompoundButtonCompat();
+        }
+    }
+
+    interface CompoundButtonCompatImpl {
+        void setButtonTintList(CompoundButton button, ColorStateList tint);
+        ColorStateList getButtonTintList(CompoundButton button);
+        void setButtonTintMode(CompoundButton button, PorterDuff.Mode tintMode);
+        PorterDuff.Mode getButtonTintMode(CompoundButton button);
+        Drawable getButtonDrawable(CompoundButton button);
+    }
+
+    static class BaseCompoundButtonCompat implements CompoundButtonCompatImpl {
+        @Override
+        public void setButtonTintList(CompoundButton button, ColorStateList tint) {
+            CompoundButtonCompatDonut.setButtonTintList(button, tint);
+        }
+
+        @Override
+        public ColorStateList getButtonTintList(CompoundButton button) {
+            return CompoundButtonCompatDonut.getButtonTintList(button);
+        }
+
+        @Override
+        public void setButtonTintMode(CompoundButton button, PorterDuff.Mode tintMode) {
+            CompoundButtonCompatDonut.setButtonTintMode(button, tintMode);
+        }
+
+        @Override
+        public PorterDuff.Mode getButtonTintMode(CompoundButton button) {
+            return CompoundButtonCompatDonut.getButtonTintMode(button);
+        }
+
+        @Override
+        public Drawable getButtonDrawable(CompoundButton button) {
+            return CompoundButtonCompatDonut.getButtonDrawable(button);
+        }
+    }
+
+    static class LollipopCompoundButtonImpl extends BaseCompoundButtonCompat {
+        @Override
+        public void setButtonTintList(CompoundButton button, ColorStateList tint) {
+            CompoundButtonCompatLollipop.setButtonTintList(button, tint);
+        }
+
+        @Override
+        public ColorStateList getButtonTintList(CompoundButton button) {
+            return CompoundButtonCompatLollipop.getButtonTintList(button);
+        }
+
+        @Override
+        public void setButtonTintMode(CompoundButton button, PorterDuff.Mode tintMode) {
+            CompoundButtonCompatLollipop.setButtonTintMode(button, tintMode);
+        }
+
+        @Override
+        public PorterDuff.Mode getButtonTintMode(CompoundButton button) {
+            return CompoundButtonCompatLollipop.getButtonTintMode(button);
+        }
+    }
+
+    static class Api23CompoundButtonImpl extends LollipopCompoundButtonImpl {
+        @Override
+        public Drawable getButtonDrawable(CompoundButton button) {
+            return CompoundButtonCompatApi23.getButtonDrawable(button);
+        }
+    }
+
+    private CompoundButtonCompat() {}
+
+    /**
+     * Applies a tint to the button drawable. Does not modify the current tint
+     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
+     * <p>
+     * Subsequent calls to {@link CompoundButton#setButtonDrawable(Drawable)} should
+     * automatically mutate the drawable and apply the specified tint and tint
+     * mode using {@link DrawableCompat#setTintList(Drawable, ColorStateList)}.
+     *
+     * @param tint the tint to apply, may be {@code null} to clear tint
+     *
+     * @see #setButtonTintList(CompoundButton, ColorStateList)
+     */
+    public static void setButtonTintList(@NonNull CompoundButton button, @Nullable ColorStateList tint) {
+        IMPL.setButtonTintList(button, tint);
+    }
+
+    /**
+     * Returns the tint applied to the button drawable
+     *
+     * @see #setButtonTintList(CompoundButton, ColorStateList)
+     */
+    @Nullable
+    public static ColorStateList getButtonTintList(@NonNull CompoundButton button) {
+        return IMPL.getButtonTintList(button);
+    }
+
+    /**
+     * Specifies the blending mode used to apply the tint specified by
+     * {@link #setButtonTintList(CompoundButton, ColorStateList)}} to the button drawable. The
+     * default mode is {@link PorterDuff.Mode#SRC_IN}.
+     *
+     * @param tintMode the blending mode used to apply the tint, may be
+     *                 {@code null} to clear tint
+     *
+     * @see #getButtonTintMode(CompoundButton)
+     * @see DrawableCompat#setTintMode(Drawable, PorterDuff.Mode)
+     */
+    public static void setButtonTintMode(@NonNull CompoundButton button,
+            @Nullable PorterDuff.Mode tintMode) {
+        IMPL.setButtonTintMode(button, tintMode);
+    }
+
+    /**
+     * @return the blending mode used to apply the tint to the button drawable
+     * @attr ref android.R.styleable#CompoundButton_buttonTintMode
+     * @see #setButtonTintMode(PorterDuff.Mode)
+     */
+    @Nullable
+    public static PorterDuff.Mode getButtonTintMode(@NonNull CompoundButton button) {
+        return IMPL.getButtonTintMode(button);
+    }
+
+    /**
+     * Returns the drawable used as the compound button image
+     *
+     * @see CompoundButton#setButtonDrawable(Drawable)
+     */
+    @Nullable
+    public static Drawable getButtonDrawable(@NonNull CompoundButton button) {
+        return IMPL.getButtonDrawable(button);
+    }
+}
diff --git a/v4/java/android/support/v4/widget/DrawerLayout.java b/v4/java/android/support/v4/widget/DrawerLayout.java
index a8967a2..b68bc28 100644
--- a/v4/java/android/support/v4/widget/DrawerLayout.java
+++ b/v4/java/android/support/v4/widget/DrawerLayout.java
@@ -29,10 +29,12 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.SystemClock;
+import android.support.annotation.ColorInt;
 import android.support.annotation.DrawableRes;
 import android.support.annotation.IntDef;
 import android.support.annotation.Nullable;
 import android.support.v4.content.ContextCompat;
+import android.support.v4.graphics.drawable.DrawableCompat;
 import android.support.v4.view.AccessibilityDelegateCompat;
 import android.support.v4.view.GravityCompat;
 import android.support.v4.view.KeyEventCompat;
@@ -134,6 +136,7 @@
 
 
     private static final int MIN_DRAWER_MARGIN = 64; // dp
+    private static final int DRAWER_ELEVATION = 10; //dp
 
     private static final int DEFAULT_SCRIM_COLOR = 0x99000000;
 
@@ -163,8 +166,13 @@
     /** Whether we can use NO_HIDE_DESCENDANTS accessibility importance. */
     private static final boolean CAN_HIDE_DESCENDANTS = Build.VERSION.SDK_INT >= 19;
 
+    /** Whether the drawer shadow comes from setting elevation on the drawer. */
+    private static final boolean SET_DRAWER_SHADOW_FROM_ELEVATION =
+            Build.VERSION.SDK_INT >= 21;
+
     private final ChildAccessibilityDelegate mChildAccessibilityDelegate =
             new ChildAccessibilityDelegate();
+    private float mDrawerElevation;
 
     private int mMinDrawerMargin;
 
@@ -189,9 +197,9 @@
     private float mInitialMotionX;
     private float mInitialMotionY;
 
-    private Drawable mShadowLeft;
-    private Drawable mShadowRight;
     private Drawable mStatusBarBackground;
+    private Drawable mShadowLeftResolved;
+    private Drawable mShadowRightResolved;
 
     private CharSequence mTitleLeft;
     private CharSequence mTitleRight;
@@ -199,6 +207,12 @@
     private Object mLastInsets;
     private boolean mDrawStatusBarBackground;
 
+    /** Shadow drawables for different gravity */
+    private Drawable mShadowStart = null;
+    private Drawable mShadowEnd = null;
+    private Drawable mShadowLeft = null;
+    private Drawable mShadowRight = null;
+
     /**
      * Listener for monitoring events about drawers.
      */
@@ -361,6 +375,38 @@
             IMPL.configureApplyInsets(this);
             mStatusBarBackground = IMPL.getDefaultStatusBarBackground(context);
         }
+
+        mDrawerElevation = DRAWER_ELEVATION * density;
+    }
+
+    /**
+     * Sets the base elevation of the drawer(s) relative to the parent, in pixels. Note that the
+     * elevation change is only supported in API 21 and above.
+     *
+     * @param elevation The base depth position of the view, in pixels.
+     */
+    public void setDrawerElevation(float elevation) {
+        mDrawerElevation = elevation;
+        for (int i = 0; i < getChildCount(); i++) {
+            View child = getChildAt(i);
+            if (isDrawerView(child)) {
+                ViewCompat.setElevation(child, mDrawerElevation);
+            }
+        }
+    }
+
+    /**
+     * The base elevation of the drawer(s) relative to the parent, in pixels. Note that the
+     * elevation change is only supported in API 21 and above. For unsupported API levels, 0 will
+     * be returned as the elevation.
+     *
+     * @return The base depth position of the view, in pixels.
+     */
+    public float getDrawerElevation() {
+        if (SET_DRAWER_SHADOW_FROM_ELEVATION) {
+            return mDrawerElevation;
+        }
+        return 0f;
     }
 
     /**
@@ -376,8 +422,15 @@
     }
 
     /**
-     * Set a simple drawable used for the left or right shadow.
-     * The drawable provided must have a nonzero intrinsic width.
+     * Set a simple drawable used for the left or right shadow. The drawable provided must have a
+     * nonzero intrinsic width. For API 21 and above, an elevation will be set on the drawer
+     * instead of the drawable provided.
+     *
+     * <p>Note that for better support for both left-to-right and right-to-left layout
+     * directions, a drawable for RTL layout (in additional to the one in LTR layout) can be
+     * defined with a resource qualifier "ldrtl" for API 17 and above with the gravity
+     * {@link GravityCompat#START}. Alternatively, for API 23 and above, the drawable can
+     * auto-mirrored such that the drawable will be mirrored in RTL layout.</p>
      *
      * @param shadowDrawable Shadow drawable to use at the edge of a drawer
      * @param gravity Which drawer the shadow should apply to
@@ -388,22 +441,35 @@
          * They're probably nuts, but we might want to consider registering callbacks,
          * setting states, etc. properly.
          */
-
-        final int absGravity = GravityCompat.getAbsoluteGravity(gravity,
-                ViewCompat.getLayoutDirection(this));
-        if ((absGravity & Gravity.LEFT) == Gravity.LEFT) {
+        if (SET_DRAWER_SHADOW_FROM_ELEVATION) {
+            // No op. Drawer shadow will come from setting an elevation on the drawer.
+            return;
+        }
+        if ((gravity & GravityCompat.START) == GravityCompat.START) {
+            mShadowStart = shadowDrawable;
+        } else if ((gravity & GravityCompat.END) == GravityCompat.END) {
+            mShadowEnd = shadowDrawable;
+        } else if ((gravity & Gravity.LEFT) == Gravity.LEFT) {
             mShadowLeft = shadowDrawable;
-            invalidate();
-        }
-        if ((absGravity & Gravity.RIGHT) == Gravity.RIGHT) {
+        } else if ((gravity & Gravity.RIGHT) == Gravity.RIGHT) {
             mShadowRight = shadowDrawable;
-            invalidate();
+        } else {
+            return;
         }
+        resolveShadowDrawables();
+        invalidate();
     }
 
     /**
-     * Set a simple drawable used for the left or right shadow.
-     * The drawable provided must have a nonzero intrinsic width.
+     * Set a simple drawable used for the left or right shadow. The drawable provided must have a
+     * nonzero intrinsic width. For API 21 and above, an elevation will be set on the drawer
+     * instead of the drawable provided.
+     *
+     * <p>Note that for better support for both left-to-right and right-to-left layout
+     * directions, a drawable for RTL layout (in additional to the one in LTR layout) can be
+     * defined with a resource qualifier "ldrtl" for API 17 and above with the gravity
+     * {@link GravityCompat#START}. Alternatively, for API 23 and above, the drawable can
+     * auto-mirrored such that the drawable will be mirrored in RTL layout.</p>
      *
      * @param resId Resource id of a shadow drawable to use at the edge of a drawer
      * @param gravity Which drawer the shadow should apply to
@@ -417,7 +483,7 @@
      *
      * @param color Color to use in 0xAARRGGBB format.
      */
-    public void setScrimColor(int color) {
+    public void setScrimColor(@ColorInt int color) {
         mScrimColor = color;
         invalidate();
     }
@@ -867,6 +933,11 @@
                         heightSize - lp.topMargin - lp.bottomMargin, MeasureSpec.EXACTLY);
                 child.measure(contentWidthSpec, contentHeightSpec);
             } else if (isDrawerView(child)) {
+                if (SET_DRAWER_SHADOW_FROM_ELEVATION) {
+                    if (ViewCompat.getElevation(child) != mDrawerElevation) {
+                        ViewCompat.setElevation(child, mDrawerElevation);
+                    }
+                }
                 final int childGravity =
                         getDrawerViewAbsoluteGravity(child) & Gravity.HORIZONTAL_GRAVITY_MASK;
                 if ((foundDrawers & childGravity) != 0) {
@@ -889,6 +960,65 @@
         }
     }
 
+    private void resolveShadowDrawables() {
+        if (SET_DRAWER_SHADOW_FROM_ELEVATION) {
+            return;
+        }
+        mShadowLeftResolved = resolveLeftShadow();
+        mShadowRightResolved = resolveRightShadow();
+    }
+
+    private Drawable resolveLeftShadow() {
+        int layoutDirection = ViewCompat.getLayoutDirection(this);
+        // Prefer shadows defined with start/end gravity over left and right.
+        if (layoutDirection == ViewCompat.LAYOUT_DIRECTION_LTR) {
+            if (mShadowStart != null) {
+                // Correct drawable layout direction, if needed.
+                mirror(mShadowStart, layoutDirection);
+                return mShadowStart;
+            }
+        } else {
+            if (mShadowEnd != null) {
+                // Correct drawable layout direction, if needed.
+                mirror(mShadowEnd, layoutDirection);
+                return mShadowEnd;
+            }
+        }
+        return mShadowLeft;
+    }
+
+    private Drawable resolveRightShadow() {
+        int layoutDirection = ViewCompat.getLayoutDirection(this);
+        if (layoutDirection == ViewCompat.LAYOUT_DIRECTION_LTR) {
+            if (mShadowEnd != null) {
+                // Correct drawable layout direction, if needed.
+                mirror(mShadowEnd, layoutDirection);
+                return mShadowEnd;
+            }
+        } else {
+            if (mShadowStart != null) {
+                // Correct drawable layout direction, if needed.
+                mirror(mShadowStart, layoutDirection);
+                return mShadowStart;
+            }
+        }
+        return mShadowRight;
+    }
+
+    /**
+     * Change the layout direction of the given drawable.
+     * Return true if auto-mirror is supported and drawable's layout direction can be changed.
+     * Otherwise, return false.
+     */
+    private boolean mirror(Drawable drawable, int layoutDirection) {
+        if (drawable == null || !DrawableCompat.isAutoMirrored(drawable)) {
+            return false;
+        }
+
+        DrawableCompat.setLayoutDirection(drawable, layoutDirection);
+        return true;
+    }
+
     @Override
     protected void onLayout(boolean changed, int l, int t, int r, int b) {
         mInLayout = true;
@@ -1042,11 +1172,15 @@
      * @param color Color to use as a background drawable to draw behind the status bar
      *              in 0xAARRGGBB format.
      */
-    public void setStatusBarBackgroundColor(int color) {
+    public void setStatusBarBackgroundColor(@ColorInt int color) {
         mStatusBarBackground = new ColorDrawable(color);
         invalidate();
     }
 
+    public void onRtlPropertiesChanged(int layoutDirection) {
+        resolveShadowDrawables();
+    }
+
     @Override
     public void onDraw(Canvas c) {
         super.onDraw(c);
@@ -1096,27 +1230,29 @@
             mScrimPaint.setColor(color);
 
             canvas.drawRect(clipLeft, 0, clipRight, getHeight(), mScrimPaint);
-        } else if (mShadowLeft != null && checkDrawerViewAbsoluteGravity(child, Gravity.LEFT)) {
-            final int shadowWidth = mShadowLeft.getIntrinsicWidth();
+        } else if (mShadowLeftResolved != null
+                &&  checkDrawerViewAbsoluteGravity(child, Gravity.LEFT)) {
+            final int shadowWidth = mShadowLeftResolved.getIntrinsicWidth();
             final int childRight = child.getRight();
             final int drawerPeekDistance = mLeftDragger.getEdgeSize();
             final float alpha =
                     Math.max(0, Math.min((float) childRight / drawerPeekDistance, 1.f));
-            mShadowLeft.setBounds(childRight, child.getTop(),
+            mShadowLeftResolved.setBounds(childRight, child.getTop(),
                     childRight + shadowWidth, child.getBottom());
-            mShadowLeft.setAlpha((int) (0xff * alpha));
-            mShadowLeft.draw(canvas);
-        } else if (mShadowRight != null && checkDrawerViewAbsoluteGravity(child, Gravity.RIGHT)) {
-            final int shadowWidth = mShadowRight.getIntrinsicWidth();
+            mShadowLeftResolved.setAlpha((int) (0xff * alpha));
+            mShadowLeftResolved.draw(canvas);
+        } else if (mShadowRightResolved != null
+                &&  checkDrawerViewAbsoluteGravity(child, Gravity.RIGHT)) {
+            final int shadowWidth = mShadowRightResolved.getIntrinsicWidth();
             final int childLeft = child.getLeft();
             final int showing = getWidth() - childLeft;
             final int drawerPeekDistance = mRightDragger.getEdgeSize();
             final float alpha =
                     Math.max(0, Math.min((float) showing / drawerPeekDistance, 1.f));
-            mShadowRight.setBounds(childLeft - shadowWidth, child.getTop(),
+            mShadowRightResolved.setBounds(childLeft - shadowWidth, child.getTop(),
                     childLeft, child.getBottom());
-            mShadowRight.setAlpha((int) (0xff * alpha));
-            mShadowRight.draw(canvas);
+            mShadowRightResolved.setAlpha((int) (0xff * alpha));
+            mShadowRightResolved.draw(canvas);
         }
         return result;
     }
diff --git a/v4/java/android/support/v4/widget/ExploreByTouchHelper.java b/v4/java/android/support/v4/widget/ExploreByTouchHelper.java
index 7adbc6f..64f6634 100644
--- a/v4/java/android/support/v4/widget/ExploreByTouchHelper.java
+++ b/v4/java/android/support/v4/widget/ExploreByTouchHelper.java
@@ -45,11 +45,11 @@
  * and managing accessibility focus. This class does not currently support
  * hierarchies of logical items.
  * <p>
- * This should be applied to the parent view using
- * {@link ViewCompat#setAccessibilityDelegate}:
+ * Clients should override abstract methods on this class and attach it to the
+ * host view using {@link ViewCompat#setAccessibilityDelegate}:
  *
  * <pre>
- * mAccessHelper = ExploreByTouchHelper.create(someView, mAccessHelperCallback);
+ * mAccessHelper = new MyExploreByTouchHelper(someView);
  * ViewCompat.setAccessibilityDelegate(someView, mAccessHelper);
  * </pre>
  */
@@ -57,6 +57,9 @@
     /** Virtual node identifier value for invalid nodes. */
     public static final int INVALID_ID = Integer.MIN_VALUE;
 
+    /** Virtual node identifier value for the host view's node. */
+    public static final int HOST_ID = View.NO_ID;
+
     /** Default class name used for virtual views. */
     private static final String DEFAULT_CLASS_NAME = View.class.getName();
 
@@ -191,7 +194,7 @@
      * parent view.
      */
     public void invalidateRoot() {
-        invalidateVirtualView(View.NO_ID);
+        invalidateVirtualView(HOST_ID);
     }
 
     /**
@@ -243,7 +246,7 @@
 
     /**
      * Constructs and returns an {@link AccessibilityEvent} for the specified
-     * virtual view id, which includes the host view ({@link View#NO_ID}).
+     * virtual view id, which includes the host view ({@link #HOST_ID}).
      *
      * @param virtualViewId The virtual view id for the item for which to
      *            construct an event.
@@ -253,7 +256,7 @@
      */
     private AccessibilityEvent createEvent(int virtualViewId, int eventType) {
         switch (virtualViewId) {
-            case View.NO_ID:
+            case HOST_ID:
                 return createEventForHost(eventType);
             default:
                 return createEventForChild(virtualViewId, eventType);
@@ -309,7 +312,7 @@
     /**
      * Constructs and returns an {@link AccessibilityNodeInfoCompat} for the
      * specified virtual view id, which includes the host view
-     * ({@link View#NO_ID}).
+     * ({@link #HOST_ID}).
      *
      * @param virtualViewId The virtual view id for the item for which to
      *            construct a node.
@@ -318,7 +321,7 @@
      */
     private AccessibilityNodeInfoCompat createNode(int virtualViewId) {
         switch (virtualViewId) {
-            case View.NO_ID:
+            case HOST_ID:
                 return createNodeForHost();
             default:
                 return createNodeForChild(virtualViewId);
@@ -335,6 +338,9 @@
         final AccessibilityNodeInfoCompat node = AccessibilityNodeInfoCompat.obtain(mView);
         ViewCompat.onInitializeAccessibilityNodeInfo(mView, node);
 
+        // Allow the client to populate the host node.
+        onPopulateNodeForHost(node);
+
         // Add the virtual descendants.
         final LinkedList<Integer> virtualViewIds = new LinkedList<Integer>();
         getVisibleVirtualViews(virtualViewIds);
@@ -439,7 +445,7 @@
 
     private boolean performAction(int virtualViewId, int action, Bundle arguments) {
         switch (virtualViewId) {
-            case View.NO_ID:
+            case HOST_ID:
                 return performActionForHost(action, arguments);
             default:
                 return performActionForChild(virtualViewId, action, arguments);
@@ -542,7 +548,15 @@
         }
         // TODO: Check virtual view visibility.
         if (!isAccessibilityFocused(virtualViewId)) {
+            // Clear focus from the previously focused view, if applicable.
+            if (mFocusedVirtualViewId != INVALID_ID) {
+                sendEventForVirtualView(mFocusedVirtualViewId,
+                        AccessibilityEventCompat.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
+            }
+
+            // Set focus on the new view.
             mFocusedVirtualViewId = virtualViewId;
+
             // TODO: Only invalidate virtual view bounds.
             mView.invalidate();
             sendEventForVirtualView(virtualViewId,
@@ -577,7 +591,7 @@
      * @param x The view-relative x coordinate
      * @param y The view-relative y coordinate
      * @return virtual view identifier for the logical item under
-     *         coordinates (x,y) or {@link View#NO_ID} if there is no item at
+     *         coordinates (x,y) or {@link #HOST_ID} if there is no item at
      *         the given coordinates
      */
     protected abstract int getVirtualViewAt(float x, float y);
@@ -683,6 +697,17 @@
             int virtualViewId, AccessibilityNodeInfoCompat node);
 
     /**
+     * Populates an {@link AccessibilityNodeInfoCompat} with information
+     * about the host view.
+     * <p>
+     * The following required fields are automatically populated by the
+     * helper class and may not be overridden:
+     */
+    public void onPopulateNodeForHost(AccessibilityNodeInfoCompat node) {
+        // Default implementation is no-op.
+    }
+
+    /**
      * Performs the specified accessibility action on the item associated
      * with the virtual view identifier. See
      * {@link AccessibilityNodeInfoCompat#performAction(int, Bundle)} for
diff --git a/v4/java/android/support/v4/widget/PopupWindowCompat.java b/v4/java/android/support/v4/widget/PopupWindowCompat.java
index be96a73..7f4c828 100644
--- a/v4/java/android/support/v4/widget/PopupWindowCompat.java
+++ b/v4/java/android/support/v4/widget/PopupWindowCompat.java
@@ -17,7 +17,7 @@
 package android.support.v4.widget;
 
 import android.view.View;
-import android.view.View.OnTouchListener;
+import android.view.WindowManager;
 import android.widget.PopupWindow;
 
 /**
@@ -29,8 +29,11 @@
      * Interface for the full API.
      */
     interface PopupWindowImpl {
-        public void showAsDropDown(PopupWindow popup, View anchor, int xoff, int yoff,
-                int gravity);
+        void showAsDropDown(PopupWindow popup, View anchor, int xoff, int yoff, int gravity);
+        void setOverlapAnchor(PopupWindow popupWindow, boolean overlapAnchor);
+        boolean getOverlapAnchor(PopupWindow popupWindow);
+        void setWindowLayoutType(PopupWindow popupWindow, int layoutType);
+        int getWindowLayoutType(PopupWindow popupWindow);
     }
 
     /**
@@ -42,12 +45,47 @@
                 int gravity) {
             popup.showAsDropDown(anchor, xoff, yoff);
         }
+
+        @Override
+        public void setOverlapAnchor(PopupWindow popupWindow, boolean overlapAnchor) {
+            // noop
+        }
+
+        @Override
+        public boolean getOverlapAnchor(PopupWindow popupWindow) {
+            return false;
+        }
+
+        @Override
+        public void setWindowLayoutType(PopupWindow popupWindow, int layoutType) {
+            // no-op
+        }
+
+        @Override
+        public int getWindowLayoutType(PopupWindow popupWindow) {
+            return 0;
+        }
+    }
+
+    /**
+     * Interface implementation that doesn't use anything above v4 APIs.
+     */
+    static class GingerbreadPopupWindowImpl extends BasePopupWindowImpl {
+        @Override
+        public void setWindowLayoutType(PopupWindow popupWindow, int layoutType) {
+            PopupWindowCompatGingerbread.setWindowLayoutType(popupWindow, layoutType);
+        }
+
+        @Override
+        public int getWindowLayoutType(PopupWindow popupWindow) {
+            return PopupWindowCompatGingerbread.getWindowLayoutType(popupWindow);
+        }
     }
 
     /**
      * Interface implementation for devices with at least KitKat APIs.
      */
-    static class KitKatPopupWindowImpl extends BasePopupWindowImpl {
+    static class KitKatPopupWindowImpl extends GingerbreadPopupWindowImpl {
         @Override
         public void showAsDropDown(PopupWindow popup, View anchor, int xoff, int yoff,
                 int gravity) {
@@ -55,14 +93,54 @@
         }
     }
 
+    static class Api21PopupWindowImpl extends KitKatPopupWindowImpl {
+        @Override
+        public void setOverlapAnchor(PopupWindow popupWindow, boolean overlapAnchor) {
+            PopupWindowCompatApi21.setOverlapAnchor(popupWindow, overlapAnchor);
+        }
+
+        @Override
+        public boolean getOverlapAnchor(PopupWindow popupWindow) {
+            return PopupWindowCompatApi21.getOverlapAnchor(popupWindow);
+        }
+    }
+
+    static class Api23PopupWindowImpl extends Api21PopupWindowImpl {
+        @Override
+        public void setOverlapAnchor(PopupWindow popupWindow, boolean overlapAnchor) {
+            PopupWindowCompatApi23.setOverlapAnchor(popupWindow, overlapAnchor);
+        }
+
+        @Override
+        public boolean getOverlapAnchor(PopupWindow popupWindow) {
+            return PopupWindowCompatApi23.getOverlapAnchor(popupWindow);
+        }
+
+        @Override
+        public void setWindowLayoutType(PopupWindow popupWindow, int layoutType) {
+            PopupWindowCompatApi23.setWindowLayoutType(popupWindow, layoutType);
+        }
+
+        @Override
+        public int getWindowLayoutType(PopupWindow popupWindow) {
+            return PopupWindowCompatApi23.getWindowLayoutType(popupWindow);
+        }
+    }
+
     /**
      * Select the correct implementation to use for the current platform.
      */
     static final PopupWindowImpl IMPL;
     static {
         final int version = android.os.Build.VERSION.SDK_INT;
-        if (version >= 19) {
+        if (version >= 23) {
+            IMPL = new Api23PopupWindowImpl();
+        } else if (version >= 21) {
+            IMPL = new Api21PopupWindowImpl();
+        } else if (version >= 19) {
             IMPL = new KitKatPopupWindowImpl();
+        } else if (version >= 9) {
+            IMPL = new GingerbreadPopupWindowImpl();
         } else {
             IMPL = new BasePopupWindowImpl();
         }
@@ -92,4 +170,46 @@
             int gravity) {
         IMPL.showAsDropDown(popup, anchor, xoff, yoff, gravity);
     }
+
+    /**
+     * Sets whether the popup window should overlap its anchor view when
+     * displayed as a drop-down.
+     *
+     * @param overlapAnchor Whether the popup should overlap its anchor.
+     */
+    public static void setOverlapAnchor(PopupWindow popupWindow, boolean overlapAnchor) {
+        IMPL.setOverlapAnchor(popupWindow, overlapAnchor);
+    }
+
+    /**
+     * Returns whether the popup window should overlap its anchor view when
+     * displayed as a drop-down.
+     *
+     * @return Whether the popup should overlap its anchor.
+     */
+    public static boolean getOverlapAnchor(PopupWindow popupWindow) {
+        return IMPL.getOverlapAnchor(popupWindow);
+    }
+
+    /**
+     * Set the layout type for this window. This value will be passed through to
+     * {@link WindowManager.LayoutParams#type} therefore the value should match any value
+     * {@link WindowManager.LayoutParams#type} accepts.
+     *
+     * @param layoutType Layout type for this window.
+     *
+     * @see WindowManager.LayoutParams#type
+     */
+    public static void setWindowLayoutType(PopupWindow popupWindow, int layoutType) {
+        IMPL.setWindowLayoutType(popupWindow, layoutType);
+    }
+
+    /**
+     * Returns the layout type for this window.
+     *
+     * @see #setWindowLayoutType(PopupWindow popupWindow, int)
+     */
+    public static int getWindowLayoutType(PopupWindow popupWindow) {
+        return IMPL.getWindowLayoutType(popupWindow);
+    }
 }
diff --git a/v4/java/android/support/v4/widget/SlidingPaneLayout.java b/v4/java/android/support/v4/widget/SlidingPaneLayout.java
index 391ba99..c5db3ef 100644
--- a/v4/java/android/support/v4/widget/SlidingPaneLayout.java
+++ b/v4/java/android/support/v4/widget/SlidingPaneLayout.java
@@ -29,6 +29,7 @@
 import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.support.annotation.ColorInt;
 import android.support.annotation.DrawableRes;
 import android.support.v4.view.AccessibilityDelegateCompat;
 import android.support.v4.view.MotionEventCompat;
@@ -297,13 +298,14 @@
      *
      * @param color An ARGB-packed color value
      */
-    public void setSliderFadeColor(int color) {
+    public void setSliderFadeColor(@ColorInt int color) {
         mSliderFadeColor = color;
     }
 
     /**
      * @return The ARGB-packed color value used to fade the sliding pane
      */
+    @ColorInt
     public int getSliderFadeColor() {
         return mSliderFadeColor;
     }
@@ -314,13 +316,14 @@
      *
      * @param color An ARGB-packed color value
      */
-    public void setCoveredFadeColor(int color) {
+    public void setCoveredFadeColor(@ColorInt int color) {
         mCoveredFadeColor = color;
     }
 
     /**
      * @return The ARGB-packed color value used to fade the fixed pane
      */
+    @ColorInt
     public int getCoveredFadeColor() {
         return mCoveredFadeColor;
     }
diff --git a/v4/java/android/support/v4/widget/SwipeRefreshLayout.java b/v4/java/android/support/v4/widget/SwipeRefreshLayout.java
index 7e20d88..d6b35ef 100644
--- a/v4/java/android/support/v4/widget/SwipeRefreshLayout.java
+++ b/v4/java/android/support/v4/widget/SwipeRefreshLayout.java
@@ -19,6 +19,8 @@
 import android.content.Context;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
+import android.support.annotation.ColorInt;
+import android.support.annotation.ColorRes;
 import android.support.v4.view.MotionEventCompat;
 import android.support.v4.view.NestedScrollingChild;
 import android.support.v4.view.NestedScrollingChildHelper;
@@ -476,7 +478,7 @@
      *
      * @param colorRes Resource id of the color.
      */
-    public void setProgressBackgroundColorSchemeResource(int colorRes) {
+    public void setProgressBackgroundColorSchemeResource(@ColorRes int colorRes) {
         setProgressBackgroundColorSchemeColor(getResources().getColor(colorRes));
     }
 
@@ -485,7 +487,7 @@
      *
      * @param color
      */
-    public void setProgressBackgroundColorSchemeColor(int color) {
+    public void setProgressBackgroundColorSchemeColor(@ColorInt int color) {
         mCircleView.setBackgroundColor(color);
         mProgress.setBackgroundColor(color);
     }
@@ -494,7 +496,7 @@
      * @deprecated Use {@link #setColorSchemeResources(int...)}
      */
     @Deprecated
-    public void setColorScheme(int... colors) {
+    public void setColorScheme(@ColorInt int... colors) {
         setColorSchemeResources(colors);
     }
 
@@ -505,7 +507,7 @@
      *
      * @param colorResIds
      */
-    public void setColorSchemeResources(int... colorResIds) {
+    public void setColorSchemeResources(@ColorRes int... colorResIds) {
         final Resources res = getResources();
         int[] colorRes = new int[colorResIds.length];
         for (int i = 0; i < colorResIds.length; i++) {
@@ -521,6 +523,7 @@
      *
      * @param colors
      */
+    @ColorInt
     public void setColorSchemeColors(int... colors) {
         ensureTarget();
         mProgress.setColorSchemeColors(colors);
diff --git a/v4/jellybean-mr1/android/support/v4/view/accessibility/AccessibilityNodeInfoCompatJellybeanMr1.java b/v4/jellybean-mr1/android/support/v4/view/accessibility/AccessibilityNodeInfoCompatJellybeanMr1.java
new file mode 100644
index 0000000..a4b9677
--- /dev/null
+++ b/v4/jellybean-mr1/android/support/v4/view/accessibility/AccessibilityNodeInfoCompatJellybeanMr1.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2013 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.v4.view.accessibility;
+
+import android.view.View;
+import android.view.accessibility.AccessibilityNodeInfo;
+
+class AccessibilityNodeInfoCompatJellybeanMr1 {
+
+    public static void setLabelFor(Object info, View labeled) {
+        ((AccessibilityNodeInfo) info).setLabelFor(labeled);
+    }
+
+    public static void setLabelFor(Object info, View root, int virtualDescendantId) {
+        ((AccessibilityNodeInfo) info).setLabelFor(root, virtualDescendantId);
+    }
+
+    public static Object getLabelFor(Object info) {
+        return ((AccessibilityNodeInfo) info).getLabelFor();
+    }
+
+    public static void setLabeledBy(Object info, View labeled) {
+        ((AccessibilityNodeInfo) info).setLabeledBy(labeled);
+    }
+
+    public static void setLabeledBy(Object info, View root, int virtualDescendantId) {
+        ((AccessibilityNodeInfo) info).setLabeledBy(root, virtualDescendantId);
+    }
+
+    public static Object getLabeledBy(Object info) {
+        return ((AccessibilityNodeInfo) info).getLabeledBy();
+    }
+}
diff --git a/v4/jellybean-mr2/android/support/v4/view/accessibility/AccessibilityNodeInfoCompatJellybeanMr2.java b/v4/jellybean-mr2/android/support/v4/view/accessibility/AccessibilityNodeInfoCompatJellybeanMr2.java
index 2b76ea0..e48d9f7 100644
--- a/v4/jellybean-mr2/android/support/v4/view/accessibility/AccessibilityNodeInfoCompatJellybeanMr2.java
+++ b/v4/jellybean-mr2/android/support/v4/view/accessibility/AccessibilityNodeInfoCompatJellybeanMr2.java
@@ -18,6 +18,8 @@
 
 import android.view.accessibility.AccessibilityNodeInfo;
 
+import java.util.List;
+
 class AccessibilityNodeInfoCompatJellybeanMr2 {
 
     public static void setViewIdResourceName(Object info, String viewId) {
@@ -27,4 +29,34 @@
     public static String getViewIdResourceName(Object info) {
         return ((AccessibilityNodeInfo) info).getViewIdResourceName();
     }
+
+    @SuppressWarnings("unchecked")
+    public static List<Object> findAccessibilityNodeInfosByViewId(Object info, String viewId) {
+        Object result = ((AccessibilityNodeInfo) info).findAccessibilityNodeInfosByViewId(viewId);
+        return (List<Object>) result;
+    }
+
+    public static void setTextSelection(Object info, int start, int end) {
+        ((AccessibilityNodeInfo) info).setTextSelection(start, end);
+    }
+
+    public static int getTextSelectionStart(Object info) {
+        return ((AccessibilityNodeInfo) info).getTextSelectionStart();
+    }
+
+    public static int getTextSelectionEnd(Object info) {
+        return ((AccessibilityNodeInfo) info).getTextSelectionEnd();
+    }
+
+    public static boolean isEditable(Object info) {
+        return ((AccessibilityNodeInfo) info).isEditable();
+    }
+
+    public static void setEditable(Object info, boolean editable) {
+        ((AccessibilityNodeInfo) info).setEditable(editable);
+    }
+
+    public static boolean refresh(Object info) {
+        return ((AccessibilityNodeInfo) info).refresh();
+    }
 }
diff --git a/v4/jellybean/android/support/v4/content/ContentResolverCompatJellybean.java b/v4/jellybean/android/support/v4/content/ContentResolverCompatJellybean.java
new file mode 100644
index 0000000..ef05746
--- /dev/null
+++ b/v4/jellybean/android/support/v4/content/ContentResolverCompatJellybean.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2013 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.v4.content;
+
+import android.content.ContentResolver;
+import android.database.Cursor;
+import android.net.Uri;
+
+class ContentResolverCompatJellybean {
+    public static Cursor query(ContentResolver resolver, Uri uri, String[] projection,
+            String selection, String[] selectionArgs, String sortOrder,
+            Object cancellationSignalObj) {
+        return resolver.query(uri, projection, selection, selectionArgs, sortOrder,
+                (android.os.CancellationSignal)cancellationSignalObj);
+    }
+}
diff --git a/v4/jellybean/android/support/v4/os/CancellationSignalCompatJellybean.java b/v4/jellybean/android/support/v4/os/CancellationSignalCompatJellybean.java
new file mode 100644
index 0000000..6029286
--- /dev/null
+++ b/v4/jellybean/android/support/v4/os/CancellationSignalCompatJellybean.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2013 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.v4.os;
+
+class CancellationSignalCompatJellybean {
+    public static Object create() {
+        return new android.os.CancellationSignal();
+    }
+
+    public static void cancel(Object cancellationSignalObj) {
+        ((android.os.CancellationSignal)cancellationSignalObj).cancel();
+    }
+}
diff --git a/v4/jellybean/android/support/v4/view/ViewCompatJB.java b/v4/jellybean/android/support/v4/view/ViewCompatJB.java
index 9373572..f1c7315 100644
--- a/v4/jellybean/android/support/v4/view/ViewCompatJB.java
+++ b/v4/jellybean/android/support/v4/view/ViewCompatJB.java
@@ -85,4 +85,8 @@
     public static boolean getFitsSystemWindows(View view) {
         return view.getFitsSystemWindows();
     }
+
+    public static boolean hasOverlappingRendering(View view) {
+        return view.hasOverlappingRendering();
+    }
 }
diff --git a/v4/kitkat/android/support/v4/view/accessibility/AccessibilityNodeInfoCompatKitKat.java b/v4/kitkat/android/support/v4/view/accessibility/AccessibilityNodeInfoCompatKitKat.java
index 32fb86f..3805d02 100644
--- a/v4/kitkat/android/support/v4/view/accessibility/AccessibilityNodeInfoCompatKitKat.java
+++ b/v4/kitkat/android/support/v4/view/accessibility/AccessibilityNodeInfoCompatKitKat.java
@@ -16,6 +16,7 @@
 
 package android.support.v4.view.accessibility;
 
+import android.os.Bundle;
 import android.view.accessibility.AccessibilityNodeInfo;
 
 /**
@@ -52,6 +53,10 @@
         return ((AccessibilityNodeInfo) info).getRangeInfo();
     }
 
+    public static void setRangeInfo(Object info, Object rangeInfo) {
+        ((AccessibilityNodeInfo) info).setRangeInfo((AccessibilityNodeInfo.RangeInfo) rangeInfo);
+    }
+
     public static Object obtainCollectionInfo(int rowCount, int columnCount,
             boolean hierarchical, int selectionMode) {
         return AccessibilityNodeInfo.CollectionInfo.obtain(rowCount, columnCount, hierarchical);
@@ -71,6 +76,42 @@
         return ((AccessibilityNodeInfo) info).isContentInvalid();
     }
 
+    public static boolean canOpenPopup(Object info) {
+        return ((AccessibilityNodeInfo) info).canOpenPopup();
+    }
+
+    public static void setCanOpenPopup(Object info, boolean opensPopup) {
+        ((AccessibilityNodeInfo) info).setCanOpenPopup(opensPopup);
+    }
+
+    public static Bundle getExtras(Object info) {
+        return ((AccessibilityNodeInfo) info).getExtras();
+    }
+
+    public static int getInputType(Object info) {
+        return ((AccessibilityNodeInfo) info).getInputType();
+    }
+
+    public static void setInputType(Object info, int inputType) {
+        ((AccessibilityNodeInfo) info).setInputType(inputType);
+    }
+
+    public static boolean isDismissable(Object info) {
+        return ((AccessibilityNodeInfo) info).isDismissable();
+    }
+
+    public static void setDismissable(Object info, boolean dismissable) {
+        ((AccessibilityNodeInfo) info).setDismissable(dismissable);
+    }
+
+    public static boolean isMultiLine(Object info) {
+        return ((AccessibilityNodeInfo) info).isMultiLine();
+    }
+
+    public static void setMultiLine(Object info, boolean multiLine) {
+        ((AccessibilityNodeInfo) info).setMultiLine(multiLine);
+    }
+
     static class CollectionInfo {
         static int getColumnCount(Object info) {
             return ((AccessibilityNodeInfo.CollectionInfo) info).getColumnCount();
diff --git a/v7/appcompat/api/current.txt b/v7/appcompat/api/current.txt
index 7651979..d1007bd 100644
--- a/v7/appcompat/api/current.txt
+++ b/v7/appcompat/api/current.txt
@@ -244,6 +244,7 @@
 
   public abstract class AppCompatDelegate {
     method public abstract void addContentView(android.view.View, android.view.ViewGroup.LayoutParams);
+    method public abstract void applyDayNight();
     method public static android.support.v7.app.AppCompatDelegate create(android.app.Activity, android.support.v7.app.AppCompatCallback);
     method public static android.support.v7.app.AppCompatDelegate create(android.app.Dialog, android.support.v7.app.AppCompatCallback);
     method public abstract android.view.View createView(android.view.View, java.lang.String, android.content.Context, android.util.AttributeSet);
@@ -265,9 +266,16 @@
     method public abstract void setContentView(int);
     method public abstract void setContentView(android.view.View, android.view.ViewGroup.LayoutParams);
     method public abstract void setHandleNativeActionModesEnabled(boolean);
+    method public abstract void setNightMode(int);
     method public abstract void setSupportActionBar(android.support.v7.widget.Toolbar);
     method public abstract void setTitle(java.lang.CharSequence);
     method public abstract android.support.v7.view.ActionMode startSupportActionMode(android.support.v7.view.ActionMode.Callback);
+    field public static final int FEATURE_ACTION_MODE_OVERLAY = 10; // 0xa
+    field public static final int FEATURE_SUPPORT_ACTION_BAR = 108; // 0x6c
+    field public static final int FEATURE_SUPPORT_ACTION_BAR_OVERLAY = 109; // 0x6d
+    field public static final int MODE_NIGHT_AUTO = 2; // 0x2
+    field public static final int MODE_NIGHT_NO = 0; // 0x0
+    field public static final int MODE_NIGHT_YES = 1; // 0x1
   }
 
   public class AppCompatDialog extends android.app.Dialog implements android.support.v7.app.AppCompatCallback {
@@ -282,6 +290,10 @@
     method public boolean supportRequestWindowFeature(int);
   }
 
+  public class AppCompatDialogFragment extends android.support.v4.app.DialogFragment {
+    ctor public AppCompatDialogFragment();
+  }
+
   public class NotificationCompat extends android.support.v4.app.NotificationCompat {
     ctor public NotificationCompat();
   }
@@ -377,6 +389,8 @@
     field public static int buttonPanelSideLayout;
     field public static int buttonStyle;
     field public static int buttonStyleSmall;
+    field public static int buttonTint;
+    field public static int buttonTintMode;
     field public static int checkboxStyle;
     field public static int checkedTextViewStyle;
     field public static int closeIcon;
@@ -397,6 +411,7 @@
     field public static int contentInsetLeft;
     field public static int contentInsetRight;
     field public static int contentInsetStart;
+    field public static int controlBackground;
     field public static int customNavigationLayout;
     field public static int defaultQueryHint;
     field public static int dialogPreferredPadding;
@@ -440,6 +455,7 @@
     field public static int listPreferredItemPaddingLeft;
     field public static int listPreferredItemPaddingRight;
     field public static int logo;
+    field public static int logoDescription;
     field public static int maxButtonHeight;
     field public static int measureWithLargestChild;
     field public static int middleBarArrowSize;
@@ -483,6 +499,7 @@
     field public static int submitBackground;
     field public static int subtitle;
     field public static int subtitleTextAppearance;
+    field public static int subtitleTextColor;
     field public static int subtitleTextStyle;
     field public static int suggestionRowLayout;
     field public static int switchMinWidth;
@@ -508,6 +525,7 @@
     field public static int titleMarginTop;
     field public static int titleMargins;
     field public static int titleTextAppearance;
+    field public static int titleTextColor;
     field public static int titleTextStyle;
     field public static int toolbarNavigationButtonStyle;
     field public static int toolbarStyle;
@@ -541,6 +559,7 @@
     ctor public R.color();
     field public static int abc_background_cache_hint_selector_material_dark;
     field public static int abc_background_cache_hint_selector_material_light;
+    field public static int abc_color_highlight_material;
     field public static int abc_input_method_navigation_guard;
     field public static int abc_primary_text_disable_only_material_dark;
     field public static int abc_primary_text_disable_only_material_light;
@@ -570,6 +589,8 @@
     field public static int dim_foreground_disabled_material_light;
     field public static int dim_foreground_material_dark;
     field public static int dim_foreground_material_light;
+    field public static int foreground_material_dark;
+    field public static int foreground_material_light;
     field public static int highlighted_text_material_dark;
     field public static int highlighted_text_material_light;
     field public static int hint_foreground_material_dark;
@@ -581,6 +602,13 @@
     field public static int material_blue_grey_950;
     field public static int material_deep_teal_200;
     field public static int material_deep_teal_500;
+    field public static int material_grey_100;
+    field public static int material_grey_300;
+    field public static int material_grey_50;
+    field public static int material_grey_600;
+    field public static int material_grey_800;
+    field public static int material_grey_850;
+    field public static int material_grey_900;
     field public static int primary_dark_material_dark;
     field public static int primary_dark_material_light;
     field public static int primary_material_dark;
@@ -671,6 +699,9 @@
     field public static int dialog_fixed_width_minor;
     field public static int disabled_alpha_material_dark;
     field public static int disabled_alpha_material_light;
+    field public static int highlight_alpha_material_colored;
+    field public static int highlight_alpha_material_dark;
+    field public static int highlight_alpha_material_light;
     field public static int notification_large_icon_height;
     field public static int notification_large_icon_width;
     field public static int notification_subtext_size;
@@ -679,10 +710,12 @@
   public static final class R.drawable {
     ctor public R.drawable();
     field public static int abc_ab_share_pack_mtrl_alpha;
+    field public static int abc_action_bar_item_background_material;
     field public static int abc_btn_borderless_material;
     field public static int abc_btn_check_material;
     field public static int abc_btn_check_to_on_mtrl_000;
     field public static int abc_btn_check_to_on_mtrl_015;
+    field public static int abc_btn_colored_material;
     field public static int abc_btn_default_mtrl_shape;
     field public static int abc_btn_radio_material;
     field public static int abc_btn_radio_to_on_mtrl_000;
@@ -694,6 +727,7 @@
     field public static int abc_cab_background_internal_bg;
     field public static int abc_cab_background_top_material;
     field public static int abc_cab_background_top_mtrl_alpha;
+    field public static int abc_control_background_material;
     field public static int abc_dialog_material_background_dark;
     field public static int abc_dialog_material_background_light;
     field public static int abc_edit_text_material;
@@ -731,7 +765,7 @@
     field public static int abc_switch_track_mtrl_alpha;
     field public static int abc_tab_indicator_material;
     field public static int abc_tab_indicator_mtrl_alpha;
-    field public static int abc_text_cursor_mtrl_alpha;
+    field public static int abc_text_cursor_material;
     field public static int abc_textfield_activated_mtrl_alpha;
     field public static int abc_textfield_default_mtrl_alpha;
     field public static int abc_textfield_search_activated_mtrl_alpha;
@@ -954,6 +988,8 @@
     field public static int Base_TextAppearance_AppCompat_Widget_ActionBar_Title_Inverse;
     field public static int Base_TextAppearance_AppCompat_Widget_ActionMode_Subtitle;
     field public static int Base_TextAppearance_AppCompat_Widget_ActionMode_Title;
+    field public static int Base_TextAppearance_AppCompat_Widget_Button;
+    field public static int Base_TextAppearance_AppCompat_Widget_Button_Inverse;
     field public static int Base_TextAppearance_AppCompat_Widget_DropDownItem;
     field public static int Base_TextAppearance_AppCompat_Widget_PopupMenu_Large;
     field public static int Base_TextAppearance_AppCompat_Widget_PopupMenu_Small;
@@ -991,6 +1027,8 @@
     field public static int Base_V21_Theme_AppCompat_Light_Dialog;
     field public static int Base_V22_Theme_AppCompat;
     field public static int Base_V22_Theme_AppCompat_Light;
+    field public static int Base_V23_Theme_AppCompat;
+    field public static int Base_V23_Theme_AppCompat_Light;
     field public static int Base_V7_Theme_AppCompat;
     field public static int Base_V7_Theme_AppCompat_Dialog;
     field public static int Base_V7_Theme_AppCompat_Light;
@@ -1014,6 +1052,7 @@
     field public static int Base_Widget_AppCompat_Button_Borderless;
     field public static int Base_Widget_AppCompat_Button_Borderless_Colored;
     field public static int Base_Widget_AppCompat_Button_ButtonBar_AlertDialog;
+    field public static int Base_Widget_AppCompat_Button_Colored;
     field public static int Base_Widget_AppCompat_Button_Small;
     field public static int Base_Widget_AppCompat_CompoundButton_CheckBox;
     field public static int Base_Widget_AppCompat_CompoundButton_RadioButton;
@@ -1108,6 +1147,8 @@
     field public static int TextAppearance_AppCompat_Widget_ActionMode_Subtitle_Inverse;
     field public static int TextAppearance_AppCompat_Widget_ActionMode_Title;
     field public static int TextAppearance_AppCompat_Widget_ActionMode_Title_Inverse;
+    field public static int TextAppearance_AppCompat_Widget_Button;
+    field public static int TextAppearance_AppCompat_Widget_Button_Inverse;
     field public static int TextAppearance_AppCompat_Widget_DropDownItem;
     field public static int TextAppearance_AppCompat_Widget_PopupMenu_Large;
     field public static int TextAppearance_AppCompat_Widget_PopupMenu_Small;
@@ -1128,6 +1169,13 @@
     field public static int ThemeOverlay_AppCompat_Light;
     field public static int Theme_AppCompat;
     field public static int Theme_AppCompat_CompactMenu;
+    field public static int Theme_AppCompat_DayNight;
+    field public static int Theme_AppCompat_DayNight_DarkActionBar;
+    field public static int Theme_AppCompat_DayNight_Dialog;
+    field public static int Theme_AppCompat_DayNight_DialogWhenLarge;
+    field public static int Theme_AppCompat_DayNight_Dialog_Alert;
+    field public static int Theme_AppCompat_DayNight_Dialog_MinWidth;
+    field public static int Theme_AppCompat_DayNight_NoActionBar;
     field public static int Theme_AppCompat_Dialog;
     field public static int Theme_AppCompat_DialogWhenLarge;
     field public static int Theme_AppCompat_Dialog_Alert;
@@ -1157,6 +1205,7 @@
     field public static int Widget_AppCompat_Button_Borderless;
     field public static int Widget_AppCompat_Button_Borderless_Colored;
     field public static int Widget_AppCompat_Button_ButtonBar_AlertDialog;
+    field public static int Widget_AppCompat_Button_Colored;
     field public static int Widget_AppCompat_Button_Small;
     field public static int Widget_AppCompat_CompoundButton_CheckBox;
     field public static int Widget_AppCompat_CompoundButton_RadioButton;
@@ -1262,6 +1311,10 @@
     field public static final int[] AppCompatTextView;
     field public static int AppCompatTextView_android_textAppearance;
     field public static int AppCompatTextView_textAllCaps;
+    field public static final int[] CompoundButton;
+    field public static int CompoundButton_android_button;
+    field public static int CompoundButton_buttonTint;
+    field public static int CompoundButton_buttonTintMode;
     field public static final int[] DrawerArrowToggle;
     field public static int DrawerArrowToggle_barSize;
     field public static int DrawerArrowToggle_color;
@@ -1432,6 +1485,7 @@
     field public static int Theme_colorPrimary;
     field public static int Theme_colorPrimaryDark;
     field public static int Theme_colorSwitchThumbNormal;
+    field public static int Theme_controlBackground;
     field public static int Theme_dialogPreferredPadding;
     field public static int Theme_dialogTheme;
     field public static int Theme_dividerHorizontal;
@@ -1492,12 +1546,15 @@
     field public static int Toolbar_contentInsetLeft;
     field public static int Toolbar_contentInsetRight;
     field public static int Toolbar_contentInsetStart;
+    field public static int Toolbar_logo;
+    field public static int Toolbar_logoDescription;
     field public static int Toolbar_maxButtonHeight;
     field public static int Toolbar_navigationContentDescription;
     field public static int Toolbar_navigationIcon;
     field public static int Toolbar_popupTheme;
     field public static int Toolbar_subtitle;
     field public static int Toolbar_subtitleTextAppearance;
+    field public static int Toolbar_subtitleTextColor;
     field public static int Toolbar_title;
     field public static int Toolbar_titleMarginBottom;
     field public static int Toolbar_titleMarginEnd;
@@ -1505,15 +1562,18 @@
     field public static int Toolbar_titleMarginTop;
     field public static int Toolbar_titleMargins;
     field public static int Toolbar_titleTextAppearance;
+    field public static int Toolbar_titleTextColor;
     field public static final int[] View;
+    field public static final int[] ViewBackgroundHelper;
+    field public static int ViewBackgroundHelper_android_background;
+    field public static int ViewBackgroundHelper_backgroundTint;
+    field public static int ViewBackgroundHelper_backgroundTintMode;
     field public static final int[] ViewStubCompat;
     field public static int ViewStubCompat_android_id;
     field public static int ViewStubCompat_android_inflatedId;
     field public static int ViewStubCompat_android_layout;
     field public static int View_android_focusable;
     field public static int View_android_theme;
-    field public static int View_backgroundTint;
-    field public static int View_backgroundTintMode;
     field public static int View_paddingEnd;
     field public static int View_paddingStart;
     field public static int View_theme;
@@ -1584,12 +1644,14 @@
     ctor public ActionMenuView(android.content.Context, android.util.AttributeSet);
     method public void dismissPopupMenus();
     method public android.view.Menu getMenu();
+    method public android.graphics.drawable.Drawable getOverflowIcon();
     method public int getPopupTheme();
     method public boolean hideOverflowMenu();
     method public boolean isOverflowMenuShowing();
     method public void onConfigurationChanged(android.content.res.Configuration);
     method public void onDetachedFromWindow();
     method public void setOnMenuItemClickListener(android.support.v7.widget.ActionMenuView.OnMenuItemClickListener);
+    method public void setOverflowIcon(android.graphics.drawable.Drawable);
     method public void setPopupTheme(int);
     method public boolean showOverflowMenu();
   }
@@ -1620,6 +1682,7 @@
     ctor public AppCompatButton(android.content.Context);
     ctor public AppCompatButton(android.content.Context, android.util.AttributeSet);
     ctor public AppCompatButton(android.content.Context, android.util.AttributeSet, int);
+    method public void setSupportAllCaps(boolean);
   }
 
   public class AppCompatCheckBox extends android.widget.CheckBox {
@@ -1780,9 +1843,11 @@
     ctor public PopupMenu(android.content.Context, android.view.View, int, int, int);
     method public void dismiss();
     method public android.view.View.OnTouchListener getDragToOpenListener();
+    method public int getGravity();
     method public android.view.Menu getMenu();
     method public android.view.MenuInflater getMenuInflater();
     method public void inflate(int);
+    method public void setGravity(int);
     method public void setOnDismissListener(android.support.v7.widget.PopupMenu.OnDismissListener);
     method public void setOnMenuItemClickListener(android.support.v7.widget.PopupMenu.OnMenuItemClickListener);
     method public void show();
@@ -1902,6 +1967,7 @@
     method public android.view.Menu getMenu();
     method public java.lang.CharSequence getNavigationContentDescription();
     method public android.graphics.drawable.Drawable getNavigationIcon();
+    method public android.graphics.drawable.Drawable getOverflowIcon();
     method public int getPopupTheme();
     method public java.lang.CharSequence getSubtitle();
     method public java.lang.CharSequence getTitle();
@@ -1922,6 +1988,7 @@
     method public void setNavigationIcon(android.graphics.drawable.Drawable);
     method public void setNavigationOnClickListener(android.view.View.OnClickListener);
     method public void setOnMenuItemClickListener(android.support.v7.widget.Toolbar.OnMenuItemClickListener);
+    method public void setOverflowIcon(android.graphics.drawable.Drawable);
     method public void setPopupTheme(int);
     method public void setSubtitle(int);
     method public void setSubtitle(java.lang.CharSequence);
diff --git a/v7/appcompat/build.gradle b/v7/appcompat/build.gradle
index bbb2fd1..6313298 100644
--- a/v7/appcompat/build.gradle
+++ b/v7/appcompat/build.gradle
@@ -12,7 +12,7 @@
     sourceSets {
         main.manifest.srcFile 'AndroidManifest.xml'
         main.java.srcDir 'src'
-        main.res.srcDir 'res'
+        main.res.srcDirs 'res', 'res-public'
         main.assets.srcDir 'assets'
         main.resources.srcDir 'src'
 
diff --git a/v7/appcompat/res-public/values/public_attrs.xml b/v7/appcompat/res-public/values/public_attrs.xml
new file mode 100644
index 0000000..0f03c4a
--- /dev/null
+++ b/v7/appcompat/res-public/values/public_attrs.xml
@@ -0,0 +1,197 @@
+<?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.
+-->
+
+<!-- Definitions of attributes to be exposed as public -->
+<resources>
+     <public type="attr" name="actionBarDivider"/>
+     <public type="attr" name="actionBarItemBackground"/>
+     <public type="attr" name="actionBarPopupTheme"/>
+     <public type="attr" name="actionBarSize"/>
+     <public type="attr" name="actionBarSplitStyle"/>
+     <public type="attr" name="actionBarStyle"/>
+     <public type="attr" name="actionBarTabBarStyle"/>
+     <public type="attr" name="actionBarTabStyle"/>
+     <public type="attr" name="actionBarTabTextStyle"/>
+     <public type="attr" name="actionBarTheme"/>
+     <public type="attr" name="actionBarWidgetTheme"/>
+     <public type="attr" name="actionButtonStyle"/>
+     <public type="attr" name="actionDropDownStyle"/>
+     <public type="attr" name="actionLayout"/>
+     <public type="attr" name="actionMenuTextAppearance"/>
+     <public type="attr" name="actionMenuTextColor"/>
+     <public type="attr" name="actionModeBackground"/>
+     <public type="attr" name="actionModeCloseButtonStyle"/>
+     <public type="attr" name="actionModeCloseDrawable"/>
+     <public type="attr" name="actionModeCopyDrawable"/>
+     <public type="attr" name="actionModeCutDrawable"/>
+     <public type="attr" name="actionModeFindDrawable"/>
+     <public type="attr" name="actionModePasteDrawable"/>
+     <public type="attr" name="actionModeSelectAllDrawable"/>
+     <public type="attr" name="actionModeShareDrawable"/>
+     <public type="attr" name="actionModeSplitBackground"/>
+     <public type="attr" name="actionModeStyle"/>
+     <public type="attr" name="actionModeWebSearchDrawable"/>
+     <public type="attr" name="actionOverflowButtonStyle"/>
+     <public type="attr" name="actionOverflowMenuStyle"/>
+     <public type="attr" name="actionProviderClass"/>
+     <public type="attr" name="actionViewClass"/>
+     <public type="attr" name="alertDialogStyle"/>
+     <public type="attr" name="alertDialogTheme"/>
+     <public type="attr" name="autoCompleteTextViewStyle"/>
+     <public type="attr" name="background"/>
+     <public type="attr" name="backgroundSplit"/>
+     <public type="attr" name="backgroundStacked"/>
+     <public type="attr" name="backgroundTint"/>
+     <public type="attr" name="backgroundTintMode"/>
+     <public type="attr" name="barSize"/>
+     <public type="attr" name="borderlessButtonStyle"/>
+     <public type="attr" name="buttonBarButtonStyle"/>
+     <public type="attr" name="buttonBarNegativeButtonStyle"/>
+     <public type="attr" name="buttonBarNeutralButtonStyle"/>
+     <public type="attr" name="buttonBarPositiveButtonStyle"/>
+     <public type="attr" name="buttonBarStyle"/>
+     <public type="attr" name="buttonStyle"/>
+     <public type="attr" name="buttonStyleSmall"/>
+     <public type="attr" name="buttonTint"/>
+     <public type="attr" name="buttonTintMode"/>
+     <public type="attr" name="checkboxStyle"/>
+     <public type="attr" name="checkedTextViewStyle"/>
+     <public type="attr" name="closeIcon"/>
+     <public type="attr" name="closeItemLayout"/>
+     <public type="attr" name="collapseContentDescription"/>
+     <public type="attr" name="collapseIcon"/>
+     <public type="attr" name="color"/>
+     <public type="attr" name="colorAccent"/>
+     <public type="attr" name="colorButtonNormal"/>
+     <public type="attr" name="colorControlActivated"/>
+     <public type="attr" name="colorControlHighlight"/>
+     <public type="attr" name="colorControlNormal"/>
+     <public type="attr" name="colorPrimary"/>
+     <public type="attr" name="colorPrimaryDark"/>
+     <public type="attr" name="colorSwitchThumbNormal"/>
+     <public type="attr" name="commitIcon"/>
+     <public type="attr" name="contentInsetEnd"/>
+     <public type="attr" name="contentInsetLeft"/>
+     <public type="attr" name="contentInsetRight"/>
+     <public type="attr" name="contentInsetStart"/>
+     <public type="attr" name="customNavigationLayout"/>
+     <public type="attr" name="dialogPreferredPadding"/>
+     <public type="attr" name="dialogTheme"/>
+     <public type="attr" name="displayOptions"/>
+     <public type="attr" name="divider"/>
+     <public type="attr" name="dividerHorizontal"/>
+     <public type="attr" name="dividerPadding"/>
+     <public type="attr" name="dividerVertical"/>
+     <public type="attr" name="drawableSize"/>
+     <public type="attr" name="drawerArrowStyle"/>
+     <public type="attr" name="dropdownListPreferredItemHeight"/>
+     <public type="attr" name="dropDownListViewStyle"/>
+     <public type="attr" name="editTextBackground"/>
+     <public type="attr" name="editTextColor"/>
+     <public type="attr" name="editTextStyle"/>
+     <public type="attr" name="elevation"/>
+     <public type="attr" name="gapBetweenBars"/>
+     <public type="attr" name="goIcon"/>
+     <public type="attr" name="height"/>
+     <public type="attr" name="hideOnContentScroll"/>
+     <public type="attr" name="homeAsUpIndicator"/>
+     <public type="attr" name="homeLayout"/>
+     <public type="attr" name="icon"/>
+     <public type="attr" name="iconifiedByDefault"/>
+     <public type="attr" name="indeterminateProgressStyle"/>
+     <public type="attr" name="isLightTheme"/>
+     <public type="attr" name="itemPadding"/>
+     <public type="attr" name="layout"/>
+     <public type="attr" name="listChoiceBackgroundIndicator"/>
+     <public type="attr" name="listDividerAlertDialog"/>
+     <public type="attr" name="listPopupWindowStyle"/>
+     <public type="attr" name="listPreferredItemHeight"/>
+     <public type="attr" name="listPreferredItemHeightLarge"/>
+     <public type="attr" name="listPreferredItemHeightSmall"/>
+     <public type="attr" name="listPreferredItemPaddingLeft"/>
+     <public type="attr" name="listPreferredItemPaddingRight"/>
+     <public type="attr" name="logo"/>
+     <public type="attr" name="measureWithLargestChild"/>
+     <public type="attr" name="middleBarArrowSize"/>
+     <public type="attr" name="navigationContentDescription"/>
+     <public type="attr" name="navigationIcon"/>
+     <public type="attr" name="navigationMode"/>
+     <public type="attr" name="overlapAnchor"/>
+     <public type="attr" name="paddingEnd"/>
+     <public type="attr" name="paddingStart"/>
+     <public type="attr" name="panelBackground"/>
+     <public type="attr" name="popupMenuStyle"/>
+     <public type="attr" name="popupTheme"/>
+     <public type="attr" name="popupWindowStyle"/>
+     <public type="attr" name="preserveIconSpacing"/>
+     <public type="attr" name="progressBarPadding"/>
+     <public type="attr" name="progressBarStyle"/>
+     <public type="attr" name="prompt"/>
+     <public type="attr" name="queryBackground"/>
+     <public type="attr" name="queryHint"/>
+     <public type="attr" name="radioButtonStyle"/>
+     <public type="attr" name="ratingBarStyle"/>
+     <public type="attr" name="searchHintIcon"/>
+     <public type="attr" name="searchIcon"/>
+     <public type="attr" name="searchViewStyle"/>
+     <public type="attr" name="selectableItemBackground"/>
+     <public type="attr" name="selectableItemBackgroundBorderless"/>
+     <public type="attr" name="showAsAction"/>
+     <public type="attr" name="showDividers"/>
+     <public type="attr" name="showText"/>
+     <public type="attr" name="spinBars"/>
+     <public type="attr" name="spinnerDropDownItemStyle"/>
+     <public type="attr" name="spinnerMode"/>
+     <public type="attr" name="spinnerStyle"/>
+     <public type="attr" name="splitTrack"/>
+     <public type="attr" name="submitBackground"/>
+     <public type="attr" name="subtitle"/>
+     <public type="attr" name="subtitleTextAppearance"/>
+     <public type="attr" name="subtitleTextStyle"/>
+     <public type="attr" name="suggestionRowLayout"/>
+     <public type="attr" name="switchMinWidth"/>
+     <public type="attr" name="switchPadding"/>
+     <public type="attr" name="switchStyle"/>
+     <public type="attr" name="switchTextAppearance"/>
+     <public type="attr" name="textAllCaps"/>
+     <public type="attr" name="textAppearanceLargePopupMenu"/>
+     <public type="attr" name="textAppearanceListItem"/>
+     <public type="attr" name="textAppearanceListItemSmall"/>
+     <public type="attr" name="textAppearanceSearchResultSubtitle"/>
+     <public type="attr" name="textAppearanceSearchResultTitle"/>
+     <public type="attr" name="textAppearanceSmallPopupMenu"/>
+     <public type="attr" name="textColorAlertDialogListItem"/>
+     <public type="attr" name="theme"/>
+     <public type="attr" name="thickness"/>
+     <public type="attr" name="thumbTextPadding"/>
+     <public type="attr" name="title"/>
+     <public type="attr" name="titleMarginBottom"/>
+     <public type="attr" name="titleMarginEnd"/>
+     <public type="attr" name="titleMargins"/>
+     <public type="attr" name="titleMarginStart"/>
+     <public type="attr" name="titleMarginTop"/>
+     <public type="attr" name="titleTextAppearance"/>
+     <public type="attr" name="titleTextStyle"/>
+     <public type="attr" name="toolbarNavigationButtonStyle"/>
+     <public type="attr" name="toolbarStyle"/>
+     <public type="attr" name="topBottomBarArrowSize"/>
+     <public type="attr" name="track"/>
+     <public type="attr" name="voiceIcon"/>
+     <public type="attr" name="windowActionBar"/>
+     <public type="attr" name="windowActionBarOverlay"/>
+     <public type="attr" name="windowActionModeOverlay"/>
+     <public type="attr" name="windowNoTitle"/>
+</resources>
diff --git a/v7/appcompat/res-public/values/public_layouts.xml b/v7/appcompat/res-public/values/public_layouts.xml
new file mode 100644
index 0000000..1c50667
--- /dev/null
+++ b/v7/appcompat/res-public/values/public_layouts.xml
@@ -0,0 +1,20 @@
+<?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.
+-->
+
+<!-- Definitions of layouts to be exposed as public -->
+<resources>
+    <public type="layout" name="support_simple_spinner_dropdown_item"/>
+</resources>
diff --git a/v7/appcompat/res-public/values/public_styles.xml b/v7/appcompat/res-public/values/public_styles.xml
new file mode 100644
index 0000000..424241b
--- /dev/null
+++ b/v7/appcompat/res-public/values/public_styles.xml
@@ -0,0 +1,150 @@
+<?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.
+-->
+
+<!-- Definitions of styles to be exposed as public -->
+<resources>
+    <public type="style" name="TextAppearance.AppCompat"/>
+    <public type="style" name="TextAppearance.AppCompat.Body1"/>
+    <public type="style" name="TextAppearance.AppCompat.Body2"/>
+    <public type="style" name="TextAppearance.AppCompat.Button"/>
+    <public type="style" name="TextAppearance.AppCompat.Caption"/>
+    <public type="style" name="TextAppearance.AppCompat.Display1"/>
+    <public type="style" name="TextAppearance.AppCompat.Display2"/>
+    <public type="style" name="TextAppearance.AppCompat.Display3"/>
+    <public type="style" name="TextAppearance.AppCompat.Display4"/>
+    <public type="style" name="TextAppearance.AppCompat.Headline"/>
+    <public type="style" name="TextAppearance.AppCompat.Inverse"/>
+    <public type="style" name="TextAppearance.AppCompat.Large"/>
+    <public type="style" name="TextAppearance.AppCompat.Large.Inverse"/>
+    <public type="style" name="TextAppearance.AppCompat.Light.SearchResult.Subtitle"/>
+    <public type="style" name="TextAppearance.AppCompat.Light.SearchResult.Title"/>
+    <public type="style" name="TextAppearance.AppCompat.Light.Widget.PopupMenu.Large"/>
+    <public type="style" name="TextAppearance.AppCompat.Light.Widget.PopupMenu.Small"/>
+    <public type="style" name="TextAppearance.AppCompat.Medium"/>
+    <public type="style" name="TextAppearance.AppCompat.Medium.Inverse"/>
+    <public type="style" name="TextAppearance.AppCompat.Menu"/>
+    <public type="style" name="TextAppearance.AppCompat.SearchResult.Subtitle"/>
+    <public type="style" name="TextAppearance.AppCompat.SearchResult.Title"/>
+    <public type="style" name="TextAppearance.AppCompat.Small"/>
+    <public type="style" name="TextAppearance.AppCompat.Small.Inverse"/>
+    <public type="style" name="TextAppearance.AppCompat.Subhead"/>
+    <public type="style" name="TextAppearance.AppCompat.Subhead.Inverse"/>
+    <public type="style" name="TextAppearance.AppCompat.Title"/>
+    <public type="style" name="TextAppearance.AppCompat.Title.Inverse"/>
+    <public type="style" name="TextAppearance.AppCompat.Widget.ActionBar.Menu"/>
+    <public type="style" name="TextAppearance.AppCompat.Widget.ActionBar.Subtitle"/>
+    <public type="style" name="TextAppearance.AppCompat.Widget.ActionBar.Subtitle.Inverse"/>
+    <public type="style" name="TextAppearance.AppCompat.Widget.ActionBar.Title"/>
+    <public type="style" name="TextAppearance.AppCompat.Widget.ActionBar.Title.Inverse"/>
+    <public type="style" name="TextAppearance.AppCompat.Widget.ActionMode.Subtitle"/>
+    <public type="style" name="TextAppearance.AppCompat.Widget.ActionMode.Subtitle.Inverse"/>
+    <public type="style" name="TextAppearance.AppCompat.Widget.ActionMode.Title"/>
+    <public type="style" name="TextAppearance.AppCompat.Widget.ActionMode.Title.Inverse"/>
+    <public type="style" name="TextAppearance.AppCompat.Widget.DropDownItem"/>
+    <public type="style" name="TextAppearance.AppCompat.Widget.PopupMenu.Large"/>
+    <public type="style" name="TextAppearance.AppCompat.Widget.PopupMenu.Small"/>
+    <public type="style" name="TextAppearance.AppCompat.Widget.Switch"/>
+    <public type="style" name="TextAppearance.AppCompat.Widget.TextView.SpinnerItem"/>
+    <public type="style" name="Theme.AppCompat"/>
+    <public type="style" name="Theme.AppCompat.Dialog"/>
+    <public type="style" name="Theme.AppCompat.Dialog.Alert"/>
+    <public type="style" name="Theme.AppCompat.Dialog.MinWidth"/>
+    <public type="style" name="Theme.AppCompat.DialogWhenLarge"/>
+    <public type="style" name="Theme.AppCompat.DayNight"/>
+    <public type="style" name="Theme.AppCompat.DayNight.DarkActionBar"/>
+    <public type="style" name="Theme.AppCompat.DayNight.Dialog"/>
+    <public type="style" name="Theme.AppCompat.DayNight.Dialog.Alert"/>
+    <public type="style" name="Theme.AppCompat.DayNight.Dialog.MinWidth"/>
+    <public type="style" name="Theme.AppCompat.DayNight.DialogWhenLarge"/>
+    <public type="style" name="Theme.AppCompat.DayNight.NoActionBar"/>
+    <public type="style" name="Theme.AppCompat.Light"/>
+    <public type="style" name="Theme.AppCompat.Light.DarkActionBar"/>
+    <public type="style" name="Theme.AppCompat.Light.Dialog"/>
+    <public type="style" name="Theme.AppCompat.Light.Dialog.Alert"/>
+    <public type="style" name="Theme.AppCompat.Light.Dialog.MinWidth"/>
+    <public type="style" name="Theme.AppCompat.Light.DialogWhenLarge"/>
+    <public type="style" name="Theme.AppCompat.Light.NoActionBar"/>
+    <public type="style" name="Theme.AppCompat.NoActionBar"/>
+    <public type="style" name="ThemeOverlay.AppCompat"/>
+    <public type="style" name="ThemeOverlay.AppCompat.ActionBar"/>
+    <public type="style" name="ThemeOverlay.AppCompat.Dark"/>
+    <public type="style" name="ThemeOverlay.AppCompat.Dark.ActionBar"/>
+    <public type="style" name="ThemeOverlay.AppCompat.Light"/>
+    <public type="style" name="Widget.AppCompat.ActionBar"/>
+    <public type="style" name="Widget.AppCompat.ActionBar.Solid"/>
+    <public type="style" name="Widget.AppCompat.ActionBar.TabBar"/>
+    <public type="style" name="Widget.AppCompat.ActionBar.TabText"/>
+    <public type="style" name="Widget.AppCompat.ActionBar.TabView"/>
+    <public type="style" name="Widget.AppCompat.ActionButton"/>
+    <public type="style" name="Widget.AppCompat.ActionButton.CloseMode"/>
+    <public type="style" name="Widget.AppCompat.ActionButton.Overflow"/>
+    <public type="style" name="Widget.AppCompat.ActionMode"/>
+    <public type="style" name="Widget.AppCompat.AutoCompleteTextView"/>
+    <public type="style" name="Widget.AppCompat.Button"/>
+    <public type="style" name="Widget.AppCompat.ButtonBar"/>
+    <public type="style" name="Widget.AppCompat.ButtonBar.AlertDialog"/>
+    <public type="style" name="Widget.AppCompat.Button.Borderless"/>
+    <public type="style" name="Widget.AppCompat.Button.Borderless.Colored"/>
+    <public type="style" name="Widget.AppCompat.Button.ButtonBar.AlertDialog"/>
+    <public type="style" name="Widget.AppCompat.Button.Colored"/>
+    <public type="style" name="Widget.AppCompat.Button.Small"/>
+    <public type="style" name="Widget.AppCompat.CompoundButton.CheckBox"/>
+    <public type="style" name="Widget.AppCompat.CompoundButton.RadioButton"/>
+    <public type="style" name="Widget.AppCompat.CompoundButton.Switch"/>
+    <public type="style" name="Widget.AppCompat.DrawerArrowToggle"/>
+    <public type="style" name="Widget.AppCompat.DropDownItem.Spinner"/>
+    <public type="style" name="Widget.AppCompat.EditText"/>
+    <public type="style" name="Widget.AppCompat.Light.ActionBar"/>
+    <public type="style" name="Widget.AppCompat.Light.ActionBar.Solid"/>
+    <public type="style" name="Widget.AppCompat.Light.ActionBar.Solid.Inverse"/>
+    <public type="style" name="Widget.AppCompat.Light.ActionBar.TabBar"/>
+    <public type="style" name="Widget.AppCompat.Light.ActionBar.TabBar.Inverse"/>
+    <public type="style" name="Widget.AppCompat.Light.ActionBar.TabText"/>
+    <public type="style" name="Widget.AppCompat.Light.ActionBar.TabText.Inverse"/>
+    <public type="style" name="Widget.AppCompat.Light.ActionBar.TabView"/>
+    <public type="style" name="Widget.AppCompat.Light.ActionBar.TabView.Inverse"/>
+    <public type="style" name="Widget.AppCompat.Light.ActionButton"/>
+    <public type="style" name="Widget.AppCompat.Light.ActionButton.CloseMode"/>
+    <public type="style" name="Widget.AppCompat.Light.ActionButton.Overflow"/>
+    <public type="style" name="Widget.AppCompat.Light.ActionMode.Inverse"/>
+    <public type="style" name="Widget.AppCompat.Light.AutoCompleteTextView"/>
+    <public type="style" name="Widget.AppCompat.Light.DropDownItem.Spinner"/>
+    <public type="style" name="Widget.AppCompat.Light.ListPopupWindow"/>
+    <public type="style" name="Widget.AppCompat.Light.ListView.DropDown"/>
+    <public type="style" name="Widget.AppCompat.Light.PopupMenu"/>
+    <public type="style" name="Widget.AppCompat.Light.PopupMenu.Overflow"/>
+    <public type="style" name="Widget.AppCompat.Light.SearchView"/>
+    <public type="style" name="Widget.AppCompat.Light.Spinner.DropDown.ActionBar"/>
+    <public type="style" name="Widget.AppCompat.ListPopupWindow"/>
+    <public type="style" name="Widget.AppCompat.ListView"/>
+    <public type="style" name="Widget.AppCompat.ListView.DropDown"/>
+    <public type="style" name="Widget.AppCompat.ListView.Menu"/>
+    <public type="style" name="Widget.AppCompat.PopupMenu"/>
+    <public type="style" name="Widget.AppCompat.PopupMenu.Overflow"/>
+    <public type="style" name="Widget.AppCompat.PopupWindow"/>
+    <public type="style" name="Widget.AppCompat.ProgressBar"/>
+    <public type="style" name="Widget.AppCompat.ProgressBar.Horizontal"/>
+    <public type="style" name="Widget.AppCompat.RatingBar"/>
+    <public type="style" name="Widget.AppCompat.SearchView"/>
+    <public type="style" name="Widget.AppCompat.SearchView.ActionBar"/>
+    <public type="style" name="Widget.AppCompat.Spinner"/>
+    <public type="style" name="Widget.AppCompat.Spinner.DropDown"/>
+    <public type="style" name="Widget.AppCompat.Spinner.DropDown.ActionBar"/>
+    <public type="style" name="Widget.AppCompat.Spinner.Underlined"/>
+    <public type="style" name="Widget.AppCompat.TextView.SpinnerItem"/>
+    <public type="style" name="Widget.AppCompat.Toolbar"/>
+    <public type="style" name="Widget.AppCompat.Toolbar.Button.Navigation"/>
+</resources>
diff --git a/v7/appcompat/res/color-v23/abc_color_highlight_material.xml b/v7/appcompat/res/color-v23/abc_color_highlight_material.xml
new file mode 100644
index 0000000..8d53611
--- /dev/null
+++ b/v7/appcompat/res/color-v23/abc_color_highlight_material.xml
@@ -0,0 +1,23 @@
+<?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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_checked="true"
+          android:state_enabled="true"
+          android:alpha="@dimen/highlight_alpha_material_colored"
+          android:color="?android:attr/colorControlActivated" />
+    <item android:color="?android:attr/colorControlHighlight" />
+</selector>
\ No newline at end of file
diff --git a/v7/appcompat/res/drawable-hdpi/abc_text_cursor_mtrl_alpha.9.png b/v7/appcompat/res/drawable-hdpi/abc_text_cursor_mtrl_alpha.9.png
deleted file mode 100644
index 5e0bf84..0000000
--- a/v7/appcompat/res/drawable-hdpi/abc_text_cursor_mtrl_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/v7/appcompat/res/drawable-mdpi/abc_text_cursor_mtrl_alpha.9.png b/v7/appcompat/res/drawable-mdpi/abc_text_cursor_mtrl_alpha.9.png
deleted file mode 100644
index 36348a8..0000000
--- a/v7/appcompat/res/drawable-mdpi/abc_text_cursor_mtrl_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/v7/appcompat/res/drawable-v21/abc_action_bar_item_background_material.xml b/v7/appcompat/res/drawable-v21/abc_action_bar_item_background_material.xml
new file mode 100644
index 0000000..595c56c
--- /dev/null
+++ b/v7/appcompat/res/drawable-v21/abc_action_bar_item_background_material.xml
@@ -0,0 +1,18 @@
+<?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.
+-->
+
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+        android:color="?android:attr/colorControlHighlight"/>
\ No newline at end of file
diff --git a/v7/appcompat/res/drawable-v21/abc_btn_colored_material.xml b/v7/appcompat/res/drawable-v21/abc_btn_colored_material.xml
new file mode 100644
index 0000000..10251aa
--- /dev/null
+++ b/v7/appcompat/res/drawable-v21/abc_btn_colored_material.xml
@@ -0,0 +1,50 @@
+<?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.
+-->
+
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+       android:insetLeft="@dimen/abc_button_inset_horizontal_material"
+       android:insetTop="@dimen/abc_button_inset_vertical_material"
+       android:insetRight="@dimen/abc_button_inset_horizontal_material"
+       android:insetBottom="@dimen/abc_button_inset_vertical_material">
+    <ripple android:color="?android:attr/colorControlHighlight">
+        <item>
+            <!-- As we can't use themed ColorStateLists in L, we'll use a Drawable selector which
+                 changes the shape's fill color. -->
+            <selector>
+                <item android:state_enabled="false">
+                    <shape android:shape="rectangle">
+                        <corners android:radius="@dimen/abc_control_corner_material"/>
+                        <solid android:color="?android:attr/colorButtonNormal"/>
+                        <padding android:left="@dimen/abc_button_padding_horizontal_material"
+                                 android:top="@dimen/abc_button_padding_vertical_material"
+                                 android:right="@dimen/abc_button_padding_horizontal_material"
+                                 android:bottom="@dimen/abc_button_padding_vertical_material"/>
+                    </shape>
+                </item>
+                <item>
+                    <shape android:shape="rectangle">
+                        <corners android:radius="@dimen/abc_control_corner_material"/>
+                        <solid android:color="?android:attr/colorAccent"/>
+                        <padding android:left="@dimen/abc_button_padding_horizontal_material"
+                                 android:top="@dimen/abc_button_padding_vertical_material"
+                                 android:right="@dimen/abc_button_padding_horizontal_material"
+                                 android:bottom="@dimen/abc_button_padding_vertical_material"/>
+                    </shape>
+                </item>
+            </selector>
+        </item>
+    </ripple>
+</inset>
\ No newline at end of file
diff --git a/v7/appcompat/res/drawable-v23/abc_control_background_material.xml b/v7/appcompat/res/drawable-v23/abc_control_background_material.xml
new file mode 100644
index 0000000..0b54039
--- /dev/null
+++ b/v7/appcompat/res/drawable-v23/abc_control_background_material.xml
@@ -0,0 +1,19 @@
+<?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.
+-->
+
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+        android:color="@color/abc_color_highlight_material"
+        android:radius="20dp" />
\ No newline at end of file
diff --git a/v7/appcompat/res/drawable-xhdpi/abc_text_cursor_mtrl_alpha.9.png b/v7/appcompat/res/drawable-xhdpi/abc_text_cursor_mtrl_alpha.9.png
deleted file mode 100644
index 666b10a..0000000
--- a/v7/appcompat/res/drawable-xhdpi/abc_text_cursor_mtrl_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/v7/appcompat/res/drawable-xxhdpi/abc_text_cursor_mtrl_alpha.9.png b/v7/appcompat/res/drawable-xxhdpi/abc_text_cursor_mtrl_alpha.9.png
deleted file mode 100644
index 08ee2b4..0000000
--- a/v7/appcompat/res/drawable-xxhdpi/abc_text_cursor_mtrl_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/v7/appcompat/res/drawable/abc_btn_colored_material.xml b/v7/appcompat/res/drawable/abc_btn_colored_material.xml
new file mode 100644
index 0000000..ec93b8b
--- /dev/null
+++ b/v7/appcompat/res/drawable/abc_btn_colored_material.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- Used as the canonical button shape. -->
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@drawable/abc_btn_default_mtrl_shape" />
+</layer-list>
diff --git a/v7/appcompat/res/drawable/abc_text_cursor_material.xml b/v7/appcompat/res/drawable/abc_text_cursor_material.xml
new file mode 100644
index 0000000..885670c
--- /dev/null
+++ b/v7/appcompat/res/drawable/abc_text_cursor_material.xml
@@ -0,0 +1,23 @@
+<?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="rectangle">
+    <size android:height="2dp"
+          android:width="2dp"/>
+    <solid android:color="@android:color/white"/>
+</shape>
\ No newline at end of file
diff --git a/v7/appcompat/res/values-az-rAZ/strings.xml b/v7/appcompat/res/values-az-rAZ/strings.xml
new file mode 100644
index 0000000..a39f5f4
--- /dev/null
+++ b/v7/appcompat/res/values-az-rAZ/strings.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2012 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="abc_action_mode_done" msgid="4076576682505996667">"Hazırdır"</string>
+    <string name="abc_action_bar_home_description" msgid="4600421777120114993">"Evə get"</string>
+    <string name="abc_action_bar_up_description" msgid="1594238315039666878">"Yuxarı get"</string>
+    <string name="abc_action_menu_overflow_description" msgid="3588849162933574182">"Daha çox seçim"</string>
+    <string name="abc_toolbar_collapse_description" msgid="1603543279005712093">"Dağıt"</string>
+    <string name="abc_action_bar_home_description_format" msgid="1397052879051804371">"%1$s, %2$s"</string>
+    <string name="abc_action_bar_home_subtitle_description_format" msgid="6623331958280229229">"%1$s, %2$s, %3$s"</string>
+    <string name="abc_searchview_description_search" msgid="8264924765203268293">"Axtarış"</string>
+    <string name="abc_search_hint" msgid="7723749260725869598">"Axtarış..."</string>
+    <string name="abc_searchview_description_query" msgid="2550479030709304392">"Axtarış sorğusu"</string>
+    <string name="abc_searchview_description_clear" msgid="3691816814315814921">"Sorğunu təmizlə"</string>
+    <string name="abc_searchview_description_submit" msgid="8928215447528550784">"Sorğunu göndərin"</string>
+    <string name="abc_searchview_description_voice" msgid="893419373245838918">"Səsli axtarış"</string>
+    <string name="abc_activitychooserview_choose_application" msgid="2031811694353399454">"Tətbiq seçin"</string>
+    <string name="abc_activity_chooser_view_see_all" msgid="7468859129482906941">"Hamısına baxın"</string>
+    <!-- String.format failed for translation -->
+    <!-- no translation found for abc_shareactionprovider_share_with_application (7165123711973476752) -->
+    <skip />
+    <string name="abc_shareactionprovider_share_with" msgid="3421042268587513524">"Bununla paylaşın"</string>
+    <string name="status_bar_notification_info_overflow" msgid="2869576371154716097">"999+"</string>
+</resources>
diff --git a/v7/appcompat/res/values-gu-rIN/strings.xml b/v7/appcompat/res/values-gu-rIN/strings.xml
new file mode 100644
index 0000000..b77acd3
--- /dev/null
+++ b/v7/appcompat/res/values-gu-rIN/strings.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2012 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="abc_action_mode_done" msgid="4076576682505996667">"થઈ ગયું"</string>
+    <string name="abc_action_bar_home_description" msgid="4600421777120114993">"હોમ પર નેવિગેટ કરો"</string>
+    <string name="abc_action_bar_up_description" msgid="1594238315039666878">"ઉપર નેવિગેટ કરો"</string>
+    <string name="abc_action_menu_overflow_description" msgid="3588849162933574182">"વધુ વિકલ્પો"</string>
+    <string name="abc_toolbar_collapse_description" msgid="1603543279005712093">"સંકુચિત કરો"</string>
+    <string name="abc_action_bar_home_description_format" msgid="1397052879051804371">"%1$s, %2$s"</string>
+    <string name="abc_action_bar_home_subtitle_description_format" msgid="6623331958280229229">"%1$s, %2$s, %3$s"</string>
+    <string name="abc_searchview_description_search" msgid="8264924765203268293">"શોધો"</string>
+    <string name="abc_search_hint" msgid="7723749260725869598">"શોધો…"</string>
+    <string name="abc_searchview_description_query" msgid="2550479030709304392">"શોધ ક્વેરી"</string>
+    <string name="abc_searchview_description_clear" msgid="3691816814315814921">"ક્વેરી સાફ કરો"</string>
+    <string name="abc_searchview_description_submit" msgid="8928215447528550784">"ક્વેરી સબમિટ કરો"</string>
+    <string name="abc_searchview_description_voice" msgid="893419373245838918">"વૉઇસ શોધ"</string>
+    <string name="abc_activitychooserview_choose_application" msgid="2031811694353399454">"એક એપ્લિકેશન પસંદ કરો"</string>
+    <string name="abc_activity_chooser_view_see_all" msgid="7468859129482906941">"બધું જુઓ"</string>
+    <string name="abc_shareactionprovider_share_with_application" msgid="7165123711973476752">"%s સાથે શેર કરો"</string>
+    <string name="abc_shareactionprovider_share_with" msgid="3421042268587513524">"આની સાથે શેર કરો"</string>
+    <string name="status_bar_notification_info_overflow" msgid="2869576371154716097">"999+"</string>
+</resources>
diff --git a/v7/appcompat/res/values-night/themes_daynight.xml b/v7/appcompat/res/values-night/themes_daynight.xml
new file mode 100644
index 0000000..965d355
--- /dev/null
+++ b/v7/appcompat/res/values-night/themes_daynight.xml
@@ -0,0 +1,50 @@
+<?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.
+-->
+
+<resources>
+
+    <!-- Material theme (day/night vesion) for activities. -->
+    <style name="Theme.AppCompat.DayNight" parent="Theme.AppCompat" />
+
+    <!-- Variant of AppCompat.DayNight that has a solid (opaque) action bar
+         with an inverse color profile. The dark action bar sharply stands out against
+         the light content (when applicable).  -->
+    <style name="Theme.AppCompat.DayNight.DarkActionBar" parent="Theme.AppCompat" />
+
+    <!-- Variant of AppCompat.DayNight with no action bar.  -->
+    <style name="Theme.AppCompat.DayNight.NoActionBar" parent="Theme.AppCompat.NoActionBar" />
+
+    <!-- Material theme (day/night vesion) for dialog windows and activities,
+         which is used by the {@code android.support.v7.app.Dialog} class. This changes
+         the window to be floating (not fill the entire screen), and puts a
+         frame around its contents. You can set this theme on an activity if
+         you would like to make an activity that looks like a Dialog. -->
+    <style name="Theme.AppCompat.DayNight.Dialog" parent="Theme.AppCompat.Dialog" />
+
+    <!-- Variant of Theme.AppCompat.DayNight.Dialog that has a nice minimum width for
+         a regular dialog. -->
+    <style name="Theme.AppCompat.DayNight.Dialog.MinWidth" parent="Theme.AppCompat.Dialog.MinWidth" />
+
+    <!-- Theme for a window that will be displayed either full-screen on
+         smaller screens (small, normal) or as a dialog on larger screens
+         (large, xlarge). -->
+    <style name="Theme.AppCompat.DayNight.DialogWhenLarge" parent="Theme.AppCompat.DialogWhenLarge" />
+
+    <!-- Material user theme for alert dialog windows, which is used by the
+         {@code android.support.v7.app.AlertDialog} class. -->
+    <style name="Theme.AppCompat.DayNight.Dialog.Alert" parent="Theme.AppCompat.Dialog.Alert" />
+
+</resources>
\ No newline at end of file
diff --git a/v7/appcompat/res/values-pa-rIN/strings.xml b/v7/appcompat/res/values-pa-rIN/strings.xml
new file mode 100644
index 0000000..af87fdf
--- /dev/null
+++ b/v7/appcompat/res/values-pa-rIN/strings.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2012 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="abc_action_mode_done" msgid="4076576682505996667">"ਹੋ ਗਿਆ"</string>
+    <string name="abc_action_bar_home_description" msgid="4600421777120114993">"ਹੋਮ ਨੈਵੀਗੇਟ ਕਰੋ"</string>
+    <string name="abc_action_bar_up_description" msgid="1594238315039666878">"ਉੱਪਰ ਨੈਵੀਗੇਟ ਕਰੋ"</string>
+    <string name="abc_action_menu_overflow_description" msgid="3588849162933574182">"ਹੋਰ ਚੋਣਾਂ"</string>
+    <string name="abc_toolbar_collapse_description" msgid="1603543279005712093">"ਨਸ਼ਟ ਕਰੋ"</string>
+    <string name="abc_action_bar_home_description_format" msgid="1397052879051804371">"%1$s, %2$s"</string>
+    <string name="abc_action_bar_home_subtitle_description_format" msgid="6623331958280229229">"%1$s, %2$s, %3$s"</string>
+    <string name="abc_searchview_description_search" msgid="8264924765203268293">"ਖੋਜੋ"</string>
+    <string name="abc_search_hint" msgid="7723749260725869598">"ਖੋਜ…"</string>
+    <string name="abc_searchview_description_query" msgid="2550479030709304392">"ਸਵਾਲ ਖੋਜੋ"</string>
+    <string name="abc_searchview_description_clear" msgid="3691816814315814921">"ਸਵਾਲ ਹਟਾਓ"</string>
+    <string name="abc_searchview_description_submit" msgid="8928215447528550784">"ਸਵਾਲ ਪ੍ਰਸਤੁਤ ਕਰੋ"</string>
+    <string name="abc_searchview_description_voice" msgid="893419373245838918">"ਵੌਇਸ ਖੋਜ"</string>
+    <string name="abc_activitychooserview_choose_application" msgid="2031811694353399454">"ਇੱਕ ਐਪ ਚੁਣੋ"</string>
+    <string name="abc_activity_chooser_view_see_all" msgid="7468859129482906941">"ਸਭ ਦੇਖੋ"</string>
+    <string name="abc_shareactionprovider_share_with_application" msgid="7165123711973476752">"%s ਨਾਲ ਸ਼ੇਅਰ ਕਰੋ"</string>
+    <string name="abc_shareactionprovider_share_with" msgid="3421042268587513524">"ਇਸ ਨਾਲ ਸ਼ੇਅਰ ਕਰੋ"</string>
+    <string name="status_bar_notification_info_overflow" msgid="2869576371154716097">"999+"</string>
+</resources>
diff --git a/v7/appcompat/res/values-sq-rAL/strings.xml b/v7/appcompat/res/values-sq-rAL/strings.xml
new file mode 100644
index 0000000..68689a6
--- /dev/null
+++ b/v7/appcompat/res/values-sq-rAL/strings.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2012 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="abc_action_mode_done" msgid="4076576682505996667">"U krye!"</string>
+    <string name="abc_action_bar_home_description" msgid="4600421777120114993">"Orientohu për në shtëpi"</string>
+    <string name="abc_action_bar_up_description" msgid="1594238315039666878">"Ngjitu lart"</string>
+    <string name="abc_action_menu_overflow_description" msgid="3588849162933574182">"Opsione të tjera"</string>
+    <string name="abc_toolbar_collapse_description" msgid="1603543279005712093">"Shpalos"</string>
+    <string name="abc_action_bar_home_description_format" msgid="1397052879051804371">"%1$s, %2$s"</string>
+    <string name="abc_action_bar_home_subtitle_description_format" msgid="6623331958280229229">"%1$s, %2$s, %3$s"</string>
+    <string name="abc_searchview_description_search" msgid="8264924765203268293">"Kërko"</string>
+    <string name="abc_search_hint" msgid="7723749260725869598">"Kërko..."</string>
+    <string name="abc_searchview_description_query" msgid="2550479030709304392">"Kërko pyetjen"</string>
+    <string name="abc_searchview_description_clear" msgid="3691816814315814921">"Pastro pyetjen"</string>
+    <string name="abc_searchview_description_submit" msgid="8928215447528550784">"Dërgo pyetjen"</string>
+    <string name="abc_searchview_description_voice" msgid="893419373245838918">"Kërkim me zë"</string>
+    <string name="abc_activitychooserview_choose_application" msgid="2031811694353399454">"Zgjidh një aplikacion"</string>
+    <string name="abc_activity_chooser_view_see_all" msgid="7468859129482906941">"Shikoji të gjitha"</string>
+    <string name="abc_shareactionprovider_share_with_application" msgid="7165123711973476752">"Shpërnda publikisht me %s"</string>
+    <string name="abc_shareactionprovider_share_with" msgid="3421042268587513524">"Shpërnda publikisht me"</string>
+    <string name="status_bar_notification_info_overflow" msgid="2869576371154716097">"999+"</string>
+</resources>
diff --git a/v7/appcompat/res/values-v11/themes_base.xml b/v7/appcompat/res/values-v11/themes_base.xml
index 2ca5b6f..c2b9aeb 100644
--- a/v7/appcompat/res/values-v11/themes_base.xml
+++ b/v7/appcompat/res/values-v11/themes_base.xml
@@ -36,8 +36,8 @@
         <item name="selectableItemBackground">?android:attr/selectableItemBackground</item>
 
         <!-- Window colors -->
-        <item name="android:colorForeground">@color/bright_foreground_material_dark</item>
-        <item name="android:colorForegroundInverse">@color/bright_foreground_material_light</item>
+        <item name="android:colorForeground">@color/foreground_material_dark</item>
+        <item name="android:colorForegroundInverse">@color/foreground_material_light</item>
         <item name="android:colorBackground">@color/background_material_dark</item>
         <item name="android:colorBackgroundCacheHint">@color/abc_background_cache_hint_selector_material_dark</item>
         <item name="android:disabledAlpha">@dimen/abc_disabled_alpha_material_dark</item>
@@ -88,8 +88,8 @@
         <item name="selectableItemBackground">?android:attr/selectableItemBackground</item>
 
         <!-- Window colors -->
-        <item name="android:colorForeground">@color/bright_foreground_material_light</item>
-        <item name="android:colorForegroundInverse">@color/bright_foreground_material_dark</item>
+        <item name="android:colorForeground">@color/foreground_material_light</item>
+        <item name="android:colorForegroundInverse">@color/foreground_material_dark</item>
         <item name="android:colorBackground">@color/background_material_light</item>
         <item name="android:colorBackgroundCacheHint">@color/abc_background_cache_hint_selector_material_light</item>
         <item name="android:disabledAlpha">@dimen/abc_disabled_alpha_material_light</item>
diff --git a/v7/appcompat/res/values-v12/styles_base.xml b/v7/appcompat/res/values-v12/styles_base.xml
index 6d87337..f7965a4 100644
--- a/v7/appcompat/res/values-v12/styles_base.xml
+++ b/v7/appcompat/res/values-v12/styles_base.xml
@@ -19,13 +19,13 @@
     <style name="Base.Widget.AppCompat.EditText" parent="Base.V12.Widget.AppCompat.EditText" />
 
     <style name="Base.V12.Widget.AppCompat.EditText" parent="Base.V7.Widget.AppCompat.EditText">
-        <item name="android:textCursorDrawable">@drawable/abc_text_cursor_mtrl_alpha</item>
+        <item name="android:textCursorDrawable">@drawable/abc_text_cursor_material</item>
     </style>
 
     <style name="Base.Widget.AppCompat.AutoCompleteTextView" parent="Base.V12.Widget.AppCompat.AutoCompleteTextView" />
 
     <style name="Base.V12.Widget.AppCompat.AutoCompleteTextView" parent="Base.V7.Widget.AppCompat.AutoCompleteTextView">
-        <item name="android:textCursorDrawable">@drawable/abc_text_cursor_mtrl_alpha</item>
+        <item name="android:textCursorDrawable">@drawable/abc_text_cursor_material</item>
     </style>
 
 </resources>
diff --git a/v7/appcompat/res/values-v21/styles_base_text.xml b/v7/appcompat/res/values-v21/styles_base_text.xml
index 241a91b..b66f7cf 100644
--- a/v7/appcompat/res/values-v21/styles_base_text.xml
+++ b/v7/appcompat/res/values-v21/styles_base_text.xml
@@ -59,6 +59,8 @@
 
     <style name="Base.TextAppearance.AppCompat.Button" parent="android:TextAppearance.Material.Button" />
 
+    <style name="Base.TextAppearance.AppCompat.Widget.Button" parent="android:TextAppearance.Material.Widget.Button" />
+
     <style name="Base.TextAppearance.AppCompat.Widget.Switch" parent="android:TextAppearance.Material.Button" />
 
 </resources>
diff --git a/v7/appcompat/res/values-v21/themes_base.xml b/v7/appcompat/res/values-v21/themes_base.xml
index 61cce2f..9d193d5 100644
--- a/v7/appcompat/res/values-v21/themes_base.xml
+++ b/v7/appcompat/res/values-v21/themes_base.xml
@@ -46,7 +46,7 @@
         <!-- Action Bar styling attributes -->
         <item name="actionBarSize">?android:attr/actionBarSize</item>
         <item name="actionBarDivider">?android:attr/actionBarDivider</item>
-        <item name="actionBarItemBackground">?android:attr/actionBarItemBackground</item>
+        <item name="actionBarItemBackground">@drawable/abc_action_bar_item_background_material</item>
         <item name="actionButtonStyle">?android:attr/actionButtonStyle</item>
         <item name="actionMenuTextColor">?android:attr/actionMenuTextColor</item>
         <item name="actionMenuTextAppearance">?android:attr/actionMenuTextAppearance</item>
@@ -95,7 +95,7 @@
         <!-- Action Bar styling attributes -->
         <item name="actionBarSize">?android:attr/actionBarSize</item>
         <item name="actionBarDivider">?android:attr/actionBarDivider</item>
-        <item name="actionBarItemBackground">?android:attr/actionBarItemBackground</item>
+        <item name="actionBarItemBackground">@drawable/abc_action_bar_item_background_material</item>
         <item name="actionButtonStyle">?android:attr/actionButtonStyle</item>
         <item name="actionMenuTextColor">?android:attr/actionMenuTextColor</item>
         <item name="actionMenuTextAppearance">?android:attr/actionMenuTextAppearance</item>
diff --git a/v7/appcompat/res/values-v23/styles_base.xml b/v7/appcompat/res/values-v23/styles_base.xml
new file mode 100644
index 0000000..e1c8910
--- /dev/null
+++ b/v7/appcompat/res/values-v23/styles_base.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+
+    <style name="Base.Widget.AppCompat.Button.Colored" parent="android:Widget.Material.Button.Colored" />
+
+</resources>
diff --git a/v7/appcompat/res/values-v23/styles_base_text.xml b/v7/appcompat/res/values-v23/styles_base_text.xml
new file mode 100644
index 0000000..3fbae02
--- /dev/null
+++ b/v7/appcompat/res/values-v23/styles_base_text.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<resources>
+
+    <style name="Base.TextAppearance.AppCompat.Widget.Button.Inverse" parent="android:TextAppearance.Material.Widget.Button.Inverse" />
+
+</resources>
\ No newline at end of file
diff --git a/v7/appcompat/res/values-v23/themes_base.xml b/v7/appcompat/res/values-v23/themes_base.xml
new file mode 100644
index 0000000..becb1f2
--- /dev/null
+++ b/v7/appcompat/res/values-v23/themes_base.xml
@@ -0,0 +1,37 @@
+<?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.
+-->
+
+<resources>
+
+    <style name="Base.Theme.AppCompat" parent="Base.V23.Theme.AppCompat" />
+    <style name="Base.Theme.AppCompat.Light" parent="Base.V23.Theme.AppCompat.Light" />
+
+    <style name="Base.V23.Theme.AppCompat" parent="Base.V22.Theme.AppCompat">
+        <!-- We can use the platform drawable on v23+ -->
+        <item name="actionBarItemBackground">?android:attr/actionBarItemBackground</item>
+
+        <item name="controlBackground">@drawable/abc_control_background_material</item>
+    </style>
+
+    <style name="Base.V23.Theme.AppCompat.Light" parent="Base.V22.Theme.AppCompat.Light">
+        <!-- We can use the platform drawable on v23+ -->
+        <item name="actionBarItemBackground">?android:attr/actionBarItemBackground</item>
+
+        <item name="controlBackground">@drawable/abc_control_background_material</item>
+    </style>
+
+</resources>
diff --git a/v7/appcompat/res/values/attrs.xml b/v7/appcompat/res/values/attrs.xml
index a7b51c1..c727a2a 100644
--- a/v7/appcompat/res/values/attrs.xml
+++ b/v7/appcompat/res/values/attrs.xml
@@ -325,6 +325,9 @@
         <!-- The color applied to framework switch thumbs in their normal state. -->
         <attr name="colorSwitchThumbNormal" format="color" />
 
+        <!-- The background used by framework controls. -->
+        <attr name="controlBackground" format="reference" />
+
         <!-- ============ -->
         <!-- Alert Dialog styles -->
         <!-- ============ -->
@@ -492,7 +495,6 @@
         <attr name="paddingStart" format="dimension"/>
         <!-- Sets the padding, in pixels, of the end edge; see {@link android.R.attr#padding}. -->
         <attr name="paddingEnd" format="dimension"/>
-
         <!-- Boolean that controls whether a view can take focus.  By default the user can not
              move focus to a view; by setting this attribute to true the view is
              allowed to take focus.  This value does not impact the behavior of
@@ -500,15 +502,16 @@
              always request focus regardless of this view.  It only impacts where
              focus navigation will try to move focus. -->
         <attr name="android:focusable" />
-
         <!-- Deprecated. -->
         <attr name="theme" format="reference" />
-
         <!-- Specifies a theme override for a view. When a theme override is set, the
              view will be inflated using a {@link android.content.Context} themed with
              the specified resource. -->
         <attr name="android:theme" />
+    </declare-styleable>
 
+    <declare-styleable name="ViewBackgroundHelper">
+        <attr name="android:background" />
         <!-- Tint to apply to the background. -->
         <attr name="backgroundTint" format="color" />
 
@@ -837,6 +840,17 @@
 
         <!-- Allows us to read in the minHeight attr pre-v16 -->
         <attr name="android:minHeight" />
+
+        <!-- Drawable to set as the logo that appears at the starting side of
+             the Toolbar, just after the navigation button. -->
+        <attr name="logo" />
+        <!-- A content description string to describe the appearance of the
+             associated logo image. -->
+        <attr name="logoDescription" format="string" />
+        <!-- A color to apply to the title string. -->
+        <attr name="titleTextColor" format="color" />
+        <!-- A color to apply to the subtitle string. -->
+        <attr name="subtitleTextColor" format="color" />
     </declare-styleable>
 
     <declare-styleable name="PopupWindowBackgroundState">
@@ -888,6 +902,30 @@
         <attr name="android:id" />
     </declare-styleable>
 
+    <declare-styleable name="CompoundButton">
+        <attr name="android:button"/>
+        <!-- Tint to apply to the button drawable. -->
+        <attr name="buttonTint" format="color" />
+
+        <!-- Blending mode used to apply the button tint. -->
+        <attr name="buttonTintMode">
+            <!-- The tint is drawn on top of the drawable.
+                 [Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc] -->
+            <enum name="src_over" value="3" />
+            <!-- The tint is masked by the alpha channel of the drawable. The drawable’s
+                 color channels are thrown out. [Sa * Da, Sc * Da] -->
+            <enum name="src_in" value="5" />
+            <!-- The tint is drawn above the drawable, but with the drawable’s alpha
+                 channel masking the result. [Da, Sc * Da + (1 - Sa) * Dc] -->
+            <enum name="src_atop" value="9" />
+            <!-- Multiplies the color and alpha channels of the drawable with those of
+                 the tint. [Sa * Da, Sc * Dc] -->
+            <enum name="multiply" value="14" />
+            <!-- [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc] -->
+            <enum name="screen" value="15" />
+        </attr>
+    </declare-styleable>
+
     <declare-styleable name="SwitchCompat">
         <!-- Drawable to use as the "thumb" that switches back and forth. -->
         <attr name="android:thumb" />
diff --git a/v7/appcompat/res/values/colors_material.xml b/v7/appcompat/res/values/colors_material.xml
index 6b3cca5..1470d18 100644
--- a/v7/appcompat/res/values/colors_material.xml
+++ b/v7/appcompat/res/values/colors_material.xml
@@ -17,17 +17,22 @@
 
 <!-- Colors specific to Material themes. -->
 <resources>
-    <color name="background_material_dark">#ff303030</color>
-    <color name="background_material_light">#ffeeeeee</color>
-    <color name="background_floating_material_dark">#ff424242</color>
-    <color name="background_floating_material_light">#ffeeeeee</color>
+    <color name="foreground_material_dark">@android:color/white</color>
+    <color name="foreground_material_light">@android:color/black</color>
 
-    <color name="primary_material_dark">#ff212121</color>
-    <color name="primary_material_light">#ffefefef</color>
-    <color name="primary_dark_material_dark">#ff000000</color>
-    <color name="primary_dark_material_light">#ff757575</color>
+    <color name="background_material_dark">@color/material_grey_850</color>
+    <color name="background_material_light">@color/material_grey_50</color>
+    <color name="background_floating_material_dark">@color/material_grey_800</color>
+    <color name="background_floating_material_light">@android:color/white</color>
 
-    <color name="ripple_material_dark">#4dffffff</color>
+    <color name="primary_material_dark">@color/material_grey_900</color>
+    <color name="primary_material_light">@color/material_grey_100</color>
+    <color name="primary_dark_material_dark">@android:color/black</color>
+    <color name="primary_dark_material_light">@color/material_grey_600</color>
+
+    <!-- 26% white (foreground) -->
+    <color name="ripple_material_dark">#42ffffff</color>
+    <!-- 12% black (foreground) -->
     <color name="ripple_material_light">#1f000000</color>
 
     <color name="accent_material_light">@color/material_deep_teal_500</color>
@@ -63,21 +68,29 @@
     <!-- TODO: This is 40% alpha on the default accent color. -->
     <color name="highlighted_text_material_light">#66009688</color>
 
-    <color name="link_text_material_dark">@color/material_deep_teal_200</color>
     <color name="link_text_material_light">@color/material_deep_teal_500</color>
+    <color name="link_text_material_dark">@color/material_deep_teal_200</color>
 
     <!-- Text & foreground colors -->
     <eat-comment />
 
+    <!-- 87% black -->
     <color name="primary_text_default_material_light">#de000000</color>
+    <!-- 54% black -->
     <color name="secondary_text_default_material_light">#8a000000</color>
 
+    <!-- 100% white -->
     <color name="primary_text_default_material_dark">#ffffffff</color>
+    <!-- 70% white -->
     <color name="secondary_text_default_material_dark">#b3ffffff</color>
 
     <item name="disabled_alpha_material_light" format="float" type="dimen">0.26</item>
     <item name="disabled_alpha_material_dark" format="float" type="dimen">0.30</item>
 
+    <item name="highlight_alpha_material_light" format="float" type="dimen">0.12</item>
+    <item name="highlight_alpha_material_dark" format="float" type="dimen">0.20</item>
+    <item name="highlight_alpha_material_colored" format="float" type="dimen">0.26</item>
+
     <!-- 26% of default values -->
     <color name="primary_text_disabled_material_light">#39000000</color>
     <color name="secondary_text_disabled_material_light">#24000000</color>
@@ -89,6 +102,14 @@
     <!-- Primary & accent colors -->
     <eat-comment />
 
+    <color name="material_grey_900">#ff212121</color>
+    <color name="material_grey_850">#ff303030</color>
+    <color name="material_grey_800">#ff424242</color>
+    <color name="material_grey_600">#ff757575</color>
+    <color name="material_grey_300">#ffe0e0e0</color>
+    <color name="material_grey_100">#fff5f5f5</color>
+    <color name="material_grey_50">#fffafafa</color>
+
     <color name="material_deep_teal_200">#ff80cbc4</color>
     <color name="material_deep_teal_500">#ff009688</color>
 
diff --git a/v7/appcompat/res/values/styles.xml b/v7/appcompat/res/values/styles.xml
index 0ac20d5..1b74fc2 100644
--- a/v7/appcompat/res/values/styles.xml
+++ b/v7/appcompat/res/values/styles.xml
@@ -35,12 +35,10 @@
     </style>
 
     <style name="TextAppearance.AppCompat.Widget.ActionBar.Title"
-           parent="Base.TextAppearance.AppCompat.Widget.ActionBar.Title">
-    </style>
+           parent="Base.TextAppearance.AppCompat.Widget.ActionBar.Title" />
 
     <style name="TextAppearance.AppCompat.Widget.ActionBar.Subtitle"
-           parent="Base.TextAppearance.AppCompat.Widget.ActionBar.Subtitle">
-    </style>
+           parent="Base.TextAppearance.AppCompat.Widget.ActionBar.Subtitle" />
 
     <style name="TextAppearance.AppCompat.Widget.ActionBar.Title.Inverse"
            parent="Base.TextAppearance.AppCompat.Widget.ActionBar.Title.Inverse">
@@ -214,6 +212,8 @@
 
     <style name="Widget.AppCompat.Button.ButtonBar.AlertDialog" parent="Base.Widget.AppCompat.Button.ButtonBar.AlertDialog" />
 
+    <style name="Widget.AppCompat.Button.Colored" parent="Base.Widget.AppCompat.Button.Colored" />
+
     <style name="Widget.AppCompat.ButtonBar" parent="Base.Widget.AppCompat.ButtonBar" />
 
     <style name="Widget.AppCompat.ButtonBar.AlertDialog" parent="Base.Widget.AppCompat.ButtonBar.AlertDialog" />
@@ -293,6 +293,10 @@
 
     <style name="TextAppearance.AppCompat.Button" parent="Base.TextAppearance.AppCompat.Button" />
 
+    <style name="TextAppearance.AppCompat.Widget.Button" parent="Base.TextAppearance.AppCompat.Widget.Button" />
+
+    <style name="TextAppearance.AppCompat.Widget.Button.Inverse" parent="Base.TextAppearance.AppCompat.Widget.Button.Inverse" />
+
     <style name="TextAppearance.AppCompat.Widget.Switch" parent="Base.TextAppearance.AppCompat.Widget.Switch" />
 
     <style name="TextAppearance.AppCompat.Widget.TextView.SpinnerItem" parent="Base.TextAppearance.AppCompat.Widget.TextView.SpinnerItem" />
diff --git a/v7/appcompat/res/values/styles_base.xml b/v7/appcompat/res/values/styles_base.xml
index 0feb530..91f51c9 100644
--- a/v7/appcompat/res/values/styles_base.xml
+++ b/v7/appcompat/res/values/styles_base.xml
@@ -73,8 +73,7 @@
     </style>
 
     <style name="Base.Widget.AppCompat.ActionButton.CloseMode">
-        <item name="android:background">?attr/selectableItemBackgroundBorderless</item>
-        <item name="android:minWidth">56dp</item>
+        <item name="android:background">?attr/controlBackground</item>
     </style>
 
     <style name="Base.Widget.AppCompat.ActionButton.Overflow">
@@ -138,34 +137,33 @@
         <item name="closeItemLayout">@layout/abc_action_mode_close_item_material</item>
     </style>
 
-    <style name="Base.TextAppearance.AppCompat.Widget.ActionMode.Title" parent="TextAppearance.AppCompat.Title">
-        <item name="android:textSize">@dimen/abc_text_size_title_material_toolbar</item>
-    </style>
+    <style name="Base.TextAppearance.AppCompat.Widget.ActionMode.Title" parent="TextAppearance.AppCompat.Widget.ActionBar.Title"/>
 
-    <style name="Base.TextAppearance.AppCompat.Widget.ActionMode.Subtitle" parent="TextAppearance.AppCompat.Subhead">
-        <item name="android:textSize">@dimen/abc_text_size_subtitle_material_toolbar</item>
-    </style>
+    <style name="Base.TextAppearance.AppCompat.Widget.ActionMode.Subtitle" parent="TextAppearance.AppCompat.Widget.ActionBar.Subtitle"/>
 
-    <style name="Base.TextAppearance.AppCompat.Widget.ActionBar.Menu" parent="android:TextAppearance.Small">
-        <item name="android:textSize">12sp</item>
-        <item name="android:textStyle">bold</item>
+    <style name="Base.TextAppearance.AppCompat.Widget.ActionBar.Menu" parent="TextAppearance.AppCompat.Menu">
         <item name="android:textColor">?attr/actionMenuTextColor</item>
+        <item name="textAllCaps">@bool/abc_config_actionMenuItemAllCaps</item>
     </style>
 
     <style name="Base.TextAppearance.AppCompat.Widget.ActionBar.Title" parent="TextAppearance.AppCompat.Title">
         <item name="android:textSize">@dimen/abc_text_size_title_material_toolbar</item>
+        <item name="android:textColor">?android:attr/textColorPrimary</item>
     </style>
 
     <style name="Base.TextAppearance.AppCompat.Widget.ActionBar.Subtitle" parent="TextAppearance.AppCompat.Subhead">
         <item name="android:textSize">@dimen/abc_text_size_subtitle_material_toolbar</item>
+        <item name="android:textColor">?android:attr/textColorSecondary</item>
     </style>
 
     <style name="Base.TextAppearance.AppCompat.Widget.ActionBar.Title.Inverse" parent="TextAppearance.AppCompat.Title.Inverse">
         <item name="android:textSize">@dimen/abc_text_size_title_material_toolbar</item>
+        <item name="android:textColor">?android:attr/textColorPrimaryInverse</item>
     </style>
 
     <style name="Base.TextAppearance.AppCompat.Widget.ActionBar.Subtitle.Inverse" parent="TextAppearance.AppCompat.Subhead.Inverse">
         <item name="android:textSize">@dimen/abc_text_size_subtitle_material_toolbar</item>
+        <item name="android:textColor">?android:attr/textColorSecondaryInverse</item>
     </style>
 
     <style name="Base.Widget.AppCompat.ProgressBar.Horizontal" parent="android:Widget.ProgressBar.Horizontal">
@@ -320,9 +318,9 @@
     </style>
 
     <style name="Base.Widget.AppCompat.Toolbar.Button.Navigation" parent="android:Widget">
+        <item name="android:background">?attr/controlBackground</item>
         <item name="android:minWidth">56dp</item>
         <item name="android:scaleType">center</item>
-        <item name="android:background">?attr/selectableItemBackground</item>
     </style>
 
     <style name="Base.TextAppearance.Widget.AppCompat.Toolbar.Title"
@@ -379,19 +377,19 @@
 
     <style name="Base.Widget.AppCompat.CompoundButton.CheckBox" parent="android:Widget.CompoundButton.CheckBox">
         <item name="android:button">?android:attr/listChoiceIndicatorMultiple</item>
-        <item name="android:background">?attr/selectableItemBackgroundBorderless</item>
+        <item name="android:background">?attr/controlBackground</item>
     </style>
 
     <style name="Base.Widget.AppCompat.CompoundButton.RadioButton" parent="android:Widget.CompoundButton.RadioButton">
         <item name="android:button">?android:attr/listChoiceIndicatorSingle</item>
-        <item name="android:background">?attr/selectableItemBackgroundBorderless</item>
+        <item name="android:background">?attr/controlBackground</item>
     </style>
 
     <style name="Base.Widget.AppCompat.CompoundButton.Switch" parent="android:Widget.CompoundButton">
         <item name="track">@drawable/abc_switch_track_mtrl_alpha</item>
         <item name="android:thumb">@drawable/abc_switch_thumb_material</item>
         <item name="switchTextAppearance">@style/TextAppearance.AppCompat.Widget.Switch</item>
-        <item name="android:background">?attr/selectableItemBackgroundBorderless</item>
+        <item name="android:background">?attr/controlBackground</item>
         <item name="showText">false</item>
         <item name="switchPadding">@dimen/abc_switch_padding</item>
     </style>
@@ -420,6 +418,12 @@
         <item name="android:minWidth">48dip</item>
     </style>
 
+    <!-- Colored bordered ink button -->
+    <style name="Base.Widget.AppCompat.Button.Colored">
+        <item name="android:background">@drawable/abc_btn_colored_material</item>
+        <item name="android:textAppearance">@style/TextAppearance.AppCompat.Widget.Button.Inverse</item>
+    </style>
+
     <!-- Borderless ink button -->
     <style name="Base.Widget.AppCompat.Button.Borderless">
         <item name="android:background">@drawable/abc_btn_borderless_material</item>
@@ -466,9 +470,7 @@
         <item name="android:background">@null</item>
     </style>
 
-    <style name="Base.Widget.AppCompat.ButtonBar.AlertDialog">
-        <item name="android:background">@null</item>
-    </style>
+    <style name="Base.Widget.AppCompat.ButtonBar.AlertDialog" />
 
     <style name="Base.Animation.AppCompat.DropDownUp" parent="android:Animation">
         <item name="android:windowEnterAnimation">@anim/abc_grow_fade_in_from_bottom</item>
diff --git a/v7/appcompat/res/values/styles_base_text.xml b/v7/appcompat/res/values/styles_base_text.xml
index 3a2799a..8597179 100644
--- a/v7/appcompat/res/values/styles_base_text.xml
+++ b/v7/appcompat/res/values/styles_base_text.xml
@@ -96,6 +96,12 @@
         <item name="android:textColor">?android:textColorPrimary</item>
     </style>
 
+    <style name="Base.TextAppearance.AppCompat.Widget.Button" parent="TextAppearance.AppCompat.Button" />
+
+    <style name="Base.TextAppearance.AppCompat.Widget.Button.Inverse" parent="TextAppearance.AppCompat.Button">
+        <item name="android:textColor">?android:textColorPrimaryInverse</item>
+    </style>
+
     <!-- Deprecated text styles -->
 
     <style name="Base.TextAppearance.AppCompat.Inverse">
diff --git a/v7/appcompat/res/values/themes_base.xml b/v7/appcompat/res/values/themes_base.xml
index 3aba36e..9e9a4ab 100644
--- a/v7/appcompat/res/values/themes_base.xml
+++ b/v7/appcompat/res/values/themes_base.xml
@@ -26,8 +26,8 @@
         <item name="android:windowNoTitle">true</item>
 
         <!-- Window colors -->
-        <item name="android:colorForeground">@color/bright_foreground_material_dark</item>
-        <item name="android:colorForegroundInverse">@color/bright_foreground_material_light</item>
+        <item name="android:colorForeground">@color/foreground_material_dark</item>
+        <item name="android:colorForegroundInverse">@color/foreground_material_light</item>
         <item name="android:colorBackground">@color/background_material_dark</item>
         <item name="android:colorBackgroundCacheHint">@color/abc_background_cache_hint_selector_material_dark</item>
         <item name="android:disabledAlpha">@dimen/abc_disabled_alpha_material_dark</item>
@@ -65,8 +65,8 @@
         <item name="android:windowNoTitle">true</item>
 
         <!-- Window colors -->
-        <item name="android:colorForeground">@color/bright_foreground_material_light</item>
-        <item name="android:colorForegroundInverse">@color/bright_foreground_material_dark</item>
+        <item name="android:colorForeground">@color/foreground_material_light</item>
+        <item name="android:colorForegroundInverse">@color/foreground_material_dark</item>
         <item name="android:colorBackground">@color/background_material_light</item>
         <item name="android:colorBackgroundCacheHint">@color/abc_background_cache_hint_selector_material_light</item>
         <item name="android:disabledAlpha">@dimen/abc_disabled_alpha_material_light</item>
@@ -219,6 +219,7 @@
         <item name="colorControlHighlight">@color/ripple_material_dark</item>
         <item name="colorButtonNormal">@color/button_material_dark</item>
         <item name="colorSwitchThumbNormal">@color/switch_thumb_material_dark</item>
+        <item name="controlBackground">?attr/selectableItemBackgroundBorderless</item>
 
         <item name="drawerArrowStyle">@style/Widget.AppCompat.DrawerArrowToggle</item>
 
@@ -231,7 +232,7 @@
         <!-- Button styles -->
         <item name="buttonStyle">@style/Widget.AppCompat.Button</item>
         <item name="buttonStyleSmall">@style/Widget.AppCompat.Button.Small</item>
-        <item name="android:textAppearanceButton">@style/TextAppearance.AppCompat.Button</item>
+        <item name="android:textAppearanceButton">@style/TextAppearance.AppCompat.Widget.Button</item>
 
         <item name="buttonBarStyle">@style/Widget.AppCompat.ButtonBar</item>
         <item name="buttonBarButtonStyle">@style/Widget.AppCompat.Button.ButtonBar.AlertDialog</item>
@@ -367,6 +368,7 @@
         <item name="colorControlHighlight">@color/ripple_material_light</item>
         <item name="colorButtonNormal">@color/button_material_light</item>
         <item name="colorSwitchThumbNormal">@color/switch_thumb_material_light</item>
+        <item name="controlBackground">?attr/selectableItemBackgroundBorderless</item>
 
         <item name="drawerArrowStyle">@style/Widget.AppCompat.DrawerArrowToggle</item>
 
@@ -379,7 +381,7 @@
         <!-- Button styles -->
         <item name="buttonStyle">@style/Widget.AppCompat.Button</item>
         <item name="buttonStyleSmall">@style/Widget.AppCompat.Button.Small</item>
-        <item name="android:textAppearanceButton">@style/TextAppearance.AppCompat.Button</item>
+        <item name="android:textAppearanceButton">@style/TextAppearance.AppCompat.Widget.Button</item>
 
         <item name="buttonBarStyle">@style/Widget.AppCompat.ButtonBar</item>
         <item name="buttonBarButtonStyle">@style/Widget.AppCompat.Button.ButtonBar.AlertDialog</item>
@@ -546,8 +548,8 @@
 
     <style name="Base.ThemeOverlay.AppCompat.Light" parent="Platform.ThemeOverlay.AppCompat.Light">
         <item name="android:windowBackground">@color/background_material_light</item>
-        <item name="android:colorForeground">@color/bright_foreground_material_light</item>
-        <item name="android:colorForegroundInverse">@color/bright_foreground_material_dark</item>
+        <item name="android:colorForeground">@color/foreground_material_light</item>
+        <item name="android:colorForegroundInverse">@color/foreground_material_dark</item>
         <item name="android:colorBackground">@color/background_material_light</item>
         <item name="android:colorBackgroundCacheHint">@color/abc_background_cache_hint_selector_material_light</item>
 
@@ -575,8 +577,8 @@
 
     <style name="Base.ThemeOverlay.AppCompat.Dark" parent="Platform.ThemeOverlay.AppCompat.Dark">
         <item name="android:windowBackground">@color/background_material_dark</item>
-        <item name="android:colorForeground">@color/bright_foreground_material_dark</item>
-        <item name="android:colorForegroundInverse">@color/bright_foreground_material_light</item>
+        <item name="android:colorForeground">@color/foreground_material_dark</item>
+        <item name="android:colorForegroundInverse">@color/foreground_material_light</item>
         <item name="android:colorBackground">@color/background_material_dark</item>
         <item name="android:colorBackgroundCacheHint">@color/abc_background_cache_hint_selector_material_dark</item>
 
diff --git a/v7/appcompat/res/values/themes_daynight.xml b/v7/appcompat/res/values/themes_daynight.xml
new file mode 100644
index 0000000..bc7001d
--- /dev/null
+++ b/v7/appcompat/res/values/themes_daynight.xml
@@ -0,0 +1,50 @@
+<?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.
+-->
+
+<resources>
+
+    <!-- Material theme (day/night vesion) for activities. -->
+    <style name="Theme.AppCompat.DayNight" parent="Theme.AppCompat.Light" />
+
+    <!-- Variant of AppCompat.DayNight that has a solid (opaque) action bar
+         with an inverse color profile. The dark action bar sharply stands out against
+         the light content (when applicable).  -->
+    <style name="Theme.AppCompat.DayNight.DarkActionBar" parent="Theme.AppCompat.Light.DarkActionBar" />
+
+    <!-- Variant of AppCompat.DayNight with no action bar.  -->
+    <style name="Theme.AppCompat.DayNight.NoActionBar" parent="Theme.AppCompat.Light.NoActionBar" />
+
+    <!-- Material theme (day/night vesion) for dialog windows and activities,
+         which is used by the {@code android.support.v7.app.Dialog} class. This changes
+         the window to be floating (not fill the entire screen), and puts a
+         frame around its contents. You can set this theme on an activity if
+         you would like to make an activity that looks like a Dialog. -->
+    <style name="Theme.AppCompat.DayNight.Dialog" parent="Theme.AppCompat.Light.Dialog" />
+
+    <!-- Variant of Theme.AppCompat.DayNight.Dialog that has a nice minimum width for
+         a regular dialog. -->
+    <style name="Theme.AppCompat.DayNight.Dialog.MinWidth" parent="Theme.AppCompat.Light.Dialog.MinWidth" />
+
+    <!-- Theme for a window that will be displayed either full-screen on
+         smaller screens (small, normal) or as a dialog on larger screens
+         (large, xlarge). -->
+    <style name="Theme.AppCompat.DayNight.DialogWhenLarge" parent="Theme.AppCompat.Light.DialogWhenLarge" />
+
+    <!-- Material user theme for alert dialog windows, which is used by the
+         {@code android.support.v7.app.AlertDialog} class. -->
+    <style name="Theme.AppCompat.DayNight.Dialog.Alert" parent="Theme.AppCompat.Light.Dialog.Alert" />
+
+</resources>
\ No newline at end of file
diff --git a/v7/appcompat/src/android/support/v7/app/ActionBar.java b/v7/appcompat/src/android/support/v7/app/ActionBar.java
index d48dd31..2564031 100644
--- a/v7/appcompat/src/android/support/v7/app/ActionBar.java
+++ b/v7/appcompat/src/android/support/v7/app/ActionBar.java
@@ -46,45 +46,38 @@
  * A primary toolbar within the activity that may display the activity title, application-level
  * navigation affordances, and other interactive items.
  *
- * <p>Beginning with Android 3.0 (API level 11), the action bar appears at the top of an
- * activity's window when the activity uses the system's {@link
- * android.R.style#Theme_Holo Holo} theme (or one of its descendant themes), which is the default.
+ * <p>The action bar appears at the top of an activity's window when the activity uses the
+ * AppCompat's {@link R.style#Theme_AppCompat AppCompat} theme (or one of its descendant themes).
  * You may otherwise add the action bar by calling {@link
- * android.view.Window#requestFeature requestFeature(FEATURE_ACTION_BAR)} or by declaring it in a
- * custom theme with the {@link android.R.styleable#Theme_windowActionBar windowActionBar} property.
+ * AppCompatDelegate#requestWindowFeature(int)  requestFeature(FEATURE_SUPPORT_ACTION_BAR)} or by
+ * declaring it in a custom theme with the {@link R.styleable#Theme_windowActionBar windowActionBar}
+ * property.
  * </p>
  *
- * <p>Beginning with Android L (API level 21), the action bar may be represented by any
- * Toolbar widget within the application layout. The application may signal to the Activity
- * which Toolbar should be treated as the Activity's action bar. Activities that use this
- * feature should use one of the supplied <code>.NoActionBar</code> themes, set the
- * {@link android.R.styleable#Theme_windowActionBar windowActionBar} attribute to <code>false</code>
+ * <p>The action bar may be represented by any Toolbar widget within the application layout.
+ * The application may signal to the Activity which Toolbar should be treated as the Activity's
+ * action bar. Activities that use this feature should use one of the supplied
+ * <code>.NoActionBar</code> themes, set the
+ * {@link R.styleable#Theme_windowActionBar windowActionBar} attribute to <code>false</code>
  * or otherwise not request the window feature.</p>
  *
- * <p>By adjusting the window features requested by the theme and the layouts used for
- * an Activity's content view, an app can use the standard system action bar on older platform
- * releases and the newer inline toolbars on newer platform releases. The <code>ActionBar</code>
- * object obtained from the Activity can be used to control either configuration transparently.</p>
+ * <p>If your activity has an options menu, you can make select items accessible directly from the
+ * action bar as "action items". You can also  modify various characteristics of the action bar or
+ * remove it completely.</p>
  *
- * <p>When using the Holo themes the action bar shows the application icon on
- * the left, followed by the activity title. If your activity has an options menu, you can make
- * select items accessible directly from the action bar as "action items". You can also
- * modify various characteristics of the action bar or remove it completely.</p>
- *
- * <p>When using the Material themes (default in API 21 or newer) the navigation button
- * (formerly "Home") takes over the space previously occupied by the application icon.
- * Apps wishing to express a stronger branding should use their brand colors heavily
- * in the action bar and other application chrome or use a {@link #setLogo(int) logo}
+ * <p>The navigation button (formerly "Home") takes over the space previously occupied by the
+ * application icon. Apps wishing to express a stronger branding should use their brand colors
+ * heavily in the action bar and other application chrome or use a {@link #setLogo(int) logo}
  * in place of their standard title text.</p>
  *
  * <p>From your activity, you can retrieve an instance of {@link ActionBar} by calling {@link
- * android.app.Activity#getActionBar getActionBar()}.</p>
+ * AppCompatActivity#getSupportActionBar()}  getSupportActionBar()}.</p>
  *
  * <p>In some cases, the action bar may be overlayed by another bar that enables contextual actions,
- * using an {@link android.view.ActionMode}. For example, when the user selects one or more items in
+ * using an {@link ActionMode}. For example, when the user selects one or more items in
  * your activity, you can enable an action mode that offers actions specific to the selected
  * items, with a UI that temporarily replaces the action bar. Although the UI may occupy the
- * same space, the {@link android.view.ActionMode} APIs are distinct and independent from those for
+ * same space, the {@link ActionMode} APIs are distinct and independent from those for
  * {@link ActionBar}.</p>
  *
  * <div class="special reference">
diff --git a/v7/appcompat/src/android/support/v7/app/AppCompatActivity.java b/v7/appcompat/src/android/support/v7/app/AppCompatActivity.java
index e4283e3..2ce12ce 100644
--- a/v7/appcompat/src/android/support/v7/app/AppCompatActivity.java
+++ b/v7/appcompat/src/android/support/v7/app/AppCompatActivity.java
@@ -19,6 +19,7 @@
 import android.content.Intent;
 import android.content.res.Configuration;
 import android.os.Bundle;
+import android.support.annotation.CallSuper;
 import android.support.annotation.LayoutRes;
 import android.support.annotation.Nullable;
 import android.support.v4.app.ActivityCompat;
@@ -27,6 +28,7 @@
 import android.support.v4.app.TaskStackBuilder;
 import android.support.v7.view.ActionMode;
 import android.support.v7.widget.Toolbar;
+import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -60,6 +62,12 @@
     }
 
     @Override
+    public void setTheme(int resid) {
+        getDelegate().applyDayNight();
+        super.setTheme(resid);
+    }
+
+    @Override
     protected void onPostCreate(@Nullable Bundle savedInstanceState) {
         super.onPostCreate(savedInstanceState);
         getDelegate().onPostCreate(savedInstanceState);
@@ -88,7 +96,8 @@
      * {@link android.R.id#home home} menu select action.</p>
      *
      * <p>In order to use a Toolbar within the Activity's window content the application
-     * must not request the window feature {@link android.view.Window#FEATURE_ACTION_BAR FEATURE_ACTION_BAR}.</p>
+     * must not request the window feature
+     * {@link android.view.Window#FEATURE_ACTION_BAR FEATURE_SUPPORT_ACTION_BAR}.</p>
      *
      * @param toolbar Toolbar to set as the Activity's action bar
      */
@@ -201,6 +210,7 @@
      *
      * @param mode The new action mode.
      */
+    @CallSuper
     public void onSupportActionModeStarted(ActionMode mode) {
     }
 
@@ -210,6 +220,7 @@
      *
      * @param mode The action mode that just finished.
      */
+    @CallSuper
     public void onSupportActionModeFinished(ActionMode mode) {
     }
 
@@ -422,6 +433,28 @@
     }
 
     /**
+     * {@inheritDoc}
+     *
+     * <p>Please note: AppCompat uses it's own feature id for the action bar:
+     * {@link AppCompatDelegate#FEATURE_SUPPORT_ACTION_BAR FEATURE_SUPPORT_ACTION_BAR}.</p>
+     */
+    @Override
+    public boolean onMenuOpened(int featureId, Menu menu) {
+        return super.onMenuOpened(featureId, menu);
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * <p>Please note: AppCompat uses it's own feature id for the action bar:
+     * {@link AppCompatDelegate#FEATURE_SUPPORT_ACTION_BAR FEATURE_SUPPORT_ACTION_BAR}.</p>
+     */
+    @Override
+    public void onPanelClosed(int featureId, Menu menu) {
+        super.onPanelClosed(featureId, menu);
+    }
+
+    /**
      * @return The {@link AppCompatDelegate} being used by this Activity.
      */
     public AppCompatDelegate getDelegate() {
diff --git a/v7/appcompat/src/android/support/v7/app/AppCompatDelegate.java b/v7/appcompat/src/android/support/v7/app/AppCompatDelegate.java
index 3abe072..d04e89e 100644
--- a/v7/appcompat/src/android/support/v7/app/AppCompatDelegate.java
+++ b/v7/appcompat/src/android/support/v7/app/AppCompatDelegate.java
@@ -22,8 +22,12 @@
 import android.content.res.Configuration;
 import android.os.Build;
 import android.os.Bundle;
+import android.support.annotation.IntDef;
+import android.support.annotation.LayoutRes;
 import android.support.annotation.NonNull;
 import android.support.v4.app.FragmentActivity;
+import android.support.v4.view.WindowCompat;
+import android.support.v7.appcompat.R;
 import android.support.v7.view.ActionMode;
 import android.support.v7.widget.Toolbar;
 import android.util.AttributeSet;
@@ -32,6 +36,9 @@
 import android.view.ViewGroup;
 import android.view.Window;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 /**
  * This class represents a delegate which you can use to extend AppCompat's support to any
  * {@link android.app.Activity}.
@@ -69,6 +76,73 @@
     static final String TAG = "AppCompatDelegate";
 
     /**
+     * Mode which means to not use night mode, and therefore not use {@code night} qualified
+     * resources, regardless of the time.
+     *
+     * @see #setNightMode(int)
+     */
+    public static final int MODE_NIGHT_NO = 0;
+
+    /**
+     * Mode which means to always use night mode, and therefore use {@code night} qualified
+     * resources, regardless of the time.
+     *
+     * @see #setNightMode(int)
+     */
+    public static final int MODE_NIGHT_YES = 1;
+
+    /**
+     * Mode which means to use night mode when it is determined that it is night or not..
+     *
+     * <p>The calculation used to determine whether it is night or not makes use of the location
+     * APIs (if this app has the necessary permissions). This allows us to generate accurate
+     * sunrise and sunset times. If this app does not have permission to access the location APIs
+     * then we use hardcoded times which will be less accurate.</p>
+     *
+     * <p>This is the default mode.</p>
+     *
+     * @see #setNightMode(int)
+     */
+    public static final int MODE_NIGHT_AUTO = 2;
+
+    @IntDef({MODE_NIGHT_NO, MODE_NIGHT_YES, MODE_NIGHT_AUTO})
+    @Retention(RetentionPolicy.SOURCE)
+    @interface NightMode {}
+
+    /**
+     * Flag for enabling the support Action Bar.
+     *
+     * <p>This is enabled by default for some devices. The Action Bar replaces the title bar and
+     * provides an alternate location for an on-screen menu button on some devices.
+     */
+    public static final int FEATURE_SUPPORT_ACTION_BAR = 100 + WindowCompat.FEATURE_ACTION_BAR;
+
+    /**
+     * Flag for requesting an support Action Bar that overlays window content.
+     * Normally an Action Bar will sit in the space above window content, but if this
+     * feature is requested along with {@link #FEATURE_SUPPORT_ACTION_BAR} it will be layered over
+     * the window content itself. This is useful if you would like your app to have more control
+     * over how the Action Bar is displayed, such as letting application content scroll beneath
+     * an Action Bar with a transparent background or otherwise displaying a transparent/translucent
+     * Action Bar over application content.
+     *
+     * <p>This mode is especially useful with {@code View.SYSTEM_UI_FLAG_FULLSCREEN}, which allows
+     * you to seamlessly hide the action bar in conjunction with other screen decorations.
+     * When an ActionBar is in this mode it will adjust the insets provided to
+     * {@link View#fitSystemWindows(android.graphics.Rect) View.fitSystemWindows(Rect)}
+     * to include the content covered by the action bar, so you can do layout within
+     * that space.
+     */
+    public static final int FEATURE_SUPPORT_ACTION_BAR_OVERLAY =
+            100 + WindowCompat.FEATURE_ACTION_BAR_OVERLAY;
+
+    /**
+     * Flag for specifying the behavior of action modes when an Action Bar is not present.
+     * If overlay is enabled, the action mode UI will be allowed to cover existing window content.
+     */
+    public static final int FEATURE_ACTION_MODE_OVERLAY = WindowCompat.FEATURE_ACTION_MODE_OVERLAY;
+
+    /**
      * Create a {@link android.support.v7.app.AppCompatDelegate} to use with {@code activity}.
      *
      * @param callback An optional callback for AppCompat specific events
@@ -89,7 +163,9 @@
     private static AppCompatDelegate create(Context context, Window window,
             AppCompatCallback callback) {
         final int sdk = Build.VERSION.SDK_INT;
-        if (sdk >= 14) {
+        if (sdk >= 23) {
+            return new AppCompatDelegateImplV23(context, window, callback);
+        } else if (sdk >= 14) {
             return new AppCompatDelegateImplV14(context, window, callback);
         } else if (sdk >= 11) {
             return new AppCompatDelegateImplV11(context, window, callback);
@@ -121,7 +197,7 @@
      *
      * <p>In order to use a Toolbar within the Activity's window content the application
      * must not request the window feature
-     * {@link android.view.Window#FEATURE_ACTION_BAR FEATURE_ACTION_BAR}.</p>
+     * {@link AppCompatDelegate#FEATURE_SUPPORT_ACTION_BAR FEATURE_SUPPORT_ACTION_BAR}.</p>
      *
      * @param toolbar Toolbar to set as the Activity's action bar
      */
@@ -166,7 +242,7 @@
     /**
      * Should be called instead of {@link Activity#setContentView(int)}}
      */
-    public abstract void setContentView(int resId);
+    public abstract void setContentView(@LayoutRes int resId);
 
     /**
      * Should be called instead of
@@ -279,4 +355,31 @@
      */
     public abstract boolean isHandleNativeActionModesEnabled();
 
+    /**
+     * Allow AppCompat to apply the {@code night} and {@code notnight} resource qualifiers.
+     *
+     * <p>Doing this enables the
+     * {@link R.style#Theme_AppCompat_DayNight Theme.AppCompat.DayNight}
+     * family of themes to work, using the computed twilight to automatically select a dark or
+     * light theme.</p>
+     *
+     * <p>You can override the night mode using {@link #setNightMode(int)}.</p>
+     *
+     * <p>This only works on devices running
+     * {@link Build.VERSION_CODES#ICE_CREAM_SANDWICH ICE_CREAM_SANDWICH} and above.</p>
+     *
+     * @see #setNightMode(int)
+     */
+    public abstract void applyDayNight();
+
+    /**
+     * Override the night mode used when {@link #applyDayNight()} is called. This method only takes
+     * effect for those situtations where {@link #applyDayNight()} works.
+     *
+     * <p>This needs to be called before {@link #applyDayNight()}. Defaults to
+     * {@link #MODE_NIGHT_AUTO}.</p>
+     *
+     * @see #applyDayNight()
+     */
+    public abstract void setNightMode(@NightMode int mode);
 }
diff --git a/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplBase.java b/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplBase.java
index 316256c..1c5f98e 100644
--- a/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplBase.java
+++ b/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplBase.java
@@ -21,7 +21,6 @@
 import android.content.res.TypedArray;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
-import android.support.v4.view.WindowCompat;
 import android.support.v7.appcompat.R;
 import android.support.v7.internal.view.SupportMenuInflater;
 import android.support.v7.internal.view.WindowCallbackWrapper;
@@ -118,20 +117,20 @@
             requestWindowFeature(Window.FEATURE_NO_TITLE);
         } else if (a.getBoolean(R.styleable.Theme_windowActionBar, false)) {
             // Don't allow an action bar if there is no title.
-            requestWindowFeature(WindowCompat.FEATURE_ACTION_BAR);
+            requestWindowFeature(FEATURE_SUPPORT_ACTION_BAR);
         }
         if (a.getBoolean(R.styleable.Theme_windowActionBarOverlay, false)) {
-            requestWindowFeature(WindowCompat.FEATURE_ACTION_BAR_OVERLAY);
+            requestWindowFeature(FEATURE_SUPPORT_ACTION_BAR_OVERLAY);
         }
         if (a.getBoolean(R.styleable.Theme_windowActionModeOverlay, false)) {
-            requestWindowFeature(WindowCompat.FEATURE_ACTION_MODE_OVERLAY);
+            requestWindowFeature(FEATURE_ACTION_MODE_OVERLAY);
         }
         mIsFloating = a.getBoolean(R.styleable.Theme_android_windowIsFloating, false);
         a.recycle();
     }
 
     // Methods used to create and respond to options menu
-    abstract boolean onPanelClosed(int featureId, Menu menu);
+    abstract void onPanelClosed(int featureId, Menu menu);
 
     abstract boolean onMenuOpened(int featureId, Menu menu);
 
@@ -140,6 +139,11 @@
     abstract boolean onKeyShortcut(int keyCode, KeyEvent event);
 
     @Override
+    public void setNightMode(@NightMode int mode) {
+        // no-op
+    }
+
+    @Override
     public final ActionBarDrawerToggle.Delegate getDrawerToggleDelegate() {
         return new ActionBarDrawableToggleImpl();
     }
@@ -216,6 +220,11 @@
         return false;
     }
 
+    @Override
+    public void applyDayNight() {
+        // no-op on v7
+    }
+
     final boolean isDestroyed() {
         return mIsDestroyed;
     }
@@ -248,12 +257,14 @@
 
         @Override
         public boolean dispatchKeyEvent(KeyEvent event) {
-            if (AppCompatDelegateImplBase.this.dispatchKeyEvent(event)) {
-                // First, let us attempt to handle it
-                return true;
-            }
-            // If we reach here, let the wrapped Callback attempt to handle it
-            return super.dispatchKeyEvent(event);
+            return AppCompatDelegateImplBase.this.dispatchKeyEvent(event)
+                    || super.dispatchKeyEvent(event);
+        }
+
+        @Override
+        public boolean dispatchKeyShortcutEvent(KeyEvent event) {
+            return super.dispatchKeyShortcutEvent(event)
+                    || AppCompatDelegateImplBase.this.onKeyShortcut(event.getKeyCode(), event);
         }
 
         @Override
@@ -267,6 +278,12 @@
         }
 
         @Override
+        public void onContentChanged() {
+            // We purposely do not propagate this call as this is called when we install
+            // our sub-decor rather than the user's content
+        }
+
+        @Override
         public boolean onPreparePanel(int featureId, View view, Menu menu) {
             final MenuBuilder mb = menu instanceof MenuBuilder ? (MenuBuilder) menu : null;
 
@@ -295,32 +312,14 @@
 
         @Override
         public boolean onMenuOpened(int featureId, Menu menu) {
-            if (AppCompatDelegateImplBase.this.onMenuOpened(featureId, menu)) {
-                return true;
-            }
-            return super.onMenuOpened(featureId, menu);
-        }
-
-        @Override
-        public boolean dispatchKeyShortcutEvent(KeyEvent event) {
-            if (AppCompatDelegateImplBase.this.onKeyShortcut(event.getKeyCode(), event)) {
-                return true;
-            }
-            return super.dispatchKeyShortcutEvent(event);
-        }
-
-        @Override
-        public void onContentChanged() {
-            // We purposely do not propagate this call as this is called when we install
-            // our sub-decor rather than the user's content
+            return super.onMenuOpened(featureId, menu)
+                    || AppCompatDelegateImplBase.this.onMenuOpened(featureId, menu);
         }
 
         @Override
         public void onPanelClosed(int featureId, Menu menu) {
-            if (AppCompatDelegateImplBase.this.onPanelClosed(featureId, menu)) {
-                return;
-            }
             super.onPanelClosed(featureId, menu);
+            AppCompatDelegateImplBase.this.onPanelClosed(featureId, menu);
         }
     }
 }
diff --git a/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplV14.java b/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplV14.java
index 5ab3a10..d6b0ea1 100644
--- a/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplV14.java
+++ b/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplV14.java
@@ -16,15 +16,23 @@
 
 package android.support.v7.app;
 
+import android.app.UiModeManager;
 import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.os.Build;
 import android.support.v7.internal.view.SupportActionModeWrapper;
 import android.view.ActionMode;
 import android.view.Window;
 
 class AppCompatDelegateImplV14 extends AppCompatDelegateImplV11 {
 
+    private TwilightManager mTwilightManager;
     private boolean mHandleNativeActionModes = true; // defaults to true
 
+    @NightMode
+    private int mNightMode = MODE_NIGHT_AUTO;
+
     AppCompatDelegateImplV14(Context context, Window window, AppCompatCallback callback) {
         super(context, window, callback);
     }
@@ -46,6 +54,90 @@
         return mHandleNativeActionModes;
     }
 
+    @Override
+    public void applyDayNight() {
+        if (!isSystemControllingNightMode()) {
+            // If the system is not controlling night mode, let's do it ourselves
+            switch (mNightMode) {
+                case MODE_NIGHT_AUTO:
+                    // For auto, we need to check whether it's night or not
+                    setDayNightUsingTwilight();
+                    break;
+                default:
+                    // Else, we'll set the value directly
+                    setDayNightConfiguration(mNightMode);
+                    break;
+            }
+        }
+    }
+
+    @Override
+    public void setNightMode(@NightMode int mode) {
+        mNightMode = mode;
+    }
+
+    /**
+     * If possible, updates the Activity's {@link uiMode} to match whether we are at night or not.
+     */
+    void setDayNightUsingTwilight() {
+        // If the system isn't controlling night mode, we'll do it ourselves
+        if (getTwilightManager().isNight()) {
+            // If we're at 'night', set the night mode
+            setDayNightConfiguration(MODE_NIGHT_YES);
+        } else {
+            // Else, set the day mode
+            setDayNightConfiguration(MODE_NIGHT_NO);
+        }
+    }
+
+    /**
+     * Updates the {@link Resources} configuration {@code uiMode} with the
+     * chosen {@code UI_MODE_NIGHT} value.
+     */
+    void setDayNightConfiguration(@NightMode int mode) {
+        final Resources res = mContext.getResources();
+        final Configuration conf = res.getConfiguration();
+        final int currentNightMode = conf.uiMode & Configuration.UI_MODE_NIGHT_MASK;
+
+        int newNightMode = Configuration.UI_MODE_NIGHT_UNDEFINED;
+        switch (mode) {
+            case MODE_NIGHT_NO:
+                newNightMode = Configuration.UI_MODE_NIGHT_NO;
+                break;
+            case MODE_NIGHT_YES:
+                newNightMode = Configuration.UI_MODE_NIGHT_YES;
+                break;
+        }
+
+        if (currentNightMode != newNightMode) {
+            conf.uiMode = (conf.uiMode & ~Configuration.UI_MODE_NIGHT_MASK) | newNightMode;
+            res.updateConfiguration(conf, res.getDisplayMetrics());
+        }
+    }
+
+    /**
+     * Returns true if the system is controlling night mode.
+     */
+    private boolean isSystemControllingNightMode() {
+        final UiModeManager uiModeManager =
+                (UiModeManager) mContext.getSystemService(Context.UI_MODE_SERVICE);
+
+        if (Build.VERSION.SDK_INT < 23
+                && uiModeManager.getCurrentModeType() != Configuration.UI_MODE_TYPE_CAR) {
+            // Night mode only has an effect with car mode enabled on < API v23
+            return false;
+        }
+
+        return uiModeManager.getNightMode() != UiModeManager.MODE_NIGHT_NO;
+    }
+
+    private TwilightManager getTwilightManager() {
+        if (mTwilightManager == null) {
+            mTwilightManager = new TwilightManager(mContext);
+        }
+        return mTwilightManager;
+    }
+
     class AppCompatWindowCallbackV14 extends AppCompatWindowCallbackBase {
         AppCompatWindowCallbackV14(Window.Callback callback) {
             super(callback);
@@ -54,7 +146,7 @@
         @Override
         public ActionMode onWindowStartingActionMode(ActionMode.Callback callback) {
             // We wrap in a support action mode on v14+ if enabled
-            if (mHandleNativeActionModes) {
+            if (isHandleNativeActionModesEnabled()) {
                 return startAsSupportActionMode(callback);
             }
             // Else, let the call fall through to the wrapped callback
diff --git a/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplV23.java b/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplV23.java
new file mode 100644
index 0000000..7b4c5ae
--- /dev/null
+++ b/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplV23.java
@@ -0,0 +1,65 @@
+/*
+ * 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.v7.app;
+
+import android.content.Context;
+import android.view.ActionMode;
+import android.view.Window;
+
+class AppCompatDelegateImplV23 extends AppCompatDelegateImplV14 {
+
+    AppCompatDelegateImplV23(Context context, Window window, AppCompatCallback callback) {
+        super(context, window, callback);
+    }
+
+    @Override
+    Window.Callback wrapWindowCallback(Window.Callback callback) {
+        // Override the window callback so that we can intercept onWindowStartingActionMode(type)
+        // calls
+        return new AppCompatWindowCallbackV23(callback);
+    }
+
+    class AppCompatWindowCallbackV23 extends AppCompatWindowCallbackV14 {
+        AppCompatWindowCallbackV23(Window.Callback callback) {
+            super(callback);
+        }
+
+        @Override
+        public ActionMode onWindowStartingActionMode(ActionMode.Callback callback, int type) {
+            if (isHandleNativeActionModesEnabled()) {
+                switch (type) {
+                    case ActionMode.TYPE_PRIMARY:
+                        // We only take over if the type is TYPE_PRIMARY
+                        return startAsSupportActionMode(callback);
+                }
+            }
+            // Else, let the call fall through to the wrapped callback
+            return super.onWindowStartingActionMode(callback, type);
+        }
+
+        @Override
+        public ActionMode onWindowStartingActionMode(ActionMode.Callback callback) {
+            // No-op on API 23+
+            return null;
+        }
+    }
+
+    @Override
+    public void applyDayNight() {
+        // no-op. Let the framework handle DayNight stuff
+    }
+}
diff --git a/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplV7.java b/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplV7.java
index f545bda..ebb00cc 100644
--- a/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplV7.java
+++ b/v7/appcompat/src/android/support/v7/app/AppCompatDelegateImplV7.java
@@ -36,7 +36,9 @@
 import android.support.v4.view.OnApplyWindowInsetsListener;
 import android.support.v4.view.ViewCompat;
 import android.support.v4.view.ViewConfigurationCompat;
+import android.support.v4.view.WindowCompat;
 import android.support.v4.view.WindowInsetsCompat;
+import android.support.v4.widget.PopupWindowCompat;
 import android.support.v7.appcompat.R;
 import android.support.v7.internal.app.AppCompatViewInflater;
 import android.support.v7.internal.app.ToolbarActionBar;
@@ -79,9 +81,6 @@
 import android.widget.PopupWindow;
 import android.widget.TextView;
 
-import static android.support.v4.view.WindowCompat.FEATURE_ACTION_BAR;
-import static android.support.v4.view.WindowCompat.FEATURE_ACTION_BAR_OVERLAY;
-import static android.support.v4.view.WindowCompat.FEATURE_ACTION_MODE_OVERLAY;
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
 import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
 import static android.view.Window.FEATURE_OPTIONS_PANEL;
@@ -122,8 +121,8 @@
             if ((mInvalidatePanelMenuFeatures & 1 << FEATURE_OPTIONS_PANEL) != 0) {
                 doInvalidatePanelMenu(FEATURE_OPTIONS_PANEL);
             }
-            if ((mInvalidatePanelMenuFeatures & 1 << FEATURE_ACTION_BAR) != 0) {
-                doInvalidatePanelMenu(FEATURE_ACTION_BAR);
+            if ((mInvalidatePanelMenuFeatures & 1 << FEATURE_SUPPORT_ACTION_BAR) != 0) {
+                doInvalidatePanelMenu(FEATURE_SUPPORT_ACTION_BAR);
             }
             mInvalidatePanelMenuPosted = false;
             mInvalidatePanelMenuFeatures = 0;
@@ -195,7 +194,7 @@
         final ActionBar ab = getSupportActionBar();
         if (ab instanceof WindowDecorActionBar) {
             throw new IllegalStateException("This Activity already has an action bar supplied " +
-                    "by the window decor. Do not request Window.FEATURE_ACTION_BAR and set " +
+                    "by the window decor. Do not request Window.FEATURE_SUPPORT_ACTION_BAR and set " +
                     "windowActionBar to false in your theme to use a Toolbar instead.");
         }
         // Clear out the MenuInflater to make sure that it is valid for the new Action Bar
@@ -313,7 +312,7 @@
                      * Propagate features to DecorContentParent
                      */
                     if (mOverlayActionBar) {
-                        mDecorContentParent.initFeature(FEATURE_ACTION_BAR_OVERLAY);
+                        mDecorContentParent.initFeature(FEATURE_SUPPORT_ACTION_BAR_OVERLAY);
                     }
                     if (mFeatureProgress) {
                         mDecorContentParent.initFeature(Window.FEATURE_PROGRESS);
@@ -428,7 +427,7 @@
             // would run normally in order to satisfy instance state restoration.
             PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false);
             if (!isDestroyed() && (st == null || st.menu == null)) {
-                invalidatePanelMenu(FEATURE_ACTION_BAR);
+                invalidatePanelMenu(FEATURE_SUPPORT_ACTION_BAR);
             }
         }
     }
@@ -472,7 +471,9 @@
 
     @Override
     public boolean requestWindowFeature(int featureId) {
-        if (mWindowNoTitle && featureId == FEATURE_ACTION_BAR) {
+        featureId = sanitizeWindowFeatureId(featureId);
+
+        if (mWindowNoTitle && featureId == FEATURE_SUPPORT_ACTION_BAR) {
             return false; // Ignore. No title dominates.
         }
         if (mHasActionBar && featureId == Window.FEATURE_NO_TITLE) {
@@ -481,11 +482,11 @@
         }
 
         switch (featureId) {
-            case FEATURE_ACTION_BAR:
+            case FEATURE_SUPPORT_ACTION_BAR:
                 throwFeatureRequestIfSubDecorInstalled();
                 mHasActionBar = true;
                 return true;
-            case FEATURE_ACTION_BAR_OVERLAY:
+            case FEATURE_SUPPORT_ACTION_BAR_OVERLAY:
                 throwFeatureRequestIfSubDecorInstalled();
                 mOverlayActionBar = true;
                 return true;
@@ -512,10 +513,11 @@
 
     @Override
     public boolean hasWindowFeature(int featureId) {
+        featureId = sanitizeWindowFeatureId(featureId);
         switch (featureId) {
-            case FEATURE_ACTION_BAR:
+            case FEATURE_SUPPORT_ACTION_BAR:
                 return mHasActionBar;
-            case FEATURE_ACTION_BAR_OVERLAY:
+            case FEATURE_SUPPORT_ACTION_BAR_OVERLAY:
                 return mOverlayActionBar;
             case FEATURE_ACTION_MODE_OVERLAY:
                 return mOverlayActionMode;
@@ -541,13 +543,12 @@
     }
 
     @Override
-    boolean onPanelClosed(final int featureId, Menu menu) {
-        if (featureId == FEATURE_ACTION_BAR) {
+    void onPanelClosed(final int featureId, Menu menu) {
+        if (featureId == FEATURE_SUPPORT_ACTION_BAR) {
             ActionBar ab = getSupportActionBar();
             if (ab != null) {
                 ab.dispatchMenuVisibilityChanged(false);
             }
-            return true;
         } else if (featureId == FEATURE_OPTIONS_PANEL) {
             // Make sure that the options panel is closed. This is mainly used when we're using a
             // ToolbarActionBar
@@ -556,12 +557,11 @@
                 closePanel(st, false);
             }
         }
-        return false;
     }
 
     @Override
     boolean onMenuOpened(final int featureId, Menu menu) {
-        if (featureId == FEATURE_ACTION_BAR) {
+        if (featureId == FEATURE_SUPPORT_ACTION_BAR) {
             ActionBar ab = getSupportActionBar();
             if (ab != null) {
                 ab.dispatchMenuVisibilityChanged(true);
@@ -665,6 +665,8 @@
                     mActionModeView = new ActionBarContextView(actionBarContext);
                     mActionModePopup = new PopupWindow(actionBarContext, null,
                             R.attr.actionModePopupWindowStyle);
+                    PopupWindowCompat.setWindowLayoutType(mActionModePopup,
+                            WindowManager.LayoutParams.TYPE_APPLICATION);
                     mActionModePopup.setContentView(mActionModeView);
                     mActionModePopup.setWidth(ViewGroup.LayoutParams.MATCH_PARENT);
 
@@ -1016,7 +1018,7 @@
                     // forget it. This is a lingering event that no longer matters.
                     if (st.menu != null && !st.refreshMenuContent &&
                             cb.onPreparePanel(FEATURE_OPTIONS_PANEL, st.createdPanelView, st.menu)) {
-                        cb.onMenuOpened(FEATURE_ACTION_BAR, st.menu);
+                        cb.onMenuOpened(FEATURE_SUPPORT_ACTION_BAR, st.menu);
                         mDecorContentParent.showOverflowMenu();
                     }
                 }
@@ -1024,7 +1026,7 @@
                 mDecorContentParent.hideOverflowMenu();
                 if (!isDestroyed()) {
                     final PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, true);
-                    cb.onPanelClosed(FEATURE_ACTION_BAR, st.menu);
+                    cb.onPanelClosed(FEATURE_SUPPORT_ACTION_BAR, st.menu);
                 }
             }
             return;
@@ -1042,7 +1044,7 @@
         Context context = mContext;
 
         // If we have an action bar, initialize the menu with the right theme.
-        if ((st.featureId == FEATURE_OPTIONS_PANEL || st.featureId == FEATURE_ACTION_BAR) &&
+        if ((st.featureId == FEATURE_OPTIONS_PANEL || st.featureId == FEATURE_SUPPORT_ACTION_BAR) &&
                 mDecorContentParent != null) {
             final TypedValue outValue = new TypedValue();
             final Resources.Theme baseTheme = context.getTheme();
@@ -1124,7 +1126,7 @@
         }
 
         final boolean isActionBarMenu =
-                (st.featureId == FEATURE_OPTIONS_PANEL || st.featureId == FEATURE_ACTION_BAR);
+                (st.featureId == FEATURE_OPTIONS_PANEL || st.featureId == FEATURE_SUPPORT_ACTION_BAR);
 
         if (isActionBarMenu && mDecorContentParent != null) {
             // Enforce ordering guarantees around events so that the action bar never
@@ -1215,7 +1217,7 @@
         mDecorContentParent.dismissPopups();
         Window.Callback cb = getWindowCallback();
         if (cb != null && !isDestroyed()) {
-            cb.onPanelClosed(FEATURE_ACTION_BAR, menu);
+            cb.onPanelClosed(FEATURE_SUPPORT_ACTION_BAR, menu);
         }
         mClosingActionMenu = false;
     }
@@ -1430,7 +1432,7 @@
         st.refreshDecorView = true;
 
         // Prepare the options panel if we have an action bar
-        if ((featureId == FEATURE_ACTION_BAR || featureId == FEATURE_OPTIONS_PANEL)
+        if ((featureId == FEATURE_SUPPORT_ACTION_BAR || featureId == FEATURE_OPTIONS_PANEL)
                 && mDecorContentParent != null) {
             st = getPanelState(Window.FEATURE_OPTIONS_PANEL, false);
             if (st != null) {
@@ -1523,6 +1525,20 @@
         }
     }
 
+    private int sanitizeWindowFeatureId(int featureId) {
+        if (featureId == WindowCompat.FEATURE_ACTION_BAR) {
+            Log.i(TAG, "You should now use the AppCompatDelegate.FEATURE_SUPPORT_ACTION_BAR"
+                    + " id when requesting this feature.");
+            return FEATURE_SUPPORT_ACTION_BAR;
+        } else if (featureId == WindowCompat.FEATURE_ACTION_BAR_OVERLAY) {
+            Log.i(TAG, "You should now use the AppCompatDelegate.FEATURE_SUPPORT_ACTION_BAR_OVERLAY"
+                    + " id when requesting this feature.");
+            return FEATURE_SUPPORT_ACTION_BAR_OVERLAY;
+        }
+        // Else we'll just return the original id
+        return featureId;
+    }
+
     ViewGroup getSubDecor() {
         return mSubDecor;
     }
@@ -1593,7 +1609,7 @@
             if (subMenu == null && mHasActionBar) {
                 Window.Callback cb = getWindowCallback();
                 if (cb != null && !isDestroyed()) {
-                    cb.onMenuOpened(FEATURE_ACTION_BAR, subMenu);
+                    cb.onMenuOpened(FEATURE_SUPPORT_ACTION_BAR, subMenu);
                 }
             }
             return true;
@@ -1605,7 +1621,7 @@
         public boolean onOpenSubMenu(MenuBuilder subMenu) {
             Window.Callback cb = getWindowCallback();
             if (cb != null) {
-                cb.onMenuOpened(FEATURE_ACTION_BAR, subMenu);
+                cb.onMenuOpened(FEATURE_SUPPORT_ACTION_BAR, subMenu);
             }
             return true;
         }
diff --git a/v7/appcompat/src/android/support/v7/app/AppCompatDialog.java b/v7/appcompat/src/android/support/v7/app/AppCompatDialog.java
index 11688e6..5f13992 100644
--- a/v7/appcompat/src/android/support/v7/app/AppCompatDialog.java
+++ b/v7/appcompat/src/android/support/v7/app/AppCompatDialog.java
@@ -46,6 +46,9 @@
         // To workaround this, we call onCreate(null) in the ctor, and then again as usual in
         // onCreate().
         getDelegate().onCreate(null);
+
+        // Apply AppCompat's DayNight resources if needed
+        getDelegate().applyDayNight();
     }
 
     protected AppCompatDialog(Context context, boolean cancelable,
diff --git a/v7/appcompat/src/android/support/v7/app/AppCompatDialogFragment.java b/v7/appcompat/src/android/support/v7/app/AppCompatDialogFragment.java
new file mode 100644
index 0000000..3051e49
--- /dev/null
+++ b/v7/appcompat/src/android/support/v7/app/AppCompatDialogFragment.java
@@ -0,0 +1,61 @@
+/*
+ * 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.v7.app;
+
+
+import android.app.Dialog;
+import android.os.Bundle;
+import android.support.v4.app.DialogFragment;
+import android.view.Window;
+import android.view.WindowManager;
+
+/**
+ * A special version of {@link DialogFragment} which uses an {@link AppCompatDialog} in place of a
+ * platform-styled dialog.
+ *
+ * @see DialogFragment
+ */
+public class AppCompatDialogFragment extends DialogFragment {
+
+    @Override
+    public Dialog onCreateDialog(Bundle savedInstanceState) {
+        return new AppCompatDialog(getActivity(), getTheme());
+    }
+
+    /** @hide */
+    @Override
+    public void setupDialog(Dialog dialog, int style) {
+        if (dialog instanceof AppCompatDialog) {
+            // If the dialog is an AppCompatDialog, we'll handle it
+            AppCompatDialog acd = (AppCompatDialog) dialog;
+            switch (style) {
+                case STYLE_NO_INPUT:
+                    dialog.getWindow().addFlags(
+                            WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
+                                    WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
+                    // fall through...
+                case STYLE_NO_FRAME:
+                case STYLE_NO_TITLE:
+                    acd.supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
+            }
+        } else {
+            // Else, just let super handle it
+            super.setupDialog(dialog, style);
+        }
+    }
+
+}
diff --git a/v7/appcompat/src/android/support/v7/app/TwilightCalculator.java b/v7/appcompat/src/android/support/v7/app/TwilightCalculator.java
new file mode 100644
index 0000000..6015e12
--- /dev/null
+++ b/v7/appcompat/src/android/support/v7/app/TwilightCalculator.java
@@ -0,0 +1,137 @@
+/*
+ * 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.v7.app;
+
+import android.text.format.DateUtils;
+
+/**
+ * Imported from frameworks/base/services/core/java/com/android/server/TwilightCalculator.java
+ *
+ * <p>Calculates the sunrise and sunsets times for a given location.</p>
+ */
+class TwilightCalculator {
+
+    private static TwilightCalculator sInstance;
+
+    static TwilightCalculator getInstance() {
+        if (sInstance == null) {
+            sInstance = new TwilightCalculator();
+        }
+        return sInstance;
+    }
+
+    /** Value of {@link #state} if it is currently day */
+    public static final int DAY = 0;
+
+    /** Value of {@link #state} if it is currently night */
+    public static final int NIGHT = 1;
+
+    private static final float DEGREES_TO_RADIANS = (float) (Math.PI / 180.0f);
+
+    // element for calculating solar transit.
+    private static final float J0 = 0.0009f;
+
+    // correction for civil twilight
+    private static final float ALTIDUTE_CORRECTION_CIVIL_TWILIGHT = -0.104719755f;
+
+    // coefficients for calculating Equation of Center.
+    private static final float C1 = 0.0334196f;
+    private static final float C2 = 0.000349066f;
+    private static final float C3 = 0.000005236f;
+
+    private static final float OBLIQUITY = 0.40927971f;
+
+    // Java time on Jan 1, 2000 12:00 UTC.
+    private static final long UTC_2000 = 946728000000L;
+
+    /**
+     * Time of sunset (civil twilight) in milliseconds or -1 in the case the day
+     * or night never ends.
+     */
+    public long sunset;
+
+    /**
+     * Time of sunrise (civil twilight) in milliseconds or -1 in the case the
+     * day or night never ends.
+     */
+    public long sunrise;
+
+    /**
+     * Current state
+     */
+    public int state;
+
+    /**
+     * calculates the civil twilight bases on time and geo-coordinates.
+     *
+     * @param time time in milliseconds.
+     * @param latiude latitude in degrees.
+     * @param longitude latitude in degrees.
+     */
+    public void calculateTwilight(long time, double latiude, double longitude) {
+        final float daysSince2000 = (float) (time - UTC_2000) / DateUtils.DAY_IN_MILLIS;
+
+        // mean anomaly
+        final float meanAnomaly = 6.240059968f + daysSince2000 * 0.01720197f;
+
+        // true anomaly
+        final double trueAnomaly = meanAnomaly + C1 * Math.sin(meanAnomaly) + C2
+                * Math.sin(2 * meanAnomaly) + C3 * Math.sin(3 * meanAnomaly);
+
+        // ecliptic longitude
+        final double solarLng = trueAnomaly + 1.796593063d + Math.PI;
+
+        // solar transit in days since 2000
+        final double arcLongitude = -longitude / 360;
+        float n = Math.round(daysSince2000 - J0 - arcLongitude);
+        double solarTransitJ2000 = n + J0 + arcLongitude + 0.0053d * Math.sin(meanAnomaly)
+                + -0.0069d * Math.sin(2 * solarLng);
+
+        // declination of sun
+        double solarDec = Math.asin(Math.sin(solarLng) * Math.sin(OBLIQUITY));
+
+        final double latRad = latiude * DEGREES_TO_RADIANS;
+
+        double cosHourAngle = (Math.sin(ALTIDUTE_CORRECTION_CIVIL_TWILIGHT) - Math.sin(latRad)
+                * Math.sin(solarDec)) / (Math.cos(latRad) * Math.cos(solarDec));
+        // The day or night never ends for the given date and location, if this value is out of
+        // range.
+        if (cosHourAngle >= 1) {
+            state = NIGHT;
+            sunset = -1;
+            sunrise = -1;
+            return;
+        } else if (cosHourAngle <= -1) {
+            state = DAY;
+            sunset = -1;
+            sunrise = -1;
+            return;
+        }
+
+        float hourAngle = (float) (Math.acos(cosHourAngle) / (2 * Math.PI));
+
+        sunset = Math.round((solarTransitJ2000 + hourAngle) * DateUtils.DAY_IN_MILLIS) + UTC_2000;
+        sunrise = Math.round((solarTransitJ2000 - hourAngle) * DateUtils.DAY_IN_MILLIS) + UTC_2000;
+
+        if (sunrise < time && sunset > time) {
+            state = DAY;
+        } else {
+            state = NIGHT;
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/v7/appcompat/src/android/support/v7/app/TwilightManager.java b/v7/appcompat/src/android/support/v7/app/TwilightManager.java
new file mode 100644
index 0000000..5872330
--- /dev/null
+++ b/v7/appcompat/src/android/support/v7/app/TwilightManager.java
@@ -0,0 +1,171 @@
+/*
+ * 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.v7.app;
+
+import android.content.Context;
+import android.location.Location;
+import android.location.LocationManager;
+import android.support.annotation.NonNull;
+import android.text.format.DateUtils;
+import android.util.Log;
+
+import java.util.Calendar;
+
+/**
+ * Class which managing whether we are in the night or not.
+ */
+class TwilightManager {
+
+    private static final String TAG = "TwilightManager";
+
+    private static final int SUNRISE = 6; // 6am
+    private static final int SUNSET = 22; // 10pm
+
+    private static final TwilightState sTwilightState = new TwilightState();
+
+    private final Context mContext;
+    private final LocationManager mLocationManager;
+
+    TwilightManager(Context context) {
+        mContext = context;
+        mLocationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
+    }
+
+    /**
+     * Returns true we are currently in the 'night'.
+     *
+     * @return true if we are at night, false if the day.
+     */
+    boolean isNight() {
+        final TwilightState state = sTwilightState;
+
+        if (isStateValid(state)) {
+            // If the current twilight state is still valid, use it
+            return state.isNight;
+        }
+
+        // Else, we will try and grab the last known location
+        final Location location = getLastKnownLocation();
+        if (location != null) {
+            updateState(location);
+            return state.isNight;
+        }
+
+        Log.i(TAG, "Could not get last known location. This is probably because the app does not"
+                + " have any location permissions. Falling back to hardcoded"
+                + " sunrise/sunset values.");
+
+        // If we don't have a location, we'll use our hardcoded sunrise/sunset values.
+        // These aren't great, but it's better than nothing.
+        Calendar calendar = Calendar.getInstance();
+        final int hour = calendar.get(Calendar.HOUR_OF_DAY);
+        return hour < SUNRISE || hour >= SUNSET;
+    }
+
+    private Location getLastKnownLocation() {
+        Location coarseLocation = getLastKnownLocationForProvider(LocationManager.NETWORK_PROVIDER);
+        Location fineLocation = getLastKnownLocationForProvider(LocationManager.GPS_PROVIDER);
+
+        if (coarseLocation != null && fineLocation != null) {
+            // If we have both a fine and coarse location, use the latest
+            if (fineLocation.getTime() > coarseLocation.getTime()) {
+                return fineLocation;
+            } else {
+                return coarseLocation;
+            }
+        } else {
+            // Else, return the non-null one (if there is one)
+            return fineLocation != null ? fineLocation : coarseLocation;
+        }
+    }
+
+    private Location getLastKnownLocationForProvider(String provider) {
+        if (mLocationManager != null) {
+            try {
+                if (mLocationManager.isProviderEnabled(provider)) {
+                    return mLocationManager.getLastKnownLocation(provider);
+                }
+            } catch (Exception e) {
+                Log.d(TAG, "Failed to get last known location", e);
+            }
+        }
+        return null;
+    }
+
+    private boolean isStateValid(TwilightState state) {
+        return state != null && state.nextUpdate > System.currentTimeMillis();
+    }
+
+    private void updateState(@NonNull Location location) {
+        final TwilightState state = sTwilightState;
+        final long now = System.currentTimeMillis();
+        final TwilightCalculator calculator = TwilightCalculator.getInstance();
+
+        // calculate yesterday's twilight
+        calculator.calculateTwilight(now - DateUtils.DAY_IN_MILLIS,
+                location.getLatitude(), location.getLongitude());
+        final long yesterdaySunset = calculator.sunset;
+
+        // calculate today's twilight
+        calculator.calculateTwilight(now, location.getLatitude(), location.getLongitude());
+        final boolean isNight = (calculator.state == TwilightCalculator.NIGHT);
+        final long todaySunrise = calculator.sunrise;
+        final long todaySunset = calculator.sunset;
+
+        // calculate tomorrow's twilight
+        calculator.calculateTwilight(now + DateUtils.DAY_IN_MILLIS,
+                location.getLatitude(), location.getLongitude());
+        final long tomorrowSunrise = calculator.sunrise;
+
+        // Set next update
+        long nextUpdate = 0;
+        if (todaySunrise == -1 || todaySunset == -1) {
+            // In the case the day or night never ends the update is scheduled 12 hours later.
+            nextUpdate = now + 12 * DateUtils.HOUR_IN_MILLIS;
+        } else {
+            if (now > todaySunset) {
+                nextUpdate += tomorrowSunrise;
+            } else if (now > todaySunrise) {
+                nextUpdate += todaySunset;
+            } else {
+                nextUpdate += todaySunrise;
+            }
+            // add some extra time to be on the safe side.
+            nextUpdate += DateUtils.MINUTE_IN_MILLIS;
+        }
+
+        // Update the twilight state
+        state.isNight = isNight;
+        state.yesterdaySunset = yesterdaySunset;
+        state.todaySunrise = todaySunrise;
+        state.todaySunset = todaySunset;
+        state.tomorrowSunrise = tomorrowSunrise;
+        state.nextUpdate = nextUpdate;
+    }
+
+    /**
+     * Describes whether it is day or night.
+     */
+    private static class TwilightState {
+        boolean isNight;
+        long yesterdaySunset;
+        long todaySunrise;
+        long todaySunset;
+        long tomorrowSunrise;
+        long nextUpdate;
+    }
+}
diff --git a/v7/appcompat/src/android/support/v7/graphics/drawable/DrawableUtils.java b/v7/appcompat/src/android/support/v7/graphics/drawable/DrawableUtils.java
new file mode 100644
index 0000000..ffe68d5
--- /dev/null
+++ b/v7/appcompat/src/android/support/v7/graphics/drawable/DrawableUtils.java
@@ -0,0 +1,40 @@
+/*
+ * 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.v7.graphics.drawable;
+
+import android.graphics.PorterDuff;
+import android.os.Build;
+
+/**
+ * @hide
+ */
+public class DrawableUtils {
+
+    public static PorterDuff.Mode parseTintMode(int value, PorterDuff.Mode defaultMode) {
+        switch (value) {
+            case 3: return PorterDuff.Mode.SRC_OVER;
+            case 5: return PorterDuff.Mode.SRC_IN;
+            case 9: return PorterDuff.Mode.SRC_ATOP;
+            case 14: return PorterDuff.Mode.MULTIPLY;
+            case 15: return PorterDuff.Mode.SCREEN;
+            case 16: return Build.VERSION.SDK_INT >= 11 ? PorterDuff.Mode.valueOf("ADD")
+                    : defaultMode;
+            default: return defaultMode;
+        }
+    }
+
+}
diff --git a/v7/appcompat/src/android/support/v7/internal/app/ToolbarActionBar.java b/v7/appcompat/src/android/support/v7/internal/app/ToolbarActionBar.java
index 1781015..c8ef657 100644
--- a/v7/appcompat/src/android/support/v7/internal/app/ToolbarActionBar.java
+++ b/v7/appcompat/src/android/support/v7/internal/app/ToolbarActionBar.java
@@ -22,8 +22,8 @@
 import android.graphics.drawable.Drawable;
 import android.support.annotation.Nullable;
 import android.support.v4.view.ViewCompat;
-import android.support.v4.view.WindowCompat;
 import android.support.v7.app.ActionBar;
+import android.support.v7.app.AppCompatDelegate;
 import android.support.v7.appcompat.R;
 import android.support.v7.internal.view.WindowCallbackWrapper;
 import android.support.v7.internal.view.menu.ListMenuPresenter;
@@ -92,7 +92,9 @@
 
     @Override
     public void setCustomView(View view, LayoutParams layoutParams) {
-        view.setLayoutParams(layoutParams);
+        if (view != null) {
+            view.setLayoutParams(layoutParams);
+        }
         mDecorToolbar.setCustomView(view);
     }
 
@@ -577,7 +579,7 @@
         @Override
         public boolean onOpenSubMenu(MenuBuilder subMenu) {
             if (mWindowCallback != null) {
-                mWindowCallback.onMenuOpened(WindowCompat.FEATURE_ACTION_BAR, subMenu);
+                mWindowCallback.onMenuOpened(AppCompatDelegate.FEATURE_SUPPORT_ACTION_BAR, subMenu);
                 return true;
             }
             return false;
@@ -592,7 +594,7 @@
             mClosingActionMenu = true;
             mDecorToolbar.dismissPopupMenus();
             if (mWindowCallback != null) {
-                mWindowCallback.onPanelClosed(WindowCompat.FEATURE_ACTION_BAR, menu);
+                mWindowCallback.onPanelClosed(AppCompatDelegate.FEATURE_SUPPORT_ACTION_BAR, menu);
             }
             mClosingActionMenu = false;
         }
@@ -626,10 +628,10 @@
         public void onMenuModeChange(MenuBuilder menu) {
             if (mWindowCallback != null) {
                 if (mDecorToolbar.isOverflowMenuShowing()) {
-                    mWindowCallback.onPanelClosed(WindowCompat.FEATURE_ACTION_BAR, menu);
+                    mWindowCallback.onPanelClosed(AppCompatDelegate.FEATURE_SUPPORT_ACTION_BAR, menu);
                 } else if (mWindowCallback.onPreparePanel(Window.FEATURE_OPTIONS_PANEL,
                         null, menu)) {
-                    mWindowCallback.onMenuOpened(WindowCompat.FEATURE_ACTION_BAR, menu);
+                    mWindowCallback.onMenuOpened(AppCompatDelegate.FEATURE_SUPPORT_ACTION_BAR, menu);
                 }
             }
         }
diff --git a/v7/appcompat/src/android/support/v7/internal/app/WindowDecorActionBar.java b/v7/appcompat/src/android/support/v7/internal/app/WindowDecorActionBar.java
index 2557d06..e76f658 100644
--- a/v7/appcompat/src/android/support/v7/internal/app/WindowDecorActionBar.java
+++ b/v7/appcompat/src/android/support/v7/internal/app/WindowDecorActionBar.java
@@ -34,8 +34,8 @@
 import android.support.v7.app.ActionBar;
 import android.support.v7.appcompat.R;
 import android.support.v7.internal.view.ActionBarPolicy;
-import android.support.v7.internal.view.ViewPropertyAnimatorCompatSet;
 import android.support.v7.internal.view.SupportMenuInflater;
+import android.support.v7.internal.view.ViewPropertyAnimatorCompatSet;
 import android.support.v7.internal.view.menu.MenuBuilder;
 import android.support.v7.internal.view.menu.MenuPopupHelper;
 import android.support.v7.internal.view.menu.SubMenuBuilder;
@@ -43,8 +43,8 @@
 import android.support.v7.internal.widget.ActionBarContextView;
 import android.support.v7.internal.widget.ActionBarOverlayLayout;
 import android.support.v7.internal.widget.DecorToolbar;
-import android.support.v7.internal.widget.TintManager;
 import android.support.v7.internal.widget.ScrollingTabContainerView;
+import android.support.v7.internal.widget.TintManager;
 import android.support.v7.view.ActionMode;
 import android.support.v7.widget.Toolbar;
 import android.util.TypedValue;
@@ -57,7 +57,10 @@
 import android.view.ViewParent;
 import android.view.Window;
 import android.view.accessibility.AccessibilityEvent;
+import android.view.animation.AccelerateInterpolator;
 import android.view.animation.AnimationUtils;
+import android.view.animation.DecelerateInterpolator;
+import android.view.animation.Interpolator;
 import android.widget.SpinnerAdapter;
 
 import java.lang.ref.WeakReference;
@@ -66,9 +69,6 @@
 /**
  * WindowDecorActionBar is the ActionBar implementation used
  * by devices of all screen sizes as part of the window decor layout.
- * If it detects a compatible decor, it will split contextual modes
- * across both the ActionBarView at the top of the screen and
- * a horizontal LinearLayout at the bottom which is normally hidden.
  *
  * @hide
  */
@@ -76,6 +76,9 @@
         ActionBarOverlayLayout.ActionBarVisibilityCallback {
     private static final String TAG = "WindowDecorActionBar";
 
+    private static final Interpolator sHideInterpolator = new AccelerateInterpolator();
+    private static final Interpolator sShowInterpolator = new DecelerateInterpolator();
+
     /**
      * Only allow show/hide animations on ICS+, as that is what ViewPropertyAnimatorCompat supports
      */
@@ -90,7 +93,6 @@
     private ActionBarContainer mContainerView;
     private DecorToolbar mDecorToolbar;
     private ActionBarContextView mContextView;
-    private ActionBarContainer mSplitView;
     private View mContentView;
     private ScrollingTabContainerView mTabScrollView;
 
@@ -109,12 +111,12 @@
     private ArrayList<OnMenuVisibilityListener> mMenuVisibilityListeners =
             new ArrayList<OnMenuVisibilityListener>();
 
-    private static final int CONTEXT_DISPLAY_NORMAL = 0;
-    private static final int CONTEXT_DISPLAY_SPLIT = 1;
-
     private static final int INVALID_POSITION = -1;
 
-    private int mContextDisplayMode;
+    // The fade duration for toolbar and action bar when entering/exiting action mode.
+    private static final long FADE_OUT_DURATION_MS = 100;
+    private static final long FADE_IN_DURATION_MS = 200;
+
     private boolean mHasEmbeddedTabs;
 
     private int mCurWindowVisibility = View.VISIBLE;
@@ -139,9 +141,6 @@
                 ViewCompat.setTranslationY(mContentView, 0f);
                 ViewCompat.setTranslationY(mContainerView, 0f);
             }
-            if (mSplitView != null && mContextDisplayMode == CONTEXT_DISPLAY_SPLIT) {
-                mSplitView.setVisibility(View.GONE);
-            }
             mContainerView.setVisibility(View.GONE);
             mContainerView.setTransitioning(false);
             mCurrentShowAnim = null;
@@ -204,16 +203,12 @@
         mContainerView = (ActionBarContainer) decor.findViewById(
                 R.id.action_bar_container);
 
-         mSplitView = (ActionBarContainer) decor.findViewById(R.id.split_action_bar);
-
         if (mDecorToolbar == null || mContextView == null || mContainerView == null) {
             throw new IllegalStateException(getClass().getSimpleName() + " can only be used " +
                     "with a compatible window decor layout");
         }
 
         mContext = mDecorToolbar.getContext();
-        mContextDisplayMode = mDecorToolbar.isSplit() ?
-                CONTEXT_DISPLAY_SPLIT : CONTEXT_DISPLAY_NORMAL;
 
         // This was initially read from the action bar style
         final int current = mDecorToolbar.getDisplayOptions();
@@ -253,9 +248,6 @@
     @Override
     public void setElevation(float elevation) {
         ViewCompat.setElevation(mContainerView, elevation);
-        if (mSplitView != null) {
-            ViewCompat.setElevation(mSplitView, elevation);
-        }
     }
 
     @Override
@@ -474,9 +466,7 @@
     }
 
     public void setSplitBackgroundDrawable(Drawable d) {
-        if (mSplitView != null) {
-            mSplitView.setSplitBackground(d);
-        }
+        // no-op. We don't support split action bars
     }
 
     public View getCustomView() {
@@ -511,15 +501,6 @@
             mode.invalidate();
             mContextView.initForMode(mode);
             animateToMode(true);
-            if (mSplitView != null && mContextDisplayMode == CONTEXT_DISPLAY_SPLIT) {
-                // TODO animate this
-                if (mSplitView.getVisibility() != View.VISIBLE) {
-                    mSplitView.setVisibility(View.VISIBLE);
-                    if (mOverlayLayout != null) {
-                        ViewCompat.requestApplyInsets(mOverlayLayout);
-                    }
-                }
-            }
             mContextView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
             mActionMode = mode;
             return mode;
@@ -793,13 +774,7 @@
                 ViewCompat.setTranslationY(mContentView, startingY);
                 anim.play(ViewCompat.animate(mContentView).translationY(0f));
             }
-            if (mSplitView != null && mContextDisplayMode == CONTEXT_DISPLAY_SPLIT) {
-                ViewCompat.setTranslationY(mSplitView, mSplitView.getHeight());
-                mSplitView.setVisibility(View.VISIBLE);
-                anim.play(ViewCompat.animate(mSplitView).translationY(0f));
-            }
-            anim.setInterpolator(AnimationUtils.loadInterpolator(mContext,
-                    android.R.anim.decelerate_interpolator));
+            anim.setInterpolator(sShowInterpolator);
             anim.setDuration(250);
             // If this is being shown from the system, add a small delay.
             // This is because we will also be animating in the status bar,
@@ -817,11 +792,6 @@
             if (mContentAnimations && mContentView != null) {
                 ViewCompat.setTranslationY(mContentView, 0);
             }
-            if (mSplitView != null && mContextDisplayMode == CONTEXT_DISPLAY_SPLIT) {
-                ViewCompat.setAlpha(mSplitView, 1f);
-                ViewCompat.setTranslationY(mSplitView, 0);
-                mSplitView.setVisibility(View.VISIBLE);
-            }
             mShowListener.onAnimationEnd(null);
         }
         if (mOverlayLayout != null) {
@@ -851,12 +821,7 @@
             if (mContentAnimations && mContentView != null) {
                 anim.play(ViewCompat.animate(mContentView).translationY(endingY));
             }
-            if (mSplitView != null && mSplitView.getVisibility() == View.VISIBLE) {
-                ViewCompat.setAlpha(mSplitView, 1f);
-                anim.play(ViewCompat.animate(mSplitView).translationY(mSplitView.getHeight()));
-            }
-            anim.setInterpolator(AnimationUtils.loadInterpolator(mContext,
-                    android.R.anim.accelerate_interpolator));
+            anim.setInterpolator(sHideInterpolator);
             anim.setDuration(250);
             anim.setListener(mHideListener);
             mCurrentShowAnim = anim;
@@ -879,8 +844,21 @@
             hideForActionMode();
         }
 
-        mDecorToolbar.animateToVisibility(toActionMode ? View.GONE : View.VISIBLE);
-        mContextView.animateToVisibility(toActionMode ? View.VISIBLE : View.GONE);
+        ViewPropertyAnimatorCompat fadeIn, fadeOut;
+        if (toActionMode) {
+            fadeOut = mDecorToolbar.setupAnimatorToVisibility(View.GONE,
+                    FADE_OUT_DURATION_MS);
+            fadeIn = mContextView.setupAnimatorToVisibility(View.VISIBLE,
+                    FADE_IN_DURATION_MS);
+        } else {
+            fadeIn = mDecorToolbar.setupAnimatorToVisibility(View.VISIBLE,
+                    FADE_IN_DURATION_MS);
+            fadeOut = mContextView.setupAnimatorToVisibility(View.GONE,
+                    FADE_OUT_DURATION_MS);
+        }
+        ViewPropertyAnimatorCompatSet set = new ViewPropertyAnimatorCompatSet();
+        set.playSequentially(fadeOut, fadeIn);
+        set.start();
         // mTabScrollView's visibility is not affected by action mode.
     }
 
diff --git a/v7/appcompat/src/android/support/v7/internal/view/SupportMenuInflater.java b/v7/appcompat/src/android/support/v7/internal/view/SupportMenuInflater.java
index 84a07da..7bc3978 100644
--- a/v7/appcompat/src/android/support/v7/internal/view/SupportMenuInflater.java
+++ b/v7/appcompat/src/android/support/v7/internal/view/SupportMenuInflater.java
@@ -496,6 +496,7 @@
             try {
                 Class<?> clazz = mContext.getClassLoader().loadClass(className);
                 Constructor<?> constructor = clazz.getConstructor(constructorSignature);
+                constructor.setAccessible(true);
                 return (T) constructor.newInstance(arguments);
             } catch (Exception e) {
                 Log.w(LOG_TAG, "Cannot instantiate class: " + className, e);
diff --git a/v7/appcompat/src/android/support/v7/internal/view/ViewPropertyAnimatorCompatSet.java b/v7/appcompat/src/android/support/v7/internal/view/ViewPropertyAnimatorCompatSet.java
index 457e1b1..ec1d567 100644
--- a/v7/appcompat/src/android/support/v7/internal/view/ViewPropertyAnimatorCompatSet.java
+++ b/v7/appcompat/src/android/support/v7/internal/view/ViewPropertyAnimatorCompatSet.java
@@ -51,6 +51,14 @@
         return this;
     }
 
+    public ViewPropertyAnimatorCompatSet playSequentially(ViewPropertyAnimatorCompat anim1,
+            ViewPropertyAnimatorCompat anim2) {
+        mAnimators.add(anim1);
+        anim2.setStartDelay(anim1.getDuration());
+        mAnimators.add(anim2);
+        return this;
+    }
+
     public void start() {
         if (mIsStarted) return;
         for (ViewPropertyAnimatorCompat animator : mAnimators) {
diff --git a/v7/appcompat/src/android/support/v7/internal/view/WindowCallbackWrapper.java b/v7/appcompat/src/android/support/v7/internal/view/WindowCallbackWrapper.java
index d799d00..900d304 100644
--- a/v7/appcompat/src/android/support/v7/internal/view/WindowCallbackWrapper.java
+++ b/v7/appcompat/src/android/support/v7/internal/view/WindowCallbackWrapper.java
@@ -21,6 +21,7 @@
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.MotionEvent;
+import android.view.SearchEvent;
 import android.view.View;
 import android.view.Window;
 import android.view.WindowManager;
@@ -130,6 +131,11 @@
     }
 
     @Override
+    public boolean onSearchRequested(SearchEvent searchEvent) {
+        return mWrapped.onSearchRequested(searchEvent);
+    }
+
+    @Override
     public boolean onSearchRequested() {
         return mWrapped.onSearchRequested();
     }
@@ -140,6 +146,11 @@
     }
 
     @Override
+    public ActionMode onWindowStartingActionMode(ActionMode.Callback callback, int type) {
+        return mWrapped.onWindowStartingActionMode(callback, type);
+    }
+
+    @Override
     public void onActionModeStarted(ActionMode mode) {
         mWrapped.onActionModeStarted(mode);
     }
diff --git a/v7/appcompat/src/android/support/v7/internal/view/menu/MenuPopupHelper.java b/v7/appcompat/src/android/support/v7/internal/view/menu/MenuPopupHelper.java
index af7deef..bdcc79a 100644
--- a/v7/appcompat/src/android/support/v7/internal/view/menu/MenuPopupHelper.java
+++ b/v7/appcompat/src/android/support/v7/internal/view/menu/MenuPopupHelper.java
@@ -121,6 +121,10 @@
         mDropDownGravity = gravity;
     }
 
+    public int getGravity() {
+        return mDropDownGravity;
+    }
+
     public void show() {
         if (!tryShow()) {
             throw new IllegalStateException("MenuPopupHelper cannot be used without an anchor");
diff --git a/v7/appcompat/src/android/support/v7/internal/widget/AbsActionBarView.java b/v7/appcompat/src/android/support/v7/internal/widget/AbsActionBarView.java
index 0d06065..a3518f5 100644
--- a/v7/appcompat/src/android/support/v7/internal/widget/AbsActionBarView.java
+++ b/v7/appcompat/src/android/support/v7/internal/widget/AbsActionBarView.java
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.support.v7.internal.widget;
 
 import android.content.Context;
@@ -23,7 +24,6 @@
 import android.support.v4.view.ViewPropertyAnimatorCompat;
 import android.support.v4.view.ViewPropertyAnimatorListener;
 import android.support.v7.appcompat.R;
-import android.support.v7.internal.view.ViewPropertyAnimatorCompatSet;
 import android.support.v7.widget.ActionMenuPresenter;
 import android.support.v7.widget.ActionMenuView;
 import android.util.AttributeSet;
@@ -31,12 +31,8 @@
 import android.view.ContextThemeWrapper;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.animation.DecelerateInterpolator;
-import android.view.animation.Interpolator;
 
 abstract class AbsActionBarView extends ViewGroup {
-    private static final Interpolator sAlphaInterpolator = new DecelerateInterpolator();
-
     private static final int FADE_DURATION = 200;
 
     protected final VisibilityAnimListener mVisAnimListener = new VisibilityAnimListener();
@@ -46,9 +42,6 @@
 
     protected ActionMenuView mMenuView;
     protected ActionMenuPresenter mActionMenuPresenter;
-    protected ViewGroup mSplitView;
-    protected boolean mSplitActionBar;
-    protected boolean mSplitWhenNarrow;
     protected int mContentHeight;
 
     protected ViewPropertyAnimatorCompat mVisibilityAnim;
@@ -91,22 +84,6 @@
         }
     }
 
-    /**
-     * Sets whether the bar should be split right now, no questions asked.
-     * @param split true if the bar should split
-     */
-    public void setSplitToolbar(boolean split) {
-        mSplitActionBar = split;
-    }
-
-    /**
-     * Sets whether the bar should split if we enter a narrow screen configuration.
-     * @param splitWhenNarrow true if the bar should check to split after a config change
-     */
-    public void setSplitWhenNarrow(boolean splitWhenNarrow) {
-        mSplitWhenNarrow = splitWhenNarrow;
-    }
-
     public void setContentHeight(int height) {
         mContentHeight = height;
         requestLayout();
@@ -116,10 +93,6 @@
         return mContentHeight;
     }
 
-    public void setSplitView(ViewGroup splitView) {
-        mSplitView = splitView;
-    }
-
     /**
      * @return Current visibility or if animating, the visibility being animated to.
      */
@@ -130,46 +103,39 @@
         return getVisibility();
     }
 
-    public void animateToVisibility(int visibility) {
+    public ViewPropertyAnimatorCompat setupAnimatorToVisibility(int visibility, long duration) {
         if (mVisibilityAnim != null) {
             mVisibilityAnim.cancel();
         }
+
         if (visibility == VISIBLE) {
             if (getVisibility() != VISIBLE) {
                 ViewCompat.setAlpha(this, 0f);
-                if (mSplitView != null && mMenuView != null) {
-                    ViewCompat.setAlpha(mMenuView, 0f);
-                }
             }
             ViewPropertyAnimatorCompat anim = ViewCompat.animate(this).alpha(1f);
-            anim.setDuration(FADE_DURATION);
-            anim.setInterpolator(sAlphaInterpolator);
-            if (mSplitView != null && mMenuView != null) {
-                ViewPropertyAnimatorCompatSet set = new ViewPropertyAnimatorCompatSet();
-                ViewPropertyAnimatorCompat splitAnim = ViewCompat.animate(mMenuView).alpha(1f);
-                splitAnim.setDuration(FADE_DURATION);
-                set.setListener(mVisAnimListener.withFinalVisibility(anim, visibility));
-                set.play(anim).play(splitAnim);
-                set.start();
-            } else {
-                anim.setListener(mVisAnimListener.withFinalVisibility(anim, visibility));
-                anim.start();
-            }
+            anim.setDuration(duration);
+            anim.setListener(mVisAnimListener.withFinalVisibility(anim, visibility));
+            return anim;
         } else {
             ViewPropertyAnimatorCompat anim = ViewCompat.animate(this).alpha(0f);
-            anim.setDuration(FADE_DURATION);
-            anim.setInterpolator(sAlphaInterpolator);
-            if (mSplitView != null && mMenuView != null) {
-                ViewPropertyAnimatorCompatSet set = new ViewPropertyAnimatorCompatSet();
-                ViewPropertyAnimatorCompat splitAnim = ViewCompat.animate(mMenuView).alpha(0f);
-                splitAnim.setDuration(FADE_DURATION);
-                set.setListener(mVisAnimListener.withFinalVisibility(anim, visibility));
-                set.play(anim).play(splitAnim);
-                set.start();
-            } else {
-                anim.setListener(mVisAnimListener.withFinalVisibility(anim, visibility));
-                anim.start();
+            anim.setDuration(duration);
+            anim.setListener(mVisAnimListener.withFinalVisibility(anim, visibility));
+            return anim;
+        }
+    }
+
+    public void animateToVisibility(int visibility) {
+        ViewPropertyAnimatorCompat anim = setupAnimatorToVisibility(visibility, FADE_DURATION);
+        anim.start();
+    }
+
+    @Override
+    public void setVisibility(int visibility) {
+        if (visibility != getVisibility()) {
+            if (mVisibilityAnim != null) {
+                mVisibilityAnim.cancel();
             }
+            super.setVisibility(visibility);
         }
     }
 
@@ -265,7 +231,7 @@
 
         @Override
         public void onAnimationStart(View view) {
-            setVisibility(VISIBLE);
+            AbsActionBarView.super.setVisibility(VISIBLE);
             mCanceled = false;
         }
 
@@ -274,10 +240,7 @@
             if (mCanceled) return;
 
             mVisibilityAnim = null;
-            setVisibility(mFinalVisibility);
-            if (mSplitView != null && mMenuView != null) {
-                mMenuView.setVisibility(mFinalVisibility);
-            }
+            AbsActionBarView.super.setVisibility(mFinalVisibility);
         }
 
         @Override
diff --git a/v7/appcompat/src/android/support/v7/internal/widget/ActionBarContextView.java b/v7/appcompat/src/android/support/v7/internal/widget/ActionBarContextView.java
index 97a44ad..7c5d221 100644
--- a/v7/appcompat/src/android/support/v7/internal/widget/ActionBarContextView.java
+++ b/v7/appcompat/src/android/support/v7/internal/widget/ActionBarContextView.java
@@ -17,32 +17,26 @@
 package android.support.v7.internal.widget;
 
 import android.content.Context;
-import android.content.res.TypedArray;
 import android.graphics.drawable.Drawable;
 import android.os.Build;
-import android.support.v4.view.ViewCompat;
-import android.support.v4.view.ViewPropertyAnimatorCompat;
-import android.support.v4.view.ViewPropertyAnimatorListener;
 import android.support.v7.appcompat.R;
-import android.support.v7.internal.view.ViewPropertyAnimatorCompatSet;
+import android.support.v7.internal.view.menu.MenuBuilder;
 import android.support.v7.view.ActionMode;
 import android.support.v7.widget.ActionMenuPresenter;
 import android.support.v7.widget.ActionMenuView;
-import android.support.v7.internal.view.menu.MenuBuilder;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityEvent;
-import android.view.animation.DecelerateInterpolator;
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
 /**
  * @hide
  */
-public class ActionBarContextView extends AbsActionBarView implements ViewPropertyAnimatorListener {
+public class ActionBarContextView extends AbsActionBarView {
     private static final String TAG = "ActionBarContextView";
 
     private CharSequence mTitle;
@@ -55,18 +49,9 @@
     private TextView mSubtitleView;
     private int mTitleStyleRes;
     private int mSubtitleStyleRes;
-    private Drawable mSplitBackground;
     private boolean mTitleOptional;
     private int mCloseItemLayout;
 
-    private ViewPropertyAnimatorCompatSet mCurrentAnimation;
-    private boolean mAnimateInOnLayout;
-    private int mAnimationMode;
-
-    private static final int ANIMATE_IDLE = 0;
-    private static final int ANIMATE_IN = 1;
-    private static final int ANIMATE_OUT = 2;
-
     public ActionBarContextView(Context context) {
         this(context, null);
     }
@@ -90,9 +75,6 @@
         mContentHeight = a.getLayoutDimension(
                 R.styleable.ActionMode_height, 0);
 
-        mSplitBackground = a.getDrawable(
-                R.styleable.ActionMode_backgroundSplit);
-
         mCloseItemLayout = a.getResourceId(
                 R.styleable.ActionMode_closeItemLayout,
                 R.layout.abc_action_mode_close_item_material);
@@ -109,39 +91,6 @@
         }
     }
 
-    @Override
-    public void setSplitToolbar(boolean split) {
-        if (mSplitActionBar != split) {
-            if (mActionMenuPresenter != null) {
-                // Mode is already active; move everything over and adjust the menu itself.
-                final LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT,
-                        LayoutParams.MATCH_PARENT);
-                if (!split) {
-                    mMenuView = (ActionMenuView) mActionMenuPresenter.getMenuView(this);
-                    mMenuView.setBackgroundDrawable(null);
-                    final ViewGroup oldParent = (ViewGroup) mMenuView.getParent();
-                    if (oldParent != null) oldParent.removeView(mMenuView);
-                    addView(mMenuView, layoutParams);
-                } else {
-                    // Allow full screen width in split mode.
-                    mActionMenuPresenter.setWidthLimit(
-                            getContext().getResources().getDisplayMetrics().widthPixels, true);
-                    // No limit to the item count; use whatever will fit.
-                    mActionMenuPresenter.setItemLimit(Integer.MAX_VALUE);
-                    // Span the whole width
-                    layoutParams.width = LayoutParams.MATCH_PARENT;
-                    layoutParams.height = mContentHeight;
-                    mMenuView = (ActionMenuView) mActionMenuPresenter.getMenuView(this);
-                    mMenuView.setBackgroundDrawable(mSplitBackground);
-                    final ViewGroup oldParent = (ViewGroup) mMenuView.getParent();
-                    if (oldParent != null) oldParent.removeView(mMenuView);
-                    mSplitView.addView(mMenuView, layoutParams);
-                }
-            }
-            super.setSplitToolbar(split);
-        }
-    }
-
     public void setContentHeight(int height) {
         mContentHeight = height;
     }
@@ -151,7 +100,7 @@
             removeView(mCustomView);
         }
         mCustomView = view;
-        if (mTitleLayout != null) {
+        if (view != null && mTitleLayout != null) {
             removeView(mTitleLayout);
             mTitleLayout = null;
         }
@@ -231,62 +180,23 @@
 
         final LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT,
                 LayoutParams.MATCH_PARENT);
-        if (!mSplitActionBar) {
-            menu.addMenuPresenter(mActionMenuPresenter, mPopupContext);
-            mMenuView = (ActionMenuView) mActionMenuPresenter.getMenuView(this);
-            mMenuView.setBackgroundDrawable(null);
-            addView(mMenuView, layoutParams);
-        } else {
-            // Allow full screen width in split mode.
-            mActionMenuPresenter.setWidthLimit(
-                    getContext().getResources().getDisplayMetrics().widthPixels, true);
-            // No limit to the item count; use whatever will fit.
-            mActionMenuPresenter.setItemLimit(Integer.MAX_VALUE);
-            // Span the whole width
-            layoutParams.width = LayoutParams.MATCH_PARENT;
-            layoutParams.height = mContentHeight;
-            menu.addMenuPresenter(mActionMenuPresenter, mPopupContext);
-            mMenuView = (ActionMenuView) mActionMenuPresenter.getMenuView(this);
-            mMenuView.setBackgroundDrawable(mSplitBackground);
-            mSplitView.addView(mMenuView, layoutParams);
-        }
-
-        mAnimateInOnLayout = true;
+        menu.addMenuPresenter(mActionMenuPresenter, mPopupContext);
+        mMenuView = (ActionMenuView) mActionMenuPresenter.getMenuView(this);
+        mMenuView.setBackgroundDrawable(null);
+        addView(mMenuView, layoutParams);
     }
 
     public void closeMode() {
-        if (mAnimationMode == ANIMATE_OUT) {
-            // Called again during close; just finish what we were doing.
-            return;
-        }
         if (mClose == null) {
             killMode();
             return;
         }
-
-        finishAnimation();
-        mAnimationMode = ANIMATE_OUT;
-        mCurrentAnimation = makeOutAnimation();
-        mCurrentAnimation.start();
-    }
-
-    private void finishAnimation() {
-        final ViewPropertyAnimatorCompatSet a = mCurrentAnimation;
-        if (a != null) {
-            mCurrentAnimation = null;
-            a.cancel();
-        }
     }
 
     public void killMode() {
-        finishAnimation();
         removeAllViews();
-        if (mSplitView != null) {
-            mSplitView.removeView(mMenuView);
-        }
         mCustomView = null;
         mMenuView = null;
-        mAnimateInOnLayout = false;
     }
 
     @Override
@@ -405,60 +315,6 @@
         }
     }
 
-    private ViewPropertyAnimatorCompatSet makeInAnimation() {
-        ViewCompat.setTranslationX(mClose, -mClose.getWidth() -
-                ((MarginLayoutParams) mClose.getLayoutParams()).leftMargin);
-        ViewPropertyAnimatorCompat buttonAnimator = ViewCompat.animate(mClose).translationX(0);
-        buttonAnimator.setDuration(200);
-        buttonAnimator.setListener(this);
-        buttonAnimator.setInterpolator(new DecelerateInterpolator());
-
-        ViewPropertyAnimatorCompatSet set = new ViewPropertyAnimatorCompatSet();
-        set.play(buttonAnimator);
-
-        if (mMenuView != null) {
-            final int count = mMenuView.getChildCount();
-            if (count > 0) {
-                for (int i = count - 1, j = 0; i >= 0; i--, j++) {
-                    View child = mMenuView.getChildAt(i);
-                    ViewCompat.setScaleY(child, 0);
-                    ViewPropertyAnimatorCompat a = ViewCompat.animate(child).scaleY(1);
-                    a.setDuration(300);
-                    set.play(a);
-                }
-            }
-        }
-
-        return set;
-    }
-
-    private ViewPropertyAnimatorCompatSet makeOutAnimation() {
-        ViewPropertyAnimatorCompat buttonAnimator = ViewCompat.animate(mClose)
-                .translationX(-mClose.getWidth() -
-                        ((MarginLayoutParams) mClose.getLayoutParams()).leftMargin);
-        buttonAnimator.setDuration(200);
-        buttonAnimator.setListener(this);
-        buttonAnimator.setInterpolator(new DecelerateInterpolator());
-
-        ViewPropertyAnimatorCompatSet set = new ViewPropertyAnimatorCompatSet();
-        set.play(buttonAnimator);
-
-        if (mMenuView != null) {
-            final int count = mMenuView.getChildCount();
-            if (count > 0) {
-                for (int i = 0; i < 0; i++) {
-                    View child = mMenuView.getChildAt(i);
-                    ViewCompat.setScaleY(child, 1);
-                    ViewPropertyAnimatorCompat a = ViewCompat.animate(child).scaleY(0);
-                    a.setDuration(300);
-                    set.play(a);
-                }
-            }
-        }
-
-        return set;
-    }
-
     @Override
     protected void onLayout(boolean changed, int l, int t, int r, int b) {
         final boolean isLayoutRtl = ViewUtils.isLayoutRtl(this);
@@ -473,13 +329,6 @@
             x = next(x, startMargin, isLayoutRtl);
             x += positionChild(mClose, x, y, contentHeight, isLayoutRtl);
             x = next(x, endMargin, isLayoutRtl);
-
-            if (mAnimateInOnLayout) {
-                mAnimationMode = ANIMATE_IN;
-                mCurrentAnimation = makeInAnimation();
-                mCurrentAnimation.start();
-                mAnimateInOnLayout = false;
-            }
         }
 
         if (mTitleLayout != null && mCustomView == null && mTitleLayout.getVisibility() != GONE) {
@@ -498,22 +347,6 @@
     }
 
     @Override
-    public void onAnimationStart(View view) {
-    }
-
-    @Override
-    public void onAnimationEnd(View view) {
-        if (mAnimationMode == ANIMATE_OUT) {
-            killMode();
-        }
-        mAnimationMode = ANIMATE_IDLE;
-    }
-
-    @Override
-    public void onAnimationCancel(View view) {
-    }
-
-    @Override
     public boolean shouldDelayChildPressedState() {
         return false;
     }
diff --git a/v7/appcompat/src/android/support/v7/internal/widget/ActionBarOverlayLayout.java b/v7/appcompat/src/android/support/v7/internal/widget/ActionBarOverlayLayout.java
index 36d70bc..d647d7f 100644
--- a/v7/appcompat/src/android/support/v7/internal/widget/ActionBarOverlayLayout.java
+++ b/v7/appcompat/src/android/support/v7/internal/widget/ActionBarOverlayLayout.java
@@ -31,6 +31,7 @@
 import android.support.v4.view.ViewPropertyAnimatorListener;
 import android.support.v4.view.ViewPropertyAnimatorListenerAdapter;
 import android.support.v4.widget.ScrollerCompat;
+import android.support.v7.app.AppCompatDelegate;
 import android.support.v7.appcompat.R;
 import android.support.v7.internal.VersionUtils;
 import android.support.v7.internal.view.menu.MenuPresenter;
@@ -58,7 +59,6 @@
 
     // The main UI elements that we handle the layout of.
     private ContentFrameLayout mContent;
-    private ActionBarContainer mActionBarBottom;
     private ActionBarContainer mActionBarTop;
 
     // Some interior UI elements.
@@ -88,7 +88,6 @@
     private ScrollerCompat mFlingEstimator;
 
     private ViewPropertyAnimatorCompat mCurrentActionBarTopAnimator;
-    private ViewPropertyAnimatorCompat mCurrentActionBarBottomAnimator;
 
     private final ViewPropertyAnimatorListener mTopAnimatorListener
             = new ViewPropertyAnimatorListenerAdapter() {
@@ -105,30 +104,11 @@
         }
     };
 
-    private final ViewPropertyAnimatorListener mBottomAnimatorListener =
-            new ViewPropertyAnimatorListenerAdapter() {
-        @Override
-        public void onAnimationEnd(View view) {
-            mCurrentActionBarBottomAnimator = null;
-            mAnimatingForFling = false;
-        }
-
-        @Override
-        public void onAnimationCancel(View view) {
-            mCurrentActionBarBottomAnimator = null;
-            mAnimatingForFling = false;
-        }
-    };
-
     private final Runnable mRemoveActionBarHideOffset = new Runnable() {
         public void run() {
             haltActionBarHideOffsetAnimations();
             mCurrentActionBarTopAnimator = ViewCompat.animate(mActionBarTop).translationY(0)
                     .setListener(mTopAnimatorListener);
-            if (mActionBarBottom != null && mActionBarBottom.getVisibility() != GONE) {
-                mCurrentActionBarBottomAnimator = ViewCompat.animate(mActionBarBottom).translationY(0)
-                        .setListener(mBottomAnimatorListener);
-            }
         }
     };
 
@@ -138,11 +118,6 @@
             mCurrentActionBarTopAnimator = ViewCompat.animate(mActionBarTop)
                     .translationY(-mActionBarTop.getHeight())
                     .setListener(mTopAnimatorListener);
-            if (mActionBarBottom != null && mActionBarBottom.getVisibility() != GONE) {
-                mCurrentActionBarBottomAnimator =  ViewCompat.animate(mActionBarBottom)
-                        .translationY(mActionBarBottom.getHeight())
-                        .setListener(mBottomAnimatorListener);
-            }
         }
     };
 
@@ -310,11 +285,8 @@
         final boolean stable = (vis & SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0;
         final Rect systemInsets = insets;
 
-        // The top and bottom action bars are always within the content area.
+        // The top action bar is always within the content area.
         boolean changed = applyInsets(mActionBarTop, systemInsets, true, true, false, true);
-        if (mActionBarBottom != null) {
-            changed |= applyInsets(mActionBarBottom, systemInsets, true, false, true, true);
-        }
 
         mBaseInnerInsets.set(systemInsets);
         ViewUtils.computeFitSystemWindows(this, mBaseInnerInsets, mBaseContentInsets);
@@ -374,18 +346,6 @@
         childState = ViewUtils.combineMeasuredStates(childState,
                 ViewCompat.getMeasuredState(mActionBarTop));
 
-        // xlarge screen layout doesn't have bottom action bar.
-        if (mActionBarBottom != null) {
-            measureChildWithMargins(mActionBarBottom, widthMeasureSpec, 0, heightMeasureSpec, 0);
-            lp = (LayoutParams) mActionBarBottom.getLayoutParams();
-            maxWidth = Math.max(maxWidth,
-                    mActionBarBottom.getMeasuredWidth() + lp.leftMargin + lp.rightMargin);
-            maxHeight = Math.max(maxHeight,
-                    mActionBarBottom.getMeasuredHeight() + lp.topMargin + lp.bottomMargin);
-            childState = ViewUtils.combineMeasuredStates(childState,
-                    ViewCompat.getMeasuredState(mActionBarBottom));
-        }
-
         final int vis = ViewCompat.getWindowSystemUiVisibility(this);
         final boolean stable = (vis & SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0;
 
@@ -406,17 +366,6 @@
             topInset = mActionBarTop.getMeasuredHeight();
         }
 
-        if (mDecorToolbar.isSplit()) {
-            // If action bar is split, adjust bottom insets for it.
-            if (mActionBarBottom != null) {
-                if (stable) {
-                    bottomInset = mActionBarHeight;
-                } else {
-                    bottomInset = mActionBarBottom.getMeasuredHeight();
-                }
-            }
-        }
-
         // If the window has not requested system UI layout flags, we need to
         // make sure its content is not being covered by system UI...  though it
         // will still be covered by the action bar if they have requested it to
@@ -483,12 +432,7 @@
                 final int height = child.getMeasuredHeight();
 
                 int childLeft = parentLeft + lp.leftMargin;
-                int childTop;
-                if (child == mActionBarBottom) {
-                    childTop = parentBottom - height - lp.bottomMargin;
-                } else {
-                    childTop = parentTop + lp.topMargin;
-                }
+                int childTop = parentTop + lp.topMargin;
 
                 child.layout(childLeft, childTop, childLeft + width, childTop + height);
             }
@@ -586,7 +530,6 @@
             mContent = (ContentFrameLayout) findViewById(R.id.action_bar_activity_content);
             mActionBarTop = (ActionBarContainer) findViewById(R.id.action_bar_container);
             mDecorToolbar = getDecorToolbar(findViewById(R.id.action_bar));
-            mActionBarBottom = (ActionBarContainer) findViewById(R.id.split_action_bar);
         }
     }
 
@@ -624,12 +567,6 @@
         final int topHeight = mActionBarTop.getHeight();
         offset = Math.max(0, Math.min(offset, topHeight));
         ViewCompat.setTranslationY(mActionBarTop, -offset);
-        if (mActionBarBottom != null && mActionBarBottom.getVisibility() != GONE) {
-            // Match the hide offset proportionally for a split bar
-            final float fOffset = (float) offset / topHeight;
-            final int bOffset = (int) (mActionBarBottom.getHeight() * fOffset);
-            ViewCompat.setTranslationY(mActionBarBottom, bOffset);
-        }
     }
 
     private void haltActionBarHideOffsetAnimations() {
@@ -638,9 +575,6 @@
         if (mCurrentActionBarTopAnimator != null) {
             mCurrentActionBarTopAnimator.cancel();
         }
-        if (mCurrentActionBarBottomAnimator != null) {
-            mCurrentActionBarBottomAnimator.cancel();
-        }
     }
 
     private void postRemoveActionBarHideOffset() {
@@ -697,7 +631,7 @@
             case Window.FEATURE_INDETERMINATE_PROGRESS:
                 mDecorToolbar.initIndeterminateProgress();
                 break;
-            case Window.FEATURE_ACTION_BAR_OVERLAY:
+            case AppCompatDelegate.FEATURE_SUPPORT_ACTION_BAR_OVERLAY:
                 setOverlayMode(true);
                 break;
         }
diff --git a/v7/appcompat/src/android/support/v7/internal/widget/ActivityChooserModel.java b/v7/appcompat/src/android/support/v7/internal/widget/ActivityChooserModel.java
index d97f8e7..32e6df2 100644
--- a/v7/appcompat/src/android/support/v7/internal/widget/ActivityChooserModel.java
+++ b/v7/appcompat/src/android/support/v7/internal/widget/ActivityChooserModel.java
@@ -972,7 +972,7 @@
         }
         try {
             XmlPullParser parser = Xml.newPullParser();
-            parser.setInput(fis, null);
+            parser.setInput(fis, "UTF-8");
 
             int type = XmlPullParser.START_DOCUMENT;
             while (type != XmlPullParser.END_DOCUMENT && type != XmlPullParser.START_TAG) {
diff --git a/v7/appcompat/src/android/support/v7/internal/widget/AppCompatPopupWindow.java b/v7/appcompat/src/android/support/v7/internal/widget/AppCompatPopupWindow.java
index 511a332..d71d606 100644
--- a/v7/appcompat/src/android/support/v7/internal/widget/AppCompatPopupWindow.java
+++ b/v7/appcompat/src/android/support/v7/internal/widget/AppCompatPopupWindow.java
@@ -19,6 +19,7 @@
 import android.annotation.TargetApi;
 import android.content.Context;
 import android.os.Build;
+import android.support.v4.widget.PopupWindowCompat;
 import android.support.v7.appcompat.R;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -35,15 +36,18 @@
 public class AppCompatPopupWindow extends PopupWindow {
 
     private static final String TAG = "AppCompatPopupWindow";
+    private static final boolean COMPAT_OVERLAP_ANCHOR = Build.VERSION.SDK_INT < 21;
 
-    private final boolean mOverlapAnchor;
+    private boolean mOverlapAnchor;
 
     public AppCompatPopupWindow(Context context, AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
 
         TintTypedArray a = TintTypedArray.obtainStyledAttributes(context, attrs,
                 R.styleable.PopupWindow, defStyleAttr, 0);
-        mOverlapAnchor = a.getBoolean(R.styleable.PopupWindow_overlapAnchor, false);
+        if (a.hasValue(R.styleable.PopupWindow_overlapAnchor)) {
+            setSupportOverlapAnchor(a.getBoolean(R.styleable.PopupWindow_overlapAnchor, false));
+        }
         // We re-set this for tinting purposes
         setBackgroundDrawable(a.getDrawable(R.styleable.PopupWindow_android_popupBackground));
         a.recycle();
@@ -57,7 +61,7 @@
 
     @Override
     public void showAsDropDown(View anchor, int xoff, int yoff) {
-        if (Build.VERSION.SDK_INT < 21 && mOverlapAnchor) {
+        if (COMPAT_OVERLAP_ANCHOR && mOverlapAnchor) {
             // If we're pre-L, emulate overlapAnchor by modifying the yOff
             yoff -= anchor.getHeight();
         }
@@ -67,7 +71,7 @@
     @TargetApi(Build.VERSION_CODES.KITKAT)
     @Override
     public void showAsDropDown(View anchor, int xoff, int yoff, int gravity) {
-        if (Build.VERSION.SDK_INT < 21 && mOverlapAnchor) {
+        if (COMPAT_OVERLAP_ANCHOR && mOverlapAnchor) {
             // If we're pre-L, emulate overlapAnchor by modifying the yOff
             yoff -= anchor.getHeight();
         }
@@ -76,7 +80,7 @@
 
     @Override
     public void update(View anchor, int xoff, int yoff, int width, int height) {
-        if (Build.VERSION.SDK_INT < 21 && mOverlapAnchor) {
+        if (COMPAT_OVERLAP_ANCHOR && mOverlapAnchor) {
             // If we're pre-L, emulate overlapAnchor by modifying the yOff
             yoff -= anchor.getHeight();
         }
@@ -117,4 +121,26 @@
         }
     }
 
+    /**
+     * @hide
+     */
+    public void setSupportOverlapAnchor(boolean overlapAnchor) {
+        if (COMPAT_OVERLAP_ANCHOR) {
+            mOverlapAnchor = overlapAnchor;
+        } else {
+            PopupWindowCompat.setOverlapAnchor(this, overlapAnchor);
+        }
+    }
+
+    /**
+     * @hide
+     */
+    public boolean getSupportOverlapAnchor() {
+        if (COMPAT_OVERLAP_ANCHOR) {
+            return mOverlapAnchor;
+        } else {
+            return PopupWindowCompat.getOverlapAnchor(this);
+        }
+    }
+
 }
diff --git a/v7/appcompat/src/android/support/v7/internal/widget/DecorToolbar.java b/v7/appcompat/src/android/support/v7/internal/widget/DecorToolbar.java
index c601e64..ebaee2a 100644
--- a/v7/appcompat/src/android/support/v7/internal/widget/DecorToolbar.java
+++ b/v7/appcompat/src/android/support/v7/internal/widget/DecorToolbar.java
@@ -20,6 +20,7 @@
 import android.content.Context;
 import android.graphics.drawable.Drawable;
 import android.os.Parcelable;
+import android.support.v4.view.ViewPropertyAnimatorCompat;
 import android.support.v7.internal.view.menu.MenuBuilder;
 import android.support.v7.internal.view.menu.MenuPresenter;
 import android.util.SparseArray;
@@ -39,7 +40,6 @@
 public interface DecorToolbar {
     ViewGroup getViewGroup();
     Context getContext();
-    boolean isSplit();
     boolean hasExpandedActionView();
     void collapseActionView();
     void setWindowCallback(Window.Callback cb);
@@ -50,10 +50,6 @@
     void setSubtitle(CharSequence subtitle);
     void initProgress();
     void initIndeterminateProgress();
-    boolean canSplit();
-    void setSplitView(ViewGroup splitView);
-    void setSplitToolbar(boolean split);
-    void setSplitWhenNarrow(boolean splitWhenNarrow);
     boolean hasIcon();
     boolean hasLogo();
     void setIcon(int resId);
@@ -85,6 +81,7 @@
     void setCustomView(View view);
     View getCustomView();
     void animateToVisibility(int visibility);
+    ViewPropertyAnimatorCompat setupAnimatorToVisibility(int visibility, long duration);
     void setNavigationIcon(Drawable icon);
     void setNavigationIcon(int resId);
     void setNavigationContentDescription(CharSequence description);
@@ -100,5 +97,4 @@
     void setMenuCallbacks(MenuPresenter.Callback presenterCallback,
             MenuBuilder.Callback menuBuilderCallback);
     Menu getMenu();
-    int getPopupTheme();
 }
\ No newline at end of file
diff --git a/v7/appcompat/src/android/support/v7/internal/widget/TintManager.java b/v7/appcompat/src/android/support/v7/internal/widget/TintManager.java
index 999fc6d..7bcaef7 100644
--- a/v7/appcompat/src/android/support/v7/internal/widget/TintManager.java
+++ b/v7/appcompat/src/android/support/v7/internal/widget/TintManager.java
@@ -90,7 +90,7 @@
             R.drawable.abc_textfield_activated_mtrl_alpha,
             R.drawable.abc_textfield_search_activated_mtrl_alpha,
             R.drawable.abc_cab_background_top_mtrl_alpha,
-            R.drawable.abc_text_cursor_mtrl_alpha
+            R.drawable.abc_text_cursor_material
     };
 
     /**
@@ -294,7 +294,9 @@
                 tint = createSwitchThumbColorStateList(context);
             } else if (resId == R.drawable.abc_btn_default_mtrl_shape
                     || resId == R.drawable.abc_btn_borderless_material) {
-                tint = createButtonColorStateList(context);
+                tint = createDefaultButtonColorStateList(context);
+            } else if (resId == R.drawable.abc_btn_colored_material) {
+                tint = createColoredButtonColorStateList(context);
             } else if (resId == R.drawable.abc_spinner_mtrl_am_alpha
                     || resId == R.drawable.abc_spinner_textfield_background_material) {
                 tint = createSpinnerColorStateList(context);
@@ -480,12 +482,20 @@
         return new ColorStateList(states, colors);
     }
 
-    private ColorStateList createButtonColorStateList(Context context) {
+    private ColorStateList createDefaultButtonColorStateList(Context context) {
+        return createButtonColorStateList(context, R.attr.colorButtonNormal);
+    }
+
+    private ColorStateList createColoredButtonColorStateList(Context context) {
+        return createButtonColorStateList(context, R.attr.colorAccent);
+    }
+
+    private ColorStateList createButtonColorStateList(Context context, int baseColorAttr) {
         final int[][] states = new int[4][];
         final int[] colors = new int[4];
         int i = 0;
 
-        final int colorButtonNormal = getThemeAttrColor(context, R.attr.colorButtonNormal);
+        final int baseColor = getThemeAttrColor(context, baseColorAttr);
         final int colorControlHighlight = getThemeAttrColor(context, R.attr.colorControlHighlight);
 
         // Disabled state
@@ -494,16 +504,16 @@
         i++;
 
         states[i] = ThemeUtils.PRESSED_STATE_SET;
-        colors[i] = ColorUtils.compositeColors(colorControlHighlight, colorButtonNormal);
+        colors[i] = ColorUtils.compositeColors(colorControlHighlight, baseColor);
         i++;
 
         states[i] = ThemeUtils.FOCUSED_STATE_SET;
-        colors[i] = ColorUtils.compositeColors(colorControlHighlight, colorButtonNormal);
+        colors[i] = ColorUtils.compositeColors(colorControlHighlight, baseColor);
         i++;
 
         // Default enabled state
         states[i] = ThemeUtils.EMPTY_STATE_SET;
-        colors[i] = colorButtonNormal;
+        colors[i] = baseColor;
         i++;
 
         return new ColorStateList(states, colors);
diff --git a/v7/appcompat/src/android/support/v7/internal/widget/ToolbarWidgetWrapper.java b/v7/appcompat/src/android/support/v7/internal/widget/ToolbarWidgetWrapper.java
index 225f8e7..8315397 100644
--- a/v7/appcompat/src/android/support/v7/internal/widget/ToolbarWidgetWrapper.java
+++ b/v7/appcompat/src/android/support/v7/internal/widget/ToolbarWidgetWrapper.java
@@ -22,6 +22,7 @@
 import android.graphics.drawable.Drawable;
 import android.os.Parcelable;
 import android.support.v4.view.ViewCompat;
+import android.support.v4.view.ViewPropertyAnimatorCompat;
 import android.support.v4.view.ViewPropertyAnimatorListenerAdapter;
 import android.support.v7.appcompat.R;
 import android.support.v7.internal.view.menu.ActionMenuItem;
@@ -56,6 +57,8 @@
 
     private static final int AFFECTS_LOGO_MASK =
             ActionBar.DISPLAY_SHOW_HOME | ActionBar.DISPLAY_USE_LOGO;
+    // Default fade duration for fading in/out tool bar.
+    private static final long DEFAULT_FADE_DURATION_MS = 200;
 
     private Toolbar mToolbar;
 
@@ -241,11 +244,6 @@
     }
 
     @Override
-    public boolean isSplit() {
-        return false;
-    }
-
-    @Override
     public boolean hasExpandedActionView() {
         return mToolbar.hasExpandedActionView();
     }
@@ -310,27 +308,6 @@
     }
 
     @Override
-    public boolean canSplit() {
-        return false;
-    }
-
-    @Override
-    public void setSplitView(ViewGroup splitView) {
-    }
-
-    @Override
-    public void setSplitToolbar(boolean split) {
-        if (split) {
-            throw new UnsupportedOperationException("Cannot split an android.widget.Toolbar");
-        }
-    }
-
-    @Override
-    public void setSplitWhenNarrow(boolean splitWhenNarrow) {
-        // Ignore.
-    }
-
-    @Override
     public boolean hasIcon() {
         return mIcon != null;
     }
@@ -599,34 +576,48 @@
 
     @Override
     public void animateToVisibility(int visibility) {
-        if (visibility == View.GONE) {
-            ViewCompat.animate(mToolbar).alpha(0)
-                    .setListener(new ViewPropertyAnimatorListenerAdapter() {
-                        private boolean mCanceled = false;
-                        @Override
-                        public void onAnimationEnd(View view) {
-                            if (!mCanceled) {
-                                mToolbar.setVisibility(View.GONE);
-                            }
-                        }
-
-                        @Override
-                        public void onAnimationCancel(View view) {
-                            mCanceled = true;
-                        }
-                    });
-        } else if (visibility == View.VISIBLE) {
-            ViewCompat.animate(mToolbar).alpha(1)
-                    .setListener(new ViewPropertyAnimatorListenerAdapter() {
-                        @Override
-                        public void onAnimationStart(View view) {
-                            mToolbar.setVisibility(View.VISIBLE);
-                        }
-                    });
+        ViewPropertyAnimatorCompat anim = setupAnimatorToVisibility(visibility,
+                DEFAULT_FADE_DURATION_MS);
+        if (anim != null) {
+            anim.start();
         }
     }
 
     @Override
+    public ViewPropertyAnimatorCompat setupAnimatorToVisibility(int visibility, long duration) {
+        if (visibility == View.GONE) {
+            ViewPropertyAnimatorCompat anim = ViewCompat.animate(mToolbar).alpha(0f);
+            anim.setDuration(duration);
+            anim.setListener(new ViewPropertyAnimatorListenerAdapter() {
+                private boolean mCanceled = false;
+                @Override
+                public void onAnimationEnd(View view) {
+                    if (!mCanceled) {
+                        mToolbar.setVisibility(View.GONE);
+                    }
+                }
+
+                @Override
+                public void onAnimationCancel(View view) {
+                    mCanceled = true;
+                }
+            });
+            return anim;
+        } else if (visibility == View.VISIBLE) {
+            ViewPropertyAnimatorCompat anim = ViewCompat.animate(mToolbar).alpha(1f);
+            anim.setDuration(duration);
+            anim.setListener(new ViewPropertyAnimatorListenerAdapter() {
+                @Override
+                public void onAnimationStart(View view) {
+                    mToolbar.setVisibility(View.VISIBLE);
+                }
+            });
+            return anim;
+        }
+        return null;
+    }
+
+    @Override
     public void setNavigationIcon(Drawable icon) {
         mNavIcon = icon;
         updateNavigationIcon();
@@ -708,9 +699,4 @@
         return mToolbar.getMenu();
     }
 
-    @Override
-    public int getPopupTheme() {
-        return mToolbar.getPopupTheme();
-    }
-
 }
\ No newline at end of file
diff --git a/v7/appcompat/src/android/support/v7/widget/ActionMenuPresenter.java b/v7/appcompat/src/android/support/v7/widget/ActionMenuPresenter.java
index bf167d6..7a84b08 100644
--- a/v7/appcompat/src/android/support/v7/widget/ActionMenuPresenter.java
+++ b/v7/appcompat/src/android/support/v7/widget/ActionMenuPresenter.java
@@ -55,7 +55,9 @@
 
     private static final String TAG = "ActionMenuPresenter";
 
-    private View mOverflowButton;
+    private OverflowMenuButton mOverflowButton;
+    private Drawable mPendingOverflowIcon;
+    private boolean mPendingOverflowIconSet;
     private boolean mReserveOverflow;
     private boolean mReserveOverflowSet;
     private int mWidthLimit;
@@ -110,6 +112,11 @@
         if (mReserveOverflow) {
             if (mOverflowButton == null) {
                 mOverflowButton = new OverflowMenuButton(mSystemContext);
+                if (mPendingOverflowIconSet) {
+                    mOverflowButton.setImageDrawable(mPendingOverflowIcon);
+                    mPendingOverflowIcon = null;
+                    mPendingOverflowIconSet = false;
+                }
                 final int spec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
                 mOverflowButton.measure(spec, spec);
             }
@@ -156,6 +163,24 @@
         mExpandedActionViewsExclusive = isExclusive;
     }
 
+    public void setOverflowIcon(Drawable icon) {
+        if (mOverflowButton != null) {
+            mOverflowButton.setImageDrawable(icon);
+        } else {
+            mPendingOverflowIconSet = true;
+            mPendingOverflowIcon = icon;
+        }
+    }
+
+    public Drawable getOverflowIcon() {
+        if (mOverflowButton != null) {
+            return mOverflowButton.getDrawable();
+        } else if (mPendingOverflowIconSet) {
+            return mPendingOverflowIcon;
+        }
+        return null;
+    }
+
     @Override
     public MenuView getMenuView(ViewGroup root) {
         MenuView result = super.getMenuView(root);
diff --git a/v7/appcompat/src/android/support/v7/widget/ActionMenuView.java b/v7/appcompat/src/android/support/v7/widget/ActionMenuView.java
index b7c9821..0e47283 100644
--- a/v7/appcompat/src/android/support/v7/widget/ActionMenuView.java
+++ b/v7/appcompat/src/android/support/v7/widget/ActionMenuView.java
@@ -17,7 +17,10 @@
 
 import android.content.Context;
 import android.content.res.Configuration;
+import android.graphics.drawable.Drawable;
 import android.os.Build;
+import android.support.annotation.Nullable;
+import android.support.annotation.StyleRes;
 import android.support.v7.internal.view.menu.ActionMenuItemView;
 import android.support.v7.internal.view.menu.MenuBuilder;
 import android.support.v7.internal.view.menu.MenuItemImpl;
@@ -50,8 +53,6 @@
 
     private MenuBuilder mMenu;
 
-    private Context mContext;
-
     /** Context against which to inflate popup menus. */
     private Context mPopupContext;
 
@@ -75,7 +76,6 @@
 
     public ActionMenuView(Context context, AttributeSet attrs) {
         super(context, attrs);
-        mContext = context;
         setBaselineAligned(false);
         final float density = context.getResources().getDisplayMetrics().density;
         mMinCellSize = (int) (MIN_CELL_SIZE * density);
@@ -91,13 +91,13 @@
      * @param resId theme used to inflate popup menus
      * @see #getPopupTheme()
      */
-    public void setPopupTheme(int resId) {
+    public void setPopupTheme(@StyleRes int resId) {
         if (mPopupTheme != resId) {
             mPopupTheme = resId;
             if (resId == 0) {
-                mPopupContext = mContext;
+                mPopupContext = getContext();
             } else {
-                mPopupContext = new ContextThemeWrapper(mContext, resId);
+                mPopupContext = new ContextThemeWrapper(getContext(), resId);
             }
         }
     }
@@ -544,6 +544,27 @@
         dismissPopupMenus();
     }
 
+    /**
+     * Set the icon to use for the overflow button.
+     *
+     * @param icon Drawable to set, may be null to clear the icon
+     */
+    public void setOverflowIcon(@Nullable Drawable icon) {
+        getMenu();
+        mPresenter.setOverflowIcon(icon);
+    }
+
+    /**
+     * Return the current drawable used as the overflow icon.
+     *
+     * @return The overflow icon drawable
+     */
+    @Nullable
+    public Drawable getOverflowIcon() {
+        getMenu();
+        return mPresenter.getOverflowIcon();
+    }
+
     /** @hide */
     public boolean isOverflowReserved() {
         return mReserveOverflow;
diff --git a/v7/appcompat/src/android/support/v7/widget/AppCompatAutoCompleteTextView.java b/v7/appcompat/src/android/support/v7/widget/AppCompatAutoCompleteTextView.java
index 285fbeb..a057677 100644
--- a/v7/appcompat/src/android/support/v7/widget/AppCompatAutoCompleteTextView.java
+++ b/v7/appcompat/src/android/support/v7/widget/AppCompatAutoCompleteTextView.java
@@ -20,33 +20,41 @@
 import android.content.res.ColorStateList;
 import android.graphics.PorterDuff;
 import android.graphics.drawable.Drawable;
+import android.support.annotation.DrawableRes;
 import android.support.annotation.Nullable;
 import android.support.v4.view.TintableBackgroundView;
 import android.support.v7.appcompat.R;
 import android.support.v7.internal.widget.TintContextWrapper;
-import android.support.v7.internal.widget.TintInfo;
 import android.support.v7.internal.widget.TintManager;
 import android.support.v7.internal.widget.TintTypedArray;
 import android.util.AttributeSet;
 import android.widget.AutoCompleteTextView;
 
 /**
- * A tint aware {@link android.widget.AutoCompleteTextView}.
- * <p>
- * This will automatically be used when you use {@link AutoCompleteTextView} in your layouts. You
- * should only need to manually use this class writing custom views.
+ * A {@link AutoCompleteTextView} which supports compatible features on older version of the
+ * platform, including:
+ * <ul>
+ *     <li>Supports {@link R.attr#textAllCaps} style attribute which works back to
+ *     {@link android.os.Build.VERSION_CODES#ECLAIR_MR1 Eclair MR1}.</li>
+ *     <li>Allows dynamic tint of it background via the background tint methods in
+ *     {@link android.support.v4.view.ViewCompat}.</li>
+ *     <li>Allows setting of the background tint using {@link R.attr#backgroundTint} and
+ *     {@link R.attr#backgroundTintMode}.</li>
+ * </ul>
+ *
+ * <p>This will automatically be used when you use {@link AutoCompleteTextView} in your layouts.
+ * You should only need to manually use this class when writing custom views.</p>
  */
 public class AppCompatAutoCompleteTextView extends AutoCompleteTextView implements
         TintableBackgroundView {
 
     private static final int[] TINT_ATTRS = {
-            android.R.attr.background,
             android.R.attr.popupBackground
     };
 
-    private TintInfo mInternalBackgroundTint;
-    private TintInfo mBackgroundTint;
     private TintManager mTintManager;
+    private AppCompatBackgroundHelper mBackgroundTintHelper;
+    private AppCompatTextHelper mTextHelper;
 
     public AppCompatAutoCompleteTextView(Context context) {
         this(context, null);
@@ -59,59 +67,57 @@
     public AppCompatAutoCompleteTextView(Context context, AttributeSet attrs, int defStyleAttr) {
         super(TintContextWrapper.wrap(context), attrs, defStyleAttr);
 
-        if (TintManager.SHOULD_BE_USED) {
-            TintTypedArray a = TintTypedArray.obtainStyledAttributes(getContext(), attrs,
-                    TINT_ATTRS, defStyleAttr, 0);
-            mTintManager = a.getTintManager();
+        TintTypedArray a = TintTypedArray.obtainStyledAttributes(getContext(), attrs,
+                TINT_ATTRS, defStyleAttr, 0);
+        mTintManager = a.getTintManager();
+        if (a.hasValue(0)) {
+            setDropDownBackgroundDrawable(a.getDrawable(0));
+        }
+        a.recycle();
 
-            if (a.hasValue(0)) {
-                ColorStateList tint = a.getTintManager().getTintList(a.getResourceId(0, -1));
-                if (tint != null) {
-                    setInternalBackgroundTint(tint);
-                }
-            }
-            if (a.hasValue(1)) {
-                setDropDownBackgroundDrawable(a.getDrawable(1));
-            }
-            a.recycle();
+        mBackgroundTintHelper = new AppCompatBackgroundHelper(this, mTintManager);
+        mBackgroundTintHelper.loadFromAttributes(attrs, defStyleAttr);
+
+        mTextHelper = new AppCompatTextHelper(this);
+        mTextHelper.loadFromAttributes(attrs, defStyleAttr);
+    }
+
+    @Override
+    public void setDropDownBackgroundResource(@DrawableRes int resId) {
+        if (mTintManager != null) {
+            setDropDownBackgroundDrawable(mTintManager.getDrawable(resId));
+        } else {
+            super.setDropDownBackgroundResource(resId);
         }
     }
 
     @Override
-    public void setBackgroundResource(int resId) {
+    public void setBackgroundResource(@DrawableRes int resId) {
         super.setBackgroundResource(resId);
-        // Update the default background tint
-        setInternalBackgroundTint(mTintManager != null ? mTintManager.getTintList(resId) : null);
+        if (mBackgroundTintHelper != null) {
+            mBackgroundTintHelper.onSetBackgroundResource(resId);
+        }
     }
 
     @Override
     public void setBackgroundDrawable(Drawable background) {
         super.setBackgroundDrawable(background);
-        // We don't know that this drawable is, so we need to clear the default background tint
-        setInternalBackgroundTint(null);
-    }
-
-    @Override
-    public void setDropDownBackgroundResource(int id) {
-        setDropDownBackgroundDrawable(mTintManager.getDrawable(id));
+        if (mBackgroundTintHelper != null) {
+            mBackgroundTintHelper.onSetBackgroundDrawable(background);
+        }
     }
 
     /**
      * This should be accessed via
-     * {@link android.support.v4.view.ViewCompat#setBackgroundTintList(android.view.View,
-     * android.content.res.ColorStateList)}
+     * {@link android.support.v4.view.ViewCompat#setBackgroundTintList(android.view.View, ColorStateList)}
      *
      * @hide
      */
     @Override
     public void setSupportBackgroundTintList(@Nullable ColorStateList tint) {
-        if (mBackgroundTint == null) {
-            mBackgroundTint = new TintInfo();
+        if (mBackgroundTintHelper != null) {
+            mBackgroundTintHelper.setSupportBackgroundTintList(tint);
         }
-        mBackgroundTint.mTintList = tint;
-        mBackgroundTint.mHasTintList = true;
-
-        applySupportBackgroundTint();
     }
 
     /**
@@ -123,24 +129,21 @@
     @Override
     @Nullable
     public ColorStateList getSupportBackgroundTintList() {
-        return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
+        return mBackgroundTintHelper != null
+                ? mBackgroundTintHelper.getSupportBackgroundTintList() : null;
     }
 
     /**
      * This should be accessed via
-     * {@link android.support.v4.view.ViewCompat#setBackgroundTintMode(android.view.View, android.graphics.PorterDuff.Mode)}
+     * {@link android.support.v4.view.ViewCompat#setBackgroundTintMode(android.view.View, PorterDuff.Mode)}
      *
      * @hide
      */
     @Override
     public void setSupportBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
-        if (mBackgroundTint == null) {
-            mBackgroundTint = new TintInfo();
+        if (mBackgroundTintHelper != null) {
+            mBackgroundTintHelper.setSupportBackgroundTintMode(tintMode);
         }
-        mBackgroundTint.mTintMode = tintMode;
-        mBackgroundTint.mHasTintMode = true;
-
-        applySupportBackgroundTint();
     }
 
     /**
@@ -152,35 +155,23 @@
     @Override
     @Nullable
     public PorterDuff.Mode getSupportBackgroundTintMode() {
-        return mBackgroundTint != null ? mBackgroundTint.mTintMode : null;
+        return mBackgroundTintHelper != null
+                ? mBackgroundTintHelper.getSupportBackgroundTintMode() : null;
     }
 
     @Override
     protected void drawableStateChanged() {
         super.drawableStateChanged();
-        applySupportBackgroundTint();
-    }
-
-    private void applySupportBackgroundTint() {
-        if (getBackground() != null) {
-            if (mBackgroundTint != null) {
-                TintManager.tintViewBackground(this, mBackgroundTint);
-            } else if (mInternalBackgroundTint != null) {
-                TintManager.tintViewBackground(this, mInternalBackgroundTint);
-            }
+        if (mBackgroundTintHelper != null) {
+            mBackgroundTintHelper.applySupportBackgroundTint();
         }
     }
 
-    private void setInternalBackgroundTint(ColorStateList tint) {
-        if (tint != null) {
-            if (mInternalBackgroundTint == null) {
-                mInternalBackgroundTint = new TintInfo();
-            }
-            mInternalBackgroundTint.mTintList = tint;
-            mInternalBackgroundTint.mHasTintList = true;
-        } else {
-            mInternalBackgroundTint = null;
+    @Override
+    public void setTextAppearance(Context context, int resId) {
+        super.setTextAppearance(context, resId);
+        if (mTextHelper != null) {
+            mTextHelper.onSetTextAppearance(context, resId);
         }
-        applySupportBackgroundTint();
     }
 }
diff --git a/v7/appcompat/src/android/support/v7/widget/AppCompatBackgroundHelper.java b/v7/appcompat/src/android/support/v7/widget/AppCompatBackgroundHelper.java
new file mode 100644
index 0000000..7494b24
--- /dev/null
+++ b/v7/appcompat/src/android/support/v7/widget/AppCompatBackgroundHelper.java
@@ -0,0 +1,130 @@
+/*
+ * 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.v7.widget;
+
+import android.content.res.ColorStateList;
+import android.content.res.TypedArray;
+import android.graphics.PorterDuff;
+import android.graphics.drawable.Drawable;
+import android.support.v4.view.ViewCompat;
+import android.support.v7.appcompat.R;
+import android.support.v7.graphics.drawable.DrawableUtils;
+import android.support.v7.internal.widget.TintInfo;
+import android.support.v7.internal.widget.TintManager;
+import android.util.AttributeSet;
+import android.view.View;
+
+class AppCompatBackgroundHelper {
+
+    private final View mView;
+    private final TintManager mTintManager;
+
+    private TintInfo mInternalBackgroundTint;
+    private TintInfo mBackgroundTint;
+
+    AppCompatBackgroundHelper(View view, TintManager tintManager) {
+        mView = view;
+        mTintManager = tintManager;
+    }
+
+    void loadFromAttributes(AttributeSet attrs, int defStyleAttr) {
+        TypedArray a = mView.getContext().obtainStyledAttributes(attrs,
+                R.styleable.ViewBackgroundHelper, defStyleAttr, 0);
+        try {
+            if (a.hasValue(R.styleable.ViewBackgroundHelper_android_background)) {
+                ColorStateList tint = mTintManager.getTintList(
+                        a.getResourceId(R.styleable.ViewBackgroundHelper_android_background, -1));
+                if (tint != null) {
+                    setInternalBackgroundTint(tint);
+                }
+            }
+            if (a.hasValue(R.styleable.ViewBackgroundHelper_backgroundTint)) {
+                ViewCompat.setBackgroundTintList(mView,
+                        a.getColorStateList(R.styleable.ViewBackgroundHelper_backgroundTint));
+            }
+            if (a.hasValue(R.styleable.ViewBackgroundHelper_backgroundTintMode)) {
+                ViewCompat.setBackgroundTintMode(mView,
+                        DrawableUtils.parseTintMode(
+                                a.getInt(R.styleable.ViewBackgroundHelper_backgroundTintMode, -1),
+                                null));
+            }
+        } finally {
+            a.recycle();
+        }
+    }
+
+    void onSetBackgroundResource(int resId) {
+        // Update the default background tint
+        setInternalBackgroundTint(mTintManager != null ? mTintManager.getTintList(resId) : null);
+    }
+
+    void onSetBackgroundDrawable(Drawable background) {
+        // We don't know that this drawable is, so we need to clear the default background tint
+        setInternalBackgroundTint(null);
+    }
+
+    void setSupportBackgroundTintList(ColorStateList tint) {
+        if (mBackgroundTint == null) {
+            mBackgroundTint = new TintInfo();
+        }
+        mBackgroundTint.mTintList = tint;
+        mBackgroundTint.mHasTintList = true;
+
+        applySupportBackgroundTint();
+    }
+
+    ColorStateList getSupportBackgroundTintList() {
+        return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
+    }
+
+    void setSupportBackgroundTintMode(PorterDuff.Mode tintMode) {
+        if (mBackgroundTint == null) {
+            mBackgroundTint = new TintInfo();
+        }
+        mBackgroundTint.mTintMode = tintMode;
+        mBackgroundTint.mHasTintMode = true;
+
+        applySupportBackgroundTint();
+    }
+
+    PorterDuff.Mode getSupportBackgroundTintMode() {
+        return mBackgroundTint != null ? mBackgroundTint.mTintMode : null;
+    }
+
+    void applySupportBackgroundTint() {
+        if (mView.getBackground() != null) {
+            if (mBackgroundTint != null) {
+                TintManager.tintViewBackground(mView, mBackgroundTint);
+            } else if (mInternalBackgroundTint != null) {
+                TintManager.tintViewBackground(mView, mInternalBackgroundTint);
+            }
+        }
+    }
+
+    void setInternalBackgroundTint(ColorStateList tint) {
+        if (tint != null) {
+            if (mInternalBackgroundTint == null) {
+                mInternalBackgroundTint = new TintInfo();
+            }
+            mInternalBackgroundTint.mTintList = tint;
+            mInternalBackgroundTint.mHasTintList = true;
+        } else {
+            mInternalBackgroundTint = null;
+        }
+        applySupportBackgroundTint();
+    }
+}
diff --git a/v7/appcompat/src/android/support/v7/widget/AppCompatButton.java b/v7/appcompat/src/android/support/v7/widget/AppCompatButton.java
index 3c6917d..91d69c8 100644
--- a/v7/appcompat/src/android/support/v7/widget/AppCompatButton.java
+++ b/v7/appcompat/src/android/support/v7/widget/AppCompatButton.java
@@ -18,38 +18,39 @@
 
 import android.content.Context;
 import android.content.res.ColorStateList;
-import android.content.res.TypedArray;
 import android.graphics.PorterDuff;
 import android.graphics.drawable.Drawable;
-import android.os.Build;
+import android.support.annotation.DrawableRes;
 import android.support.annotation.Nullable;
 import android.support.v4.view.TintableBackgroundView;
 import android.support.v7.appcompat.R;
 import android.support.v7.internal.text.AllCapsTransformationMethod;
-import android.support.v7.internal.widget.ThemeUtils;
-import android.support.v7.internal.widget.TintInfo;
 import android.support.v7.internal.widget.TintManager;
-import android.support.v7.internal.widget.TintTypedArray;
 import android.util.AttributeSet;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.Button;
 
 /**
- * A tint aware {@link android.widget.Button}.
- * <p>
- * This will automatically be used when you use {@link android.widget.Button} in your layouts. You
- * should only need to manually use this class when writing custom views.
+ * A {@link Button} which supports compatible features on older version of the platform,
+ * including:
+ * <ul>
+ *     <li>Supports {@link R.attr#textAllCaps} style attribute which works back to
+ *     {@link android.os.Build.VERSION_CODES#ECLAIR_MR1 Eclair MR1}.</li>
+ *     <li>Allows dynamic tint of it background via the background tint methods in
+ *     {@link android.support.v4.view.ViewCompat}.</li>
+ *     <li>Allows setting of the background tint using {@link R.attr#backgroundTint} and
+ *     {@link R.attr#backgroundTintMode}.</li>
+ * </ul>
+ *
+ * <p>This will automatically be used when you use {@link android.widget.Button} in your
+ * layouts. You should only need to manually use this class when writing custom views.</p>
  */
 public class AppCompatButton extends Button implements TintableBackgroundView {
 
-    private static final int[] TINT_ATTRS = {
-            android.R.attr.background
-    };
-
-    private TintInfo mInternalBackgroundTint;
-    private TintInfo mBackgroundTint;
-    private TintManager mTintManager;
+    private final TintManager mTintManager;
+    private final AppCompatBackgroundHelper mBackgroundTintHelper;
+    private final AppCompatTextHelper mTextHelper;
 
     public AppCompatButton(Context context) {
         this(context, null);
@@ -62,95 +63,41 @@
     public AppCompatButton(Context context, AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
 
-        if (TintManager.SHOULD_BE_USED) {
-            TintTypedArray a = TintTypedArray.obtainStyledAttributes(getContext(), attrs,
-                    TINT_ATTRS, defStyleAttr, 0);
-            if (a.hasValue(0)) {
-                ColorStateList tint = a.getTintManager().getTintList(a.getResourceId(0, -1));
-                if (tint != null) {
-                    setInternalBackgroundTint(tint);
-                }
-            }
-            mTintManager = a.getTintManager();
-            a.recycle();
-        }
+        mTintManager = TintManager.get(getContext());
+        mBackgroundTintHelper = new AppCompatBackgroundHelper(this, mTintManager);
+        mBackgroundTintHelper.loadFromAttributes(attrs, defStyleAttr);
 
-        // First read the TextAppearance style id
-        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.AppCompatTextView,
-                defStyleAttr, 0);
-        final int ap = a.getResourceId(R.styleable.AppCompatTextView_android_textAppearance, -1);
-        a.recycle();
-
-        // Now check TextAppearance's textAllCaps value
-        if (ap != -1) {
-            TypedArray appearance = context.obtainStyledAttributes(ap, R.styleable.TextAppearance);
-            if (appearance.hasValue(R.styleable.TextAppearance_textAllCaps)) {
-                setAllCaps(appearance.getBoolean(R.styleable.TextAppearance_textAllCaps, false));
-            }
-            appearance.recycle();
-        }
-
-        // Now read the style's value
-        a = context.obtainStyledAttributes(attrs, R.styleable.AppCompatTextView, defStyleAttr, 0);
-        if (a.hasValue(R.styleable.AppCompatTextView_textAllCaps)) {
-            setAllCaps(a.getBoolean(R.styleable.AppCompatTextView_textAllCaps, false));
-        }
-        a.recycle();
-
-        final ColorStateList textColors = getTextColors();
-        if (textColors != null && !textColors.isStateful()) {
-            // If we have a ColorStateList which isn't stateful, create one which includes
-            // a disabled state
-
-            final int disabledTextColor;
-            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
-                // Pre-Lollipop, we will use textColorSecondary with android:disabledAlpha
-                // applied
-                disabledTextColor = ThemeUtils.getDisabledThemeAttrColor(context,
-                        android.R.attr.textColorSecondary);
-            } else {
-                // With certain styles on Lollipop, there is a StateListAnimator which sets
-                // an alpha on the whole view, so we don't need to apply disabledAlpha to
-                // textColorSecondary
-                disabledTextColor = ThemeUtils.getThemeAttrColor(context,
-                        android.R.attr.textColorSecondary);
-            }
-
-            setTextColor(ThemeUtils.createDisabledStateList(
-                    textColors.getDefaultColor(), disabledTextColor));
-        }
+        mTextHelper = new AppCompatTextHelper(this);
+        mTextHelper.loadFromAttributes(attrs, defStyleAttr);
     }
 
     @Override
-    public void setBackgroundResource(int resId) {
+    public void setBackgroundResource(@DrawableRes int resId) {
         super.setBackgroundResource(resId);
-        // Update the default background tint
-        setInternalBackgroundTint(mTintManager != null ? mTintManager.getTintList(resId) : null);
+        if (mBackgroundTintHelper != null) {
+            mBackgroundTintHelper.onSetBackgroundResource(resId);
+        }
     }
 
     @Override
     public void setBackgroundDrawable(Drawable background) {
         super.setBackgroundDrawable(background);
-        // We don't know that this drawable is, so we need to clear the default background tint
-        setInternalBackgroundTint(null);
+        if (mBackgroundTintHelper != null) {
+            mBackgroundTintHelper.onSetBackgroundDrawable(background);
+        }
     }
 
     /**
      * This should be accessed via
-     * {@link android.support.v4.view.ViewCompat#setBackgroundTintList(android.view.View,
-     * android.content.res.ColorStateList)}
+     * {@link android.support.v4.view.ViewCompat#setBackgroundTintList(android.view.View, ColorStateList)}
      *
      * @hide
      */
     @Override
     public void setSupportBackgroundTintList(@Nullable ColorStateList tint) {
-        if (mBackgroundTint == null) {
-            mBackgroundTint = new TintInfo();
+        if (mBackgroundTintHelper != null) {
+            mBackgroundTintHelper.setSupportBackgroundTintList(tint);
         }
-        mBackgroundTint.mTintList = tint;
-        mBackgroundTint.mHasTintList = true;
-
-        applySupportBackgroundTint();
     }
 
     /**
@@ -162,24 +109,21 @@
     @Override
     @Nullable
     public ColorStateList getSupportBackgroundTintList() {
-        return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
+        return mBackgroundTintHelper != null
+                ? mBackgroundTintHelper.getSupportBackgroundTintList() : null;
     }
 
     /**
      * This should be accessed via
-     * {@link android.support.v4.view.ViewCompat#setBackgroundTintMode(android.view.View, android.graphics.PorterDuff.Mode)}
+     * {@link android.support.v4.view.ViewCompat#setBackgroundTintMode(android.view.View, PorterDuff.Mode)}
      *
      * @hide
      */
     @Override
     public void setSupportBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
-        if (mBackgroundTint == null) {
-            mBackgroundTint = new TintInfo();
+        if (mBackgroundTintHelper != null) {
+            mBackgroundTintHelper.setSupportBackgroundTintMode(tintMode);
         }
-        mBackgroundTint.mTintMode = tintMode;
-        mBackgroundTint.mHasTintMode = true;
-
-        applySupportBackgroundTint();
     }
 
     /**
@@ -191,36 +135,24 @@
     @Override
     @Nullable
     public PorterDuff.Mode getSupportBackgroundTintMode() {
-        return mBackgroundTint != null ? mBackgroundTint.mTintMode : null;
+        return mBackgroundTintHelper != null
+                ? mBackgroundTintHelper.getSupportBackgroundTintMode() : null;
     }
 
     @Override
     protected void drawableStateChanged() {
         super.drawableStateChanged();
-        applySupportBackgroundTint();
-    }
-
-    private void applySupportBackgroundTint() {
-        if (getBackground() != null) {
-            if (mBackgroundTint != null) {
-                TintManager.tintViewBackground(this, mBackgroundTint);
-            } else if (mInternalBackgroundTint != null) {
-                TintManager.tintViewBackground(this, mInternalBackgroundTint);
-            }
+        if (mBackgroundTintHelper != null) {
+            mBackgroundTintHelper.applySupportBackgroundTint();
         }
     }
 
-    private void setInternalBackgroundTint(ColorStateList tint) {
-        if (tint != null) {
-            if (mInternalBackgroundTint == null) {
-                mInternalBackgroundTint = new TintInfo();
-            }
-            mInternalBackgroundTint.mTintList = tint;
-            mInternalBackgroundTint.mHasTintList = true;
-        } else {
-            mInternalBackgroundTint = null;
+    @Override
+    public void setTextAppearance(Context context, int resId) {
+        super.setTextAppearance(context, resId);
+        if (mTextHelper != null) {
+            mTextHelper.onSetTextAppearance(context, resId);
         }
-        applySupportBackgroundTint();
     }
 
     @Override
@@ -235,19 +167,18 @@
         info.setClassName(Button.class.getName());
     }
 
-    public void setAllCaps(boolean allCaps) {
-        setTransformationMethod(allCaps ? new AllCapsTransformationMethod(getContext()) : null);
-    }
-
-    @Override
-    public void setTextAppearance(Context context, int resId) {
-        super.setTextAppearance(context, resId);
-
-        TypedArray appearance = context.obtainStyledAttributes(resId, R.styleable.TextAppearance);
-        if (appearance.hasValue(R.styleable.TextAppearance_textAllCaps)) {
-            setAllCaps(appearance.getBoolean(R.styleable.TextAppearance_textAllCaps, false));
+    /**
+     * Sets the properties of this field to transform input to ALL CAPS
+     * display. This may use a "small caps" formatting if available.
+     * This setting will be ignored if this field is editable or selectable.
+     *
+     * This call replaces the current transformation method. Disabling this
+     * will not necessarily restore the previous behavior from before this
+     * was enabled.
+     */
+    public void setSupportAllCaps(boolean allCaps) {
+        if (mTextHelper != null) {
+            mTextHelper.setAllCaps(allCaps);
         }
-        appearance.recycle();
     }
-
 }
diff --git a/v7/appcompat/src/android/support/v7/widget/AppCompatCheckBox.java b/v7/appcompat/src/android/support/v7/widget/AppCompatCheckBox.java
index 6cbcdd1..1ad2c77 100644
--- a/v7/appcompat/src/android/support/v7/widget/AppCompatCheckBox.java
+++ b/v7/appcompat/src/android/support/v7/widget/AppCompatCheckBox.java
@@ -17,29 +17,35 @@
 package android.support.v7.widget;
 
 import android.content.Context;
+import android.content.res.ColorStateList;
+import android.graphics.PorterDuff;
 import android.graphics.drawable.Drawable;
-import android.os.Build;
 import android.support.annotation.DrawableRes;
+import android.support.annotation.Nullable;
+import android.support.v4.content.ContextCompat;
+import android.support.v4.widget.TintableCompoundButton;
 import android.support.v7.appcompat.R;
 import android.support.v7.internal.widget.TintManager;
-import android.support.v7.internal.widget.TintTypedArray;
 import android.util.AttributeSet;
 import android.widget.CheckBox;
 
 /**
- * A tint aware {@link android.widget.CheckBox}.
- * <p>
- * This will automatically be used when you use {@link android.widget.CheckBox} in your layouts.
- * You should only need to manually use this class when writing custom views.
+ * A {@link CheckBox} which supports compatible features on older version of the platform,
+ * including:
+ * <ul>
+ *     <li>Allows dynamic tint of it background via the background tint methods in
+ *     {@link android.support.v4.widget.CompoundButtonCompat}.</li>
+ *     <li>Allows setting of the background tint using {@link R.attr#buttonTint} and
+ *     {@link R.attr#buttonTintMode}.</li>
+ * </ul>
+ *
+ * <p>This will automatically be used when you use {@link CheckBox} in your layouts.
+ * You should only need to manually use this class when writing custom views.</p>
  */
-public class AppCompatCheckBox extends CheckBox {
-
-    private static final int[] TINT_ATTRS = {
-            android.R.attr.button
-    };
+public class AppCompatCheckBox extends CheckBox implements TintableCompoundButton {
 
     private TintManager mTintManager;
-    private Drawable mButtonDrawable;
+    private AppCompatCompoundButtonHelper mCompoundButtonHelper;
 
     public AppCompatCheckBox(Context context) {
         this(context, null);
@@ -51,43 +57,77 @@
 
     public AppCompatCheckBox(Context context, AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
-
-        if (TintManager.SHOULD_BE_USED) {
-            TintTypedArray a = TintTypedArray.obtainStyledAttributes(getContext(), attrs,
-                    TINT_ATTRS, defStyleAttr, 0);
-            setButtonDrawable(a.getDrawable(0));
-            a.recycle();
-
-            mTintManager = a.getTintManager();
-        }
+        mTintManager = TintManager.get(context);
+        mCompoundButtonHelper = new AppCompatCompoundButtonHelper(this, mTintManager);
+        mCompoundButtonHelper.loadFromAttributes(attrs, defStyleAttr);
     }
 
     @Override
     public void setButtonDrawable(Drawable buttonDrawable) {
         super.setButtonDrawable(buttonDrawable);
-        mButtonDrawable = buttonDrawable;
+        if (mCompoundButtonHelper != null) {
+            mCompoundButtonHelper.onSetButtonDrawable();
+        }
     }
 
     @Override
     public void setButtonDrawable(@DrawableRes int resId) {
-        if (mTintManager != null) {
-            setButtonDrawable(mTintManager.getDrawable(resId));
-        } else {
-            super.setButtonDrawable(resId);
-        }
+        setButtonDrawable(mTintManager != null
+                ? mTintManager.getDrawable(resId)
+                : ContextCompat.getDrawable(getContext(), resId));
     }
 
     @Override
     public int getCompoundPaddingLeft() {
-        int padding = super.getCompoundPaddingLeft();
-        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
-            // Before JB-MR1 the button drawable wasn't taken into account for padding. We'll
-            // workaround that here
-            if (mButtonDrawable != null) {
-                padding += mButtonDrawable.getIntrinsicWidth();
-            }
-        }
-        return padding;
+        final int value = super.getCompoundPaddingLeft();
+        return mCompoundButtonHelper != null
+                ? mCompoundButtonHelper.getCompoundPaddingLeft(value)
+                : value;
     }
 
+    /**
+     * This should be accessed from {@link android.support.v4.widget.CompoundButtonCompat}
+     * @hide
+     */
+    @Override
+    public void setSupportButtonTintList(@Nullable ColorStateList tint) {
+        if (mCompoundButtonHelper != null) {
+            mCompoundButtonHelper.setSupportButtonTintList(tint);
+        }
+    }
+
+    /**
+     * This should be accessed from {@link android.support.v4.widget.CompoundButtonCompat}
+     * @hide
+     */
+    @Nullable
+    @Override
+    public ColorStateList getSupportButtonTintList() {
+        return mCompoundButtonHelper != null
+                ? mCompoundButtonHelper.getSupportButtonTintList()
+                : null;
+    }
+
+    /**
+     * This should be accessed from {@link android.support.v4.widget.CompoundButtonCompat}
+     * @hide
+     */
+    @Override
+    public void setSupportButtonTintMode(@Nullable PorterDuff.Mode tintMode) {
+        if (mCompoundButtonHelper != null) {
+            mCompoundButtonHelper.setSupportButtonTintMode(tintMode);
+        }
+    }
+
+    /**
+     * This should be accessed from {@link android.support.v4.widget.CompoundButtonCompat}
+     * @hide
+     */
+    @Nullable
+    @Override
+    public PorterDuff.Mode getSupportButtonTintMode() {
+        return mCompoundButtonHelper != null
+                ? mCompoundButtonHelper.getSupportButtonTintMode()
+                : null;
+    }
 }
diff --git a/v7/appcompat/src/android/support/v7/widget/AppCompatCheckedTextView.java b/v7/appcompat/src/android/support/v7/widget/AppCompatCheckedTextView.java
index 04836c6..4776b83 100644
--- a/v7/appcompat/src/android/support/v7/widget/AppCompatCheckedTextView.java
+++ b/v7/appcompat/src/android/support/v7/widget/AppCompatCheckedTextView.java
@@ -18,17 +18,16 @@
 
 import android.content.Context;
 import android.support.annotation.DrawableRes;
-import android.support.v7.appcompat.R;
 import android.support.v7.internal.widget.TintManager;
 import android.support.v7.internal.widget.TintTypedArray;
 import android.util.AttributeSet;
 import android.widget.CheckedTextView;
 
 /**
- * A tint aware {@link android.widget.CheckedTextView}.
- * <p>
- * This will automatically be used when you use {@link android.widget.CheckedTextView} in your
- * layouts. You should only need to manually use this class when writing custom views.
+ * A {@link CheckedTextView} which supports compatible features on older version of the platform.
+ *
+ * <p>This will automatically be used when you use {@link CheckedTextView} in your layouts.
+ * You should only need to manually use this class when writing custom views.</p>
  */
 public class AppCompatCheckedTextView extends CheckedTextView {
 
diff --git a/v7/appcompat/src/android/support/v7/widget/AppCompatCompoundButtonHelper.java b/v7/appcompat/src/android/support/v7/widget/AppCompatCompoundButtonHelper.java
new file mode 100644
index 0000000..20c3667
--- /dev/null
+++ b/v7/appcompat/src/android/support/v7/widget/AppCompatCompoundButtonHelper.java
@@ -0,0 +1,147 @@
+/*
+ * 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.v7.widget;
+
+import android.content.res.ColorStateList;
+import android.content.res.TypedArray;
+import android.graphics.PorterDuff;
+import android.graphics.drawable.Drawable;
+import android.os.Build;
+import android.support.annotation.Nullable;
+import android.support.v4.graphics.drawable.DrawableCompat;
+import android.support.v4.widget.CompoundButtonCompat;
+import android.support.v7.appcompat.R;
+import android.support.v7.graphics.drawable.DrawableUtils;
+import android.support.v7.internal.widget.TintManager;
+import android.util.AttributeSet;
+import android.widget.CompoundButton;
+
+class AppCompatCompoundButtonHelper {
+
+    private final CompoundButton mView;
+    private final TintManager mTintManager;
+
+    private ColorStateList mButtonTintList = null;
+    private PorterDuff.Mode mButtonTintMode = null;
+    private boolean mHasButtonTint = false;
+    private boolean mHasButtonTintMode = false;
+
+    private boolean mSkipNextApply;
+
+    /**
+     * Interface which allows us to directly set a button, bypass any calls back to ourselves.
+     */
+    interface DirectSetButtonDrawableInterface {
+        void setButtonDrawable(Drawable buttonDrawable);
+    }
+
+    AppCompatCompoundButtonHelper(CompoundButton view, TintManager tintManager) {
+        mView = view;
+        mTintManager = tintManager;
+    }
+
+    void loadFromAttributes(AttributeSet attrs, int defStyleAttr) {
+        TypedArray a = mView.getContext().obtainStyledAttributes(attrs, R.styleable.CompoundButton,
+                defStyleAttr, 0);
+        try {
+            if (a.hasValue(R.styleable.CompoundButton_android_button)) {
+                final int resourceId = a.getResourceId(
+                        R.styleable.CompoundButton_android_button, 0);
+                if (resourceId != 0) {
+                    mView.setButtonDrawable(mTintManager.getDrawable(resourceId));
+                }
+            }
+            if (a.hasValue(R.styleable.CompoundButton_buttonTint)) {
+                CompoundButtonCompat.setButtonTintList(mView,
+                        a.getColorStateList(R.styleable.CompoundButton_buttonTint));
+            }
+            if (a.hasValue(R.styleable.CompoundButton_buttonTintMode)) {
+                CompoundButtonCompat.setButtonTintMode(mView,
+                        DrawableUtils.parseTintMode(
+                                a.getInt(R.styleable.CompoundButton_buttonTintMode, -1),
+                                null));
+            }
+        } finally {
+            a.recycle();
+        }
+    }
+
+    void setSupportButtonTintList(ColorStateList tint) {
+        mButtonTintList = tint;
+        mHasButtonTint = true;
+
+        applyButtonTint();
+    }
+
+    ColorStateList getSupportButtonTintList() {
+        return mButtonTintList;
+    }
+
+    void setSupportButtonTintMode(@Nullable PorterDuff.Mode tintMode) {
+        mButtonTintMode = tintMode;
+        mHasButtonTintMode = true;
+
+        applyButtonTint();
+    }
+
+    PorterDuff.Mode getSupportButtonTintMode() {
+        return mButtonTintMode;
+    }
+
+    void onSetButtonDrawable() {
+        if (mSkipNextApply) {
+            mSkipNextApply = false;
+            return;
+        }
+
+        mSkipNextApply = true;
+        applyButtonTint();
+    }
+
+    void applyButtonTint() {
+        Drawable buttonDrawable = CompoundButtonCompat.getButtonDrawable(mView);
+
+        if (buttonDrawable != null && (mHasButtonTint || mHasButtonTintMode)) {
+            buttonDrawable = DrawableCompat.wrap(buttonDrawable);
+            buttonDrawable = buttonDrawable.mutate();
+            if (mHasButtonTint) {
+                DrawableCompat.setTintList(buttonDrawable, mButtonTintList);
+            }
+            if (mHasButtonTintMode) {
+                DrawableCompat.setTintMode(buttonDrawable, mButtonTintMode);
+            }
+            // The drawable (or one of its children) may not have been
+            // stateful before applying the tint, so let's try again.
+            if (buttonDrawable.isStateful()) {
+                buttonDrawable.setState(mView.getDrawableState());
+            }
+            mView.setButtonDrawable(buttonDrawable);
+        }
+    }
+
+    int getCompoundPaddingLeft(int superValue) {
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
+            // Before JB-MR1 the button drawable wasn't taken into account for padding. We'll
+            // workaround that here
+            Drawable buttonDrawable = CompoundButtonCompat.getButtonDrawable(mView);
+            if (buttonDrawable != null) {
+                superValue += buttonDrawable.getIntrinsicWidth();
+            }
+        }
+        return superValue;
+    }
+}
diff --git a/v7/appcompat/src/android/support/v7/widget/AppCompatEditText.java b/v7/appcompat/src/android/support/v7/widget/AppCompatEditText.java
index 8df271f..885fd6d 100644
--- a/v7/appcompat/src/android/support/v7/widget/AppCompatEditText.java
+++ b/v7/appcompat/src/android/support/v7/widget/AppCompatEditText.java
@@ -20,31 +20,35 @@
 import android.content.res.ColorStateList;
 import android.graphics.PorterDuff;
 import android.graphics.drawable.Drawable;
+import android.support.annotation.DrawableRes;
 import android.support.annotation.Nullable;
 import android.support.v4.view.TintableBackgroundView;
 import android.support.v7.appcompat.R;
 import android.support.v7.internal.widget.TintContextWrapper;
-import android.support.v7.internal.widget.TintInfo;
 import android.support.v7.internal.widget.TintManager;
-import android.support.v7.internal.widget.TintTypedArray;
 import android.util.AttributeSet;
 import android.widget.EditText;
 
 /**
- * A tint aware {@link android.widget.EditText}.
- * <p>
- * This will automatically be used when you use {@link android.widget.EditText} in your
- * layouts. You should only need to manually use this class when writing custom views.
+ * A {@link EditText} which supports compatible features on older version of the platform,
+ * including:
+ * <ul>
+ *     <li>Supports {@link R.attr#textAllCaps} style attribute which works back to
+ *     {@link android.os.Build.VERSION_CODES#ECLAIR_MR1 Eclair MR1}.</li>
+ *     <li>Allows dynamic tint of it background via the background tint methods in
+ *     {@link android.support.v4.view.ViewCompat}.</li>
+ *     <li>Allows setting of the background tint using {@link R.attr#backgroundTint} and
+ *     {@link R.attr#backgroundTintMode}.</li>
+ * </ul>
+ *
+ * <p>This will automatically be used when you use {@link android.widget.EditText} in your
+ * layouts. You should only need to manually use this class when writing custom views.</p>
  */
 public class AppCompatEditText extends EditText implements TintableBackgroundView {
 
-    private static final int[] TINT_ATTRS = {
-            android.R.attr.background
-    };
-
-    private TintInfo mInternalBackgroundTint;
-    private TintInfo mBackgroundTint;
     private TintManager mTintManager;
+    private AppCompatBackgroundHelper mBackgroundTintHelper;
+    private AppCompatTextHelper mTextHelper;
 
     public AppCompatEditText(Context context) {
         this(context, null);
@@ -57,50 +61,41 @@
     public AppCompatEditText(Context context, AttributeSet attrs, int defStyleAttr) {
         super(TintContextWrapper.wrap(context), attrs, defStyleAttr);
 
-        if (TintManager.SHOULD_BE_USED) {
-            TintTypedArray a = TintTypedArray.obtainStyledAttributes(getContext(), attrs,
-                    TINT_ATTRS, defStyleAttr, 0);
-            if (a.hasValue(0)) {
-                ColorStateList tint = a.getTintManager().getTintList(a.getResourceId(0, -1));
-                if (tint != null) {
-                    setInternalBackgroundTint(tint);
-                }
-            }
-            mTintManager = a.getTintManager();
-            a.recycle();
-        }
+        mTintManager = TintManager.get(getContext());
+        mBackgroundTintHelper = new AppCompatBackgroundHelper(this, mTintManager);
+        mBackgroundTintHelper.loadFromAttributes(attrs, defStyleAttr);
+
+        mTextHelper = new AppCompatTextHelper(this);
+        mTextHelper.loadFromAttributes(attrs, defStyleAttr);
     }
 
     @Override
-    public void setBackgroundResource(int resId) {
+    public void setBackgroundResource(@DrawableRes int resId) {
         super.setBackgroundResource(resId);
-        // Update the default background tint
-        setInternalBackgroundTint(mTintManager != null ? mTintManager.getTintList(resId) : null);
+        if (mBackgroundTintHelper != null) {
+            mBackgroundTintHelper.onSetBackgroundResource(resId);
+        }
     }
 
     @Override
     public void setBackgroundDrawable(Drawable background) {
         super.setBackgroundDrawable(background);
-        // We don't know that this drawable is, so we need to clear the default background tint
-        setInternalBackgroundTint(null);
+        if (mBackgroundTintHelper != null) {
+            mBackgroundTintHelper.onSetBackgroundDrawable(background);
+        }
     }
 
     /**
      * This should be accessed via
-     * {@link android.support.v4.view.ViewCompat#setBackgroundTintList(android.view.View,
-     * android.content.res.ColorStateList)}
+     * {@link android.support.v4.view.ViewCompat#setBackgroundTintList(android.view.View, ColorStateList)}
      *
      * @hide
      */
     @Override
     public void setSupportBackgroundTintList(@Nullable ColorStateList tint) {
-        if (mBackgroundTint == null) {
-            mBackgroundTint = new TintInfo();
+        if (mBackgroundTintHelper != null) {
+            mBackgroundTintHelper.setSupportBackgroundTintList(tint);
         }
-        mBackgroundTint.mTintList = tint;
-        mBackgroundTint.mHasTintList = true;
-
-        applySupportBackgroundTint();
     }
 
     /**
@@ -112,24 +107,21 @@
     @Override
     @Nullable
     public ColorStateList getSupportBackgroundTintList() {
-        return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
+        return mBackgroundTintHelper != null
+                ? mBackgroundTintHelper.getSupportBackgroundTintList() : null;
     }
 
     /**
      * This should be accessed via
-     * {@link android.support.v4.view.ViewCompat#setBackgroundTintMode(android.view.View, android.graphics.PorterDuff.Mode)}
+     * {@link android.support.v4.view.ViewCompat#setBackgroundTintMode(android.view.View, PorterDuff.Mode)}
      *
      * @hide
      */
     @Override
     public void setSupportBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
-        if (mBackgroundTint == null) {
-            mBackgroundTint = new TintInfo();
+        if (mBackgroundTintHelper != null) {
+            mBackgroundTintHelper.setSupportBackgroundTintMode(tintMode);
         }
-        mBackgroundTint.mTintMode = tintMode;
-        mBackgroundTint.mHasTintMode = true;
-
-        applySupportBackgroundTint();
     }
 
     /**
@@ -141,35 +133,23 @@
     @Override
     @Nullable
     public PorterDuff.Mode getSupportBackgroundTintMode() {
-        return mBackgroundTint != null ? mBackgroundTint.mTintMode : null;
+        return mBackgroundTintHelper != null
+                ? mBackgroundTintHelper.getSupportBackgroundTintMode() : null;
     }
 
     @Override
     protected void drawableStateChanged() {
         super.drawableStateChanged();
-        applySupportBackgroundTint();
-    }
-
-    private void applySupportBackgroundTint() {
-        if (getBackground() != null) {
-            if (mBackgroundTint != null) {
-                TintManager.tintViewBackground(this, mBackgroundTint);
-            } else if (mInternalBackgroundTint != null) {
-                TintManager.tintViewBackground(this, mInternalBackgroundTint);
-            }
+        if (mBackgroundTintHelper != null) {
+            mBackgroundTintHelper.applySupportBackgroundTint();
         }
     }
 
-    private void setInternalBackgroundTint(ColorStateList tint) {
-        if (tint != null) {
-            if (mInternalBackgroundTint == null) {
-                mInternalBackgroundTint = new TintInfo();
-            }
-            mInternalBackgroundTint.mTintList = tint;
-            mInternalBackgroundTint.mHasTintList = true;
-        } else {
-            mInternalBackgroundTint = null;
+    @Override
+    public void setTextAppearance(Context context, int resId) {
+        super.setTextAppearance(context, resId);
+        if (mTextHelper != null) {
+            mTextHelper.onSetTextAppearance(context, resId);
         }
-        applySupportBackgroundTint();
     }
 }
diff --git a/v7/appcompat/src/android/support/v7/widget/AppCompatMultiAutoCompleteTextView.java b/v7/appcompat/src/android/support/v7/widget/AppCompatMultiAutoCompleteTextView.java
index 7334cc4..6f97adb 100644
--- a/v7/appcompat/src/android/support/v7/widget/AppCompatMultiAutoCompleteTextView.java
+++ b/v7/appcompat/src/android/support/v7/widget/AppCompatMultiAutoCompleteTextView.java
@@ -25,29 +25,36 @@
 import android.support.v4.view.TintableBackgroundView;
 import android.support.v7.appcompat.R;
 import android.support.v7.internal.widget.TintContextWrapper;
-import android.support.v7.internal.widget.TintInfo;
 import android.support.v7.internal.widget.TintManager;
 import android.support.v7.internal.widget.TintTypedArray;
 import android.util.AttributeSet;
 import android.widget.MultiAutoCompleteTextView;
 
 /**
- * A tint aware {@link android.widget.MultiAutoCompleteTextView}.
- * <p>
- * This will automatically be used when you use {@link android.widget.MultiAutoCompleteTextView}
- * in your layouts. You should only need to manually use this class when writing custom views.
+ * A {@link MultiAutoCompleteTextView} which supports compatible features on older version of the
+ * platform, including:
+ * <ul>
+ *     <li>Supports {@link R.attr#textAllCaps} style attribute which works back to
+ *     {@link android.os.Build.VERSION_CODES#ECLAIR_MR1 Eclair MR1}.</li>
+ *     <li>Allows dynamic tint of it background via the background tint methods in
+ *     {@link android.support.v4.view.ViewCompat}.</li>
+ *     <li>Allows setting of the background tint using {@link R.attr#backgroundTint} and
+ *     {@link R.attr#backgroundTintMode}.</li>
+ * </ul>
+ *
+ * <p>This will automatically be used when you use {@link MultiAutoCompleteTextView} in your layouts.
+ * You should only need to manually use this class when writing custom views.</p>
  */
 public class AppCompatMultiAutoCompleteTextView extends MultiAutoCompleteTextView
         implements TintableBackgroundView {
 
     private static final int[] TINT_ATTRS = {
-            android.R.attr.background,
             android.R.attr.popupBackground
     };
 
-    private TintInfo mInternalBackgroundTint;
-    private TintInfo mBackgroundTint;
     private TintManager mTintManager;
+    private AppCompatBackgroundHelper mBackgroundTintHelper;
+    private AppCompatTextHelper mTextHelper;
 
     public AppCompatMultiAutoCompleteTextView(Context context) {
         this(context, null);
@@ -60,63 +67,57 @@
     public AppCompatMultiAutoCompleteTextView(Context context, AttributeSet attrs, int defStyleAttr) {
         super(TintContextWrapper.wrap(context), attrs, defStyleAttr);
 
-        if (TintManager.SHOULD_BE_USED) {
-            TintTypedArray a = TintTypedArray.obtainStyledAttributes(getContext(), attrs,
-                    TINT_ATTRS, defStyleAttr, 0);
-            mTintManager = a.getTintManager();
+        TintTypedArray a = TintTypedArray.obtainStyledAttributes(getContext(), attrs,
+                TINT_ATTRS, defStyleAttr, 0);
+        mTintManager = a.getTintManager();
+        if (a.hasValue(0)) {
+            setDropDownBackgroundDrawable(a.getDrawable(0));
+        }
+        a.recycle();
 
-            if (a.hasValue(0)) {
-                ColorStateList tint = a.getTintManager().getTintList(a.getResourceId(0, -1));
-                if (tint != null) {
-                    setInternalBackgroundTint(tint);
-                }
-            }
-            if (a.hasValue(1)) {
-                setDropDownBackgroundDrawable(a.getDrawable(1));
-            }
-            a.recycle();
+        mBackgroundTintHelper = new AppCompatBackgroundHelper(this, mTintManager);
+        mBackgroundTintHelper.loadFromAttributes(attrs, defStyleAttr);
+
+        mTextHelper = new AppCompatTextHelper(this);
+        mTextHelper.loadFromAttributes(attrs, defStyleAttr);
+    }
+
+    @Override
+    public void setDropDownBackgroundResource(@DrawableRes int resId) {
+        if (mTintManager != null) {
+            setDropDownBackgroundDrawable(mTintManager.getDrawable(resId));
+        } else {
+            super.setDropDownBackgroundResource(resId);
         }
     }
 
     @Override
-    public void setBackgroundResource(int resId) {
+    public void setBackgroundResource(@DrawableRes int resId) {
         super.setBackgroundResource(resId);
-        // Update the default background tint
-        setInternalBackgroundTint(mTintManager != null ? mTintManager.getTintList(resId) : null);
+        if (mBackgroundTintHelper != null) {
+            mBackgroundTintHelper.onSetBackgroundResource(resId);
+        }
     }
 
     @Override
     public void setBackgroundDrawable(Drawable background) {
         super.setBackgroundDrawable(background);
-        // We don't know that this drawable is, so we need to clear the default background tint
-        setInternalBackgroundTint(null);
-    }
-
-    @Override
-    public void setDropDownBackgroundResource(@DrawableRes int id) {
-        if (mTintManager != null) {
-            setDropDownBackgroundDrawable(mTintManager.getDrawable(id));
-        } else {
-            super.setDropDownBackgroundResource(id);
+        if (mBackgroundTintHelper != null) {
+            mBackgroundTintHelper.onSetBackgroundDrawable(background);
         }
     }
 
     /**
      * This should be accessed via
-     * {@link android.support.v4.view.ViewCompat#setBackgroundTintList(android.view.View,
-     * android.content.res.ColorStateList)}
+     * {@link android.support.v4.view.ViewCompat#setBackgroundTintList(android.view.View, ColorStateList)}
      *
      * @hide
      */
     @Override
     public void setSupportBackgroundTintList(@Nullable ColorStateList tint) {
-        if (mBackgroundTint == null) {
-            mBackgroundTint = new TintInfo();
+        if (mBackgroundTintHelper != null) {
+            mBackgroundTintHelper.setSupportBackgroundTintList(tint);
         }
-        mBackgroundTint.mTintList = tint;
-        mBackgroundTint.mHasTintList = true;
-
-        applySupportBackgroundTint();
     }
 
     /**
@@ -128,24 +129,21 @@
     @Override
     @Nullable
     public ColorStateList getSupportBackgroundTintList() {
-        return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
+        return mBackgroundTintHelper != null
+                ? mBackgroundTintHelper.getSupportBackgroundTintList() : null;
     }
 
     /**
      * This should be accessed via
-     * {@link android.support.v4.view.ViewCompat#setBackgroundTintMode(android.view.View, android.graphics.PorterDuff.Mode)}
+     * {@link android.support.v4.view.ViewCompat#setBackgroundTintMode(android.view.View, PorterDuff.Mode)}
      *
      * @hide
      */
     @Override
     public void setSupportBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
-        if (mBackgroundTint == null) {
-            mBackgroundTint = new TintInfo();
+        if (mBackgroundTintHelper != null) {
+            mBackgroundTintHelper.setSupportBackgroundTintMode(tintMode);
         }
-        mBackgroundTint.mTintMode = tintMode;
-        mBackgroundTint.mHasTintMode = true;
-
-        applySupportBackgroundTint();
     }
 
     /**
@@ -157,35 +155,23 @@
     @Override
     @Nullable
     public PorterDuff.Mode getSupportBackgroundTintMode() {
-        return mBackgroundTint != null ? mBackgroundTint.mTintMode : null;
+        return mBackgroundTintHelper != null
+                ? mBackgroundTintHelper.getSupportBackgroundTintMode() : null;
     }
 
     @Override
     protected void drawableStateChanged() {
         super.drawableStateChanged();
-        applySupportBackgroundTint();
-    }
-
-    private void applySupportBackgroundTint() {
-        if (getBackground() != null) {
-            if (mBackgroundTint != null) {
-                TintManager.tintViewBackground(this, mBackgroundTint);
-            } else if (mInternalBackgroundTint != null) {
-                TintManager.tintViewBackground(this, mInternalBackgroundTint);
-            }
+        if (mBackgroundTintHelper != null) {
+            mBackgroundTintHelper.applySupportBackgroundTint();
         }
     }
 
-    private void setInternalBackgroundTint(ColorStateList tint) {
-        if (tint != null) {
-            if (mInternalBackgroundTint == null) {
-                mInternalBackgroundTint = new TintInfo();
-            }
-            mInternalBackgroundTint.mTintList = tint;
-            mInternalBackgroundTint.mHasTintList = true;
-        } else {
-            mInternalBackgroundTint = null;
+    @Override
+    public void setTextAppearance(Context context, int resId) {
+        super.setTextAppearance(context, resId);
+        if (mTextHelper != null) {
+            mTextHelper.onSetTextAppearance(context, resId);
         }
-        applySupportBackgroundTint();
     }
 }
diff --git a/v7/appcompat/src/android/support/v7/widget/AppCompatRadioButton.java b/v7/appcompat/src/android/support/v7/widget/AppCompatRadioButton.java
index a9df4dc..0d928fc 100644
--- a/v7/appcompat/src/android/support/v7/widget/AppCompatRadioButton.java
+++ b/v7/appcompat/src/android/support/v7/widget/AppCompatRadioButton.java
@@ -17,29 +17,35 @@
 package android.support.v7.widget;
 
 import android.content.Context;
+import android.content.res.ColorStateList;
+import android.graphics.PorterDuff;
 import android.graphics.drawable.Drawable;
-import android.os.Build;
 import android.support.annotation.DrawableRes;
+import android.support.annotation.Nullable;
+import android.support.v4.content.ContextCompat;
+import android.support.v4.widget.TintableCompoundButton;
 import android.support.v7.appcompat.R;
 import android.support.v7.internal.widget.TintManager;
-import android.support.v7.internal.widget.TintTypedArray;
 import android.util.AttributeSet;
 import android.widget.RadioButton;
 
 /**
- * A tint aware {@link android.widget.RadioButton}.
- * <p>
- * This will automatically be used when you use {@link android.widget.RadioButton} in your
- * layouts. You should only need to manually use this class when writing custom views.
+ * A {@link RadioButton} which supports compatible features on older version of the platform,
+ * including:
+ * <ul>
+ *     <li>Allows dynamic tint of it background via the background tint methods in
+ *     {@link android.support.v4.widget.CompoundButtonCompat}.</li>
+ *     <li>Allows setting of the background tint using {@link R.attr#buttonTint} and
+ *     {@link R.attr#buttonTintMode}.</li>
+ * </ul>
+ *
+ * <p>This will automatically be used when you use {@link RadioButton} in your layouts.
+ * You should only need to manually use this class when writing custom views.</p>
  */
-public class AppCompatRadioButton extends RadioButton {
-
-    private static final int[] TINT_ATTRS = {
-            android.R.attr.button
-    };
+public class AppCompatRadioButton extends RadioButton implements TintableCompoundButton {
 
     private TintManager mTintManager;
-    private Drawable mButtonDrawable;
+    private AppCompatCompoundButtonHelper mCompoundButtonHelper;
 
     public AppCompatRadioButton(Context context) {
         this(context, null);
@@ -51,42 +57,77 @@
 
     public AppCompatRadioButton(Context context, AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
-
-        if (TintManager.SHOULD_BE_USED) {
-            TintTypedArray a = TintTypedArray.obtainStyledAttributes(getContext(), attrs,
-                    TINT_ATTRS, defStyleAttr, 0);
-            setButtonDrawable(a.getDrawable(0));
-            a.recycle();
-
-            mTintManager = a.getTintManager();
-        }
+        mTintManager = TintManager.get(context);
+        mCompoundButtonHelper = new AppCompatCompoundButtonHelper(this, mTintManager);
+        mCompoundButtonHelper.loadFromAttributes(attrs, defStyleAttr);
     }
 
     @Override
     public void setButtonDrawable(Drawable buttonDrawable) {
         super.setButtonDrawable(buttonDrawable);
-        mButtonDrawable = buttonDrawable;
+        if (mCompoundButtonHelper != null) {
+            mCompoundButtonHelper.onSetButtonDrawable();
+        }
     }
 
     @Override
-    public void setButtonDrawable(@DrawableRes int resid) {
-        if (mTintManager != null) {
-            setButtonDrawable(mTintManager.getDrawable(resid));
-        } else {
-            super.setButtonDrawable(resid);
-        }
+    public void setButtonDrawable(@DrawableRes int resId) {
+        setButtonDrawable(mTintManager != null
+                ? mTintManager.getDrawable(resId)
+                : ContextCompat.getDrawable(getContext(), resId));
     }
 
     @Override
     public int getCompoundPaddingLeft() {
-        int padding = super.getCompoundPaddingLeft();
-        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
-            // Before JB-MR1 the button drawable wasn't taken into account for padding. We'll
-            // workaround that here
-            if (mButtonDrawable != null) {
-                padding += mButtonDrawable.getIntrinsicWidth();
-            }
+        final int value = super.getCompoundPaddingLeft();
+        return mCompoundButtonHelper != null
+                ? mCompoundButtonHelper.getCompoundPaddingLeft(value)
+                : value;
+    }
+
+    /**
+     * This should be accessed from {@link android.support.v4.widget.CompoundButtonCompat}
+     * @hide
+     */
+    @Override
+    public void setSupportButtonTintList(@Nullable ColorStateList tint) {
+        if (mCompoundButtonHelper != null) {
+            mCompoundButtonHelper.setSupportButtonTintList(tint);
         }
-        return padding;
+    }
+
+    /**
+     * This should be accessed from {@link android.support.v4.widget.CompoundButtonCompat}
+     * @hide
+     */
+    @Nullable
+    @Override
+    public ColorStateList getSupportButtonTintList() {
+        return mCompoundButtonHelper != null
+                ? mCompoundButtonHelper.getSupportButtonTintList()
+                : null;
+    }
+
+    /**
+     * This should be accessed from {@link android.support.v4.widget.CompoundButtonCompat}
+     * @hide
+     */
+    @Override
+    public void setSupportButtonTintMode(@Nullable PorterDuff.Mode tintMode) {
+        if (mCompoundButtonHelper != null) {
+            mCompoundButtonHelper.setSupportButtonTintMode(tintMode);
+        }
+    }
+
+    /**
+     * This should be accessed from {@link android.support.v4.widget.CompoundButtonCompat}
+     * @hide
+     */
+    @Nullable
+    @Override
+    public PorterDuff.Mode getSupportButtonTintMode() {
+        return mCompoundButtonHelper != null
+                ? mCompoundButtonHelper.getSupportButtonTintMode()
+                : null;
     }
 }
diff --git a/v7/appcompat/src/android/support/v7/widget/AppCompatRatingBar.java b/v7/appcompat/src/android/support/v7/widget/AppCompatRatingBar.java
index daf2650..51811a8 100644
--- a/v7/appcompat/src/android/support/v7/widget/AppCompatRatingBar.java
+++ b/v7/appcompat/src/android/support/v7/widget/AppCompatRatingBar.java
@@ -38,10 +38,10 @@
 import android.widget.RatingBar;
 
 /**
- * A tint aware {@link android.widget.RatingBar}.
- * <p>
- * This will automatically be used when you use {@link android.widget.RatingBar} in your
- * layouts. You should only need to manually use this class when writing custom views.
+ * A {@link RatingBar} which supports compatible features on older version of the platform.
+ *
+ * <p>This will automatically be used when you use {@link RatingBar} in your layouts.
+ * You should only need to manually use this class when writing custom views.</p>
  */
 public class AppCompatRatingBar extends RatingBar {
 
diff --git a/v7/appcompat/src/android/support/v7/widget/AppCompatSpinner.java b/v7/appcompat/src/android/support/v7/widget/AppCompatSpinner.java
index 4ce1275..c50afb5 100644
--- a/v7/appcompat/src/android/support/v7/widget/AppCompatSpinner.java
+++ b/v7/appcompat/src/android/support/v7/widget/AppCompatSpinner.java
@@ -22,10 +22,10 @@
 import android.graphics.PorterDuff;
 import android.graphics.drawable.Drawable;
 import android.os.Build;
+import android.support.annotation.DrawableRes;
 import android.support.annotation.Nullable;
 import android.support.v4.view.TintableBackgroundView;
 import android.support.v7.appcompat.R;
-import android.support.v7.internal.widget.TintInfo;
 import android.support.v7.internal.widget.TintManager;
 import android.support.v7.internal.widget.TintTypedArray;
 import android.util.AttributeSet;
@@ -35,21 +35,26 @@
 import java.lang.reflect.Field;
 
 /**
- * A tint aware {@link android.widget.Spinner}.
- * <p>
- * This will automatically be used when you use {@link android.widget.Spinner} in your
- * layouts. You should only need to manually use this class when writing custom views.
+ * A {@link Spinner} which supports compatible features on older version of the platform,
+ * including:
+ * <ul>
+ *     <li>Allows dynamic tint of it background via the background tint methods in
+ *     {@link android.support.v4.view.ViewCompat}.</li>
+ *     <li>Allows setting of the background tint using {@link R.attr#backgroundTint} and
+ *     {@link R.attr#backgroundTintMode}.</li>
+ * </ul>
+ *
+ * <p>This will automatically be used when you use {@link Spinner} in your layouts.
+ * You should only need to manually use this class when writing custom views.</p>
  */
 public class AppCompatSpinner extends Spinner implements TintableBackgroundView {
 
     private static final int[] TINT_ATTRS = {
-            android.R.attr.background,
             android.R.attr.popupBackground
     };
 
-    private TintInfo mInternalBackgroundTint;
-    private TintInfo mBackgroundTint;
     private TintManager mTintManager;
+    private AppCompatBackgroundHelper mBackgroundTintHelper;
 
     public AppCompatSpinner(Context context) {
         this(context, null);
@@ -62,40 +67,23 @@
     public AppCompatSpinner(Context context, AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
 
-        if (TintManager.SHOULD_BE_USED) {
-            TintTypedArray a = TintTypedArray.obtainStyledAttributes(getContext(), attrs,
-                    TINT_ATTRS, defStyleAttr, 0);
-            if (a.hasValue(0)) {
-                ColorStateList tint = a.getTintManager().getTintList(a.getResourceId(0, -1));
-                if (tint != null) {
-                    setInternalBackgroundTint(tint);
-                }
+        TintTypedArray a = TintTypedArray.obtainStyledAttributes(getContext(), attrs,
+                TINT_ATTRS, defStyleAttr, 0);
+        mTintManager = a.getTintManager();
+        mBackgroundTintHelper = new AppCompatBackgroundHelper(this, mTintManager);
+
+        if (a.hasValue(0)) {
+            final Drawable popupBackground = a.getDrawable(0);
+            if (Build.VERSION.SDK_INT >= 16) {
+                setPopupBackgroundDrawable(popupBackground);
+            } else if (Build.VERSION.SDK_INT >= 11) {
+                setPopupBackgroundDrawableV11(this, popupBackground);
             }
-            if (a.hasValue(1)) {
-                final Drawable popupBackground = a.getDrawable(1);
-                if (Build.VERSION.SDK_INT >= 16) {
-                    setPopupBackgroundDrawable(popupBackground);
-                } else if (Build.VERSION.SDK_INT >= 11) {
-                    setPopupBackgroundDrawableV11(this, popupBackground);
-                }
-            }
-            mTintManager = a.getTintManager();
-            a.recycle();
         }
-    }
+        a.recycle();
 
-    @Override
-    public void setBackgroundResource(int resId) {
-        super.setBackgroundResource(resId);
-        // Update the default background tint
-        setInternalBackgroundTint(mTintManager != null ? mTintManager.getTintList(resId) : null);
-    }
+        mBackgroundTintHelper.loadFromAttributes(attrs, defStyleAttr);
 
-    @Override
-    public void setBackgroundDrawable(Drawable background) {
-        super.setBackgroundDrawable(background);
-        // We don't know that this drawable is, so we need to clear the default background tint
-        setInternalBackgroundTint(null);
     }
 
     @TargetApi(Build.VERSION_CODES.HONEYCOMB)
@@ -116,22 +104,33 @@
         }
     }
 
+    @Override
+    public void setBackgroundResource(@DrawableRes int resId) {
+        super.setBackgroundResource(resId);
+        if (mBackgroundTintHelper != null) {
+            mBackgroundTintHelper.onSetBackgroundResource(resId);
+        }
+    }
+
+    @Override
+    public void setBackgroundDrawable(Drawable background) {
+        super.setBackgroundDrawable(background);
+        if (mBackgroundTintHelper != null) {
+            mBackgroundTintHelper.onSetBackgroundDrawable(background);
+        }
+    }
+
     /**
      * This should be accessed via
-     * {@link android.support.v4.view.ViewCompat#setBackgroundTintList(android.view.View,
-     * android.content.res.ColorStateList)}
+     * {@link android.support.v4.view.ViewCompat#setBackgroundTintList(android.view.View, ColorStateList)}
      *
      * @hide
      */
     @Override
     public void setSupportBackgroundTintList(@Nullable ColorStateList tint) {
-        if (mBackgroundTint == null) {
-            mBackgroundTint = new TintInfo();
+        if (mBackgroundTintHelper != null) {
+            mBackgroundTintHelper.setSupportBackgroundTintList(tint);
         }
-        mBackgroundTint.mTintList = tint;
-        mBackgroundTint.mHasTintList = true;
-
-        applySupportBackgroundTint();
     }
 
     /**
@@ -143,24 +142,21 @@
     @Override
     @Nullable
     public ColorStateList getSupportBackgroundTintList() {
-        return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
+        return mBackgroundTintHelper != null
+                ? mBackgroundTintHelper.getSupportBackgroundTintList() : null;
     }
 
     /**
      * This should be accessed via
-     * {@link android.support.v4.view.ViewCompat#setBackgroundTintMode(android.view.View, android.graphics.PorterDuff.Mode)}
+     * {@link android.support.v4.view.ViewCompat#setBackgroundTintMode(android.view.View, PorterDuff.Mode)}
      *
      * @hide
      */
     @Override
     public void setSupportBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
-        if (mBackgroundTint == null) {
-            mBackgroundTint = new TintInfo();
+        if (mBackgroundTintHelper != null) {
+            mBackgroundTintHelper.setSupportBackgroundTintMode(tintMode);
         }
-        mBackgroundTint.mTintMode = tintMode;
-        mBackgroundTint.mHasTintMode = true;
-
-        applySupportBackgroundTint();
     }
 
     /**
@@ -172,35 +168,15 @@
     @Override
     @Nullable
     public PorterDuff.Mode getSupportBackgroundTintMode() {
-        return mBackgroundTint != null ? mBackgroundTint.mTintMode : null;
+        return mBackgroundTintHelper != null
+                ? mBackgroundTintHelper.getSupportBackgroundTintMode() : null;
     }
 
     @Override
     protected void drawableStateChanged() {
         super.drawableStateChanged();
-        applySupportBackgroundTint();
-    }
-
-    private void applySupportBackgroundTint() {
-        if (getBackground() != null) {
-            if (mBackgroundTint != null) {
-                TintManager.tintViewBackground(this, mBackgroundTint);
-            } else if (mInternalBackgroundTint != null) {
-                TintManager.tintViewBackground(this, mInternalBackgroundTint);
-            }
+        if (mBackgroundTintHelper != null) {
+            mBackgroundTintHelper.applySupportBackgroundTint();
         }
     }
-
-    private void setInternalBackgroundTint(ColorStateList tint) {
-        if (tint != null) {
-            if (mInternalBackgroundTint == null) {
-                mInternalBackgroundTint = new TintInfo();
-            }
-            mInternalBackgroundTint.mTintList = tint;
-            mInternalBackgroundTint.mHasTintList = true;
-        } else {
-            mInternalBackgroundTint = null;
-        }
-        applySupportBackgroundTint();
-    }
 }
diff --git a/v7/appcompat/src/android/support/v7/widget/AppCompatTextHelper.java b/v7/appcompat/src/android/support/v7/widget/AppCompatTextHelper.java
new file mode 100644
index 0000000..7a75e76
--- /dev/null
+++ b/v7/appcompat/src/android/support/v7/widget/AppCompatTextHelper.java
@@ -0,0 +1,101 @@
+/*
+ * 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.v7.widget;
+
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.content.res.TypedArray;
+import android.os.Build;
+import android.support.v7.appcompat.R;
+import android.support.v7.internal.text.AllCapsTransformationMethod;
+import android.support.v7.internal.widget.ThemeUtils;
+import android.util.AttributeSet;
+import android.widget.TextView;
+
+class AppCompatTextHelper {
+
+    private static final int[] VIEW_ATTRS = {android.R.attr.textAppearance};
+    private static final int[] TEXT_APPEARANCE_ATTRS = {R.attr.textAllCaps};
+
+    private final TextView mView;
+
+    AppCompatTextHelper(TextView view) {
+        mView = view;
+    }
+
+    void loadFromAttributes(AttributeSet attrs, int defStyleAttr) {
+        Context context = mView.getContext();
+
+        // First read the TextAppearance style id
+        TypedArray a = context.obtainStyledAttributes(attrs, VIEW_ATTRS, defStyleAttr, 0);
+        final int ap = a.getResourceId(0, -1);
+        a.recycle();
+
+        // Now check TextAppearance's textAllCaps value
+        if (ap != -1) {
+            TypedArray appearance = context.obtainStyledAttributes(ap, R.styleable.TextAppearance);
+            if (appearance.hasValue(R.styleable.TextAppearance_textAllCaps)) {
+                setAllCaps(appearance.getBoolean(R.styleable.TextAppearance_textAllCaps, false));
+            }
+            appearance.recycle();
+        }
+
+        // Now read the style's value
+        a = context.obtainStyledAttributes(attrs, TEXT_APPEARANCE_ATTRS, defStyleAttr, 0);
+        if (a.hasValue(0)) {
+            setAllCaps(a.getBoolean(0, false));
+        }
+        a.recycle();
+
+        final ColorStateList textColors = mView.getTextColors();
+        if (textColors != null && !textColors.isStateful()) {
+            // If we have a ColorStateList which isn't stateful, create one which includes
+            // a disabled state
+
+            final int disabledTextColor;
+            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
+                // Pre-Lollipop, we will use textColorSecondary with android:disabledAlpha
+                // applied
+                disabledTextColor = ThemeUtils.getDisabledThemeAttrColor(context,
+                        android.R.attr.textColorSecondary);
+            } else {
+                // With certain styles on Lollipop, there is a StateListAnimator which sets
+                // an alpha on the whole view, so we don't need to apply disabledAlpha to
+                // textColorSecondary
+                disabledTextColor = ThemeUtils.getThemeAttrColor(context,
+                        android.R.attr.textColorSecondary);
+            }
+
+            mView.setTextColor(ThemeUtils.createDisabledStateList(
+                    textColors.getDefaultColor(), disabledTextColor));
+        }
+    }
+
+    void onSetTextAppearance(Context context, int resId) {
+        TypedArray appearance = context.obtainStyledAttributes(resId, TEXT_APPEARANCE_ATTRS);
+        if (appearance.hasValue(0)) {
+            setAllCaps(appearance.getBoolean(0, false));
+        }
+        appearance.recycle();
+    }
+
+    void setAllCaps(boolean allCaps) {
+        mView.setTransformationMethod(allCaps
+                ? new AllCapsTransformationMethod(mView.getContext())
+                : null);
+    }
+}
diff --git a/v7/appcompat/src/android/support/v7/widget/AppCompatTextView.java b/v7/appcompat/src/android/support/v7/widget/AppCompatTextView.java
index a05c4a8..ccedfe0 100644
--- a/v7/appcompat/src/android/support/v7/widget/AppCompatTextView.java
+++ b/v7/appcompat/src/android/support/v7/widget/AppCompatTextView.java
@@ -17,21 +17,25 @@
 package android.support.v7.widget;
 
 import android.content.Context;
-import android.content.res.TypedArray;
 import android.support.v7.appcompat.R;
-import android.support.v7.internal.text.AllCapsTransformationMethod;
 import android.util.AttributeSet;
 import android.widget.TextView;
 
 /**
- * A {@link android.widget.TextView} which supports compatible features on older version of the
- * platform.
- * <p>
- * This will automatically be used when you use {@link android.widget.TextView} in your
- * layouts. You should only need to manually use this class when writing custom views.
+ * A {@link TextView} which supports compatible features on older version of the platform,
+ * including:
+ * <ul>
+ *     <li>Supports {@link R.attr#textAllCaps} style attribute which works back to
+ *     {@link android.os.Build.VERSION_CODES#ECLAIR_MR1 Eclair MR1}.</li>
+ * </ul>
+ *
+ * <p>This will automatically be used when you use {@link TextView} in your layouts.
+ * You should only need to manually use this class when writing custom views.</p>
  */
 public class AppCompatTextView extends TextView {
 
+    private AppCompatTextHelper mTextHelper;
+
     public AppCompatTextView(Context context) {
         this(context, null);
     }
@@ -40,44 +44,18 @@
         this(context, attrs, android.R.attr.textViewStyle);
     }
 
-    public AppCompatTextView(Context context, AttributeSet attrs, int defStyle) {
-        super(context, attrs, defStyle);
+    public AppCompatTextView(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
 
-        // First read the TextAppearance style id
-        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.AppCompatTextView,
-                defStyle, 0);
-        final int ap = a.getResourceId(R.styleable.AppCompatTextView_android_textAppearance, -1);
-        a.recycle();
-
-        // Now check TextAppearance's textAllCaps value
-        if (ap != -1) {
-            TypedArray appearance = context.obtainStyledAttributes(ap, R.styleable.TextAppearance);
-            if (appearance.hasValue(R.styleable.TextAppearance_textAllCaps)) {
-                setAllCaps(appearance.getBoolean(R.styleable.TextAppearance_textAllCaps, false));
-            }
-            appearance.recycle();
-        }
-
-        // Now read the style's value
-        a = context.obtainStyledAttributes(attrs, R.styleable.AppCompatTextView, defStyle, 0);
-        if (a.hasValue(R.styleable.AppCompatTextView_textAllCaps)) {
-            setAllCaps(a.getBoolean(R.styleable.AppCompatTextView_textAllCaps, false));
-        }
-        a.recycle();
-    }
-
-    public void setAllCaps(boolean allCaps) {
-        setTransformationMethod(allCaps ? new AllCapsTransformationMethod(getContext()) : null);
+        mTextHelper = new AppCompatTextHelper(this);
+        mTextHelper.loadFromAttributes(attrs, defStyleAttr);
     }
 
     @Override
     public void setTextAppearance(Context context, int resId) {
         super.setTextAppearance(context, resId);
-
-        TypedArray appearance = context.obtainStyledAttributes(resId, R.styleable.TextAppearance);
-        if (appearance.hasValue(R.styleable.TextAppearance_textAllCaps)) {
-            setAllCaps(appearance.getBoolean(R.styleable.TextAppearance_textAllCaps, false));
+        if (mTextHelper != null) {
+            mTextHelper.onSetTextAppearance(context, resId);
         }
-        appearance.recycle();
     }
 }
diff --git a/v7/appcompat/src/android/support/v7/widget/PopupMenu.java b/v7/appcompat/src/android/support/v7/widget/PopupMenu.java
index 5b7d333..5c4dde8 100644
--- a/v7/appcompat/src/android/support/v7/widget/PopupMenu.java
+++ b/v7/appcompat/src/android/support/v7/widget/PopupMenu.java
@@ -114,6 +114,29 @@
     }
 
     /**
+     * Sets the gravity used to align the popup window to its anchor view.
+     * <p>
+     * If the popup is showing, calling this method will take effect only
+     * the next time the popup is shown.
+     *
+     * @param gravity the gravity used to align the popup window
+     *
+     * @see #getGravity()
+     */
+    public void setGravity(int gravity) {
+        mPopup.setGravity(gravity);
+    }
+
+    /**
+     * @return the gravity used to align the popup window to its anchor view
+     *
+     * @see #setGravity(int)
+     */
+    public int getGravity() {
+        return mPopup.getGravity();
+    }
+
+    /**
      * Returns an {@link android.view.View.OnTouchListener} that can be added to the anchor view
      * to implement drag-to-open behavior.
      * <p>
diff --git a/v7/appcompat/src/android/support/v7/widget/Toolbar.java b/v7/appcompat/src/android/support/v7/widget/Toolbar.java
index 970bbbb..0e8e318 100644
--- a/v7/appcompat/src/android/support/v7/widget/Toolbar.java
+++ b/v7/appcompat/src/android/support/v7/widget/Toolbar.java
@@ -17,12 +17,20 @@
 package android.support.v7.widget;
 
 import android.content.Context;
+import android.content.res.ColorStateList;
 import android.content.res.TypedArray;
+import android.graphics.PorterDuff;
 import android.graphics.drawable.Drawable;
 import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.support.annotation.ColorInt;
+import android.support.annotation.DrawableRes;
+import android.support.annotation.MenuRes;
+import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
+import android.support.annotation.StringRes;
+import android.support.annotation.StyleRes;
 import android.support.v4.view.GravityCompat;
 import android.support.v4.view.MarginLayoutParamsCompat;
 import android.support.v4.view.MenuItemCompat;
@@ -30,6 +38,7 @@
 import android.support.v4.view.ViewCompat;
 import android.support.v7.app.ActionBar;
 import android.support.v7.appcompat.R;
+import android.support.v7.graphics.drawable.DrawableUtils;
 import android.support.v7.internal.view.SupportMenuInflater;
 import android.support.v7.internal.view.menu.MenuBuilder;
 import android.support.v7.internal.view.menu.MenuItemImpl;
@@ -38,6 +47,7 @@
 import android.support.v7.internal.view.menu.SubMenuBuilder;
 import android.support.v7.internal.widget.DecorToolbar;
 import android.support.v7.internal.widget.RtlSpacingHelper;
+import android.support.v7.internal.widget.TintInfo;
 import android.support.v7.internal.widget.TintManager;
 import android.support.v7.internal.widget.TintTypedArray;
 import android.support.v7.internal.widget.ToolbarWidgetWrapper;
@@ -79,7 +89,9 @@
  *     <li><em>A navigation button.</em> This may be an Up arrow, navigation menu toggle, close,
  *     collapse, done or another glyph of the app's choosing. This button should always be used
  *     to access other navigational destinations within the container of the Toolbar and
- *     its signified content or otherwise leave the current context signified by the Toolbar.</li>
+ *     its signified content or otherwise leave the current context signified by the Toolbar.
+ *     The navigation button is vertically aligned within the Toolbar's minimum height,
+ *     if set.</li>
  *     <li><em>A branded logo image.</em> This may extend to the height of the bar and can be
  *     arbitrarily wide.</li>
  *     <li><em>A title and subtitle.</em> The title should be a signpost for the Toolbar's current
@@ -95,8 +107,9 @@
  *     <li><em>An {@link ActionMenuView action menu}.</em> The menu of actions will pin to the
  *     end of the Toolbar offering a few
  *     <a href="http://developer.android.com/design/patterns/actionbar.html#ActionButtons">
- *         frequent, important or typical</a> actions along with an optional overflow menu for
- *         additional actions.</li>
+ *     frequent, important or typical</a> actions along with an optional overflow menu for
+ *     additional actions. Action buttons are vertically aligned within the Toolbar's
+ *     minimum height, if set.</li>
  * </ul>
  * </p>
  *
@@ -152,6 +165,9 @@
     // Clear me after use.
     private final ArrayList<View> mTempViews = new ArrayList<View>();
 
+    // Used to hold views that will be removed while we have an expanded action view.
+    private final ArrayList<View> mHiddenViews = new ArrayList<>();
+
     private final int[] mTempMargins = new int[2];
 
     private OnMenuItemClickListener mOnMenuItemClickListener;
@@ -271,6 +287,23 @@
             setNavigationContentDescription(navDesc);
         }
 
+        final Drawable logo = a.getDrawable(R.styleable.Toolbar_logo);
+        if (logo != null) {
+            setLogo(logo);
+        }
+
+        final CharSequence logoDesc = a.getText(R.styleable.Toolbar_logoDescription);
+        if (!TextUtils.isEmpty(logoDesc)) {
+            setLogoDescription(logoDesc);
+        }
+
+        if (a.hasValue(R.styleable.Toolbar_titleTextColor)) {
+            setTitleTextColor(a.getColor(R.styleable.Toolbar_titleTextColor, 0xffffffff));
+        }
+
+        if (a.hasValue(R.styleable.Toolbar_subtitleTextColor)) {
+            setSubtitleTextColor(a.getColor(R.styleable.Toolbar_subtitleTextColor, 0xffffffff));
+        }
         a.recycle();
 
         // Keep the TintManager in case we need it later
@@ -284,7 +317,7 @@
      * @param resId theme used to inflate popup menus
      * @see #getPopupTheme()
      */
-    public void setPopupTheme(int resId) {
+    public void setPopupTheme(@StyleRes int resId) {
         if (mPopupTheme != resId) {
             mPopupTheme = resId;
             if (resId == 0) {
@@ -320,7 +353,7 @@
      *
      * @param resId ID of a drawable resource
      */
-    public void setLogo(int resId) {
+    public void setLogo(@DrawableRes int resId) {
         setLogo(mTintManager.getDrawable(resId));
     }
 
@@ -439,12 +472,12 @@
     public void setLogo(Drawable drawable) {
         if (drawable != null) {
             ensureLogoView();
-            if (mLogoView.getParent() == null) {
-                addSystemView(mLogoView);
-                updateChildVisibilityForExpandedActionView(mLogoView);
+            if (!isChildOrHidden(mLogoView)) {
+                addSystemView(mLogoView, true);
             }
-        } else if (mLogoView != null && mLogoView.getParent() != null) {
+        } else if (mLogoView != null && isChildOrHidden(mLogoView)) {
             removeView(mLogoView);
+            mHiddenViews.remove(mLogoView);
         }
         if (mLogoView != null) {
             mLogoView.setImageDrawable(drawable);
@@ -470,7 +503,7 @@
      *
      * @param resId String resource id
      */
-    public void setLogoDescription(int resId) {
+    public void setLogoDescription(@StringRes int resId) {
         setLogoDescription(getContext().getText(resId));
     }
 
@@ -555,7 +588,7 @@
      *
      * @param resId Resource ID of a string to set as the title
      */
-    public void setTitle(int resId) {
+    public void setTitle(@StringRes int resId) {
         setTitle(getContext().getText(resId));
     }
 
@@ -581,12 +614,12 @@
                     mTitleTextView.setTextColor(mTitleTextColor);
                 }
             }
-            if (mTitleTextView.getParent() == null) {
-                addSystemView(mTitleTextView);
-                updateChildVisibilityForExpandedActionView(mTitleTextView);
+            if (!isChildOrHidden(mTitleTextView)) {
+                addSystemView(mTitleTextView, true);
             }
-        } else if (mTitleTextView != null && mTitleTextView.getParent() != null) {
+        } else if (mTitleTextView != null && isChildOrHidden(mTitleTextView)) {
             removeView(mTitleTextView);
+            mHiddenViews.remove(mTitleTextView);
         }
         if (mTitleTextView != null) {
             mTitleTextView.setText(title);
@@ -610,7 +643,7 @@
      *
      * @param resId String resource ID
      */
-    public void setSubtitle(int resId) {
+    public void setSubtitle(@StringRes int resId) {
         setSubtitle(getContext().getText(resId));
     }
 
@@ -635,12 +668,12 @@
                     mSubtitleTextView.setTextColor(mSubtitleTextColor);
                 }
             }
-            if (mSubtitleTextView.getParent() == null) {
-                addSystemView(mSubtitleTextView);
-                updateChildVisibilityForExpandedActionView(mSubtitleTextView);
+            if (!isChildOrHidden(mSubtitleTextView)) {
+                addSystemView(mSubtitleTextView, true);
             }
-        } else if (mSubtitleTextView != null && mSubtitleTextView.getParent() != null) {
+        } else if (mSubtitleTextView != null && isChildOrHidden(mSubtitleTextView)) {
             removeView(mSubtitleTextView);
+            mHiddenViews.remove(mSubtitleTextView);
         }
         if (mSubtitleTextView != null) {
             mSubtitleTextView.setText(subtitle);
@@ -652,7 +685,7 @@
      * Sets the text color, size, style, hint color, and highlight color
      * from the specified TextAppearance resource.
      */
-    public void setTitleTextAppearance(Context context, int resId) {
+    public void setTitleTextAppearance(Context context, @StyleRes int resId) {
         mTitleTextAppearance = resId;
         if (mTitleTextView != null) {
             mTitleTextView.setTextAppearance(context, resId);
@@ -663,7 +696,7 @@
      * Sets the text color, size, style, hint color, and highlight color
      * from the specified TextAppearance resource.
      */
-    public void setSubtitleTextAppearance(Context context, int resId) {
+    public void setSubtitleTextAppearance(Context context, @StyleRes int resId) {
         mSubtitleTextAppearance = resId;
         if (mSubtitleTextView != null) {
             mSubtitleTextView.setTextAppearance(context, resId);
@@ -675,7 +708,7 @@
      *
      * @param color The new text color in 0xAARRGGBB format
      */
-    public void setTitleTextColor(int color) {
+    public void setTitleTextColor(@ColorInt int color) {
         mTitleTextColor = color;
         if (mTitleTextView != null) {
             mTitleTextView.setTextColor(color);
@@ -687,7 +720,7 @@
      *
      * @param color The new text color in 0xAARRGGBB format
      */
-    public void setSubtitleTextColor(int color) {
+    public void setSubtitleTextColor(@ColorInt int color) {
         mSubtitleTextColor = color;
         if (mSubtitleTextView != null) {
             mSubtitleTextView.setTextColor(color);
@@ -714,7 +747,7 @@
      * @param resId Resource ID of a content description string to set, or 0 to
      *              clear the description
      */
-    public void setNavigationContentDescription(int resId) {
+    public void setNavigationContentDescription(@StringRes int resId) {
         setNavigationContentDescription(resId != 0 ? getContext().getText(resId) : null);
     }
 
@@ -734,7 +767,7 @@
             mNavButtonView.setContentDescription(description);
         }
     }
-    
+
     /**
      * Set the icon to use for the toolbar's navigation button.
      *
@@ -747,7 +780,7 @@
      *
      * @param resId Resource ID of a drawable to set
      */
-    public void setNavigationIcon(int resId) {
+    public void setNavigationIcon(@DrawableRes int resId) {
         setNavigationIcon(mTintManager.getDrawable(resId));
     }
 
@@ -766,12 +799,12 @@
     public void setNavigationIcon(@Nullable Drawable icon) {
         if (icon != null) {
             ensureNavButtonView();
-            if (mNavButtonView.getParent() == null) {
-                addSystemView(mNavButtonView);
-                updateChildVisibilityForExpandedActionView(mNavButtonView);
+            if (!isChildOrHidden(mNavButtonView)) {
+                addSystemView(mNavButtonView, true);
             }
-        } else if (mNavButtonView != null && mNavButtonView.getParent() != null) {
+        } else if (mNavButtonView != null && isChildOrHidden(mNavButtonView)) {
             removeView(mNavButtonView);
+            mHiddenViews.remove(mNavButtonView);
         }
         if (mNavButtonView != null) {
             mNavButtonView.setImageDrawable(icon);
@@ -815,6 +848,27 @@
         return mMenuView.getMenu();
     }
 
+    /**
+     * Set the icon to use for the overflow button.
+     *
+     * @param icon Drawable to set, may be null to clear the icon
+     */
+    public void setOverflowIcon(@Nullable Drawable icon) {
+        ensureMenu();
+        mMenuView.setOverflowIcon(icon);
+    }
+
+    /**
+     * Return the current drawable used as the overflow icon.
+     *
+     * @return The overflow icon drawable
+     */
+    @Nullable
+    public Drawable getOverflowIcon() {
+        ensureMenu();
+        return mMenuView.getOverflowIcon();
+    }
+
     private void ensureMenu() {
         ensureMenuView();
         if (mMenuView.peekMenu() == null) {
@@ -837,7 +891,7 @@
             final LayoutParams lp = generateDefaultLayoutParams();
             lp.gravity = GravityCompat.END | (mButtonGravity & Gravity.VERTICAL_GRAVITY_MASK);
             mMenuView.setLayoutParams(lp);
-            addSystemView(mMenuView);
+            addSystemView(mMenuView, false);
         }
     }
 
@@ -853,7 +907,7 @@
      *
      * @param resId ID of a menu resource to inflate
      */
-    public void inflateMenu(int resId) {
+    public void inflateMenu(@MenuRes int resId) {
         getMenuInflater().inflate(resId, getMenu());
     }
 
@@ -1014,7 +1068,7 @@
         }
     }
 
-    private void addSystemView(View v) {
+    private void addSystemView(View v, boolean allowHide) {
         final ViewGroup.LayoutParams vlp = v.getLayoutParams();
         final LayoutParams lp;
         if (vlp == null) {
@@ -1025,7 +1079,13 @@
             lp = (LayoutParams) vlp;
         }
         lp.mViewType = LayoutParams.SYSTEM;
-        addView(v, lp);
+
+        if (allowHide && mExpandedActionView != null) {
+            v.setLayoutParams(lp);
+            mHiddenViews.add(v);
+        } else {
+            addView(v, lp);
+        }
     }
 
     @Override
@@ -1729,22 +1789,30 @@
         return mWrapper;
     }
 
-    private void setChildVisibilityForExpandedActionView(boolean expand) {
+    void removeChildrenForExpandedActionView() {
         final int childCount = getChildCount();
-        for (int i = 0; i < childCount; i++) {
+        // Go backwards since we're removing from the list
+        for (int i = childCount - 1; i >= 0; i--) {
             final View child = getChildAt(i);
             final LayoutParams lp = (LayoutParams) child.getLayoutParams();
             if (lp.mViewType != LayoutParams.EXPANDED && child != mMenuView) {
-                child.setVisibility(expand ? GONE : VISIBLE);
+                removeViewAt(i);
+                mHiddenViews.add(child);
             }
         }
     }
 
-    private void updateChildVisibilityForExpandedActionView(View child) {
-        final LayoutParams lp = (LayoutParams) child.getLayoutParams();
-        if (lp.mViewType != LayoutParams.EXPANDED && child != mMenuView) {
-            child.setVisibility(mExpandedActionView != null ? GONE : VISIBLE);
+    void addChildrenForExpandedActionView() {
+        final int count = mHiddenViews.size();
+        // Re-add in reverse order since we removed in reverse order
+        for (int i = count - 1; i >= 0; i--) {
+            addView(mHiddenViews.get(i));
         }
+        mHiddenViews.clear();
+    }
+
+    private boolean isChildOrHidden(View child) {
+        return child.getParent() == this || mHiddenViews.contains(child);
     }
 
     /**
@@ -1797,7 +1865,7 @@
 
         int mViewType = CUSTOM;
 
-        public LayoutParams(Context c, AttributeSet attrs) {
+        public LayoutParams(@NonNull Context c, AttributeSet attrs) {
             super(c, attrs);
         }
 
@@ -1954,7 +2022,7 @@
                 addView(mExpandedActionView);
             }
 
-            setChildVisibilityForExpandedActionView(true);
+            removeChildrenForExpandedActionView();
             requestLayout();
             item.setActionViewExpanded(true);
 
@@ -1977,7 +2045,7 @@
             removeView(mCollapseButtonView);
             mExpandedActionView = null;
 
-            setChildVisibilityForExpandedActionView(false);
+            addChildrenForExpandedActionView();
             mCurrentExpandedItem = null;
             requestLayout();
             item.setActionViewExpanded(false);
diff --git a/v7/gridlayout/tests/src/android/support/v7/widget/test/GridLayoutTest.java b/v7/gridlayout/tests/src/android/support/v7/widget/test/GridLayoutTest.java
index 3a3d10a..1a88be5 100644
--- a/v7/gridlayout/tests/src/android/support/v7/widget/test/GridLayoutTest.java
+++ b/v7/gridlayout/tests/src/android/support/v7/widget/test/GridLayoutTest.java
@@ -20,7 +20,7 @@
 import android.os.Debug;
 import android.support.v7.widget.GridLayout;
 import android.test.ActivityInstrumentationTestCase2;
-import android.support.v7.gridlayout.test.R;
+import android.support.v7.gridlayout.R;
 import android.test.UiThreadTest;
 import android.view.Gravity;
 import android.view.View;
diff --git a/v7/mediarouter/api/current.txt b/v7/mediarouter/api/current.txt
index a382a89..0ae96cd 100644
--- a/v7/mediarouter/api/current.txt
+++ b/v7/mediarouter/api/current.txt
@@ -20,6 +20,7 @@
     method public void onAttachedToWindow();
     method public void onDetachedFromWindow();
     method public void setDialogFactory(android.support.v7.app.MediaRouteDialogFactory);
+    method public void setRemoteIndicatorDrawable(android.graphics.drawable.Drawable);
     method public void setRouteSelector(android.support.v7.media.MediaRouteSelector);
     method public boolean showDialog();
   }
diff --git a/v7/mediarouter/res/layout/mr_media_route_controller_material_dialog_b.xml b/v7/mediarouter/res/layout/mr_media_route_controller_material_dialog_b.xml
index 9482642..5e16057 100644
--- a/v7/mediarouter/res/layout/mr_media_route_controller_material_dialog_b.xml
+++ b/v7/mediarouter/res/layout/mr_media_route_controller_material_dialog_b.xml
@@ -14,126 +14,129 @@
      limitations under the License.
 -->
 
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
         android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:orientation="vertical">
-    <LinearLayout android:id="@+id/title_bar"
-            android:layout_width="match_parent"
+        android:layout_height="wrap_content">
+    <LinearLayout android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:orientation="horizontal" >
-        <TextView android:id="@+id/route_name"
-                android:layout_width="0dp"
-                android:layout_height="72dp"
-                android:layout_weight="1"
-                android:layout_marginLeft="24dip"
-                android:layout_marginRight="24dip"
-                android:gravity="center_vertical"
-                android:singleLine="true"
-                android:ellipsize="end"
-                android:textAppearance="?android:attr/textAppearanceMedium"
-                android:textColor="?android:attr/textColorPrimary" />
-        <ImageButton android:id="@+id/settings"
-                android:layout_width="48dip"
-                android:layout_height="48dip"
-                android:padding="12dip"
-                android:layout_marginTop="12dip"
-                android:layout_marginBottom="12dip"
-                android:layout_marginRight="12dip"
-                android:contentDescription="@string/mr_media_route_controller_settings_description"
-                android:src="?attr/mediaRouteSettingsDrawable"
-                android:background="?attr/selectableItemBackgroundBorderless"
-                android:visibility="gone" />
-    </LinearLayout>
-    <FrameLayout android:id="@+id/media_route_control_frame"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content" >
-        <RelativeLayout android:id="@+id/default_control_frame"
+            android:orientation="vertical">
+        <LinearLayout android:id="@+id/title_bar"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:background="?attr/colorPrimary" >
-            <ImageView android:id="@+id/art"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    android:maxHeight="@dimen/mr_media_route_controller_art_max_height"
-                    android:adjustViewBounds="true"
-                    android:scaleType="centerCrop"/>
-            <ImageButton android:id="@+id/play_pause"
+                android:orientation="horizontal" >
+            <TextView android:id="@+id/route_name"
+                    android:layout_width="0dp"
+                    android:layout_height="72dp"
+                    android:layout_weight="1"
+                    android:layout_marginLeft="24dip"
+                    android:layout_marginRight="24dip"
+                    android:gravity="center_vertical"
+                    android:singleLine="true"
+                    android:ellipsize="end"
+                    android:textAppearance="?android:attr/textAppearanceMedium"
+                    android:textColor="?android:attr/textColorPrimary" />
+            <ImageButton android:id="@+id/settings"
                     android:layout_width="48dip"
                     android:layout_height="48dip"
                     android:padding="12dip"
-                    android:layout_marginTop="8dip"
-                    android:layout_marginBottom="8dip"
-                    android:layout_alignParentRight="true"
-                    android:layout_below="@id/art"
-                    android:contentDescription="@string/mr_media_route_controller_play"
-                    android:background="?attr/selectableItemBackgroundBorderless"/>
-            <LinearLayout android:id="@+id/text_wrapper"
-                    android:orientation="vertical"
+                    android:layout_marginTop="12dip"
+                    android:layout_marginBottom="12dip"
+                    android:layout_marginRight="12dip"
+                    android:contentDescription="@string/mr_media_route_controller_settings_description"
+                    android:src="?attr/mediaRouteSettingsDrawable"
+                    android:background="?attr/selectableItemBackgroundBorderless"
+                    android:visibility="gone" />
+        </LinearLayout>
+        <FrameLayout android:id="@+id/media_route_control_frame"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content" >
+            <RelativeLayout android:id="@+id/default_control_frame"
+                    android:layout_width="match_parent"
                     android:layout_height="wrap_content"
-                    android:layout_width="wrap_content"
-                    android:minHeight="64dip"
-                    android:layout_marginLeft="24dip"
-                    android:gravity="center_vertical"
-                    android:layout_toLeftOf="@id/play_pause"
-                    android:layout_below="@id/art"
-                    android:layout_alignParentLeft="true" >
-                <TextView android:id="@+id/title"
-                        android:layout_width="wrap_content"
+                    android:background="?attr/colorPrimary" >
+                <ImageView android:id="@+id/art"
+                        android:layout_width="match_parent"
                         android:layout_height="wrap_content"
-                        android:textAppearance="?android:attr/textAppearanceSmall"
-                        android:textColor="?android:attr/textColorPrimary"
-                        android:textSize="16sp"
-                        android:textStyle="bold"
-                        android:singleLine="true" />
-                <TextView android:id="@+id/subtitle"
-                        android:layout_width="wrap_content"
+                        android:maxHeight="@dimen/mr_media_route_controller_art_max_height"
+                        android:adjustViewBounds="true"
+                        android:scaleType="centerCrop"/>
+                <ImageButton android:id="@+id/play_pause"
+                        android:layout_width="48dip"
+                        android:layout_height="48dip"
+                        android:padding="12dip"
+                        android:layout_marginTop="8dip"
+                        android:layout_marginBottom="8dip"
+                        android:layout_alignParentRight="true"
+                        android:layout_below="@id/art"
+                        android:contentDescription="@string/mr_media_route_controller_play"
+                        android:background="?attr/selectableItemBackgroundBorderless"/>
+                <LinearLayout android:id="@+id/text_wrapper"
+                        android:orientation="vertical"
                         android:layout_height="wrap_content"
-                        android:textAppearance="?android:attr/textAppearanceSmall"
-                        android:textColor="?android:attr/textColorPrimary"
-                        android:textSize="14sp"
-                        android:singleLine="true" />
-            </LinearLayout>
-        </RelativeLayout>
-    </FrameLayout>
-    <!-- Optional volume slider section. -->
-    <LinearLayout android:id="@+id/media_route_volume_layout"
-                  android:layout_width="fill_parent"
-                  android:layout_height="64dp"
-                  android:gravity="center_vertical"
-                  android:padding="8dp"
-                  android:visibility="gone">
-        <ImageView android:layout_width="48dp"
-                   android:layout_height="48dp"
-                   android:src="@drawable/mr_ic_audio_vol"
-                   android:gravity="center"
-                   android:scaleType="center" />
-        <SeekBar android:id="@+id/media_route_volume_slider"
-                 android:layout_width="0dp"
-                 android:layout_height="wrap_content"
-                 android:layout_weight="1"
-                 android:layout_marginLeft="8dp"
-                 android:layout_marginRight="8dp" />
+                        android:layout_width="wrap_content"
+                        android:minHeight="64dip"
+                        android:layout_marginLeft="24dip"
+                        android:gravity="center_vertical"
+                        android:layout_toLeftOf="@id/play_pause"
+                        android:layout_below="@id/art"
+                        android:layout_alignParentLeft="true" >
+                    <TextView android:id="@+id/title"
+                            android:layout_width="wrap_content"
+                            android:layout_height="wrap_content"
+                            android:textAppearance="?android:attr/textAppearanceSmall"
+                            android:textColor="?android:attr/textColorPrimary"
+                            android:textSize="16sp"
+                            android:textStyle="bold"
+                            android:singleLine="true" />
+                    <TextView android:id="@+id/subtitle"
+                            android:layout_width="wrap_content"
+                            android:layout_height="wrap_content"
+                            android:textAppearance="?android:attr/textAppearanceSmall"
+                            android:textColor="?android:attr/textColorPrimary"
+                            android:textSize="14sp"
+                            android:singleLine="true" />
+                </LinearLayout>
+            </RelativeLayout>
+        </FrameLayout>
+        <!-- Optional volume slider section. -->
+        <LinearLayout android:id="@+id/media_route_volume_layout"
+                      android:layout_width="fill_parent"
+                      android:layout_height="64dp"
+                      android:gravity="center_vertical"
+                      android:padding="8dp"
+                      android:visibility="gone">
+            <ImageView android:layout_width="48dp"
+                       android:layout_height="48dp"
+                       android:src="@drawable/mr_ic_audio_vol"
+                       android:gravity="center"
+                       android:scaleType="center" />
+            <SeekBar android:id="@+id/media_route_volume_slider"
+                     android:layout_width="0dp"
+                     android:layout_height="wrap_content"
+                     android:layout_weight="1"
+                     android:layout_marginLeft="8dp"
+                     android:layout_marginRight="8dp" />
+        </LinearLayout>
+        <LinearLayout android:id="@+id/buttons"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:orientation="horizontal" >
+            <Button android:id="@+id/disconnect"
+                android:layout_width="0dp"
+                android:layout_height="48dp"
+                android:gravity="center"
+                android:layout_weight="1"
+                android:background="?attr/selectableItemBackgroundBorderless"
+                android:text="@string/mr_media_route_controller_disconnect"
+                android:visibility="gone" />
+            <Button android:id="@+id/stop"
+                android:layout_width="0dp"
+                android:layout_height="48dp"
+                android:gravity="center"
+                android:layout_weight="1"
+                android:textColor="?attr/colorAccent"
+                android:background="?attr/selectableItemBackgroundBorderless"
+                android:text="@string/mr_media_route_controller_stop" />
+        </LinearLayout>
     </LinearLayout>
-    <LinearLayout android:id="@+id/buttons"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:orientation="horizontal" >
-        <Button android:id="@+id/disconnect"
-            android:layout_width="0dp"
-            android:layout_height="48dp"
-            android:gravity="center"
-            android:layout_weight="1"
-            android:background="?attr/selectableItemBackgroundBorderless"
-            android:text="@string/mr_media_route_controller_disconnect"
-            android:visibility="gone" />
-        <Button android:id="@+id/stop"
-            android:layout_width="0dp"
-            android:layout_height="48dp"
-            android:gravity="center"
-            android:layout_weight="1"
-            android:textColor="?attr/colorAccent"
-            android:background="?attr/selectableItemBackgroundBorderless"
-            android:text="@string/mr_media_route_controller_stop" />
-    </LinearLayout>
-</LinearLayout>
+</ScrollView>
diff --git a/v7/mediarouter/res/values-af/strings.xml b/v7/mediarouter/res/values-af/strings.xml
index 885af10..0dcfa86 100644
--- a/v7/mediarouter/res/values-af/strings.xml
+++ b/v7/mediarouter/res/values-af/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"Stelsel"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"Toestelle"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"Media-uitvoer"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"Saai uit"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"Koppel aan toestel"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"Soek tans vir toestelle…"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"Ontkoppel"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"Hou op uitsaai"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"Roete-instellings"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"Speel"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"Laat wag"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-am/strings.xml b/v7/mediarouter/res/values-am/strings.xml
index 0027737..5d061c9 100644
--- a/v7/mediarouter/res/values-am/strings.xml
+++ b/v7/mediarouter/res/values-am/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"ስርዓት"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"መሣሪያዎች"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"የሚዲያ ውፅዓት"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"ውሰድ"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"ከመሳሪያ ጋር ያገናኙ"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"መሳሪያዎችን በመፈለግ ላይ…"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"ግንኙነት አቋርጥ"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"መውሰድ አቁም"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"የመንገድ ቅንብሮች"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"አጫውት"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"ለአፍታ አቁም"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-ar/strings.xml b/v7/mediarouter/res/values-ar/strings.xml
index 9289a35..ac0fb5d 100644
--- a/v7/mediarouter/res/values-ar/strings.xml
+++ b/v7/mediarouter/res/values-ar/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"النظام"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"الأجهزة"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"المنفذ الإعلامي"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"إرسال"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"الاتصال بجهاز"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"جارٍ البحث عن الأجهزة…"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"قطع الاتصال"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"إيقاف الإرسال"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"إعدادات المسار"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"تشغيل"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"إيقاف مؤقت"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-az-rAZ/strings.xml b/v7/mediarouter/res/values-az-rAZ/strings.xml
new file mode 100644
index 0000000..2f3ff74
--- /dev/null
+++ b/v7/mediarouter/res/values-az-rAZ/strings.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2013 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="mr_system_route_name" msgid="5441529851481176817">"Sistem"</string>
+    <string name="mr_user_route_category_name" msgid="7498112907524977311">"Cihazlar"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"İştirakçılar"</string>
+    <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"Cihaza qoş"</string>
+    <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"Cihazları axtarır..."</string>
+    <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"Bağlantını kəs"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"Yayımı dayandır"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"Marşrut parametrləri"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"Göstər"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"Fasilə ver"</string>
+</resources>
diff --git a/v7/mediarouter/res/values-bg/strings.xml b/v7/mediarouter/res/values-bg/strings.xml
index ff1401e..0918332 100644
--- a/v7/mediarouter/res/values-bg/strings.xml
+++ b/v7/mediarouter/res/values-bg/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"Система"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"Устройства"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"Изходяща мултимедия"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"Предаване"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"Свързване с устройство"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"Търсят се устройства…"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"Прекратяване на връзката"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"Спиране на предаването"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"Настройки за маршрута"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"Пускане"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"Поставяне на пауза"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-bn-rBD/strings.xml b/v7/mediarouter/res/values-bn-rBD/strings.xml
index d0b2c32..de862e5 100644
--- a/v7/mediarouter/res/values-bn-rBD/strings.xml
+++ b/v7/mediarouter/res/values-bn-rBD/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"সিস্টেম"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"ডিভাইসগুলি"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"মিডিয়া আউটপুট"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"কাস্ট করুন"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"ডিভাইসে সংযোগ করুন"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"ডিভাইসগুলি অনুসন্ধান করা হচ্ছে…"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"সংযোগ বিচ্ছিন্ন করুন"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"কাস্ট করা বন্ধ করুন"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"সেটিংস রুট করুন"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"চালান"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"বিরাম দিন"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-ca/strings.xml b/v7/mediarouter/res/values-ca/strings.xml
index dd485de..eac6632 100644
--- a/v7/mediarouter/res/values-ca/strings.xml
+++ b/v7/mediarouter/res/values-ca/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"Sistema"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"Dispositius"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"Sortida de contingut multimèdia"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"Emet"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"Connecta al dispositiu"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"S\'estan cercant dispositius…"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"Desconnecta"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"Atura l\'emissió"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"Configuració de la ruta"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"Reprodueix"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"Posa en pausa"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-cs/strings.xml b/v7/mediarouter/res/values-cs/strings.xml
index 4687100..111c02a 100644
--- a/v7/mediarouter/res/values-cs/strings.xml
+++ b/v7/mediarouter/res/values-cs/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"Systém"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"Zařízení"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"Výstup médií"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"Odeslat"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"Připojení k zařízení"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"Vyhledávání zařízení…"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"Odpojit"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"Ukončit odesílání"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"Nastavení trasy"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"Přehrát"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"Pozastavit"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-da/strings.xml b/v7/mediarouter/res/values-da/strings.xml
index fd3b0fb..3b4fbf6 100644
--- a/v7/mediarouter/res/values-da/strings.xml
+++ b/v7/mediarouter/res/values-da/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"System"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"Enheder"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"Medieudgang"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"Cast"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"Opret forbindelse til enheden"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"Søger efter enheder..."</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"Afbryd forbindelsen"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"Stop med at caste"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"Ruteindstillinger"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"Afspil"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"Sæt på pause"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-de/strings.xml b/v7/mediarouter/res/values-de/strings.xml
index 9df0ebf..5b8e494 100644
--- a/v7/mediarouter/res/values-de/strings.xml
+++ b/v7/mediarouter/res/values-de/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"System"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"Geräte"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"Medienausgabe"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"Übertragen"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"Mit Gerät verbinden"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"Geräte werden gesucht…"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"Verbindung aufheben"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"Übertragung stoppen"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"Routingeinstellungen"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"Wiedergabe"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"Pause"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-el/strings.xml b/v7/mediarouter/res/values-el/strings.xml
index 5a61395..3640111 100644
--- a/v7/mediarouter/res/values-el/strings.xml
+++ b/v7/mediarouter/res/values-el/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"Σύστημα"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"Συσκευές"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"Έξοδος μέσων"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"Μετάδοση"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"Σύνδεση με τη συσκευή"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"Αναζήτηση συσκευών…"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"Αποσύνδεση"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"Διακοπή μετάδοσης"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"Ρυθμίσεις διαδρομής"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"Αναπαραγωγή"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"Παύση"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-en-rAU/strings.xml b/v7/mediarouter/res/values-en-rAU/strings.xml
new file mode 100644
index 0000000..f5a8531
--- /dev/null
+++ b/v7/mediarouter/res/values-en-rAU/strings.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2013 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="mr_system_route_name" msgid="5441529851481176817">"System"</string>
+    <string name="mr_user_route_category_name" msgid="7498112907524977311">"Devices"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"Cast"</string>
+    <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"Connect to device"</string>
+    <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"Searching for devices…"</string>
+    <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"Disconnect"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"Stop casting"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"Route settings"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"Play"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"Pause"</string>
+</resources>
diff --git a/v7/mediarouter/res/values-en-rGB/strings.xml b/v7/mediarouter/res/values-en-rGB/strings.xml
index b9af4bf..f5a8531 100644
--- a/v7/mediarouter/res/values-en-rGB/strings.xml
+++ b/v7/mediarouter/res/values-en-rGB/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"System"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"Devices"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"Media output"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"Cast"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"Connect to device"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"Searching for devices…"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"Disconnect"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"Stop casting"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"Route settings"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"Play"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"Pause"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-en-rIN/strings.xml b/v7/mediarouter/res/values-en-rIN/strings.xml
index b9af4bf..f5a8531 100644
--- a/v7/mediarouter/res/values-en-rIN/strings.xml
+++ b/v7/mediarouter/res/values-en-rIN/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"System"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"Devices"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"Media output"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"Cast"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"Connect to device"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"Searching for devices…"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"Disconnect"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"Stop casting"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"Route settings"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"Play"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"Pause"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-es-rUS/strings.xml b/v7/mediarouter/res/values-es-rUS/strings.xml
index 211b400..e1cf915 100644
--- a/v7/mediarouter/res/values-es-rUS/strings.xml
+++ b/v7/mediarouter/res/values-es-rUS/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"Sistema"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"Dispositivos"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"Salida multimedia"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"Transmitir"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"Conectar al dispositivo"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"Buscando dispositivos…"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"Desconectar"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"Detener transmisión"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"Configuración de ruta"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"Reproducir"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"Pausar"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-es/strings.xml b/v7/mediarouter/res/values-es/strings.xml
index d3a1639..0f2a8ea 100644
--- a/v7/mediarouter/res/values-es/strings.xml
+++ b/v7/mediarouter/res/values-es/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"Sistema"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"Dispositivos"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"Salida multimedia"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"Enviar contenido"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"Conectar a dispositivo"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"Buscando dispositivos…"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"Desconectar"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"Dejar de enviar contenido"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"Ajustes de ruta"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"Reproducir"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"Pausa"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-et-rEE/strings.xml b/v7/mediarouter/res/values-et-rEE/strings.xml
index 7dbdf74..ebc63fd 100644
--- a/v7/mediarouter/res/values-et-rEE/strings.xml
+++ b/v7/mediarouter/res/values-et-rEE/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"Süsteem"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"Seadmed"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"Meediaväljund"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"Ülekandmine"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"Seadmega ühendamine"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"Seadmete otsimine …"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"Katkesta ühendus"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"Lõpeta ülekanne"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"Marsruudi seaded"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"Esitamine"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"Peatamine"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-eu-rES/strings.xml b/v7/mediarouter/res/values-eu-rES/strings.xml
index 728672d..d177a55 100644
--- a/v7/mediarouter/res/values-eu-rES/strings.xml
+++ b/v7/mediarouter/res/values-eu-rES/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"Sistema"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"Gailuak"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"Multimedia-irteera"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"Igorri"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"Konektatu gailura"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"Gailuak bilatzen…"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"Deskonektatu"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"Utzi igortzeari"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"Ibilbidearen ezarpenak"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"Erreproduzitu"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"Pausatu"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-fa/strings.xml b/v7/mediarouter/res/values-fa/strings.xml
index 2ffed50..e094982 100644
--- a/v7/mediarouter/res/values-fa/strings.xml
+++ b/v7/mediarouter/res/values-fa/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"سیستم"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"دستگاه‌ها"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"خروجی رسانه"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"فرستادن"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"برقراری ارتباط با دستگاه"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"در حال جستجو برای دستگاه‌ها..."</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"قطع ارتباط"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"توقف فرستادن"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"تنظیمات مسیر"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"پخش"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"توقف موقت"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-fi/strings.xml b/v7/mediarouter/res/values-fi/strings.xml
index 0692c2f..a21dc91 100644
--- a/v7/mediarouter/res/values-fi/strings.xml
+++ b/v7/mediarouter/res/values-fi/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"Järjestelmä"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"Laitteet"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"Median äänentoisto"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"Lähetä"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"Yhdistä laitteeseen"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"Etsitään laitteita…"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"Katkaise yhteys"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"Lopeta suoratoisto"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"Reitin asetukset"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"Toista"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"Keskeytä"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-fr-rCA/strings.xml b/v7/mediarouter/res/values-fr-rCA/strings.xml
index 9fa3c9c..0655526 100644
--- a/v7/mediarouter/res/values-fr-rCA/strings.xml
+++ b/v7/mediarouter/res/values-fr-rCA/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"Système"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"Appareils"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"Sortie multimédia"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"Diffuser"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"Connexion au périphérique"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"Recherche d\'appareils en cours…"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"Déconnecter"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"Arrêter la diffusion"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"Paramètres de l\'itinéraire"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"Lecture"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"Suspendre"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-fr/strings.xml b/v7/mediarouter/res/values-fr/strings.xml
index 5607a1c..9fce08a 100644
--- a/v7/mediarouter/res/values-fr/strings.xml
+++ b/v7/mediarouter/res/values-fr/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"Système"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"Appareils"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"Sortie multimédia"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"Caster"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"Connecter à l\'appareil"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"Recherche d\'appareils en cours…"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"Déconnecter"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"Arrêter la diffusion"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"Paramètres de l\'itinéraire"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"Lecture"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"Pause"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-gl-rES/strings.xml b/v7/mediarouter/res/values-gl-rES/strings.xml
index d700c14..d1d73f9 100644
--- a/v7/mediarouter/res/values-gl-rES/strings.xml
+++ b/v7/mediarouter/res/values-gl-rES/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"Sistema"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"Dispositivos"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"Saída multimedia"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"Emitir"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"Conectar co dispositivo"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"Buscando dispositivos…"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"Desconectar"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"Parar de emitir"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"Configuración da ruta"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"Reproduce"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"Pausa"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-gu-rIN/strings.xml b/v7/mediarouter/res/values-gu-rIN/strings.xml
new file mode 100644
index 0000000..2002115
--- /dev/null
+++ b/v7/mediarouter/res/values-gu-rIN/strings.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2013 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="mr_system_route_name" msgid="5441529851481176817">"સિસ્ટમ"</string>
+    <string name="mr_user_route_category_name" msgid="7498112907524977311">"ઉપકરણો"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"કાસ્ટ કરો"</string>
+    <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"ઉપકરણ સાથે કનેક્ટ કરો"</string>
+    <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"ઉપકરણો માટે શોધી રહ્યું છે…"</string>
+    <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"ડિસ્કનેક્ટ કરો"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"કાસ્ટ કરવાનું રોકો"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"રૂટ સેટિંગ્સ"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"ચલાવો"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"થોભો"</string>
+</resources>
diff --git a/v7/mediarouter/res/values-hi/strings.xml b/v7/mediarouter/res/values-hi/strings.xml
index 8acc2bb..6d100ea 100644
--- a/v7/mediarouter/res/values-hi/strings.xml
+++ b/v7/mediarouter/res/values-hi/strings.xml
@@ -17,9 +17,13 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"सिस्टम"</string>
-    <string name="mr_user_route_category_name" msgid="7498112907524977311">"उपकरण"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"मीडिया आउटपुट"</string>
-    <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"उपकरण से कनेक्ट करें"</string>
-    <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"उपकरणों की खोज हो रही है…"</string>
+    <string name="mr_user_route_category_name" msgid="7498112907524977311">"डिवाइस"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"कास्ट करें"</string>
+    <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"डिवाइस से कनेक्ट करें"</string>
+    <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"डिवाइस की खोज हो रही है…"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"डिस्कनेक्ट करें"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"कास्ट करना बंद करें"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"मार्ग सेटिंग"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"चलाएं"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"रोकें"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-hr/strings.xml b/v7/mediarouter/res/values-hr/strings.xml
index 2946433..74e9270 100644
--- a/v7/mediarouter/res/values-hr/strings.xml
+++ b/v7/mediarouter/res/values-hr/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"Sustav"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"Uređaji"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"Medijski izlaz"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"Emitiranje"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"Povezivanje s uređajem"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"Traženje uređaja…"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"Prekini vezu"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"Zaustavi emitiranje"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"Postavke rute"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"Reprodukcija"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"Pauziraj"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-hu/strings.xml b/v7/mediarouter/res/values-hu/strings.xml
index b68fe16..efbc193 100644
--- a/v7/mediarouter/res/values-hu/strings.xml
+++ b/v7/mediarouter/res/values-hu/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"Rendszer"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"Eszközök"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"Médiakimenet"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"Tartalomátküldés"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"Csatlakozás adott eszközhöz"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"Eszközkeresés…"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"Leválasztás"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"Átküldés leállítása"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"Útvonal-beállítások"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"Indítás"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"Szüneteltetés"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-hy-rAM/strings.xml b/v7/mediarouter/res/values-hy-rAM/strings.xml
index 77f1136..faa6020 100644
--- a/v7/mediarouter/res/values-hy-rAM/strings.xml
+++ b/v7/mediarouter/res/values-hy-rAM/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"Համակարգ"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"Սարքեր"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"Մեդիա արտածում"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"Հեռարձակում"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"Միանալ սարքին"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"Որոնվում են սարքեր..."</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"Անջատել"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"Դադարեցնել հեռարձակումը"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"Ֆայլերի փոխանցման կարգավորումներ"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"Նվագարկել"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"Դադար"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-in/strings.xml b/v7/mediarouter/res/values-in/strings.xml
index 1d3b387..e3123c1 100644
--- a/v7/mediarouter/res/values-in/strings.xml
+++ b/v7/mediarouter/res/values-in/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"Sistem"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"Perangkat"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"Keluaran media"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"Transmisi"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"Sambungkan ke perangkat"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"Menelusuri perangkat…"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"Putuskan sambungan"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"Hentikan transmisi"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"Setelan rute"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"Putar"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"Jeda"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-is-rIS/strings.xml b/v7/mediarouter/res/values-is-rIS/strings.xml
index 45d7329..262e4e9 100644
--- a/v7/mediarouter/res/values-is-rIS/strings.xml
+++ b/v7/mediarouter/res/values-is-rIS/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"Kerfi"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"Tæki"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"Margmiðlunarúttak"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"Senda út"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"Tengjast tæki"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"Leitar að tækjum…"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"Aftengja"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"Stöðva útsendingu"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"Leiðarstillingar"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"Spila"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"Hlé"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-it/strings.xml b/v7/mediarouter/res/values-it/strings.xml
index bd58755..bedd617 100644
--- a/v7/mediarouter/res/values-it/strings.xml
+++ b/v7/mediarouter/res/values-it/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"Sistema"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"Dispositivi"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"Uscita media"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"Trasmetti"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"Connetti al dispositivo"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"Ricerca di dispositivi…"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"Disconnetti"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"Interrompi trasmissione"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"Impostazioni percorso"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"Riproduci"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"Pausa"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-iw/strings.xml b/v7/mediarouter/res/values-iw/strings.xml
index 59753b4..12d17b9 100644
--- a/v7/mediarouter/res/values-iw/strings.xml
+++ b/v7/mediarouter/res/values-iw/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"מערכת"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"מכשירים"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"פלט מדיה"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"העבר"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"התחבר למכשיר"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"מחפש מכשירים…"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"התנתק"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"עצור העברה"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"הגדרות נתיב"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"הפעל"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"השהה"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-ja/strings.xml b/v7/mediarouter/res/values-ja/strings.xml
index 1367489..e97a65a 100644
--- a/v7/mediarouter/res/values-ja/strings.xml
+++ b/v7/mediarouter/res/values-ja/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"システム"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"端末"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"メディア出力"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"キャスト"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"端末に接続"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"端末を検索しています…"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"接続を解除"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"キャストを停止"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"ルーティング設定"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"再生"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"一時停止"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-ka-rGE/strings.xml b/v7/mediarouter/res/values-ka-rGE/strings.xml
index 413257e..758fe73 100644
--- a/v7/mediarouter/res/values-ka-rGE/strings.xml
+++ b/v7/mediarouter/res/values-ka-rGE/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"სისტემა"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"მოწყობილობები"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"მედია გამოსასვლელი"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"მსახიობები"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"მოწყობილობასთან დაკავშირება"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"მოწყობილობების ძიება…"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"კავშირის გაწყვეტა"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"ტრანსლაციის შეჩერება"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"მარშრუტის პარამეტრები"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"დაკვრა"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"პაუზა"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-kk-rKZ/strings.xml b/v7/mediarouter/res/values-kk-rKZ/strings.xml
index e8da02a..c549a8c 100644
--- a/v7/mediarouter/res/values-kk-rKZ/strings.xml
+++ b/v7/mediarouter/res/values-kk-rKZ/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"Жүйе"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"Құрылғылар"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"Meдиа құрылғылары"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"Трансляциялау"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"Құрылғыға жалғау"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"Құрылғыларды іздеуде…"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"Ажырату"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"Трансляциялауды тоқтату"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"Жол параметрлері"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"Ойнату"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"Кідірту"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-km-rKH/strings.xml b/v7/mediarouter/res/values-km-rKH/strings.xml
index e001dde..b3e53c5 100644
--- a/v7/mediarouter/res/values-km-rKH/strings.xml
+++ b/v7/mediarouter/res/values-km-rKH/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"ប្រព័ន្ធ"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"ឧបករណ៍"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"លទ្ធផល​មេឌៀ"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"បញ្ជូន"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"ភ្ជាប់​ឧបករណ៍"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"កំពុង​ស្វែងរក​ឧបករណ៍..."</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"ផ្ដាច់"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"បញ្ឈប់ការខាស"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"ការកំណត់ផ្លូវ"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"ចាក់"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"ផ្អាក"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-kn-rIN/strings.xml b/v7/mediarouter/res/values-kn-rIN/strings.xml
index 147ebc8..36c3aaa 100644
--- a/v7/mediarouter/res/values-kn-rIN/strings.xml
+++ b/v7/mediarouter/res/values-kn-rIN/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"ಸಿಸ್ಟಂ"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"ಸಾಧನಗಳು"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"ಮಾಧ್ಯಮ ಔಟ್‌ಪುಟ್"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"ಪಾತ್ರ"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"ಸಾಧನಕ್ಕೆ ಸಂಪರ್ಕಪಡಿಸಿ"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"ಸಾಧನಗಳನ್ನು ಹುಡುಕಲಾಗುತ್ತಿದೆ…"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"ಸಂಪರ್ಕ ಕಡಿತಗೊಳಿಸು"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"ಬಿತ್ತರಿಸುವಿಕೆ ನಿಲ್ಲಿಸು"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"ಮಾರ್ಗ ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"ಪ್ಲೇ ಮಾಡು"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"ವಿರಾಮ"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-ko/strings.xml b/v7/mediarouter/res/values-ko/strings.xml
index 21f82a0..d165e52 100644
--- a/v7/mediarouter/res/values-ko/strings.xml
+++ b/v7/mediarouter/res/values-ko/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"시스템"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"기기"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"미디어 출력"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"전송"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"기기에 연결"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"기기 검색 중…"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"연결 해제"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"전송 중지"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"경로 설정"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"재생"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"일시중지"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-ky-rKG/strings.xml b/v7/mediarouter/res/values-ky-rKG/strings.xml
index 4a587ac..1f7aba0 100644
--- a/v7/mediarouter/res/values-ky-rKG/strings.xml
+++ b/v7/mediarouter/res/values-ky-rKG/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"Систем"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"Түзмөктөр"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"Медиа чыгаруу"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"Тандалгандар"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"Түзмөккө туташуу"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"Түзмөктөр изделүүдө..."</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"Ажыратуу"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"Тышк экранга чыгарну токтотуу"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"Багыт жөндөөлөрү"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"Ойнотуу"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"Тындыруу"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-lo-rLA/strings.xml b/v7/mediarouter/res/values-lo-rLA/strings.xml
index 31a03cd..6d61f7d 100644
--- a/v7/mediarouter/res/values-lo-rLA/strings.xml
+++ b/v7/mediarouter/res/values-lo-rLA/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"ລະບົບ"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"ອຸປະກອນ"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"ມີເດຍເອົ້າພຸດ"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"ສົ່ງ​ສັນ​ຍານ"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"ເຊື່ອມຕໍ່ຫາອຸປະກອນ"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"ກຳລັງຊອກຫາອຸປະກອນ..."</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"ຕັດການເຊື່ອມຕໍ່"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"ຢຸດການສົ່ງສັນຍານ"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"ການ​ຕັ້ງ​ຄ່າ​ເສັ້ນ​ທາງ"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"ຫຼິ້ນ"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"ຢຸດຊົ່ວຄາວ"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-lt/strings.xml b/v7/mediarouter/res/values-lt/strings.xml
index ead3b73..2315618 100644
--- a/v7/mediarouter/res/values-lt/strings.xml
+++ b/v7/mediarouter/res/values-lt/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"Sistema"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"Įrenginiai"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"Medijos išvestis"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"Perduoti"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"Prijungimas prie įrenginio"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"Ieškoma įrenginių…"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"Atjungti"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"Sustabdyti perdavimą"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"Maršruto nustatymai"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"Leisti"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"Pristabdyti"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-lv/strings.xml b/v7/mediarouter/res/values-lv/strings.xml
index 0914990..93e45de 100644
--- a/v7/mediarouter/res/values-lv/strings.xml
+++ b/v7/mediarouter/res/values-lv/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"Sistēma"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"Ierīces"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"Multivides izeja"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"Apraidīt"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"Savienojuma izveide ar ierīci"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"Notiek ierīču meklēšana..."</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"Atvienot"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"Pārtraukt apraidi"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"Maršruta iestatījumi"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"Atskaņot"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"Apturēt"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-mk-rMK/strings.xml b/v7/mediarouter/res/values-mk-rMK/strings.xml
index 363f16b..9b3f875 100644
--- a/v7/mediarouter/res/values-mk-rMK/strings.xml
+++ b/v7/mediarouter/res/values-mk-rMK/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"Систем"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"Уреди"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"Излез за медиум"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"Емитувај"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"Поврзи се со уредот"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"Се пребаруваат уреди..."</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"Исклучи се"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"Запри префрлување"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"Поставки на маршрутата"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"Репродуцирај"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"Пауза"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-ml-rIN/strings.xml b/v7/mediarouter/res/values-ml-rIN/strings.xml
index d20ba1d..64c74b1 100644
--- a/v7/mediarouter/res/values-ml-rIN/strings.xml
+++ b/v7/mediarouter/res/values-ml-rIN/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"സിസ്റ്റം"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"ഉപകരണങ്ങൾ"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"മീഡിയ ഔട്ട്പുട്ട്"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"കാസ്‌റ്റുചെയ്യുക"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"ഉപകരണത്തിലേക്ക് കണക്റ്റുചെയ്യുക"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"ഉപകരണങ്ങൾക്കായി തിരയുന്നു…"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"വിച്ഛേദിക്കുക"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"കാസ്റ്റുചെയ്യൽ നിർത്തുക"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"റൂട്ട് ക്രമീകരണം"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"പ്ലേ ചെയ്യുക"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"താൽക്കാലികമായി നിർത്തുക"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-mn-rMN/strings.xml b/v7/mediarouter/res/values-mn-rMN/strings.xml
index 4eecdb4..2074767 100644
--- a/v7/mediarouter/res/values-mn-rMN/strings.xml
+++ b/v7/mediarouter/res/values-mn-rMN/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"Систем"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"Төхөөрөмжүүд"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"Медиа гаралт"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"Дамжуулах"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"Төхөөрөмжтэй холбох"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"Төхөөрөмжүүдийг хайж байна…"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"Салгах"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"Нэвтрүүлэхийг зогсоох"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"Маршрут тохиргоо"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"Тоглуулах"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"Түр зогсоох"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-mr-rIN/strings.xml b/v7/mediarouter/res/values-mr-rIN/strings.xml
index 9187b5d..bd020a7 100644
--- a/v7/mediarouter/res/values-mr-rIN/strings.xml
+++ b/v7/mediarouter/res/values-mr-rIN/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"सिस्टम"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"डिव्हाइसेस"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"माध्यम आउटपुट"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"कास्‍ट करा"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"डिव्हाइसला कनेक्ट करा"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"डिव्‍हाइसेस शोधत आहे…"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"‍डिस्कनेक्ट करा"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"कास्ट करणे थांबवा"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"मार्ग सेटिंग्ज"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"प्ले करा"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"विराम द्या"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-ms-rMY/strings.xml b/v7/mediarouter/res/values-ms-rMY/strings.xml
index dadaa30..05e9ffa 100644
--- a/v7/mediarouter/res/values-ms-rMY/strings.xml
+++ b/v7/mediarouter/res/values-ms-rMY/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"Sistem"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"Peranti"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"Output media"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"Barisan pelakon"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"Sambung kepada peranti"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"Mencari peranti..."</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"Putuskan sambungan"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"Berhenti menghantar"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"Tetapan laluan"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"Main"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"Jeda"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-my-rMM/strings.xml b/v7/mediarouter/res/values-my-rMM/strings.xml
index c417d57..20bfd8d 100644
--- a/v7/mediarouter/res/values-my-rMM/strings.xml
+++ b/v7/mediarouter/res/values-my-rMM/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"စနစ်"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"စက်ပစ္စည်းများ"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"မီဒီယာထွက်ပေါက်"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"သရုပ်ဆောင်​များ"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"စက်တစ်ခုကို ချိတ်ဆက်ပါ"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"စက်ပစ္စည်းများကို ရှာဖွေနေပါသည်"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"ချိတ်ဆက်ခြင်းရပ်တန့်ရန်"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"ပုံစံသွင်းမှု ရပ်ရန်"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"လမ်းကြောင်း အပြင်အဆင်များ"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"ဖွင့်ရန်"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"ခဏရပ်ရန်"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-nb/strings.xml b/v7/mediarouter/res/values-nb/strings.xml
index fa4d9a4..5ee8ec8 100644
--- a/v7/mediarouter/res/values-nb/strings.xml
+++ b/v7/mediarouter/res/values-nb/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"System"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"Enheter"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"Medieutgang"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"Cast"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"Koble til enheten"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"Søker etter enheter …"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"Koble fra"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"Stopp castingen"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"Ruteinnstillinger"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"Spill av"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"Sett på pause"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-ne-rNP/strings.xml b/v7/mediarouter/res/values-ne-rNP/strings.xml
index 3fe9ac3..aadcbcf 100644
--- a/v7/mediarouter/res/values-ne-rNP/strings.xml
+++ b/v7/mediarouter/res/values-ne-rNP/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"प्रणाली"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"उपकरणहरू"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"मिडियाको उत्पादन"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"कास्ट"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"उपकरणसँग जडान गर्नुहोस्"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"उपकरणहरूका लागि खोजी गरिँदै..."</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"विच्छेदन गर्नुहोस्"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"कास्टिंग रोक्नुहोस्"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"मार्ग सेटिङ"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"बजाउनुहोस्"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"रोक्नुहोस्"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-nl/strings.xml b/v7/mediarouter/res/values-nl/strings.xml
index 5572449..fcfac4d 100644
--- a/v7/mediarouter/res/values-nl/strings.xml
+++ b/v7/mediarouter/res/values-nl/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"Systeem"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"Apparaten"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"Media-uitvoer"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"Casten"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"Verbinding maken met apparaat"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"Zoeken naar apparaten…"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"Verbinding verbreken"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"Casten stoppen"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"Route-instellingen"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"Afspelen"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"Onderbreken"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-pa-rIN/strings.xml b/v7/mediarouter/res/values-pa-rIN/strings.xml
new file mode 100644
index 0000000..fb87320
--- /dev/null
+++ b/v7/mediarouter/res/values-pa-rIN/strings.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2013 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="mr_system_route_name" msgid="5441529851481176817">"ਸਿਸਟਮ"</string>
+    <string name="mr_user_route_category_name" msgid="7498112907524977311">"ਡਿਵਾਈਸਾਂ"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"ਜੋੜੋ"</string>
+    <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"ਡਿਵਾਈਸ ਨਾਲ ਕਨੈਕਟ ਕਰੋ"</string>
+    <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"ਡਿਵਾਈਸਾਂ ਦੀ ਖੋਜ ਕਰ ਰਿਹਾ ਹੈ…"</string>
+    <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"ਡਿਸਕਨੈਕਟ ਕਰੋ"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"ਜੋੜਨਾ ਰੋਕੋ"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"ਰੂਟ ਸੈਟਿੰਗਾਂ"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"ਪਲੇ ਕਰੋ"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"ਰੋਕੋ"</string>
+</resources>
diff --git a/v7/mediarouter/res/values-pl/strings.xml b/v7/mediarouter/res/values-pl/strings.xml
index 95a1d03..34fea86 100644
--- a/v7/mediarouter/res/values-pl/strings.xml
+++ b/v7/mediarouter/res/values-pl/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"System"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"Urządzenia"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"Wyjście multimediów"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"Przesyłaj"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"Połącz z urządzeniem"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"Szukam urządzeń…"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"Rozłącz"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"Zakończ przesyłanie"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"Ustawienia trasy"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"Odtwórz"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"Wstrzymaj"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-pt-rPT/strings.xml b/v7/mediarouter/res/values-pt-rPT/strings.xml
index 54b1dfc..1e1dbbb 100644
--- a/v7/mediarouter/res/values-pt-rPT/strings.xml
+++ b/v7/mediarouter/res/values-pt-rPT/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"Sistema"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"Dispositivos"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"Saída de som multimédia"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"Transmitir"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"Ligar ao dispositivo"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"A pesquisar dispositivos…"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"Desassociar"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"Parar a transmissão"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"Definições de trajeto"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"Reproduzir"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"Colocar em pausa"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-pt/strings.xml b/v7/mediarouter/res/values-pt/strings.xml
index 3ce1c38..67648a7 100644
--- a/v7/mediarouter/res/values-pt/strings.xml
+++ b/v7/mediarouter/res/values-pt/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"Sistema"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"Dispositivos"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"Saída de mídia"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"Transmitir"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"Conectar ao dispositivo"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"Procurando dispositivos…"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"Desconectar"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"Interromper transmissão"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"Configurações de rota"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"Reproduzir"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"Pausar"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-ro/strings.xml b/v7/mediarouter/res/values-ro/strings.xml
index 4c9e4b9..d738bab 100644
--- a/v7/mediarouter/res/values-ro/strings.xml
+++ b/v7/mediarouter/res/values-ro/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"Sistem"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"Dispozitive"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"Rezultate media"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"Trimiteți"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"Conectați-vă la dispozitiv"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"Se caută dispozitive..."</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"Deconectați-vă"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"Nu mai proiectați"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"Setări pentru traseu"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"Redați"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"Întrerupeți"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-ru/strings.xml b/v7/mediarouter/res/values-ru/strings.xml
index 5cc2bba..dfa836c 100644
--- a/v7/mediarouter/res/values-ru/strings.xml
+++ b/v7/mediarouter/res/values-ru/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"Система"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"Устройства"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"Перенаправлять поток мультимедиа"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"Транслировать."</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"Подключение к устройству"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"Поиск устройств…"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"Отключить"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"Остановить трансляцию"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"Настройки передачи файлов"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"Воспроизвести."</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"Приостановить."</string>
 </resources>
diff --git a/v7/mediarouter/res/values-si-rLK/strings.xml b/v7/mediarouter/res/values-si-rLK/strings.xml
index 2eba3c8..1ac7319 100644
--- a/v7/mediarouter/res/values-si-rLK/strings.xml
+++ b/v7/mediarouter/res/values-si-rLK/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"පද්ධතිය"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"උපාංග"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"මාධ්‍ය ප්‍රතිදානය"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"Cast"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"උපාංගයට සම්බන්ධ වන්න"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"උපාංග සඳහා සොයමින්…"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"විසන්ධි කරන්න"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"කාස්ට් කිරීම නවත්වන්න"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"ගමන් මගේ සැකසීම්"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"ධාවනය කරන්න"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"විරාමය"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-sk/strings.xml b/v7/mediarouter/res/values-sk/strings.xml
index 668800f..3156edf 100644
--- a/v7/mediarouter/res/values-sk/strings.xml
+++ b/v7/mediarouter/res/values-sk/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"Systém"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"Zariadenia"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"Výstup médií"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"Preniesť"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"Pripojenie k zariadeniu"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"Prebieha vyhľadávanie zariadení…"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"Odpojiť"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"Zastaviť prenášanie"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"Nastavenia trasy"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"Prehrať"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"Pozastaviť"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-sl/strings.xml b/v7/mediarouter/res/values-sl/strings.xml
index 3e3e8bb..3de14aa 100644
--- a/v7/mediarouter/res/values-sl/strings.xml
+++ b/v7/mediarouter/res/values-sl/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"Sistem"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"Naprave"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"Izhod za predstavnost"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"Predvajanje"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"Povezovanje z napravo"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"Iskanje naprav …"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"Prekini povezavo"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"Ustavi predvajanje"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"Nastavitve poti"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"Predvajaj"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"Zaustavi"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-sq-rAL/strings.xml b/v7/mediarouter/res/values-sq-rAL/strings.xml
new file mode 100644
index 0000000..2df43b1
--- /dev/null
+++ b/v7/mediarouter/res/values-sq-rAL/strings.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2013 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="mr_system_route_name" msgid="5441529851481176817">"Sistemi"</string>
+    <string name="mr_user_route_category_name" msgid="7498112907524977311">"Pajisjet"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"Transmeto"</string>
+    <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"Lidhu me pajisjen"</string>
+    <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"Po kërkon për pajisje…"</string>
+    <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"Shkëputu"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"Ndalo transmetimin"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"Cilësimet e rrugës"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"Luaj"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"Pauzë"</string>
+</resources>
diff --git a/v7/mediarouter/res/values-sr/strings.xml b/v7/mediarouter/res/values-sr/strings.xml
index 320f3e8..de10685 100644
--- a/v7/mediarouter/res/values-sr/strings.xml
+++ b/v7/mediarouter/res/values-sr/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"Систем"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"Уређаји"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"Излаз медија"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"Пребацуј"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"Повежите са уређајем"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"Претраживање уређаја…"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"Прекини везу"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"Заустави пребацивање"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"Подешавања путање"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"Пусти"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"Паузирај"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-sv/strings.xml b/v7/mediarouter/res/values-sv/strings.xml
index 910c6f1..3ac428a 100644
--- a/v7/mediarouter/res/values-sv/strings.xml
+++ b/v7/mediarouter/res/values-sv/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"System"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"Enheter"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"Medieuppspelning"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"Casta"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"Anslut till enhet"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"Söker efter enheter ..."</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"Koppla från"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"Sluta casta"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"Inställningar för omdirigering"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"Spela upp"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"Pausa"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-sw/strings.xml b/v7/mediarouter/res/values-sw/strings.xml
index fcbc590..00ce337 100644
--- a/v7/mediarouter/res/values-sw/strings.xml
+++ b/v7/mediarouter/res/values-sw/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"Mfumo"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"Vifaa"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"Towe la vyombo vya habari"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"Tuma"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"Unganisha kwenye kifaa"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"Inatafuta vifaa..."</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"Tenganisha"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"Acha kutuma"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"Mipangilio ya njia"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"Google Play"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"Sitisha"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-ta-rIN/strings.xml b/v7/mediarouter/res/values-ta-rIN/strings.xml
index d5d1386..f92c432 100644
--- a/v7/mediarouter/res/values-ta-rIN/strings.xml
+++ b/v7/mediarouter/res/values-ta-rIN/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"அமைப்பு"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"சாதனங்கள்"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"மீடியா வெளியீடு"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"அனுப்பு"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"சாதனத்துடன் இணைக்கவும்"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"சாதனங்களைத் தேடுகிறது..."</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"துண்டி"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"அனுப்புவதை நிறுத்து"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"வழி அமைப்புகள்"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"இயக்கு"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"இடைநிறுத்து"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-te-rIN/strings.xml b/v7/mediarouter/res/values-te-rIN/strings.xml
index 9fa6e90..0913420 100644
--- a/v7/mediarouter/res/values-te-rIN/strings.xml
+++ b/v7/mediarouter/res/values-te-rIN/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"సిస్టమ్"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"పరికరాలు"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"మీడియా అవుట్‌పుట్"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"ప్రసారం చేయండి"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"పరికరానికి కనెక్ట్ చేయండి"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"పరికరాల కోసం శోధిస్తోంది…"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"డిస్‌కనెక్ట్ చేయి"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"ప్రసారాన్ని ఆపివేయి"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"మార్గ సెట్టింగ్‌లు"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"ప్లే చేయి"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"పాజ్ చేయి"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-th/strings.xml b/v7/mediarouter/res/values-th/strings.xml
index 78e5a73..31fc9c7 100644
--- a/v7/mediarouter/res/values-th/strings.xml
+++ b/v7/mediarouter/res/values-th/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"ระบบ"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"อุปกรณ์"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"เอาต์พุตสื่อ"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"ส่ง"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"เชื่อมต่อกับอุปกรณ์"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"กำลังค้นหาอุปกรณ์…"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"ยกเลิกการเชื่อมต่อ"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"หยุดการส่ง"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"การตั้งค่าเส้นทาง"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"เล่น"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"หยุดชั่วคราว"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-tl/strings.xml b/v7/mediarouter/res/values-tl/strings.xml
index 0953787..d4896b5 100644
--- a/v7/mediarouter/res/values-tl/strings.xml
+++ b/v7/mediarouter/res/values-tl/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"System"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"Mga Device"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"Output ng media"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"I-cast"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"Kumonekta sa device"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"Naghahanap ng mga device…"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"Idiskonekta"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"Itigil ang pagca-cast"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"Mga setting ng ruta"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"I-play"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"I-pause"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-tr/strings.xml b/v7/mediarouter/res/values-tr/strings.xml
index 12faaa6..05344ff 100644
--- a/v7/mediarouter/res/values-tr/strings.xml
+++ b/v7/mediarouter/res/values-tr/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"Sistem"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"Cihazlar"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"Medya çıkışı"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"Yayınla"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"Cihaza bağlanın"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"Cihaz arayın…"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"Bağlantıyı kes"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"Yayını durdur"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"Rota ayarları"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"Oynat"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"Duraklat"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-uk/strings.xml b/v7/mediarouter/res/values-uk/strings.xml
index b036dea..b445b9c 100644
--- a/v7/mediarouter/res/values-uk/strings.xml
+++ b/v7/mediarouter/res/values-uk/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"Система"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"Пристрої"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"Вивід медіа-даних"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"Транслювати"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"Під’єднатися до пристрою"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"Пошук пристроїв…"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"Від’єднатися"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"Зупинити трансляцію"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"Налаштування маршруту"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"Відтворити"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"Призупинити"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-ur-rPK/strings.xml b/v7/mediarouter/res/values-ur-rPK/strings.xml
index bce0e0c..e6ce4d6 100644
--- a/v7/mediarouter/res/values-ur-rPK/strings.xml
+++ b/v7/mediarouter/res/values-ur-rPK/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"سسٹم"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"آلات"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"میڈیا آؤٹ پٹ"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"کاسٹ کریں"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"آلہ سے مربوط ہوں"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"آلات تلاش کر رہا ہے…"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"غیر مربوط کریں"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"کاسٹ کرنا بند کریں"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"روٹ کی ترتیبات"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"چلائیں"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"موقوف کریں"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-uz-rUZ/strings.xml b/v7/mediarouter/res/values-uz-rUZ/strings.xml
index f191fd9..d2829ee 100644
--- a/v7/mediarouter/res/values-uz-rUZ/strings.xml
+++ b/v7/mediarouter/res/values-uz-rUZ/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"Tizim"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"Qurilmalar"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"Media chiqish"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"Translatsiya qilish"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"Qurilmaga ulanish"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"Qurilmalar izlanmoqda…"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"Uzish"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"Translatsiyani to‘xtatish"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"Yo‘naltirish sozlamalari"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"Ijro qilish"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"To‘xtatib turish"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-vi/strings.xml b/v7/mediarouter/res/values-vi/strings.xml
index a58d0e4..01ec106 100644
--- a/v7/mediarouter/res/values-vi/strings.xml
+++ b/v7/mediarouter/res/values-vi/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"Hệ thống"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"Thiết bị"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"Đầu ra phương tiện"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"Truyền"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"Kết nối với thiết bị"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"Đang tìm kiếm thiết bị…"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"Ngắt kết nối"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"Ngừng truyền"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"Cài đặt tuyến đường"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"Phát"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"Tạm dừng"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-zh-rCN/strings.xml b/v7/mediarouter/res/values-zh-rCN/strings.xml
index 71c4407..070f1de 100644
--- a/v7/mediarouter/res/values-zh-rCN/strings.xml
+++ b/v7/mediarouter/res/values-zh-rCN/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"系统"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"设备"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"媒体输出线路"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"投射"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"连接到设备"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"正在搜索设备…"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"断开连接"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"停止投射"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"路由设置"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"播放"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"暂停"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-zh-rHK/strings.xml b/v7/mediarouter/res/values-zh-rHK/strings.xml
index f499169..a73d636 100644
--- a/v7/mediarouter/res/values-zh-rHK/strings.xml
+++ b/v7/mediarouter/res/values-zh-rHK/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"系統"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"裝置"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"媒體輸出"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"投放"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"連線至裝置"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"正在搜尋裝置…"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"中斷連線"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"停止投放"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"路由設定"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"播放"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"暫停"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-zh-rTW/strings.xml b/v7/mediarouter/res/values-zh-rTW/strings.xml
index a847615..cb07c25 100644
--- a/v7/mediarouter/res/values-zh-rTW/strings.xml
+++ b/v7/mediarouter/res/values-zh-rTW/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"系統"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"裝置"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"媒體輸出"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"投放"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"連線至裝置"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"正在搜尋裝置..."</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"中斷連線"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"停止投放"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"路由設定"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"播放"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"暫停"</string>
 </resources>
diff --git a/v7/mediarouter/res/values-zu/strings.xml b/v7/mediarouter/res/values-zu/strings.xml
index be195be..24f0a37 100644
--- a/v7/mediarouter/res/values-zu/strings.xml
+++ b/v7/mediarouter/res/values-zu/strings.xml
@@ -18,8 +18,12 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="mr_system_route_name" msgid="5441529851481176817">"Isistimu"</string>
     <string name="mr_user_route_category_name" msgid="7498112907524977311">"Amadivayisi"</string>
-    <string name="mr_media_route_button_content_description" msgid="4271159405637008602">"Okukhiphayo kwabezindaba"</string>
+    <string name="mr_media_route_button_content_description" msgid="8327680881775995150">"Abalingisi"</string>
     <string name="mr_media_route_chooser_title" msgid="7106830097177242655">"Xhumeka kudivayisi"</string>
     <string name="mr_media_route_chooser_searching" msgid="7553005460920830010">"Iseshela amadivayisi…"</string>
     <string name="mr_media_route_controller_disconnect" msgid="109793632378378069">"Nqamula"</string>
+    <string name="mr_media_route_controller_stop" msgid="5398645111664294430">"Misa ukusakaza"</string>
+    <string name="mr_media_route_controller_settings_description" msgid="379358765881274425">"Izilungiselelo zomzila"</string>
+    <string name="mr_media_route_controller_play" msgid="5214423499524760404">"Dlala"</string>
+    <string name="mr_media_route_controller_pause" msgid="8315773974194466049">"Misa isikhashana"</string>
 </resources>
diff --git a/v7/mediarouter/src/android/support/v7/app/MediaRouteButton.java b/v7/mediarouter/src/android/support/v7/app/MediaRouteButton.java
index 896c116..8a5f507 100644
--- a/v7/mediarouter/src/android/support/v7/app/MediaRouteButton.java
+++ b/v7/mediarouter/src/android/support/v7/app/MediaRouteButton.java
@@ -356,7 +356,10 @@
         }
     }
 
-    private void setRemoteIndicatorDrawable(Drawable d) {
+    /**
+     * Sets a drawable to use as the remote route indicator.
+     */
+    public void setRemoteIndicatorDrawable(Drawable d) {
         if (mRemoteIndicator != null) {
             mRemoteIndicator.setCallback(null);
             unscheduleDrawable(mRemoteIndicator);
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 c3f3e78..1ffb7a1 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
@@ -19,6 +19,8 @@
 import android.graphics.Bitmap;
 import android.graphics.Color;
 import android.os.AsyncTask;
+import android.support.annotation.ColorInt;
+import android.support.annotation.Nullable;
 import android.support.v4.graphics.ColorUtils;
 import android.support.v4.os.AsyncTaskCompat;
 import android.util.TimingLogger;
@@ -153,6 +155,7 @@
     /**
      * Returns the most vibrant swatch in the palette. Might be null.
      */
+    @Nullable
     public Swatch getVibrantSwatch() {
         return mGenerator.getVibrantSwatch();
     }
@@ -160,6 +163,7 @@
     /**
      * Returns a light and vibrant swatch from the palette. Might be null.
      */
+    @Nullable
     public Swatch getLightVibrantSwatch() {
         return mGenerator.getLightVibrantSwatch();
     }
@@ -167,6 +171,7 @@
     /**
      * Returns a dark and vibrant swatch from the palette. Might be null.
      */
+    @Nullable
     public Swatch getDarkVibrantSwatch() {
         return mGenerator.getDarkVibrantSwatch();
     }
@@ -174,6 +179,7 @@
     /**
      * Returns a muted swatch from the palette. Might be null.
      */
+    @Nullable
     public Swatch getMutedSwatch() {
         return mGenerator.getMutedSwatch();
     }
@@ -181,6 +187,7 @@
     /**
      * Returns a muted and light swatch from the palette. Might be null.
      */
+    @Nullable
     public Swatch getLightMutedSwatch() {
         return mGenerator.getLightMutedSwatch();
     }
@@ -188,6 +195,7 @@
     /**
      * Returns a muted and dark swatch from the palette. Might be null.
      */
+    @Nullable
     public Swatch getDarkMutedSwatch() {
         return mGenerator.getDarkMutedSwatch();
     }
@@ -197,7 +205,8 @@
      *
      * @param defaultColor value to return if the swatch isn't available
      */
-    public int getVibrantColor(int defaultColor) {
+    @ColorInt
+    public int getVibrantColor(@ColorInt int defaultColor) {
         Swatch swatch = getVibrantSwatch();
         return swatch != null ? swatch.getRgb() : defaultColor;
     }
@@ -207,7 +216,8 @@
      *
      * @param defaultColor value to return if the swatch isn't available
      */
-    public int getLightVibrantColor(int defaultColor) {
+    @ColorInt
+    public int getLightVibrantColor(@ColorInt int defaultColor) {
         Swatch swatch = getLightVibrantSwatch();
         return swatch != null ? swatch.getRgb() : defaultColor;
     }
@@ -217,7 +227,8 @@
      *
      * @param defaultColor value to return if the swatch isn't available
      */
-    public int getDarkVibrantColor(int defaultColor) {
+    @ColorInt
+    public int getDarkVibrantColor(@ColorInt int defaultColor) {
         Swatch swatch = getDarkVibrantSwatch();
         return swatch != null ? swatch.getRgb() : defaultColor;
     }
@@ -227,7 +238,8 @@
      *
      * @param defaultColor value to return if the swatch isn't available
      */
-    public int getMutedColor(int defaultColor) {
+    @ColorInt
+    public int getMutedColor(@ColorInt int defaultColor) {
         Swatch swatch = getMutedSwatch();
         return swatch != null ? swatch.getRgb() : defaultColor;
     }
@@ -237,7 +249,8 @@
      *
      * @param defaultColor value to return if the swatch isn't available
      */
-    public int getLightMutedColor(int defaultColor) {
+    @ColorInt
+    public int getLightMutedColor(@ColorInt int defaultColor) {
         Swatch swatch = getLightMutedSwatch();
         return swatch != null ? swatch.getRgb() : defaultColor;
     }
@@ -247,7 +260,8 @@
      *
      * @param defaultColor value to return if the swatch isn't available
      */
-    public int getDarkMutedColor(int defaultColor) {
+    @ColorInt
+    public int getDarkMutedColor(@ColorInt int defaultColor) {
         Swatch swatch = getDarkMutedSwatch();
         return swatch != null ? swatch.getRgb() : defaultColor;
     }
@@ -286,7 +300,7 @@
 
         private float[] mHsl;
 
-        public Swatch(int color, int population) {
+        public Swatch(@ColorInt int color, int population) {
             mRed = Color.red(color);
             mGreen = Color.green(color);
             mBlue = Color.blue(color);
@@ -305,6 +319,7 @@
         /**
          * @return this swatch's RGB color value
          */
+        @ColorInt
         public int getRgb() {
             return mRgb;
         }
@@ -334,6 +349,7 @@
          * Returns an appropriate color to use for any 'title' text which is displayed over this
          * {@link Swatch}'s color. This color is guaranteed to have sufficient contrast.
          */
+        @ColorInt
         public int getTitleTextColor() {
             ensureTextColorsGenerated();
             return mTitleTextColor;
@@ -343,6 +359,7 @@
          * Returns an appropriate color to use for any 'body' text which is displayed over this
          * {@link Swatch}'s color. This color is guaranteed to have sufficient contrast.
          */
+        @ColorInt
         public int getBodyTextColor() {
             ensureTextColorsGenerated();
             return mBodyTextColor;
diff --git a/v7/preference/Android.mk b/v7/preference/Android.mk
new file mode 100644
index 0000000..e2db0f1
--- /dev/null
+++ b/v7/preference/Android.mk
@@ -0,0 +1,58 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+# Build the resources using the current SDK version.
+# We do this here because the final static library must be compiled with an older
+# SDK version than the resources.  The resources library and the R class that it
+# contains will not be linked into the final static library.
+include $(CLEAR_VARS)
+LOCAL_MODULE := android-support-v7-preference-res
+LOCAL_SDK_VERSION := current
+LOCAL_SRC_FILES := $(call all-java-files-under, dummy)
+LOCAL_RESOURCE_DIR := \
+        frameworks/support/v7/appcompat/res \
+        frameworks/support/v7/recyclerview/res \
+        $(LOCAL_PATH)/res
+LOCAL_AAPT_FLAGS := \
+	--auto-add-overlay
+LOCAL_JAR_EXCLUDE_FILES := none
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+# Here is the final static library that apps can link against.
+# The R class is automatically excluded from the generated library.
+# Applications that use this library must specify LOCAL_RESOURCE_DIR
+# in their makefiles to include the resources in their package.
+include $(CLEAR_VARS)
+LOCAL_MODULE := android-support-v7-preference
+LOCAL_SDK_VERSION := 7
+LOCAL_SRC_FILES := $(call all-java-files-under,src)
+# LOCAL_STATIC_JAVA_LIBRARIES :=
+LOCAL_JAVA_LIBRARIES := \
+        android-support-v4 \
+        android-support-v7-appcompat \
+        android-support-v7-recyclerview \
+        android-support-annotations \
+        android-support-v7-preference-res
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+# API Check
+# ---------------------------------------------
+support_module := $(LOCAL_MODULE)
+support_module_api_dir := $(LOCAL_PATH)/api
+support_module_src_files := $(LOCAL_SRC_FILES)
+support_module_java_libraries := $(LOCAL_JAVA_LIBRARIES)
+support_module_java_packages := android.support.v7.preference
+include $(SUPPORT_API_CHECK)
diff --git a/v7/preference/AndroidManifest.xml b/v7/preference/AndroidManifest.xml
new file mode 100644
index 0000000..e5aa094
--- /dev/null
+++ b/v7/preference/AndroidManifest.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.support.v7.preference"
+    android:versionCode="1"
+    android:versionName="1.0">
+    <uses-sdk android:minSdkVersion="7" />
+    <application />
+</manifest>
diff --git a/v7/preference/api/current.txt b/v7/preference/api/current.txt
new file mode 100644
index 0000000..a432b43
--- /dev/null
+++ b/v7/preference/api/current.txt
@@ -0,0 +1,318 @@
+package android.support.v7.preference {
+
+  public class CheckBoxPreference extends android.support.v7.preference.TwoStatePreference {
+    ctor public CheckBoxPreference(android.content.Context, android.util.AttributeSet, int);
+    ctor public CheckBoxPreference(android.content.Context, android.util.AttributeSet, int, int);
+    ctor public CheckBoxPreference(android.content.Context, android.util.AttributeSet);
+    ctor public CheckBoxPreference(android.content.Context);
+  }
+
+  public abstract class DialogPreference extends android.support.v7.preference.Preference {
+    ctor public DialogPreference(android.content.Context, android.util.AttributeSet, int, int);
+    ctor public DialogPreference(android.content.Context, android.util.AttributeSet, int);
+    ctor public DialogPreference(android.content.Context, android.util.AttributeSet);
+    ctor public DialogPreference(android.content.Context);
+    method public android.graphics.drawable.Drawable getDialogIcon();
+    method public int getDialogLayoutResource();
+    method public java.lang.CharSequence getDialogMessage();
+    method public java.lang.CharSequence getDialogTitle();
+    method public java.lang.CharSequence getNegativeButtonText();
+    method public java.lang.CharSequence getPositiveButtonText();
+    method public void setDialogIcon(android.graphics.drawable.Drawable);
+    method public void setDialogIcon(int);
+    method public void setDialogLayoutResource(int);
+    method public void setDialogMessage(java.lang.CharSequence);
+    method public void setDialogMessage(int);
+    method public void setDialogTitle(java.lang.CharSequence);
+    method public void setDialogTitle(int);
+    method public void setNegativeButtonText(java.lang.CharSequence);
+    method public void setNegativeButtonText(int);
+    method public void setPositiveButtonText(java.lang.CharSequence);
+    method public void setPositiveButtonText(int);
+  }
+
+  public static abstract interface DialogPreference.TargetFragment {
+    method public abstract android.support.v7.preference.Preference findPreference(java.lang.CharSequence);
+  }
+
+  public class EditTextPreference extends android.support.v7.preference.DialogPreference {
+    ctor public EditTextPreference(android.content.Context, android.util.AttributeSet, int, int);
+    ctor public EditTextPreference(android.content.Context, android.util.AttributeSet, int);
+    ctor public EditTextPreference(android.content.Context, android.util.AttributeSet);
+    ctor public EditTextPreference(android.content.Context);
+    method public java.lang.String getText();
+    method public void setText(java.lang.String);
+  }
+
+  public class EditTextPreferenceDialogFragmentCompat extends android.support.v7.preference.PreferenceDialogFragmentCompat {
+    ctor public EditTextPreferenceDialogFragmentCompat();
+    method public static android.support.v7.preference.EditTextPreferenceDialogFragmentCompat newInstance(java.lang.String);
+    method protected void onAddEditTextToDialogView(android.view.View, android.widget.EditText);
+    method public void onDialogClosed(boolean);
+  }
+
+  public class ListPreference extends android.support.v7.preference.DialogPreference {
+    ctor public ListPreference(android.content.Context, android.util.AttributeSet, int, int);
+    ctor public ListPreference(android.content.Context, android.util.AttributeSet, int);
+    ctor public ListPreference(android.content.Context, android.util.AttributeSet);
+    ctor public ListPreference(android.content.Context);
+    method public int findIndexOfValue(java.lang.String);
+    method public java.lang.CharSequence[] getEntries();
+    method public java.lang.CharSequence getEntry();
+    method public java.lang.CharSequence[] getEntryValues();
+    method public java.lang.String getValue();
+    method public void setEntries(java.lang.CharSequence[]);
+    method public void setEntries(int);
+    method public void setEntryValues(java.lang.CharSequence[]);
+    method public void setEntryValues(int);
+    method public void setValue(java.lang.String);
+    method public void setValueIndex(int);
+  }
+
+  public class ListPreferenceDialogFragmentCompat extends android.support.v7.preference.PreferenceDialogFragmentCompat {
+    ctor public ListPreferenceDialogFragmentCompat();
+    method public static android.support.v7.preference.ListPreferenceDialogFragmentCompat newInstance(java.lang.String);
+    method public void onDialogClosed(boolean);
+  }
+
+  public class Preference {
+    ctor public Preference(android.content.Context, android.util.AttributeSet, int, int);
+    ctor public Preference(android.content.Context, android.util.AttributeSet, int);
+    ctor public Preference(android.content.Context, android.util.AttributeSet);
+    ctor public Preference(android.content.Context);
+    method public boolean callChangeListener(java.lang.Object);
+    method public int compareTo(android.support.v7.preference.Preference);
+    method protected android.support.v7.preference.Preference findPreferenceInHierarchy(java.lang.String);
+    method public android.content.Context getContext();
+    method public java.lang.String getDependency();
+    method public android.os.Bundle getExtras();
+    method public java.lang.String getFragment();
+    method public android.graphics.drawable.Drawable getIcon();
+    method public android.content.Intent getIntent();
+    method public java.lang.String getKey();
+    method public final int getLayoutResource();
+    method public android.support.v7.preference.Preference.OnPreferenceChangeListener getOnPreferenceChangeListener();
+    method public android.support.v7.preference.Preference.OnPreferenceClickListener getOnPreferenceClickListener();
+    method public int getOrder();
+    method protected boolean getPersistedBoolean(boolean);
+    method protected float getPersistedFloat(float);
+    method protected int getPersistedInt(int);
+    method protected long getPersistedLong(long);
+    method protected java.lang.String getPersistedString(java.lang.String);
+    method public android.support.v7.preference.PreferenceManager getPreferenceManager();
+    method public android.content.SharedPreferences getSharedPreferences();
+    method public boolean getShouldDisableView();
+    method public java.lang.CharSequence getSummary();
+    method public java.lang.CharSequence getTitle();
+    method public final int getWidgetLayoutResource();
+    method public boolean hasKey();
+    method public boolean isEnabled();
+    method public boolean isPersistent();
+    method public boolean isSelectable();
+    method public final boolean isVisible();
+    method protected void notifyChanged();
+    method public void notifyDependencyChange(boolean);
+    method protected void notifyHierarchyChanged();
+    method protected void onAttached();
+    method protected void onAttachedToHierarchy(android.support.v7.preference.PreferenceManager);
+    method public void onBindViewHolder(android.support.v7.preference.PreferenceViewHolder);
+    method protected void onClick();
+    method public void onDependencyChanged(android.support.v7.preference.Preference, boolean);
+    method protected java.lang.Object onGetDefaultValue(android.content.res.TypedArray, int);
+    method public void onParentChanged(android.support.v7.preference.Preference, boolean);
+    method protected void onPrepareForRemoval();
+    method protected void onRestoreInstanceState(android.os.Parcelable);
+    method protected android.os.Parcelable onSaveInstanceState();
+    method protected void onSetInitialValue(boolean, java.lang.Object);
+    method public android.os.Bundle peekExtras();
+    method protected boolean persistBoolean(boolean);
+    method protected boolean persistFloat(float);
+    method protected boolean persistInt(int);
+    method protected boolean persistLong(long);
+    method protected boolean persistString(java.lang.String);
+    method public void restoreHierarchyState(android.os.Bundle);
+    method public void saveHierarchyState(android.os.Bundle);
+    method public void setDefaultValue(java.lang.Object);
+    method public void setDependency(java.lang.String);
+    method public void setEnabled(boolean);
+    method public void setFragment(java.lang.String);
+    method public void setIcon(android.graphics.drawable.Drawable);
+    method public void setIcon(int);
+    method public void setIntent(android.content.Intent);
+    method public void setKey(java.lang.String);
+    method public void setLayoutResource(int);
+    method public void setOnPreferenceChangeListener(android.support.v7.preference.Preference.OnPreferenceChangeListener);
+    method public void setOnPreferenceClickListener(android.support.v7.preference.Preference.OnPreferenceClickListener);
+    method public void setOrder(int);
+    method public void setPersistent(boolean);
+    method public void setSelectable(boolean);
+    method public void setShouldDisableView(boolean);
+    method public void setSummary(java.lang.CharSequence);
+    method public void setSummary(int);
+    method public void setTitle(java.lang.CharSequence);
+    method public void setTitle(int);
+    method public final void setVisible(boolean);
+    method public void setWidgetLayoutResource(int);
+    method public boolean shouldDisableDependents();
+    method protected boolean shouldPersist();
+    field public static final int DEFAULT_ORDER = 2147483647; // 0x7fffffff
+  }
+
+  public static class Preference.BaseSavedState extends android.view.AbsSavedState {
+    ctor public Preference.BaseSavedState(android.os.Parcel);
+    ctor public Preference.BaseSavedState(android.os.Parcelable);
+    field public static final android.os.Parcelable.Creator<android.support.v7.preference.Preference.BaseSavedState> CREATOR;
+  }
+
+  public static abstract interface Preference.OnPreferenceChangeListener {
+    method public abstract boolean onPreferenceChange(android.support.v7.preference.Preference, java.lang.Object);
+  }
+
+  public static abstract interface Preference.OnPreferenceClickListener {
+    method public abstract boolean onPreferenceClick(android.support.v7.preference.Preference);
+  }
+
+  public class PreferenceCategory extends android.support.v7.preference.PreferenceGroup {
+    ctor public PreferenceCategory(android.content.Context, android.util.AttributeSet, int, int);
+    ctor public PreferenceCategory(android.content.Context, android.util.AttributeSet, int);
+    ctor public PreferenceCategory(android.content.Context, android.util.AttributeSet);
+    ctor public PreferenceCategory(android.content.Context);
+  }
+
+  public abstract class PreferenceDialogFragmentCompat extends android.support.v4.app.DialogFragment implements android.content.DialogInterface.OnClickListener {
+    ctor public PreferenceDialogFragmentCompat();
+    method public android.support.v7.preference.DialogPreference getPreference();
+    method protected void onBindDialogView(android.view.View);
+    method public void onClick(android.content.DialogInterface, int);
+    method protected android.view.View onCreateDialogView(android.content.Context);
+    method public abstract void onDialogClosed(boolean);
+    method protected void onPrepareDialogBuilder(android.support.v7.app.AlertDialog.Builder);
+    field protected static final java.lang.String ARG_KEY = "key";
+  }
+
+  public abstract class PreferenceFragmentCompat extends android.support.v4.app.Fragment implements android.support.v7.preference.DialogPreference.TargetFragment android.support.v7.preference.PreferenceManager.OnDisplayPreferenceDialogListener android.support.v7.preference.PreferenceManager.OnNavigateToScreenListener android.support.v7.preference.PreferenceManager.OnPreferenceTreeClickListener {
+    ctor public PreferenceFragmentCompat();
+    method public void addPreferencesFromResource(int);
+    method public android.support.v7.preference.Preference findPreference(java.lang.CharSequence);
+    method public final android.support.v7.widget.RecyclerView getListView();
+    method public android.support.v7.preference.PreferenceManager getPreferenceManager();
+    method public android.support.v7.preference.PreferenceScreen getPreferenceScreen();
+    method protected android.support.v7.widget.RecyclerView.Adapter onCreateAdapter(android.support.v7.preference.PreferenceScreen);
+    method public android.support.v7.widget.RecyclerView.LayoutManager onCreateLayoutManager();
+    method public abstract void onCreatePreferences(android.os.Bundle, java.lang.String);
+    method public android.support.v7.widget.RecyclerView onCreateRecyclerView(android.view.LayoutInflater, android.view.ViewGroup, android.os.Bundle);
+    method public void onDisplayPreferenceDialog(android.support.v7.preference.Preference);
+    method public void onNavigateToScreen(android.support.v7.preference.PreferenceScreen);
+    method public boolean onPreferenceTreeClick(android.support.v7.preference.Preference);
+    method public void setPreferenceScreen(android.support.v7.preference.PreferenceScreen);
+    method public void setPreferencesFromResource(int, java.lang.String);
+    field public static final java.lang.String ARG_PREFERENCE_ROOT = "android.support.v7.preference.PreferenceFragmentCompat.PREFERENCE_ROOT";
+  }
+
+  public static abstract interface PreferenceFragmentCompat.OnPreferenceDisplayDialogCallback {
+    method public abstract boolean onPreferenceDisplayDialog(android.support.v7.preference.PreferenceFragmentCompat, android.support.v7.preference.Preference);
+  }
+
+  public static abstract interface PreferenceFragmentCompat.OnPreferenceStartFragmentCallback {
+    method public abstract boolean onPreferenceStartFragment(android.support.v7.preference.PreferenceFragmentCompat, android.support.v7.preference.Preference);
+  }
+
+  public static abstract interface PreferenceFragmentCompat.OnPreferenceStartScreenCallback {
+    method public abstract boolean onPreferenceStartScreen(android.support.v7.preference.PreferenceFragmentCompat, android.support.v7.preference.PreferenceScreen);
+  }
+
+  public abstract class PreferenceGroup extends android.support.v7.preference.Preference {
+    ctor public PreferenceGroup(android.content.Context, android.util.AttributeSet, int, int);
+    ctor public PreferenceGroup(android.content.Context, android.util.AttributeSet, int);
+    ctor public PreferenceGroup(android.content.Context, android.util.AttributeSet);
+    method public void addItemFromInflater(android.support.v7.preference.Preference);
+    method public boolean addPreference(android.support.v7.preference.Preference);
+    method protected void dispatchRestoreInstanceState(android.os.Bundle);
+    method protected void dispatchSaveInstanceState(android.os.Bundle);
+    method public android.support.v7.preference.Preference findPreference(java.lang.CharSequence);
+    method public android.support.v7.preference.Preference getPreference(int);
+    method public int getPreferenceCount();
+    method protected boolean isOnSameScreenAsChildren();
+    method public boolean isOrderingAsAdded();
+    method protected boolean onPrepareAddPreference(android.support.v7.preference.Preference);
+    method public void removeAll();
+    method public boolean removePreference(android.support.v7.preference.Preference);
+    method public void setOrderingAsAdded(boolean);
+  }
+
+  public class PreferenceManager {
+    method public android.support.v7.preference.PreferenceScreen createPreferenceScreen(android.content.Context);
+    method public android.support.v7.preference.Preference findPreference(java.lang.CharSequence);
+    method public static android.content.SharedPreferences getDefaultSharedPreferences(android.content.Context);
+    method public android.support.v7.preference.PreferenceManager.OnDisplayPreferenceDialogListener getOnDisplayPreferenceDialogListener();
+    method public android.support.v7.preference.PreferenceManager.OnNavigateToScreenListener getOnNavigateToScreenListener();
+    method public android.support.v7.preference.PreferenceManager.OnPreferenceTreeClickListener getOnPreferenceTreeClickListener();
+    method public android.support.v7.preference.PreferenceScreen getPreferenceScreen();
+    method public android.content.SharedPreferences getSharedPreferences();
+    method public int getSharedPreferencesMode();
+    method public java.lang.String getSharedPreferencesName();
+    method public static void setDefaultValues(android.content.Context, int, boolean);
+    method public static void setDefaultValues(android.content.Context, java.lang.String, int, int, boolean);
+    method public void setOnDisplayPreferenceDialogListener(android.support.v7.preference.PreferenceManager.OnDisplayPreferenceDialogListener);
+    method public void setOnNavigateToScreenListener(android.support.v7.preference.PreferenceManager.OnNavigateToScreenListener);
+    method public void setOnPreferenceTreeClickListener(android.support.v7.preference.PreferenceManager.OnPreferenceTreeClickListener);
+    method public boolean setPreferences(android.support.v7.preference.PreferenceScreen);
+    method public void setSharedPreferencesMode(int);
+    method public void setSharedPreferencesName(java.lang.String);
+    method public void showDialog(android.support.v7.preference.Preference);
+    field public static final java.lang.String KEY_HAS_SET_DEFAULT_VALUES = "_has_set_default_values";
+  }
+
+  public static abstract interface PreferenceManager.OnDisplayPreferenceDialogListener {
+    method public abstract void onDisplayPreferenceDialog(android.support.v7.preference.Preference);
+  }
+
+  public static abstract interface PreferenceManager.OnNavigateToScreenListener {
+    method public abstract void onNavigateToScreen(android.support.v7.preference.PreferenceScreen);
+  }
+
+  public static abstract interface PreferenceManager.OnPreferenceTreeClickListener {
+    method public abstract boolean onPreferenceTreeClick(android.support.v7.preference.Preference);
+  }
+
+  public final class PreferenceScreen extends android.support.v7.preference.PreferenceGroup {
+  }
+
+  public class PreferenceViewHolder extends android.support.v7.widget.RecyclerView.ViewHolder {
+    method public android.view.View findViewById(int);
+  }
+
+  public class SwitchPreferenceCompat extends android.support.v7.preference.TwoStatePreference {
+    ctor public SwitchPreferenceCompat(android.content.Context, android.util.AttributeSet, int, int);
+    ctor public SwitchPreferenceCompat(android.content.Context, android.util.AttributeSet, int);
+    ctor public SwitchPreferenceCompat(android.content.Context, android.util.AttributeSet);
+    ctor public SwitchPreferenceCompat(android.content.Context);
+    method public java.lang.CharSequence getSwitchTextOff();
+    method public java.lang.CharSequence getSwitchTextOn();
+    method public void setSwitchTextOff(java.lang.CharSequence);
+    method public void setSwitchTextOff(int);
+    method public void setSwitchTextOn(java.lang.CharSequence);
+    method public void setSwitchTextOn(int);
+  }
+
+  public abstract class TwoStatePreference extends android.support.v7.preference.Preference {
+    ctor public TwoStatePreference(android.content.Context, android.util.AttributeSet, int, int);
+    ctor public TwoStatePreference(android.content.Context, android.util.AttributeSet, int);
+    ctor public TwoStatePreference(android.content.Context, android.util.AttributeSet);
+    ctor public TwoStatePreference(android.content.Context);
+    method public boolean getDisableDependentsState();
+    method public java.lang.CharSequence getSummaryOff();
+    method public java.lang.CharSequence getSummaryOn();
+    method public boolean isChecked();
+    method public void setChecked(boolean);
+    method public void setDisableDependentsState(boolean);
+    method public void setSummaryOff(java.lang.CharSequence);
+    method public void setSummaryOff(int);
+    method public void setSummaryOn(java.lang.CharSequence);
+    method public void setSummaryOn(int);
+    method protected void syncSummaryView(android.support.v7.preference.PreferenceViewHolder);
+    field protected boolean mChecked;
+  }
+
+}
+
diff --git a/v7/preference/api/removed.txt b/v7/preference/api/removed.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/v7/preference/api/removed.txt
diff --git a/v7/preference/build.gradle b/v7/preference/build.gradle
new file mode 100644
index 0000000..6576e5f
--- /dev/null
+++ b/v7/preference/build.gradle
@@ -0,0 +1,53 @@
+/*
+ * 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
+ */
+
+apply plugin: 'android-library'
+
+archivesBaseName = 'preference-v7'
+
+dependencies {
+    compile project(':support-v4')
+    compile project(':support-appcompat-v7')
+    compile project(':support-recyclerview-v7')
+}
+
+android {
+    compileSdkVersion 'current'
+
+    sourceSets {
+        main.manifest.srcFile 'AndroidManifest.xml'
+        main.java.srcDir 'src'
+        main.res.srcDir 'res'
+        main.assets.srcDir 'assets'
+        main.resources.srcDir 'src'
+
+        // this moves src/instrumentTest to tests so all folders follow:
+        // tests/java, tests/res, tests/assets, ...
+        // This is a *reset* so it replaces the default paths
+        androidTest.setRoot('tests')
+        androidTest.java.srcDir 'tests/src'
+    }
+
+    compileOptions {
+        sourceCompatibility JavaVersion.VERSION_1_7
+        targetCompatibility JavaVersion.VERSION_1_7
+    }
+
+    lintOptions {
+        // TODO: fix errors and reenable.
+        abortOnError false
+    }
+}
diff --git a/v7/preference/res/layout-v11/preference.xml b/v7/preference/res/layout-v11/preference.xml
new file mode 100644
index 0000000..dbf6210
--- /dev/null
+++ b/v7/preference/res/layout-v11/preference.xml
@@ -0,0 +1,75 @@
+<?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
+  -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:minHeight="?android:attr/listPreferredItemHeight"
+    android:gravity="center_vertical"
+    android:paddingEnd="?android:attr/scrollbarSize"
+    android:background="?android:attr/selectableItemBackground"
+    android:focusable="true" >
+
+    <FrameLayout
+        android:id="@+id/icon_frame"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content">
+        <ImageView
+            android:id="@android:id/icon"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center"
+            />
+    </FrameLayout>
+
+    <RelativeLayout
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="15dip"
+        android:layout_marginEnd="6dip"
+        android:layout_marginTop="6dip"
+        android:layout_marginBottom="6dip"
+        android:layout_weight="1">
+
+        <TextView android:id="@android:id/title"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:singleLine="true"
+            android:textAppearance="?android:attr/textAppearanceLarge"
+            android:textColor="?android:attr/textColorPrimary"
+            android:ellipsize="marquee"
+            android:fadingEdge="horizontal" />
+
+        <TextView android:id="@android:id/summary"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_below="@android:id/title"
+            android:layout_alignStart="@android:id/title"
+            android:textAppearance="?android:attr/textAppearanceSmall"
+            android:textColor="?android:attr/textColorSecondary"
+            android:maxLines="4" />
+
+    </RelativeLayout>
+
+    <!-- Preference should place its actual preference widget here. -->
+    <LinearLayout android:id="@+id/widget_frame"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:gravity="center_vertical"
+        android:orientation="vertical" />
+
+</LinearLayout>
diff --git a/v7/preference/res/layout/preference.xml b/v7/preference/res/layout/preference.xml
new file mode 100644
index 0000000..9f610a3
--- /dev/null
+++ b/v7/preference/res/layout/preference.xml
@@ -0,0 +1,75 @@
+<?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
+  -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:minHeight="?android:attr/listPreferredItemHeight"
+    android:gravity="center_vertical"
+    android:paddingEnd="?android:attr/scrollbarSize"
+    android:background="@android:drawable/list_selector_background"
+    android:focusable="true" >
+
+    <FrameLayout
+        android:id="@+id/icon_frame"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content">
+        <ImageView
+            android:id="@android:id/icon"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center"
+            />
+    </FrameLayout>
+
+    <RelativeLayout
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="15dip"
+        android:layout_marginEnd="6dip"
+        android:layout_marginTop="6dip"
+        android:layout_marginBottom="6dip"
+        android:layout_weight="1">
+
+        <TextView android:id="@android:id/title"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:singleLine="true"
+            android:textAppearance="?android:attr/textAppearanceLarge"
+            android:textColor="?android:attr/textColorPrimary"
+            android:ellipsize="marquee"
+            android:fadingEdge="horizontal" />
+
+        <TextView android:id="@android:id/summary"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_below="@android:id/title"
+            android:layout_alignStart="@android:id/title"
+            android:textAppearance="?android:attr/textAppearanceSmall"
+            android:textColor="?android:attr/textColorSecondary"
+            android:maxLines="4" />
+
+    </RelativeLayout>
+
+    <!-- Preference should place its actual preference widget here. -->
+    <LinearLayout android:id="@+id/widget_frame"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:gravity="center_vertical"
+        android:orientation="vertical" />
+
+</LinearLayout>
diff --git a/v7/preference/res/layout/preference_category.xml b/v7/preference/res/layout/preference_category.xml
new file mode 100644
index 0000000..280d952
--- /dev/null
+++ b/v7/preference/res/layout/preference_category.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2006 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.
+-->
+
+<!-- Layout used for PreferenceCategory in a PreferenceActivity. -->
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    style="?android:attr/listSeparatorTextViewStyle"
+    android:id="@+android:id/title"
+/>
diff --git a/v7/preference/res/layout/preference_dialog_edittext.xml b/v7/preference/res/layout/preference_dialog_edittext.xml
new file mode 100644
index 0000000..527a7de
--- /dev/null
+++ b/v7/preference/res/layout/preference_dialog_edittext.xml
@@ -0,0 +1,41 @@
+<?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
+  -->
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:layout_marginTop="48dp"
+    android:layout_marginBottom="48dp"
+    android:overScrollMode="ifContentScrolls">
+
+  <LinearLayout
+      android:id="@+id/edittext_container"
+      android:layout_width="match_parent"
+      android:layout_height="wrap_content"
+      android:padding="5dip"
+      android:orientation="vertical">
+
+    <TextView android:id="@android:id/message"
+        style="?android:attr/textAppearanceSmall"
+        android:layout_marginBottom="48dp"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:textColor="?android:attr/textColorSecondary" />
+
+  </LinearLayout>
+
+</ScrollView>
diff --git a/v7/preference/res/layout/preference_information.xml b/v7/preference/res/layout/preference_information.xml
new file mode 100644
index 0000000..e3be382
--- /dev/null
+++ b/v7/preference/res/layout/preference_information.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2006 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.
+-->
+
+<!-- Layout for a Preference in a PreferenceActivity. The
+     Preference is able to place a specific widget for its particular
+     type in the "widget_frame" layout. -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:minHeight="?android:attr/listPreferredItemHeight"
+    android:gravity="center_vertical"
+    android:paddingEnd="?android:attr/scrollbarSize">
+
+    <RelativeLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="16sp"
+        android:layout_marginEnd="6sp"
+        android:layout_marginTop="6sp"
+        android:layout_marginBottom="6sp"
+        android:layout_weight="1">
+
+        <TextView android:id="@+android:id/title"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:singleLine="true"
+            android:textAppearance="?android:attr/textAppearanceLarge"
+            android:textColor="?android:attr/textColorSecondary" />
+
+        <TextView android:id="@+android:id/summary"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_below="@android:id/title"
+            android:layout_alignStart="@android:id/title"
+            android:textAppearance="?android:attr/textAppearanceSmall"
+            android:textColor="?android:attr/textColorSecondary"
+            android:maxLines="2" />
+
+    </RelativeLayout>
+
+    <!-- Preference should place its actual preference widget here. -->
+    <LinearLayout android:id="@+android:id/widget_frame"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:gravity="center_vertical"
+        android:orientation="vertical" />
+
+</LinearLayout>
diff --git a/v7/preference/res/layout/preference_list_fragment.xml b/v7/preference/res/layout/preference_list_fragment.xml
new file mode 100644
index 0000000..44c5438
--- /dev/null
+++ b/v7/preference/res/layout/preference_list_fragment.xml
@@ -0,0 +1,36 @@
+<?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
+  -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_height="match_parent"
+    android:layout_width="match_parent" >
+
+    <FrameLayout
+        android:id="@+id/list_container"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1" />
+
+    <TextView android:id="@android:id/empty"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:padding="8dp"
+        android:gravity="center"
+        android:visibility="gone" />
+
+</LinearLayout>
diff --git a/v7/preference/res/layout/preference_recyclerview.xml b/v7/preference/res/layout/preference_recyclerview.xml
new file mode 100644
index 0000000..13385e6
--- /dev/null
+++ b/v7/preference/res/layout/preference_recyclerview.xml
@@ -0,0 +1,25 @@
+<?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
+  -->
+
+<android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/list"
+    style="?attr/preferenceFragmentListStyle"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:paddingTop="0dp"
+    android:paddingBottom="0dp"
+    android:clipToPadding="false" />
diff --git a/v7/preference/res/layout/preference_widget_checkbox.xml b/v7/preference/res/layout/preference_widget_checkbox.xml
new file mode 100644
index 0000000..e53b7df
--- /dev/null
+++ b/v7/preference/res/layout/preference_widget_checkbox.xml
@@ -0,0 +1,26 @@
+<?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
+  -->
+
+<!-- Layout used by CheckBoxPreference for the checkbox style. This is inflated
+     inside android.R.layout.preference. -->
+<CheckBox xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/checkbox"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:focusable="false"
+    android:clickable="false"
+    android:background="@null" />
diff --git a/v7/preference/res/layout/preference_widget_switch_compat.xml b/v7/preference/res/layout/preference_widget_switch_compat.xml
new file mode 100644
index 0000000..3324073
--- /dev/null
+++ b/v7/preference/res/layout/preference_widget_switch_compat.xml
@@ -0,0 +1,26 @@
+<?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
+  -->
+
+<!-- Layout used by SwitchPreference for the switch widget style. This is inflated
+     inside android.R.layout.preference. -->
+<android.support.v7.widget.SwitchCompat xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/switchWidget"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:focusable="false"
+    android:clickable="false"
+    android:background="@null" />
diff --git a/v7/preference/res/values-v17/styles.xml b/v7/preference/res/values-v17/styles.xml
new file mode 100644
index 0000000..20168b2
--- /dev/null
+++ b/v7/preference/res/values-v17/styles.xml
@@ -0,0 +1,29 @@
+<?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
+  -->
+
+<resources>
+    <style name="PreferenceFragment">
+        <item name="android:paddingStart">0dp</item>
+        <item name="android:paddingEnd">0dp</item>
+    </style>
+
+    <style name="PreferenceFragmentList">
+        <item name="android:paddingStart">16dp</item>
+        <item name="android:paddingEnd">16dp</item>
+    </style>
+
+</resources>
diff --git a/v7/preference/res/values/attrs.xml b/v7/preference/res/values/attrs.xml
new file mode 100644
index 0000000..b93c1e6
--- /dev/null
+++ b/v7/preference/res/values/attrs.xml
@@ -0,0 +1,243 @@
+<?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
+  -->
+
+<resources>
+  <declare-styleable name="Theme">
+
+    <!-- =================== -->
+    <!-- Preference styles   -->
+    <!-- =================== -->
+    <eat-comment />
+
+    <!-- Theme for inflating Preference objects -->
+    <attr name="preferenceTheme" format="reference" />
+
+    <!-- Default style for PreferenceScreen. -->
+    <attr name="preferenceScreenStyle" format="reference" />
+    <!-- Default style for the PreferenceActivity. -->
+    <attr name="preferenceActivityStyle" format="reference" />
+    <!-- Default style for Headers pane in PreferenceActivity. -->
+    <attr name="preferenceFragmentStyle" format="reference" />
+    <!-- Default style for PreferenceCategory. -->
+    <attr name="preferenceCategoryStyle" format="reference" />
+    <!-- Default style for Preference. -->
+    <attr name="preferenceStyle" format="reference" />
+    <!-- Default style for informational Preference. -->
+    <attr name="preferenceInformationStyle" format="reference" />
+    <!-- Default style for CheckBoxPreference. -->
+    <attr name="checkBoxPreferenceStyle" format="reference" />
+    <!-- Default style for YesNoPreference. -->
+    <attr name="yesNoPreferenceStyle" format="reference" />
+    <!-- Default style for DialogPreference. -->
+    <attr name="dialogPreferenceStyle" format="reference" />
+    <!-- Default style for EditTextPreference. -->
+    <attr name="editTextPreferenceStyle" format="reference" />
+    <!-- Default style for RingtonePreference. -->
+    <attr name="ringtonePreferenceStyle" format="reference" />
+    <!-- The preference layout that has the child/tabbed effect. -->
+    <attr name="preferenceLayoutChild" format="reference" />
+    <!-- Preference panel style -->
+    <attr name="preferencePanelStyle" format="reference" />
+    <!-- Preference headers panel style -->
+    <attr name="preferenceHeaderPanelStyle" format="reference" />
+    <!-- Preference list style -->
+    <attr name="preferenceListStyle" format="reference" />
+    <!-- Preference fragment list style -->
+    <attr name="preferenceFragmentListStyle" format="reference" />
+    <!-- Preference fragment padding side -->
+    <attr name="preferenceFragmentPaddingSide" format="dimension" />
+    <!-- Default style for switch preferences. -->
+    <attr name="switchPreferenceStyle" format="reference" />
+    <!-- Default style for switch compat preferences. -->
+    <attr name="switchPreferenceCompatStyle" format="reference" />
+    <!-- Default style for seekbar preferences. -->
+    <attr name="seekBarPreferenceStyle" format="reference" />
+  </declare-styleable>
+
+  <!-- Base attributes available to PreferenceFragment. -->
+  <declare-styleable name="PreferenceFragmentCompat">
+    <!-- The layout for the PreferenceFragment. This should rarely need to be changed. -->
+    <attr name="layout" />
+    <attr name="android:layout" />
+  </declare-styleable>
+
+  <!-- Base attributes available to PreferenceGroup. -->
+  <declare-styleable name="PreferenceGroup">
+    <!-- Whether to order the Preference under this group as they appear in the XML file.
+         If this is false, the ordering will follow the Preference order attribute and
+         default to alphabetic for those without the order attribute. -->
+    <attr name="orderingFromXml" format="boolean" />
+    <attr name="android:orderingFromXml" />
+  </declare-styleable>
+
+  <!-- Base attributes available to Preference. -->
+  <declare-styleable name="Preference">
+    <!-- The optional icon for the preference -->
+    <attr name="icon" />
+    <attr name="android:icon" />
+    <!-- The key to store the Preference value. -->
+    <attr name="key" format="string" />
+    <attr name="android:key" />
+    <!-- The title for the Preference in a PreferenceActivity screen. -->
+    <attr name="title" />
+    <attr name="android:title" />
+    <!-- The summary for the Preference in a PreferenceActivity screen. -->
+    <attr name="summary" format="string" />
+    <attr name="android:summary" />
+    <!-- The order for the Preference (lower values are to be ordered first). If this is not
+         specified, the default ordering will be alphabetic. -->
+    <attr name="order" format="integer" />
+    <attr name="android:order" />
+    <!-- When used inside of a modern PreferenceActivity, this declares
+         a new PreferenceFragment to be shown when the user selects this item. -->
+    <attr name="fragment" format="string" />
+    <attr name="android:fragment" />
+    <!-- The layout for the Preference in a PreferenceActivity screen. This should
+         rarely need to be changed, look at widgetLayout instead. -->
+    <attr name="layout" />
+    <attr name="android:layout" />
+    <!-- The layout for the controllable widget portion of a Preference. This is inflated
+         into the layout for a Preference and should be used more frequently than
+         the layout attribute. For example, a checkbox preference would specify
+         a custom layout (consisting of just the CheckBox) here. -->
+    <attr name="widgetLayout" format="reference" />
+    <attr name="android:widgetLayout" />
+    <!-- Whether the Preference is enabled. -->
+    <attr name="enabled" format="boolean" />
+    <attr name="android:enabled" />
+    <!-- Whether the Preference is selectable. -->
+    <attr name="selectable" format="boolean" />
+    <attr name="android:selectable" />
+    <!-- The key of another Preference that this Preference will depend on.  If the other
+         Preference is not set or is off, this Preference will be disabled. -->
+    <attr name="dependency" format="string" />
+    <attr name="android:dependency" />
+    <!-- Whether the Preference stores its value to the shared preferences. -->
+    <attr name="persistent" format="boolean" />
+    <attr name="android:persistent" />
+    <!-- The default value for the preference, which will be set either if persistence
+         is off or persistence is on and the preference is not found in the persistent
+         storage.  -->
+    <attr name="defaultValue" format="string|boolean|integer|reference|float" />
+    <attr name="android:defaultValue" />
+    <!-- Whether the view of this Preference should be disabled when
+         this Preference is disabled. -->
+    <attr name="shouldDisableView" format="boolean" />
+    <attr name="android:shouldDisableView" />
+  </declare-styleable>
+
+  <!-- Base attributes available to CheckBoxPreference. -->
+  <declare-styleable name="CheckBoxPreference">
+    <!-- The summary for the Preference in a PreferenceActivity screen when the
+         CheckBoxPreference is checked. If separate on/off summaries are not
+         needed, the summary attribute can be used instead. -->
+    <attr name="summaryOn" format="string" />
+    <attr name="android:summaryOn" />
+    <!-- The summary for the Preference in a PreferenceActivity screen when the
+         CheckBoxPreference is unchecked. If separate on/off summaries are not
+         needed, the summary attribute can be used instead. -->
+    <attr name="summaryOff" format="string" />
+    <attr name="android:summaryOff" />
+    <!-- The state (true for on, or false for off) that causes dependents to be disabled. By default,
+         dependents will be disabled when this is unchecked, so the value of this preference is false. -->
+    <attr name="disableDependentsState" format="boolean" />
+    <attr name="android:disableDependentsState" />
+  </declare-styleable>
+
+  <!-- Base attributes available to DialogPreference. -->
+  <declare-styleable name="DialogPreference">
+    <!-- The title in the dialog. -->
+    <attr name="dialogTitle" format="string" />
+    <attr name="android:dialogTitle" />
+    <!-- The message in the dialog. If a dialogLayout is provided and contains
+         a TextView with ID android:id/message, this message will be placed in there. -->
+    <attr name="dialogMessage" format="string" />
+    <attr name="android:dialogMessage" />
+    <!-- The icon for the dialog. -->
+    <attr name="dialogIcon" format="reference" />
+    <attr name="android:dialogIcon" />
+    <!-- The positive button text for the dialog. Set to @null to hide the positive button. -->
+    <attr name="positiveButtonText" format="string" />
+    <attr name="android:positiveButtonText" />
+    <!-- The negative button text for the dialog. Set to @null to hide the negative button. -->
+    <attr name="negativeButtonText" format="string" />
+    <attr name="android:negativeButtonText" />
+    <!-- A layout to be used as the content View for the dialog. By default, this shouldn't
+         be needed. If a custom DialogPreference is required, this should be set. For example,
+         the EditTextPreference uses a layout with an EditText as this attribute. -->
+    <attr name="dialogLayout" format="reference" />
+    <attr name="android:dialogLayout" />
+  </declare-styleable>
+
+  <!-- Base attributes available to ListPreference. -->
+  <declare-styleable name="ListPreference">
+    <!-- The human-readable array to present as a list. Each entry must have a corresponding
+         index in entryValues. -->
+    <attr name="entries" format="reference" />
+    <attr name="android:entries" />
+    <!-- The array to find the value to save for a preference when an entry from
+         entries is selected. If a user clicks on the second item in entries, the
+         second item in this array will be saved to the preference. -->
+    <attr name="entryValues" format="reference" />
+    <attr name="android:entryValues" />
+  </declare-styleable>
+
+  <declare-styleable name="MultiSelectListPreference">
+    <!-- The human-readable array to present as a list. Each entry must have a corresponding
+         index in entryValues. -->
+    <attr name="entries" />
+    <attr name="android:entries" />
+    <!-- The array to find the value to save for a preference when an entry from
+         entries is selected. If a user clicks the second item in entries, the
+         second item in this array will be saved to the preference. -->
+    <attr name="entryValues" />
+    <attr name="android:entryValues" />
+  </declare-styleable>
+
+  <declare-styleable name="SwitchPreferenceCompat">
+    <!-- The summary for the Preference in a PreferenceActivity screen when the
+         SwitchPreference is checked. If separate on/off summaries are not
+         needed, the summary attribute can be used instead. -->
+    <attr name="summaryOn" />
+    <attr name="android:summaryOn" />
+    <!-- The summary for the Preference in a PreferenceActivity screen when the
+         SwitchPreference is unchecked. If separate on/off summaries are not
+         needed, the summary attribute can be used instead. -->
+    <attr name="summaryOff" />
+    <attr name="android:summaryOff" />
+    <!-- The text used on the switch itself when in the "on" state.
+         This should be a very SHORT string, as it appears in a small space. -->
+    <attr name="switchTextOn" format="string" />
+    <attr name="android:switchTextOn" />
+    <!-- The text used on the switch itself when in the "off" state.
+         This should be a very SHORT string, as it appears in a small space. -->
+    <attr name="switchTextOff" format="string" />
+    <attr name="android:switchTextOff" />
+    <!-- The state (true for on, or false for off) that causes dependents to be disabled. By default,
+         dependents will be disabled when this is unchecked, so the value of this preference is false. -->
+    <attr name="disableDependentsState" />
+    <attr name="android:disableDependentsState" />
+  </declare-styleable>
+
+  <declare-styleable name="PreferenceImageView">
+    <attr name="maxWidth" format="dimension" />
+    <attr name="android:maxWidth" />
+    <attr name="maxHeight" format="dimension" />
+    <attr name="android:maxHeight" />
+  </declare-styleable>
+
+</resources>
diff --git a/v7/preference/res/values/strings.xml b/v7/preference/res/values/strings.xml
new file mode 100644
index 0000000..3414e44
--- /dev/null
+++ b/v7/preference/res/values/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="v7_preference_on">ON</string>
+    <string name="v7_preference_off">OFF</string>
+</resources>
diff --git a/v7/preference/res/values/styles.xml b/v7/preference/res/values/styles.xml
new file mode 100644
index 0000000..3af31a4
--- /dev/null
+++ b/v7/preference/res/values/styles.xml
@@ -0,0 +1,67 @@
+<?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
+  -->
+
+<resources>
+    <style name="Preference">
+        <item name="layout">@layout/preference</item>
+    </style>
+
+    <style name="PreferenceFragment">
+        <item name="android:paddingLeft">0dp</item>
+        <item name="android:paddingRight">0dp</item>
+    </style>
+
+    <style name="Preference.Information">
+        <item name="layout">@layout/preference_information</item>
+        <item name="enabled">false</item>
+        <item name="shouldDisableView">false</item>
+    </style>
+
+    <style name="Preference.Category">
+        <item name="layout">@layout/preference_category</item>
+        <!-- The title should not dim if the category is disabled, instead only the preference children should dim. -->
+        <item name="shouldDisableView">false</item>
+        <item name="selectable">false</item>
+    </style>
+
+    <style name="Preference.CheckBoxPreference">
+        <item name="widgetLayout">@layout/preference_widget_checkbox</item>
+    </style>
+
+    <style name="Preference.SwitchPreferenceCompat">
+        <item name="widgetLayout">@layout/preference_widget_switch_compat</item>
+        <item name="switchTextOn">@string/v7_preference_on</item>
+        <item name="switchTextOff">@string/v7_preference_off</item>
+    </style>
+
+    <style name="Preference.PreferenceScreen">
+    </style>
+
+    <style name="Preference.DialogPreference">
+        <item name="positiveButtonText">@android:string/ok</item>
+        <item name="negativeButtonText">@android:string/cancel</item>
+    </style>
+
+    <style name="Preference.DialogPreference.EditTextPreference">
+        <item name="dialogLayout">@layout/preference_dialog_edittext</item>
+    </style>
+
+    <style name="PreferenceFragmentList">
+        <item name="android:paddingLeft">16dp</item>
+        <item name="android:paddingRight">16dp</item>
+    </style>
+</resources>
diff --git a/v7/preference/res/values/themes.xml b/v7/preference/res/values/themes.xml
new file mode 100644
index 0000000..c2c2c3c
--- /dev/null
+++ b/v7/preference/res/values/themes.xml
@@ -0,0 +1,31 @@
+<?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
+  -->
+
+<resources>
+    <style name="PreferenceThemeOverlay">
+        <item name="preferenceScreenStyle">@style/Preference.PreferenceScreen</item>
+        <item name="preferenceFragmentStyle">@style/PreferenceFragment</item>
+        <item name="preferenceCategoryStyle">@style/Preference.Category</item>
+        <item name="preferenceStyle">@style/Preference</item>
+        <item name="preferenceInformationStyle">@style/Preference.Information</item>
+        <item name="checkBoxPreferenceStyle">@style/Preference.CheckBoxPreference</item>
+        <item name="switchPreferenceCompatStyle">@style/Preference.SwitchPreferenceCompat</item>
+        <item name="dialogPreferenceStyle">@style/Preference.DialogPreference</item>
+        <item name="editTextPreferenceStyle">@style/Preference.DialogPreference.EditTextPreference</item>
+        <item name="preferenceFragmentListStyle">@style/PreferenceFragmentList</item>
+    </style>
+</resources>
diff --git a/v7/preference/src/android/support/v7/internal/widget/PreferenceImageView.java b/v7/preference/src/android/support/v7/internal/widget/PreferenceImageView.java
new file mode 100644
index 0000000..e3d430d
--- /dev/null
+++ b/v7/preference/src/android/support/v7/internal/widget/PreferenceImageView.java
@@ -0,0 +1,106 @@
+/*
+ * 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.v7.internal.widget;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.support.v7.preference.R;
+import android.util.AttributeSet;
+import android.widget.ImageView;
+
+/**
+ * Extension of ImageView that correctly applies maxWidth and maxHeight.
+ * @hide
+ */
+public class PreferenceImageView extends ImageView {
+
+    private int mMaxWidth = Integer.MAX_VALUE;
+    private int mMaxHeight = Integer.MAX_VALUE;
+
+    public PreferenceImageView(Context context) {
+        this(context, null);
+    }
+
+    public PreferenceImageView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public PreferenceImageView(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+
+        final TypedArray a = context.obtainStyledAttributes(
+                attrs, R.styleable.PreferenceImageView, defStyleAttr, 0);
+
+        setMaxWidth(a.getDimensionPixelSize(
+                R.styleable.PreferenceImageView_maxWidth, Integer.MAX_VALUE));
+
+        setMaxHeight(a.getDimensionPixelSize(
+                R.styleable.PreferenceImageView_maxHeight, Integer.MAX_VALUE));
+
+        a.recycle();
+    }
+
+//    public PreferenceImageView(Context context, AttributeSet attrs, int defStyleAttr,
+//            int defStyleRes) {
+//        super(context, attrs, defStyleAttr, defStyleRes);
+//    }
+
+    @Override
+    public void setMaxWidth(int maxWidth) {
+        mMaxWidth = maxWidth;
+        super.setMaxWidth(maxWidth);
+    }
+
+    public int getMaxWidth() {
+        return mMaxWidth;
+    }
+
+    @Override
+    public void setMaxHeight(int maxHeight) {
+        mMaxHeight = maxHeight;
+        super.setMaxHeight(maxHeight);
+    }
+
+    public int getMaxHeight() {
+        return mMaxHeight;
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
+        if (widthMode == MeasureSpec.AT_MOST || widthMode == MeasureSpec.UNSPECIFIED) {
+            final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
+            final int maxWidth = getMaxWidth();
+            if (maxWidth != Integer.MAX_VALUE
+                    && (maxWidth < widthSize || widthMode == MeasureSpec.UNSPECIFIED)) {
+                widthMeasureSpec = MeasureSpec.makeMeasureSpec(maxWidth, MeasureSpec.AT_MOST);
+            }
+        }
+
+        final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
+        if (heightMode == MeasureSpec.AT_MOST || heightMode == MeasureSpec.UNSPECIFIED) {
+            final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
+            final int maxHeight = getMaxHeight();
+            if (maxHeight != Integer.MAX_VALUE
+                    && (maxHeight < heightSize || heightMode == MeasureSpec.UNSPECIFIED)) {
+                heightMeasureSpec = MeasureSpec.makeMeasureSpec(maxHeight, MeasureSpec.AT_MOST);
+            }
+        }
+
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+    }
+}
diff --git a/v7/preference/src/android/support/v7/preference/CheckBoxPreference.java b/v7/preference/src/android/support/v7/preference/CheckBoxPreference.java
new file mode 100644
index 0000000..f49b0d6
--- /dev/null
+++ b/v7/preference/src/android/support/v7/preference/CheckBoxPreference.java
@@ -0,0 +1,81 @@
+/*
+ * 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.v7.preference;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.support.v4.content.res.TypedArrayUtils;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.Checkable;
+
+/**
+ * A {@link Preference} that provides checkbox widget
+ * functionality.
+ * <p>
+ * This preference will store a boolean into the SharedPreferences.
+ *
+ * @attr ref android.R.styleable#CheckBoxPreference_summaryOff
+ * @attr ref android.R.styleable#CheckBoxPreference_summaryOn
+ * @attr ref android.R.styleable#CheckBoxPreference_disableDependentsState
+ */
+public class CheckBoxPreference extends TwoStatePreference {
+
+    public CheckBoxPreference(Context context, AttributeSet attrs, int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0);
+    }
+
+    public CheckBoxPreference(
+            Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+
+        final TypedArray a = context.obtainStyledAttributes(attrs,
+                R.styleable.CheckBoxPreference, defStyleAttr, defStyleRes);
+
+        setSummaryOn(TypedArrayUtils.getString(a, R.styleable.CheckBoxPreference_summaryOn,
+                R.styleable.CheckBoxPreference_android_summaryOn));
+
+        setSummaryOff(TypedArrayUtils.getString(a, R.styleable.CheckBoxPreference_summaryOff,
+                R.styleable.CheckBoxPreference_android_summaryOff));
+
+        setDisableDependentsState(TypedArrayUtils.getBoolean(a,
+                R.styleable.CheckBoxPreference_disableDependentsState,
+                R.styleable.CheckBoxPreference_android_disableDependentsState, false));
+
+        a.recycle();
+    }
+
+    public CheckBoxPreference(Context context, AttributeSet attrs) {
+        this(context, attrs, R.attr.checkBoxPreferenceStyle);
+    }
+
+    public CheckBoxPreference(Context context) {
+        this(context, null);
+    }
+
+    @Override
+    public void onBindViewHolder(PreferenceViewHolder holder) {
+        super.onBindViewHolder(holder);
+
+        View checkboxView = holder.findViewById(R.id.checkbox);
+        if (checkboxView != null && checkboxView instanceof Checkable) {
+            ((Checkable) checkboxView).setChecked(mChecked);
+        }
+
+        syncSummaryView(holder);
+    }
+}
diff --git a/v7/preference/src/android/support/v7/preference/DialogPreference.java b/v7/preference/src/android/support/v7/preference/DialogPreference.java
new file mode 100644
index 0000000..bf0f4ef
--- /dev/null
+++ b/v7/preference/src/android/support/v7/preference/DialogPreference.java
@@ -0,0 +1,264 @@
+/*
+ * 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.v7.preference;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
+import android.support.v4.content.ContextCompat;
+import android.support.v4.content.res.TypedArrayUtils;
+import android.util.AttributeSet;
+import android.view.View;
+
+/**
+ * A base class for {@link Preference} objects that are
+ * dialog-based. These preferences will, when clicked, open a dialog showing the
+ * actual preference controls.
+ *
+ * @attr ref android.R.styleable#DialogPreference_dialogTitle
+ * @attr ref android.R.styleable#DialogPreference_dialogMessage
+ * @attr ref android.R.styleable#DialogPreference_dialogIcon
+ * @attr ref android.R.styleable#DialogPreference_dialogLayout
+ * @attr ref android.R.styleable#DialogPreference_positiveButtonText
+ * @attr ref android.R.styleable#DialogPreference_negativeButtonText
+ */
+public abstract class DialogPreference extends Preference {
+
+    public interface TargetFragment {
+        Preference findPreference(CharSequence key);
+    }
+
+    private CharSequence mDialogTitle;
+    private CharSequence mDialogMessage;
+    private Drawable mDialogIcon;
+    private CharSequence mPositiveButtonText;
+    private CharSequence mNegativeButtonText;
+    private int mDialogLayoutResId;
+
+    public DialogPreference(
+            Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+
+        final TypedArray a = context.obtainStyledAttributes(attrs,
+                R.styleable.DialogPreference, defStyleAttr, defStyleRes);
+
+        mDialogTitle = TypedArrayUtils.getString(a, R.styleable.DialogPreference_dialogTitle,
+                R.styleable.DialogPreference_android_dialogTitle);
+        if (mDialogTitle == null) {
+            // Fall back on the regular title of the preference
+            // (the one that is seen in the list)
+            mDialogTitle = getTitle();
+        }
+
+        mDialogMessage = TypedArrayUtils.getString(a, R.styleable.DialogPreference_dialogMessage,
+                R.styleable.DialogPreference_android_dialogMessage);
+
+        mDialogIcon = TypedArrayUtils.getDrawable(a, R.styleable.DialogPreference_dialogIcon,
+                R.styleable.DialogPreference_android_dialogIcon);
+
+        mPositiveButtonText = TypedArrayUtils.getString(a,
+                R.styleable.DialogPreference_positiveButtonText,
+                R.styleable.DialogPreference_android_positiveButtonText);
+
+        mNegativeButtonText = TypedArrayUtils.getString(a,
+                R.styleable.DialogPreference_negativeButtonText,
+                R.styleable.DialogPreference_android_negativeButtonText);
+
+        mDialogLayoutResId = TypedArrayUtils.getResourceId(a,
+                R.styleable.DialogPreference_dialogLayout,
+                R.styleable.DialogPreference_android_dialogLayout, 0);
+
+        a.recycle();
+    }
+
+    public DialogPreference(Context context, AttributeSet attrs, int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0);
+    }
+
+    public DialogPreference(Context context, AttributeSet attrs) {
+        this(context, attrs, R.attr.dialogPreferenceStyle);
+    }
+
+    public DialogPreference(Context context) {
+        this(context, null);
+    }
+
+    /**
+     * Sets the title of the dialog. This will be shown on subsequent dialogs.
+     *
+     * @param dialogTitle The title.
+     */
+    public void setDialogTitle(CharSequence dialogTitle) {
+        mDialogTitle = dialogTitle;
+    }
+
+    /**
+     * @see #setDialogTitle(CharSequence)
+     * @param dialogTitleResId The dialog title as a resource.
+     */
+    public void setDialogTitle(int dialogTitleResId) {
+        setDialogTitle(getContext().getString(dialogTitleResId));
+    }
+
+    /**
+     * Returns the title to be shown on subsequent dialogs.
+     * @return The title.
+     */
+    public CharSequence getDialogTitle() {
+        return mDialogTitle;
+    }
+
+    /**
+     * Sets the message of the dialog. This will be shown on subsequent dialogs.
+     * <p>
+     * This message forms the content View of the dialog and conflicts with
+     * list-based dialogs, for example. If setting a custom View on a dialog via
+     * {@link #setDialogLayoutResource(int)}, include a text View with ID
+     * {@link android.R.id#message} and it will be populated with this message.
+     *
+     * @param dialogMessage The message.
+     */
+    public void setDialogMessage(CharSequence dialogMessage) {
+        mDialogMessage = dialogMessage;
+    }
+
+    /**
+     * @see #setDialogMessage(CharSequence)
+     * @param dialogMessageResId The dialog message as a resource.
+     */
+    public void setDialogMessage(int dialogMessageResId) {
+        setDialogMessage(getContext().getString(dialogMessageResId));
+    }
+
+    /**
+     * Returns the message to be shown on subsequent dialogs.
+     * @return The message.
+     */
+    public CharSequence getDialogMessage() {
+        return mDialogMessage;
+    }
+
+    /**
+     * Sets the icon of the dialog. This will be shown on subsequent dialogs.
+     *
+     * @param dialogIcon The icon, as a {@link Drawable}.
+     */
+    public void setDialogIcon(Drawable dialogIcon) {
+        mDialogIcon = dialogIcon;
+    }
+
+    /**
+     * Sets the icon (resource ID) of the dialog. This will be shown on
+     * subsequent dialogs.
+     *
+     * @param dialogIconRes The icon, as a resource ID.
+     */
+    public void setDialogIcon(int dialogIconRes) {
+        mDialogIcon = ContextCompat.getDrawable(getContext(), dialogIconRes);
+    }
+
+    /**
+     * Returns the icon to be shown on subsequent dialogs.
+     * @return The icon, as a {@link Drawable}.
+     */
+    public Drawable getDialogIcon() {
+        return mDialogIcon;
+    }
+
+    /**
+     * Sets the text of the positive button of the dialog. This will be shown on
+     * subsequent dialogs.
+     *
+     * @param positiveButtonText The text of the positive button.
+     */
+    public void setPositiveButtonText(CharSequence positiveButtonText) {
+        mPositiveButtonText = positiveButtonText;
+    }
+
+    /**
+     * @see #setPositiveButtonText(CharSequence)
+     * @param positiveButtonTextResId The positive button text as a resource.
+     */
+    public void setPositiveButtonText(int positiveButtonTextResId) {
+        setPositiveButtonText(getContext().getString(positiveButtonTextResId));
+    }
+
+    /**
+     * Returns the text of the positive button to be shown on subsequent
+     * dialogs.
+     *
+     * @return The text of the positive button.
+     */
+    public CharSequence getPositiveButtonText() {
+        return mPositiveButtonText;
+    }
+
+    /**
+     * Sets the text of the negative button of the dialog. This will be shown on
+     * subsequent dialogs.
+     *
+     * @param negativeButtonText The text of the negative button.
+     */
+    public void setNegativeButtonText(CharSequence negativeButtonText) {
+        mNegativeButtonText = negativeButtonText;
+    }
+
+    /**
+     * @see #setNegativeButtonText(CharSequence)
+     * @param negativeButtonTextResId The negative button text as a resource.
+     */
+    public void setNegativeButtonText(int negativeButtonTextResId) {
+        setNegativeButtonText(getContext().getString(negativeButtonTextResId));
+    }
+
+    /**
+     * Returns the text of the negative button to be shown on subsequent
+     * dialogs.
+     *
+     * @return The text of the negative button.
+     */
+    public CharSequence getNegativeButtonText() {
+        return mNegativeButtonText;
+    }
+
+    /**
+     * Sets the layout resource that is inflated as the {@link View} to be shown
+     * as the content View of subsequent dialogs.
+     *
+     * @param dialogLayoutResId The layout resource ID to be inflated.
+     * @see #setDialogMessage(CharSequence)
+     */
+    public void setDialogLayoutResource(int dialogLayoutResId) {
+        mDialogLayoutResId = dialogLayoutResId;
+    }
+
+    /**
+     * Returns the layout resource that is used as the content View for
+     * subsequent dialogs.
+     *
+     * @return The layout resource.
+     */
+    public int getDialogLayoutResource() {
+        return mDialogLayoutResId;
+    }
+
+    @Override
+    protected void onClick() {
+        getPreferenceManager().showDialog(this);
+    }
+
+}
diff --git a/v7/preference/src/android/support/v7/preference/EditTextPreference.java b/v7/preference/src/android/support/v7/preference/EditTextPreference.java
new file mode 100644
index 0000000..c4941e6
--- /dev/null
+++ b/v7/preference/src/android/support/v7/preference/EditTextPreference.java
@@ -0,0 +1,154 @@
+/*
+ * 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.v7.preference;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.widget.EditText;
+
+/**
+ * A {@link Preference} that allows for string
+ * input.
+ * <p>
+ * It is a subclass of {@link DialogPreference} and shows the {@link EditText}
+ * in a dialog.
+ * <p>
+ * This preference will store a string into the SharedPreferences.
+ */
+public class EditTextPreference extends DialogPreference {
+    private String mText;
+
+    public EditTextPreference(Context context, AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+    }
+
+    public EditTextPreference(Context context, AttributeSet attrs, int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0);
+    }
+
+    public EditTextPreference(Context context, AttributeSet attrs) {
+        this(context, attrs, R.attr.editTextPreferenceStyle);
+    }
+
+    public EditTextPreference(Context context) {
+        this(context, null);
+    }
+
+    /**
+     * Saves the text to the {@link android.content.SharedPreferences}.
+     *
+     * @param text The text to save
+     */
+    public void setText(String text) {
+        final boolean wasBlocking = shouldDisableDependents();
+
+        mText = text;
+
+        persistString(text);
+
+        final boolean isBlocking = shouldDisableDependents();
+        if (isBlocking != wasBlocking) {
+            notifyDependencyChange(isBlocking);
+        }
+    }
+
+    /**
+     * Gets the text from the {@link android.content.SharedPreferences}.
+     *
+     * @return The current preference value.
+     */
+    public String getText() {
+        return mText;
+    }
+
+    @Override
+    protected Object onGetDefaultValue(TypedArray a, int index) {
+        return a.getString(index);
+    }
+
+    @Override
+    protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
+        setText(restoreValue ? getPersistedString(mText) : (String) defaultValue);
+    }
+
+    @Override
+    public boolean shouldDisableDependents() {
+        return TextUtils.isEmpty(mText) || super.shouldDisableDependents();
+    }
+
+    @Override
+    protected Parcelable onSaveInstanceState() {
+        final Parcelable superState = super.onSaveInstanceState();
+        if (isPersistent()) {
+            // No need to save instance state since it's persistent
+            return superState;
+        }
+
+        final SavedState myState = new SavedState(superState);
+        myState.text = getText();
+        return myState;
+    }
+
+    @Override
+    protected void onRestoreInstanceState(Parcelable state) {
+        if (state == null || !state.getClass().equals(SavedState.class)) {
+            // Didn't save state for us in onSaveInstanceState
+            super.onRestoreInstanceState(state);
+            return;
+        }
+
+        SavedState myState = (SavedState) state;
+        super.onRestoreInstanceState(myState.getSuperState());
+        setText(myState.text);
+    }
+
+    private static class SavedState extends BaseSavedState {
+        String text;
+
+        public SavedState(Parcel source) {
+            super(source);
+            text = source.readString();
+        }
+
+        @Override
+        public void writeToParcel(Parcel dest, int flags) {
+            super.writeToParcel(dest, flags);
+            dest.writeString(text);
+        }
+
+        public SavedState(Parcelable superState) {
+            super(superState);
+        }
+
+        public static final Parcelable.Creator<SavedState> CREATOR =
+                new Parcelable.Creator<SavedState>() {
+            public SavedState createFromParcel(Parcel in) {
+                return new SavedState(in);
+            }
+
+            public SavedState[] newArray(int size) {
+                return new SavedState[size];
+            }
+        };
+    }
+
+}
diff --git a/v7/preference/src/android/support/v7/preference/EditTextPreferenceDialogFragmentCompat.java b/v7/preference/src/android/support/v7/preference/EditTextPreferenceDialogFragmentCompat.java
new file mode 100644
index 0000000..182cf28
--- /dev/null
+++ b/v7/preference/src/android/support/v7/preference/EditTextPreferenceDialogFragmentCompat.java
@@ -0,0 +1,93 @@
+/*
+ * 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.v7.preference;
+
+import android.os.Bundle;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewParent;
+import android.widget.EditText;
+
+public class EditTextPreferenceDialogFragmentCompat extends PreferenceDialogFragmentCompat {
+
+    private EditText mEditText;
+
+    public static EditTextPreferenceDialogFragmentCompat newInstance(String key) {
+        final EditTextPreferenceDialogFragmentCompat
+                fragment = new EditTextPreferenceDialogFragmentCompat();
+        final Bundle b = new Bundle(1);
+        b.putString(ARG_KEY, key);
+        fragment.setArguments(b);
+        return fragment;
+    }
+
+    @Override
+    protected void onBindDialogView(View view) {
+        super.onBindDialogView(view);
+
+        mEditText = new EditText(view.getContext());
+        // Give it an ID so it can be saved/restored
+        mEditText.setId(android.R.id.edit);
+
+        mEditText.setText(getEditTextPreference().getText());
+
+        ViewParent oldParent = mEditText.getParent();
+        if (oldParent != view) {
+            if (oldParent != null) {
+                ((ViewGroup) oldParent).removeView(mEditText);
+            }
+            onAddEditTextToDialogView(view, mEditText);
+        }
+    }
+
+    private EditTextPreference getEditTextPreference() {
+        return (EditTextPreference) getPreference();
+    }
+
+    /** @hide */
+    @Override
+    protected boolean needInputMethod() {
+        // We want the input method to show, if possible, when dialog is displayed
+        return true;
+    }
+
+    /**
+     * Adds the EditText widget of this preference to the dialog's view.
+     *
+     * @param dialogView The dialog view.
+     */
+    protected void onAddEditTextToDialogView(View dialogView, EditText editText) {
+        ViewGroup container = (ViewGroup) dialogView
+                .findViewById(R.id.edittext_container);
+        if (container != null) {
+            container.addView(editText, ViewGroup.LayoutParams.FILL_PARENT,
+                    ViewGroup.LayoutParams.WRAP_CONTENT);
+        }
+    }
+
+    @Override
+    public void onDialogClosed(boolean positiveResult) {
+
+        if (positiveResult) {
+            String value = mEditText.getText().toString();
+            if (getEditTextPreference().callChangeListener(value)) {
+                getEditTextPreference().setText(value);
+            }
+        }
+    }
+
+}
diff --git a/v7/preference/src/android/support/v7/preference/ListPreference.java b/v7/preference/src/android/support/v7/preference/ListPreference.java
new file mode 100644
index 0000000..848cfad
--- /dev/null
+++ b/v7/preference/src/android/support/v7/preference/ListPreference.java
@@ -0,0 +1,317 @@
+/*
+ * 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.v7.preference;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.support.annotation.ArrayRes;
+import android.support.annotation.NonNull;
+import android.support.v4.content.res.TypedArrayUtils;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+
+/**
+ * A {@link Preference} that displays a list of entries as
+ * a dialog.
+ * <p>
+ * This preference will store a string into the SharedPreferences. This string will be the value
+ * from the {@link #setEntryValues(CharSequence[])} array.
+ *
+ * @attr ref android.R.styleable#ListPreference_entries
+ * @attr ref android.R.styleable#ListPreference_entryValues
+ */
+public class ListPreference extends DialogPreference {
+    private CharSequence[] mEntries;
+    private CharSequence[] mEntryValues;
+    private String mValue;
+    private String mSummary;
+    private boolean mValueSet;
+
+    public ListPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+
+        TypedArray a = context.obtainStyledAttributes(
+                attrs, R.styleable.ListPreference, defStyleAttr, defStyleRes);
+
+        mEntries = TypedArrayUtils.getTextArray(a, R.styleable.ListPreference_entries,
+                R.styleable.ListPreference_android_entries);
+
+        mEntryValues = TypedArrayUtils.getTextArray(a, R.styleable.ListPreference_entryValues,
+                R.styleable.ListPreference_android_entryValues);
+
+        a.recycle();
+
+        /* Retrieve the Preference summary attribute since it's private
+         * in the Preference class.
+         */
+        a = context.obtainStyledAttributes(attrs,
+                R.styleable.Preference, defStyleAttr, defStyleRes);
+
+        mSummary = TypedArrayUtils.getString(a, R.styleable.Preference_summary,
+                R.styleable.Preference_android_summary);
+
+        a.recycle();
+    }
+
+    public ListPreference(Context context, AttributeSet attrs, int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0);
+    }
+
+    public ListPreference(Context context, AttributeSet attrs) {
+        this(context, attrs, R.attr.dialogPreferenceStyle);
+    }
+
+    public ListPreference(Context context) {
+        this(context, null);
+    }
+
+    /**
+     * Sets the human-readable entries to be shown in the list. This will be
+     * shown in subsequent dialogs.
+     * <p>
+     * Each entry must have a corresponding index in
+     * {@link #setEntryValues(CharSequence[])}.
+     *
+     * @param entries The entries.
+     * @see #setEntryValues(CharSequence[])
+     */
+    public void setEntries(CharSequence[] entries) {
+        mEntries = entries;
+    }
+
+    /**
+     * @see #setEntries(CharSequence[])
+     * @param entriesResId The entries array as a resource.
+     */
+    public void setEntries(@ArrayRes int entriesResId) {
+        setEntries(getContext().getResources().getTextArray(entriesResId));
+    }
+
+    /**
+     * The list of entries to be shown in the list in subsequent dialogs.
+     *
+     * @return The list as an array.
+     */
+    public CharSequence[] getEntries() {
+        return mEntries;
+    }
+
+    /**
+     * The array to find the value to save for a preference when an entry from
+     * entries is selected. If a user clicks on the second item in entries, the
+     * second item in this array will be saved to the preference.
+     *
+     * @param entryValues The array to be used as values to save for the preference.
+     */
+    public void setEntryValues(CharSequence[] entryValues) {
+        mEntryValues = entryValues;
+    }
+
+    /**
+     * @see #setEntryValues(CharSequence[])
+     * @param entryValuesResId The entry values array as a resource.
+     */
+    public void setEntryValues(@ArrayRes int entryValuesResId) {
+        setEntryValues(getContext().getResources().getTextArray(entryValuesResId));
+    }
+
+    /**
+     * Returns the array of values to be saved for the preference.
+     *
+     * @return The array of values.
+     */
+    public CharSequence[] getEntryValues() {
+        return mEntryValues;
+    }
+
+    /**
+     * Sets the value of the key. This should be one of the entries in
+     * {@link #getEntryValues()}.
+     *
+     * @param value The value to set for the key.
+     */
+    public void setValue(String value) {
+        // Always persist/notify the first time.
+        final boolean changed = !TextUtils.equals(mValue, value);
+        if (changed || !mValueSet) {
+            mValue = value;
+            mValueSet = true;
+            persistString(value);
+            if (changed) {
+                notifyChanged();
+            }
+        }
+    }
+
+    /**
+     * Returns the summary of this ListPreference. If the summary
+     * has a {@linkplain java.lang.String#format String formatting}
+     * marker in it (i.e. "%s" or "%1$s"), then the current entry
+     * value will be substituted in its place.
+     *
+     * @return the summary with appropriate string substitution
+     */
+    @Override
+    public CharSequence getSummary() {
+        final CharSequence entry = getEntry();
+        if (mSummary == null) {
+            return super.getSummary();
+        } else {
+            return String.format(mSummary, entry == null ? "" : entry);
+        }
+    }
+
+    /**
+     * Sets the summary for this Preference with a CharSequence.
+     * If the summary has a
+     * {@linkplain java.lang.String#format String formatting}
+     * marker in it (i.e. "%s" or "%1$s"), then the current entry
+     * value will be substituted in its place when it's retrieved.
+     *
+     * @param summary The summary for the preference.
+     */
+    @Override
+    public void setSummary(CharSequence summary) {
+        super.setSummary(summary);
+        if (summary == null && mSummary != null) {
+            mSummary = null;
+        } else if (summary != null && !summary.equals(mSummary)) {
+            mSummary = summary.toString();
+        }
+    }
+
+    /**
+     * Sets the value to the given index from the entry values.
+     *
+     * @param index The index of the value to set.
+     */
+    public void setValueIndex(int index) {
+        if (mEntryValues != null) {
+            setValue(mEntryValues[index].toString());
+        }
+    }
+
+    /**
+     * Returns the value of the key. This should be one of the entries in
+     * {@link #getEntryValues()}.
+     *
+     * @return The value of the key.
+     */
+    public String getValue() {
+        return mValue;
+    }
+
+    /**
+     * Returns the entry corresponding to the current value.
+     *
+     * @return The entry corresponding to the current value, or null.
+     */
+    public CharSequence getEntry() {
+        int index = getValueIndex();
+        return index >= 0 && mEntries != null ? mEntries[index] : null;
+    }
+
+    /**
+     * Returns the index of the given value (in the entry values array).
+     *
+     * @param value The value whose index should be returned.
+     * @return The index of the value, or -1 if not found.
+     */
+    public int findIndexOfValue(String value) {
+        if (value != null && mEntryValues != null) {
+            for (int i = mEntryValues.length - 1; i >= 0; i--) {
+                if (mEntryValues[i].equals(value)) {
+                    return i;
+                }
+            }
+        }
+        return -1;
+    }
+
+    private int getValueIndex() {
+        return findIndexOfValue(mValue);
+    }
+
+    @Override
+    protected Object onGetDefaultValue(TypedArray a, int index) {
+        return a.getString(index);
+    }
+
+    @Override
+    protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
+        setValue(restoreValue ? getPersistedString(mValue) : (String) defaultValue);
+    }
+
+    @Override
+    protected Parcelable onSaveInstanceState() {
+        final Parcelable superState = super.onSaveInstanceState();
+        if (isPersistent()) {
+            // No need to save instance state since it's persistent
+            return superState;
+        }
+
+        final SavedState myState = new SavedState(superState);
+        myState.value = getValue();
+        return myState;
+    }
+
+    @Override
+    protected void onRestoreInstanceState(Parcelable state) {
+        if (state == null || !state.getClass().equals(SavedState.class)) {
+            // Didn't save state for us in onSaveInstanceState
+            super.onRestoreInstanceState(state);
+            return;
+        }
+
+        SavedState myState = (SavedState) state;
+        super.onRestoreInstanceState(myState.getSuperState());
+        setValue(myState.value);
+    }
+
+    private static class SavedState extends BaseSavedState {
+        String value;
+
+        public SavedState(Parcel source) {
+            super(source);
+            value = source.readString();
+        }
+
+        @Override
+        public void writeToParcel(@NonNull Parcel dest, int flags) {
+            super.writeToParcel(dest, flags);
+            dest.writeString(value);
+        }
+
+        public SavedState(Parcelable superState) {
+            super(superState);
+        }
+
+        public static final Parcelable.Creator<SavedState> CREATOR =
+                new Parcelable.Creator<SavedState>() {
+            public SavedState createFromParcel(Parcel in) {
+                return new SavedState(in);
+            }
+
+            public SavedState[] newArray(int size) {
+                return new SavedState[size];
+            }
+        };
+    }
+
+}
diff --git a/v7/preference/src/android/support/v7/preference/ListPreferenceDialogFragmentCompat.java b/v7/preference/src/android/support/v7/preference/ListPreferenceDialogFragmentCompat.java
new file mode 100644
index 0000000..351ed0b
--- /dev/null
+++ b/v7/preference/src/android/support/v7/preference/ListPreferenceDialogFragmentCompat.java
@@ -0,0 +1,87 @@
+/*
+ * 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.v7.preference;
+
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.support.v7.app.AlertDialog;
+
+public class ListPreferenceDialogFragmentCompat extends PreferenceDialogFragmentCompat {
+
+    private int mClickedDialogEntryIndex;
+
+    public static ListPreferenceDialogFragmentCompat newInstance(String key) {
+        final ListPreferenceDialogFragmentCompat fragment =
+                new ListPreferenceDialogFragmentCompat();
+        final Bundle b = new Bundle(1);
+        b.putString(ARG_KEY, key);
+        fragment.setArguments(b);
+        return fragment;
+    }
+
+    private ListPreference getListPreference() {
+        return (ListPreference) getPreference();
+    }
+
+    @Override
+    protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
+        super.onPrepareDialogBuilder(builder);
+
+        final ListPreference preference = getListPreference();
+
+        if (preference.getEntries() == null || preference.getEntryValues() == null) {
+            throw new IllegalStateException(
+                    "ListPreference requires an entries array and an entryValues array.");
+        }
+
+        mClickedDialogEntryIndex = preference.findIndexOfValue(preference.getValue());
+        builder.setSingleChoiceItems(preference.getEntries(), mClickedDialogEntryIndex,
+                new DialogInterface.OnClickListener() {
+                    public void onClick(DialogInterface dialog, int which) {
+                        mClickedDialogEntryIndex = which;
+
+                        /*
+                         * Clicking on an item simulates the positive button
+                         * click, and dismisses the dialog.
+                         */
+                        ListPreferenceDialogFragmentCompat.this.onClick(dialog,
+                                DialogInterface.BUTTON_POSITIVE);
+                        dialog.dismiss();
+                    }
+                });
+
+        /*
+         * The typical interaction for list-based dialogs is to have
+         * click-on-an-item dismiss the dialog instead of the user having to
+         * press 'Ok'.
+         */
+        builder.setPositiveButton(null, null);
+    }
+
+    @Override
+    public void onDialogClosed(boolean positiveResult) {
+        final ListPreference preference = getListPreference();
+        if (positiveResult && mClickedDialogEntryIndex >= 0 &&
+                preference.getEntryValues() != null) {
+            String value = preference.getEntryValues()[mClickedDialogEntryIndex].toString();
+            if (preference.callChangeListener(value)) {
+                preference.setValue(value);
+            }
+        }
+    }
+
+}
diff --git a/v7/preference/src/android/support/v7/preference/Preference.java b/v7/preference/src/android/support/v7/preference/Preference.java
new file mode 100644
index 0000000..7d01005
--- /dev/null
+++ b/v7/preference/src/android/support/v7/preference/Preference.java
@@ -0,0 +1,1688 @@
+/*
+ * 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.v7.preference;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.support.annotation.NonNull;
+import android.support.v4.content.ContextCompat;
+import android.support.v4.content.SharedPreferencesCompat;
+import android.support.v4.content.res.TypedArrayUtils;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.view.AbsSavedState;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Represents the basic Preference UI building
+ * block displayed by a {@link PreferenceFragmentCompat} in the form of a
+ * {@link android.support.v7.widget.RecyclerView}. This class provides data for the
+ * {@link android.view.View} to be displayed
+ * in the list and associates with a {@link SharedPreferences} to
+ * store/retrieve the preference data.
+ * <p>
+ * When specifying a preference hierarchy in XML, each element can point to a
+ * subclass of {@link Preference}, similar to the view hierarchy and layouts.
+ * <p>
+ * This class contains a {@code key} that will be used as the key into the
+ * {@link SharedPreferences}. It is up to the subclass to decide how to store
+ * the value.
+ *
+ * <div class="special reference">
+ * <h3>Developer Guides</h3>
+ * <p>For information about building a settings UI with Preferences,
+ * read the <a href="{@docRoot}guide/topics/ui/settings.html">Settings</a>
+ * guide.</p>
+ * </div>
+ *
+ * @attr ref android.R.styleable#Preference_icon
+ * @attr ref android.R.styleable#Preference_key
+ * @attr ref android.R.styleable#Preference_title
+ * @attr ref android.R.styleable#Preference_summary
+ * @attr ref android.R.styleable#Preference_order
+ * @attr ref android.R.styleable#Preference_fragment
+ * @attr ref android.R.styleable#Preference_layout
+ * @attr ref android.R.styleable#Preference_widgetLayout
+ * @attr ref android.R.styleable#Preference_enabled
+ * @attr ref android.R.styleable#Preference_selectable
+ * @attr ref android.R.styleable#Preference_dependency
+ * @attr ref android.R.styleable#Preference_persistent
+ * @attr ref android.R.styleable#Preference_defaultValue
+ * @attr ref android.R.styleable#Preference_shouldDisableView
+ */
+public class Preference implements Comparable<Preference> {
+    /**
+     * Specify for {@link #setOrder(int)} if a specific order is not required.
+     */
+    public static final int DEFAULT_ORDER = Integer.MAX_VALUE;
+
+    private Context mContext;
+    private PreferenceManager mPreferenceManager;
+
+    /**
+     * Set when added to hierarchy since we need a unique ID within that
+     * hierarchy.
+     */
+    private long mId;
+
+    private OnPreferenceChangeListener mOnChangeListener;
+    private OnPreferenceClickListener mOnClickListener;
+
+    private int mOrder = DEFAULT_ORDER;
+    private CharSequence mTitle;
+    private CharSequence mSummary;
+    /**
+     * mIconResId is overridden by mIcon, if mIcon is specified.
+     */
+    private int mIconResId;
+    private Drawable mIcon;
+    private String mKey;
+    private Intent mIntent;
+    private String mFragment;
+    private Bundle mExtras;
+    private boolean mEnabled = true;
+    private boolean mSelectable = true;
+    private boolean mRequiresKey;
+    private boolean mPersistent = true;
+    private String mDependencyKey;
+    private Object mDefaultValue;
+    private boolean mDependencyMet = true;
+    private boolean mParentDependencyMet = true;
+    private boolean mVisible = true;
+
+    /**
+     * @see #setShouldDisableView(boolean)
+     */
+    private boolean mShouldDisableView = true;
+
+    private int mLayoutResId = R.layout.preference;
+    private int mWidgetLayoutResId;
+
+    private OnPreferenceChangeInternalListener mListener;
+
+    private List<Preference> mDependents;
+
+    private boolean mBaseMethodCalled;
+
+    private final View.OnClickListener mClickListener = new View.OnClickListener() {
+        @Override
+        public void onClick(View v) {
+            performClick();
+        }
+    };
+
+    /**
+     * Interface definition for a callback to be invoked when the value of this
+     * {@link Preference} has been changed by the user and is
+     * about to be set and/or persisted.  This gives the client a chance
+     * to prevent setting and/or persisting the value.
+     */
+    public interface OnPreferenceChangeListener {
+        /**
+         * Called when a Preference has been changed by the user. This is
+         * called before the state of the Preference is about to be updated and
+         * before the state is persisted.
+         *
+         * @param preference The changed Preference.
+         * @param newValue The new value of the Preference.
+         * @return True to update the state of the Preference with the new value.
+         */
+        boolean onPreferenceChange(Preference preference, Object newValue);
+    }
+
+    /**
+     * Interface definition for a callback to be invoked when a {@link Preference} is
+     * clicked.
+     */
+    public interface OnPreferenceClickListener {
+        /**
+         * Called when a Preference has been clicked.
+         *
+         * @param preference The Preference that was clicked.
+         * @return True if the click was handled.
+         */
+        boolean onPreferenceClick(Preference preference);
+    }
+
+    /**
+     * Interface definition for a callback to be invoked when this
+     * {@link Preference} is changed or, if this is a group, there is an
+     * addition/removal of {@link Preference}(s). This is used internally.
+     */
+    interface OnPreferenceChangeInternalListener {
+        /**
+         * Called when this Preference has changed.
+         *
+         * @param preference This preference.
+         */
+        void onPreferenceChange(Preference preference);
+
+        /**
+         * Called when this group has added/removed {@link Preference}(s).
+         *
+         * @param preference This Preference.
+         */
+        void onPreferenceHierarchyChange(Preference preference);
+
+        /**
+         * Called when this preference has changed its visibility.
+         *
+         * @param preference This Preference.
+         */
+        void onPreferenceVisibilityChange(Preference preference);
+    }
+
+    /**
+     * Perform inflation from XML and apply a class-specific base style. This
+     * constructor of Preference allows subclasses to use their own base style
+     * when they are inflating. For example, a {@link CheckBoxPreference}
+     * constructor calls this version of the super class constructor and
+     * supplies {@code android.R.attr.checkBoxPreferenceStyle} for
+     * <var>defStyleAttr</var>. This allows the theme's checkbox preference
+     * style to modify all of the base preference attributes as well as the
+     * {@link CheckBoxPreference} class's attributes.
+     *
+     * @param context The Context this is associated with, through which it can
+     *            access the current theme, resources,
+     *            {@link android.content.SharedPreferences}, etc.
+     * @param attrs The attributes of the XML tag that is inflating the
+     *            preference.
+     * @param defStyleAttr An attribute in the current theme that contains a
+     *            reference to a style resource that supplies default values for
+     *            the view. Can be 0 to not look for defaults.
+     * @param defStyleRes A resource identifier of a style resource that
+     *            supplies default values for the view, used only if
+     *            defStyleAttr is 0 or can not be found in the theme. Can be 0
+     *            to not look for defaults.
+     * @see #Preference(Context, android.util.AttributeSet)
+     */
+    public Preference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+        mContext = context;
+
+        final TypedArray a = context.obtainStyledAttributes(
+                attrs, R.styleable.Preference, defStyleAttr, defStyleRes);
+
+        mIconResId = TypedArrayUtils.getResourceId(a, R.styleable.Preference_icon,
+                R.styleable.Preference_android_icon, 0);
+
+        mKey = TypedArrayUtils.getString(a, R.styleable.Preference_key,
+                R.styleable.Preference_android_key);
+
+        mTitle = TypedArrayUtils.getString(a, R.styleable.Preference_title,
+                R.styleable.Preference_android_title);
+
+        mSummary = TypedArrayUtils.getString(a, R.styleable.Preference_summary,
+                R.styleable.Preference_android_summary);
+
+        mOrder = TypedArrayUtils.getInt(a, R.styleable.Preference_order,
+                R.styleable.Preference_android_order, DEFAULT_ORDER);
+
+        mFragment = TypedArrayUtils.getString(a, R.styleable.Preference_fragment,
+                R.styleable.Preference_android_fragment);
+
+        mLayoutResId = TypedArrayUtils.getResourceId(a, R.styleable.Preference_layout,
+                R.styleable.Preference_android_layout, R.layout.preference);
+
+        mWidgetLayoutResId = TypedArrayUtils.getResourceId(a, R.styleable.Preference_widgetLayout,
+                R.styleable.Preference_android_widgetLayout, 0);
+
+        mEnabled = TypedArrayUtils.getBoolean(a, R.styleable.Preference_enabled,
+                R.styleable.Preference_android_enabled, true);
+
+        mSelectable = TypedArrayUtils.getBoolean(a, R.styleable.Preference_selectable,
+                R.styleable.Preference_android_selectable, true);
+
+        mPersistent = TypedArrayUtils.getBoolean(a, R.styleable.Preference_persistent,
+                R.styleable.Preference_android_persistent, true);
+
+        mDependencyKey = TypedArrayUtils.getString(a, R.styleable.Preference_dependency,
+                R.styleable.Preference_android_dependency);
+
+        if (a.hasValue(R.styleable.Preference_defaultValue)) {
+            mDefaultValue = onGetDefaultValue(a, R.styleable.Preference_defaultValue);
+        } else if (a.hasValue(R.styleable.Preference_android_defaultValue)) {
+            mDefaultValue = onGetDefaultValue(a, R.styleable.Preference_android_defaultValue);
+        }
+
+        mShouldDisableView =
+                TypedArrayUtils.getBoolean(a, R.styleable.Preference_shouldDisableView,
+                        R.styleable.Preference_shouldDisableView, true);
+
+        a.recycle();
+    }
+
+    /**
+     * Perform inflation from XML and apply a class-specific base style. This
+     * constructor of Preference allows subclasses to use their own base style
+     * when they are inflating. For example, a {@link CheckBoxPreference}
+     * constructor calls this version of the super class constructor and
+     * supplies {@code android.R.attr.checkBoxPreferenceStyle} for
+     * <var>defStyleAttr</var>. This allows the theme's checkbox preference
+     * style to modify all of the base preference attributes as well as the
+     * {@link CheckBoxPreference} class's attributes.
+     *
+     * @param context The Context this is associated with, through which it can
+     *            access the current theme, resources,
+     *            {@link android.content.SharedPreferences}, etc.
+     * @param attrs The attributes of the XML tag that is inflating the
+     *            preference.
+     * @param defStyleAttr An attribute in the current theme that contains a
+     *            reference to a style resource that supplies default values for
+     *            the view. Can be 0 to not look for defaults.
+     * @see #Preference(Context, AttributeSet)
+     */
+    public Preference(Context context, AttributeSet attrs, int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0);
+    }
+
+    /**
+     * Constructor that is called when inflating a Preference from XML. This is
+     * called when a Preference is being constructed from an XML file, supplying
+     * attributes that were specified in the XML file. This version uses a
+     * default style of 0, so the only attribute values applied are those in the
+     * Context's Theme and the given AttributeSet.
+     *
+     * @param context The Context this is associated with, through which it can
+     *            access the current theme, resources, {@link android.content.SharedPreferences},
+     *            etc.
+     * @param attrs The attributes of the XML tag that is inflating the
+     *            preference.
+     * @see #Preference(Context, AttributeSet, int)
+     */
+    public Preference(Context context, AttributeSet attrs) {
+        this(context, attrs, R.attr.preferenceStyle);
+    }
+
+    /**
+     * Constructor to create a Preference.
+     *
+     * @param context The Context in which to store Preference values.
+     */
+    public Preference(Context context) {
+        this(context, null);
+    }
+
+    /**
+     * Called when a Preference is being inflated and the default value
+     * attribute needs to be read. Since different Preference types have
+     * different value types, the subclass should get and return the default
+     * value which will be its value type.
+     * <p>
+     * For example, if the value type is String, the body of the method would
+     * proxy to {@link TypedArray#getString(int)}.
+     *
+     * @param a The set of attributes.
+     * @param index The index of the default value attribute.
+     * @return The default value of this preference type.
+     */
+    protected Object onGetDefaultValue(TypedArray a, int index) {
+        return null;
+    }
+
+    /**
+     * Sets an {@link Intent} to be used for
+     * {@link Context#startActivity(Intent)} when this Preference is clicked.
+     *
+     * @param intent The intent associated with this Preference.
+     */
+    public void setIntent(Intent intent) {
+        mIntent = intent;
+    }
+
+    /**
+     * Return the {@link Intent} associated with this Preference.
+     *
+     * @return The {@link Intent} last set via {@link #setIntent(Intent)} or XML.
+     */
+    public Intent getIntent() {
+        return mIntent;
+    }
+
+    /**
+     * Sets the class name of a fragment to be shown when this Preference is clicked.
+     *
+     * @param fragment The class name of the fragment associated with this Preference.
+     */
+    public void setFragment(String fragment) {
+        mFragment = fragment;
+    }
+
+    /**
+     * Return the fragment class name associated with this Preference.
+     *
+     * @return The fragment class name last set via {@link #setFragment} or XML.
+     */
+    public String getFragment() {
+        return mFragment;
+    }
+
+    /**
+     * Return the extras Bundle object associated with this preference, creating
+     * a new Bundle if there currently isn't one.  You can use this to get and
+     * set individual extra key/value pairs.
+     */
+    public Bundle getExtras() {
+        if (mExtras == null) {
+            mExtras = new Bundle();
+        }
+        return mExtras;
+    }
+
+    /**
+     * Return the extras Bundle object associated with this preference,
+     * returning null if there is not currently one.
+     */
+    public Bundle peekExtras() {
+        return mExtras;
+    }
+
+    /**
+     * Sets the layout resource that is inflated as the {@link View} to be shown
+     * for this Preference. In most cases, the default layout is sufficient for
+     * custom Preference objects and only the widget layout needs to be changed.
+     * <p>
+     * This layout should contain a {@link ViewGroup} with ID
+     * {@link android.R.id#widget_frame} to be the parent of the specific widget
+     * for this Preference. It should similarly contain
+     * {@link android.R.id#title} and {@link android.R.id#summary}.
+     * <p>
+     * It is an error to change the layout after adding the preference to a {@link PreferenceGroup}
+     *
+     * @param layoutResId The layout resource ID to be inflated and returned as
+     *            a {@link View}.
+     * @see #setWidgetLayoutResource(int)
+     */
+    public void setLayoutResource(int layoutResId) {
+        mLayoutResId = layoutResId;
+    }
+
+    /**
+     * Gets the layout resource that will be shown as the {@link View} for this Preference.
+     *
+     * @return The layout resource ID.
+     */
+    public final int getLayoutResource() {
+        return mLayoutResId;
+    }
+
+    /**
+     * Sets the layout for the controllable widget portion of this Preference. This
+     * is inflated into the main layout. For example, a {@link CheckBoxPreference}
+     * would specify a custom layout (consisting of just the CheckBox) here,
+     * instead of creating its own main layout.
+     * <p>
+     * It is an error to change the layout after adding the preference to a {@link PreferenceGroup}
+     *
+     * @param widgetLayoutResId The layout resource ID to be inflated into the
+     *            main layout.
+     * @see #setLayoutResource(int)
+     */
+    public void setWidgetLayoutResource(int widgetLayoutResId) {
+        mWidgetLayoutResId = widgetLayoutResId;
+    }
+
+    /**
+     * Gets the layout resource for the controllable widget portion of this Preference.
+     *
+     * @return The layout resource ID.
+     */
+    public final int getWidgetLayoutResource() {
+        return mWidgetLayoutResId;
+    }
+
+    /**
+     * Binds the created View to the data for this Preference.
+     * <p>
+     * This is a good place to grab references to custom Views in the layout and
+     * set properties on them.
+     * <p>
+     * Make sure to call through to the superclass's implementation.
+     *
+     * @param holder The ViewHolder that provides references to the views to fill in. These views
+     *               will be recycled, so you should not hold a reference to them after this method
+     *               returns.
+     */
+    public void onBindViewHolder(PreferenceViewHolder holder) {
+        holder.itemView.setOnClickListener(mClickListener);
+
+        final TextView titleView = (TextView) holder.findViewById(android.R.id.title);
+        if (titleView != null) {
+            final CharSequence title = getTitle();
+            if (!TextUtils.isEmpty(title)) {
+                titleView.setText(title);
+                titleView.setVisibility(View.VISIBLE);
+            } else {
+                titleView.setVisibility(View.GONE);
+            }
+        }
+
+        final TextView summaryView = (TextView) holder.findViewById(android.R.id.summary);
+        if (summaryView != null) {
+            final CharSequence summary = getSummary();
+            if (!TextUtils.isEmpty(summary)) {
+                summaryView.setText(summary);
+                summaryView.setVisibility(View.VISIBLE);
+            } else {
+                summaryView.setVisibility(View.GONE);
+            }
+        }
+
+        final ImageView imageView = (ImageView) holder.findViewById(android.R.id.icon);
+        if (imageView != null) {
+            if (mIconResId != 0 || mIcon != null) {
+                if (mIcon == null) {
+                    mIcon = ContextCompat.getDrawable(getContext(), mIconResId);
+                }
+                if (mIcon != null) {
+                    imageView.setImageDrawable(mIcon);
+                }
+            }
+            imageView.setVisibility(mIcon != null ? View.VISIBLE : View.GONE);
+        }
+
+        final View imageFrame = holder.findViewById(R.id.icon_frame);
+        if (imageFrame != null) {
+            imageFrame.setVisibility(mIcon != null ? View.VISIBLE : View.GONE);
+        }
+
+        if (mShouldDisableView) {
+            setEnabledStateOnViews(holder.itemView, isEnabled());
+        } else {
+            setEnabledStateOnViews(holder.itemView, true);
+        }
+    }
+
+    /**
+     * Makes sure the view (and any children) get the enabled state changed.
+     */
+    private void setEnabledStateOnViews(View v, boolean enabled) {
+        v.setEnabled(enabled);
+
+        if (v instanceof ViewGroup) {
+            final ViewGroup vg = (ViewGroup) v;
+            for (int i = vg.getChildCount() - 1; i >= 0; i--) {
+                setEnabledStateOnViews(vg.getChildAt(i), enabled);
+            }
+        }
+    }
+
+    /**
+     * Sets the order of this Preference with respect to other
+     * Preference objects on the same level. If this is not specified, the
+     * default behavior is to sort alphabetically. The
+     * {@link PreferenceGroup#setOrderingAsAdded(boolean)} can be used to order
+     * Preference objects based on the order they appear in the XML.
+     *
+     * @param order The order for this Preference. A lower value will be shown
+     *            first. Use {@link #DEFAULT_ORDER} to sort alphabetically or
+     *            allow ordering from XML.
+     * @see PreferenceGroup#setOrderingAsAdded(boolean)
+     * @see #DEFAULT_ORDER
+     */
+    public void setOrder(int order) {
+        if (order != mOrder) {
+            mOrder = order;
+
+            // Reorder the list
+            notifyHierarchyChanged();
+        }
+    }
+
+    /**
+     * Gets the order of this Preference with respect to other Preference objects
+     * on the same level.
+     *
+     * @return The order of this Preference.
+     * @see #setOrder(int)
+     */
+    public int getOrder() {
+        return mOrder;
+    }
+
+    /**
+     * Sets the title for this Preference with a CharSequence.
+     * This title will be placed into the ID
+     * {@link android.R.id#title} within the View bound by
+     * {@link #onBindViewHolder(PreferenceViewHolder)}.
+     *
+     * @param title The title for this Preference.
+     */
+    public void setTitle(CharSequence title) {
+        if (title == null && mTitle != null || title != null && !title.equals(mTitle)) {
+            mTitle = title;
+            notifyChanged();
+        }
+    }
+
+    /**
+     * Sets the title for this Preference with a resource ID.
+     *
+     * @see #setTitle(CharSequence)
+     * @param titleResId The title as a resource ID.
+     */
+    public void setTitle(int titleResId) {
+        setTitle(mContext.getString(titleResId));
+    }
+
+    /**
+     * Returns the title of this Preference.
+     *
+     * @return The title.
+     * @see #setTitle(CharSequence)
+     */
+    public CharSequence getTitle() {
+        return mTitle;
+    }
+
+    /**
+     * Sets the icon for this Preference with a Drawable.
+     * This icon will be placed into the ID
+     * {@link android.R.id#icon} within the View created by
+     * {@link #onBindViewHolder(PreferenceViewHolder)}.
+     *
+     * @param icon The optional icon for this Preference.
+     */
+    public void setIcon(Drawable icon) {
+        if ((icon == null && mIcon != null) || (icon != null && mIcon != icon)) {
+            mIcon = icon;
+            mIconResId = 0;
+            notifyChanged();
+        }
+    }
+
+    /**
+     * Sets the icon for this Preference with a resource ID.
+     *
+     * @see #setIcon(Drawable)
+     * @param iconResId The icon as a resource ID.
+     */
+    public void setIcon(int iconResId) {
+        setIcon(ContextCompat.getDrawable(mContext, iconResId));
+        mIconResId = iconResId;
+    }
+
+    /**
+     * Returns the icon of this Preference.
+     *
+     * @return The icon.
+     * @see #setIcon(Drawable)
+     */
+    public Drawable getIcon() {
+        return mIcon;
+    }
+
+    /**
+     * Returns the summary of this Preference.
+     *
+     * @return The summary.
+     * @see #setSummary(CharSequence)
+     */
+    public CharSequence getSummary() {
+        return mSummary;
+    }
+
+    /**
+     * Sets the summary for this Preference with a CharSequence.
+     *
+     * @param summary The summary for the preference.
+     */
+    public void setSummary(CharSequence summary) {
+        if (summary == null && mSummary != null || summary != null && !summary.equals(mSummary)) {
+            mSummary = summary;
+            notifyChanged();
+        }
+    }
+
+    /**
+     * Sets the summary for this Preference with a resource ID.
+     *
+     * @see #setSummary(CharSequence)
+     * @param summaryResId The summary as a resource.
+     */
+    public void setSummary(int summaryResId) {
+        setSummary(mContext.getString(summaryResId));
+    }
+
+    /**
+     * Sets whether this Preference is enabled. If disabled, it will
+     * not handle clicks.
+     *
+     * @param enabled Set true to enable it.
+     */
+    public void setEnabled(boolean enabled) {
+        if (mEnabled != enabled) {
+            mEnabled = enabled;
+
+            // Enabled state can change dependent preferences' states, so notify
+            notifyDependencyChange(shouldDisableDependents());
+
+            notifyChanged();
+        }
+    }
+
+    /**
+     * Checks whether this Preference should be enabled in the list.
+     *
+     * @return True if this Preference is enabled, false otherwise.
+     */
+    public boolean isEnabled() {
+        return mEnabled && mDependencyMet && mParentDependencyMet;
+    }
+
+    /**
+     * Sets whether this Preference is selectable.
+     *
+     * @param selectable Set true to make it selectable.
+     */
+    public void setSelectable(boolean selectable) {
+        if (mSelectable != selectable) {
+            mSelectable = selectable;
+            notifyChanged();
+        }
+    }
+
+    /**
+     * Checks whether this Preference should be selectable in the list.
+     *
+     * @return True if it is selectable, false otherwise.
+     */
+    public boolean isSelectable() {
+        return mSelectable;
+    }
+
+    /**
+     * Sets whether this Preference should disable its view when it gets
+     * disabled.
+     * <p>
+     * For example, set this and {@link #setEnabled(boolean)} to false for
+     * preferences that are only displaying information and 1) should not be
+     * clickable 2) should not have the view set to the disabled state.
+     *
+     * @param shouldDisableView Set true if this preference should disable its view
+     *            when the preference is disabled.
+     */
+    public void setShouldDisableView(boolean shouldDisableView) {
+        mShouldDisableView = shouldDisableView;
+        notifyChanged();
+    }
+
+    /**
+     * Checks whether this Preference should disable its view when it's action is disabled.
+     * @see #setShouldDisableView(boolean)
+     * @return True if it should disable the view.
+     */
+    public boolean getShouldDisableView() {
+        return mShouldDisableView;
+    }
+
+    /**
+     * Sets whether this preference should be visible in the list. If false, it is excluded from
+     * the adapter, but can still be retrieved using
+     * {@link PreferenceFragmentCompat#findPreference(CharSequence)}.
+     *
+     * @param visible Set false if this preference should be hidden from the list.
+     */
+    public final void setVisible(boolean visible) {
+        mVisible = visible;
+        if (mListener != null) {
+            mListener.onPreferenceVisibilityChange(this);
+        }
+    }
+
+    /**
+     * Checks whether this preference should be visible to the user in the list.
+     * @see #setVisible(boolean)
+     * @return True if this preference should be displayed.
+     */
+    public final boolean isVisible() {
+        return mVisible;
+    }
+
+    /**
+     * Returns a unique ID for this Preference.  This ID should be unique across all
+     * Preference objects in a hierarchy.
+     *
+     * @return A unique ID for this Preference.
+     */
+    long getId() {
+        return mId;
+    }
+
+    /**
+     * Processes a click on the preference. This includes saving the value to
+     * the {@link android.content.SharedPreferences}. However, the overridden method should
+     * call {@link #callChangeListener(Object)} to make sure the client wants to
+     * update the preference's state with the new value.
+     */
+    protected void onClick() {
+    }
+
+    /**
+     * Sets the key for this Preference, which is used as a key to the
+     * {@link android.content.SharedPreferences}. This should be unique for the package.
+     *
+     * @param key The key for the preference.
+     */
+    public void setKey(String key) {
+        mKey = key;
+
+        if (mRequiresKey && !hasKey()) {
+            requireKey();
+        }
+    }
+
+    /**
+     * Gets the key for this Preference, which is also the key used for storing
+     * values into SharedPreferences.
+     *
+     * @return The key.
+     */
+    public String getKey() {
+        return mKey;
+    }
+
+    /**
+     * Checks whether the key is present, and if it isn't throws an
+     * exception. This should be called by subclasses that store preferences in
+     * the {@link android.content.SharedPreferences}.
+     *
+     * @throws IllegalStateException If there is no key assigned.
+     */
+    void requireKey() {
+        if (TextUtils.isEmpty(mKey)) {
+            throw new IllegalStateException("Preference does not have a key assigned.");
+        }
+
+        mRequiresKey = true;
+    }
+
+    /**
+     * Checks whether this Preference has a valid key.
+     *
+     * @return True if the key exists and is not a blank string, false otherwise.
+     */
+    public boolean hasKey() {
+        return !TextUtils.isEmpty(mKey);
+    }
+
+    /**
+     * Checks whether this Preference is persistent. If it is, it stores its value(s) into
+     * the persistent {@link android.content.SharedPreferences} storage.
+     *
+     * @return True if it is persistent.
+     */
+    public boolean isPersistent() {
+        return mPersistent;
+    }
+
+    /**
+     * Checks whether, at the given time this method is called,
+     * this Preference should store/restore its value(s) into the
+     * {@link android.content.SharedPreferences}. This, at minimum, checks whether this
+     * Preference is persistent and it currently has a key. Before you
+     * save/restore from the {@link android.content.SharedPreferences}, check this first.
+     *
+     * @return True if it should persist the value.
+     */
+    protected boolean shouldPersist() {
+        return mPreferenceManager != null && isPersistent() && hasKey();
+    }
+
+    /**
+     * Sets whether this Preference is persistent. When persistent,
+     * it stores its value(s) into the persistent {@link android.content.SharedPreferences}
+     * storage.
+     *
+     * @param persistent Set true if it should store its value(s) into the
+     *                   {@link android.content.SharedPreferences}.
+     */
+    public void setPersistent(boolean persistent) {
+        mPersistent = persistent;
+    }
+
+    /**
+     * Call this method after the user changes the preference, but before the
+     * internal state is set. This allows the client to ignore the user value.
+     *
+     * @param newValue The new value of this Preference.
+     * @return True if the user value should be set as the preference
+     *         value (and persisted).
+     */
+    public boolean callChangeListener(Object newValue) {
+        return mOnChangeListener == null || mOnChangeListener.onPreferenceChange(this, newValue);
+    }
+
+    /**
+     * Sets the callback to be invoked when this Preference is changed by the
+     * user (but before the internal state has been updated).
+     *
+     * @param onPreferenceChangeListener The callback to be invoked.
+     */
+    public void setOnPreferenceChangeListener(
+            OnPreferenceChangeListener onPreferenceChangeListener) {
+        mOnChangeListener = onPreferenceChangeListener;
+    }
+
+    /**
+     * Returns the callback to be invoked when this Preference is changed by the
+     * user (but before the internal state has been updated).
+     *
+     * @return The callback to be invoked.
+     */
+    public OnPreferenceChangeListener getOnPreferenceChangeListener() {
+        return mOnChangeListener;
+    }
+
+    /**
+     * Sets the callback to be invoked when this Preference is clicked.
+     *
+     * @param onPreferenceClickListener The callback to be invoked.
+     */
+    public void setOnPreferenceClickListener(OnPreferenceClickListener onPreferenceClickListener) {
+        mOnClickListener = onPreferenceClickListener;
+    }
+
+    /**
+     * Returns the callback to be invoked when this Preference is clicked.
+     *
+     * @return The callback to be invoked.
+     */
+    public OnPreferenceClickListener getOnPreferenceClickListener() {
+        return mOnClickListener;
+    }
+
+    /**
+     * Called when a click should be performed.
+     *
+     * @hide
+     */
+    public void performClick() {
+
+        if (!isEnabled()) {
+            return;
+        }
+
+        onClick();
+
+        if (mOnClickListener != null && mOnClickListener.onPreferenceClick(this)) {
+            return;
+        }
+
+        PreferenceManager preferenceManager = getPreferenceManager();
+        if (preferenceManager != null) {
+            PreferenceManager.OnPreferenceTreeClickListener listener = preferenceManager
+                    .getOnPreferenceTreeClickListener();
+            if (listener != null && listener.onPreferenceTreeClick(this)) {
+                return;
+            }
+        }
+
+        if (mIntent != null) {
+            Context context = getContext();
+            context.startActivity(mIntent);
+        }
+    }
+
+    /**
+     * Returns the {@link android.content.Context} of this Preference.
+     * Each Preference in a Preference hierarchy can be
+     * from different Context (for example, if multiple activities provide preferences into a single
+     * {@link PreferenceFragmentCompat}). This Context will be used to save the Preference values.
+     *
+     * @return The Context of this Preference.
+     */
+    public Context getContext() {
+        return mContext;
+    }
+
+    /**
+     * Returns the {@link android.content.SharedPreferences} where this Preference can read its
+     * value(s). Usually, it's easier to use one of the helper read methods:
+     * {@link #getPersistedBoolean(boolean)}, {@link #getPersistedFloat(float)},
+     * {@link #getPersistedInt(int)}, {@link #getPersistedLong(long)},
+     * {@link #getPersistedString(String)}. To save values, see
+     * {@link #getEditor()}.
+     * <p>
+     * In some cases, writes to the {@link #getEditor()} will not be committed
+     * right away and hence not show up in the returned
+     * {@link android.content.SharedPreferences}, this is intended behavior to improve
+     * performance.
+     *
+     * @return The {@link android.content.SharedPreferences} where this Preference reads its
+     *         value(s), or null if it isn't attached to a Preference hierarchy.
+     * @see #getEditor()
+     */
+    public SharedPreferences getSharedPreferences() {
+        if (mPreferenceManager == null) {
+            return null;
+        }
+
+        return mPreferenceManager.getSharedPreferences();
+    }
+
+    /**
+     * Compares Preference objects based on order (if set), otherwise alphabetically on the titles.
+     *
+     * @param another The Preference to compare to this one.
+     * @return 0 if the same; less than 0 if this Preference sorts ahead of <var>another</var>;
+     *          greater than 0 if this Preference sorts after <var>another</var>.
+     */
+    @Override
+    public int compareTo(@NonNull Preference another) {
+        if (mOrder != another.mOrder) {
+            // Do order comparison
+            return mOrder - another.mOrder;
+        } else if (mTitle == another.mTitle) {
+            // If titles are null or share same object comparison
+            return 0;
+        } else if (mTitle == null) {
+            return 1;
+        } else if (another.mTitle == null) {
+            return -1;
+        } else {
+            // Do name comparison
+            return mTitle.toString().compareToIgnoreCase(another.mTitle.toString());
+        }
+    }
+
+    /**
+     * Sets the internal change listener.
+     *
+     * @param listener The listener.
+     * @see #notifyChanged()
+     */
+    final void setOnPreferenceChangeInternalListener(OnPreferenceChangeInternalListener listener) {
+        mListener = listener;
+    }
+
+    /**
+     * Should be called when the data of this {@link Preference} has changed.
+     */
+    protected void notifyChanged() {
+        if (mListener != null) {
+            mListener.onPreferenceChange(this);
+        }
+    }
+
+    /**
+     * Should be called when a Preference has been
+     * added/removed from this group, or the ordering should be
+     * re-evaluated.
+     */
+    protected void notifyHierarchyChanged() {
+        if (mListener != null) {
+            mListener.onPreferenceHierarchyChange(this);
+        }
+    }
+
+    /**
+     * Gets the {@link PreferenceManager} that manages this Preference object's tree.
+     *
+     * @return The {@link PreferenceManager}.
+     */
+    public PreferenceManager getPreferenceManager() {
+        return mPreferenceManager;
+    }
+
+    /**
+     * Called when this Preference has been attached to a Preference hierarchy.
+     * Make sure to call the super implementation.
+     *
+     * @param preferenceManager The PreferenceManager of the hierarchy.
+     */
+    protected void onAttachedToHierarchy(PreferenceManager preferenceManager) {
+        mPreferenceManager = preferenceManager;
+
+        mId = preferenceManager.getNextId();
+
+        dispatchSetInitialValue();
+    }
+
+    /**
+     * Called when the Preference hierarchy has been attached to the
+     * list of preferences. This can also be called when this
+     * Preference has been attached to a group that was already attached
+     * to the list of preferences.
+     */
+    protected void onAttached() {
+        // At this point, the hierarchy that this preference is in is connected
+        // with all other preferences.
+        registerDependency();
+    }
+
+    private void registerDependency() {
+
+        if (TextUtils.isEmpty(mDependencyKey)) return;
+
+        Preference preference = findPreferenceInHierarchy(mDependencyKey);
+        if (preference != null) {
+            preference.registerDependent(this);
+        } else {
+            throw new IllegalStateException("Dependency \"" + mDependencyKey
+                    + "\" not found for preference \"" + mKey + "\" (title: \"" + mTitle + "\"");
+        }
+    }
+
+    private void unregisterDependency() {
+        if (mDependencyKey != null) {
+            final Preference oldDependency = findPreferenceInHierarchy(mDependencyKey);
+            if (oldDependency != null) {
+                oldDependency.unregisterDependent(this);
+            }
+        }
+    }
+
+    /**
+     * Finds a Preference in this hierarchy (the whole thing,
+     * even above/below your {@link PreferenceScreen} screen break) with the given
+     * key.
+     * <p>
+     * This only functions after we have been attached to a hierarchy.
+     *
+     * @param key The key of the Preference to find.
+     * @return The Preference that uses the given key.
+     */
+    protected Preference findPreferenceInHierarchy(String key) {
+        if (TextUtils.isEmpty(key) || mPreferenceManager == null) {
+            return null;
+        }
+
+        return mPreferenceManager.findPreference(key);
+    }
+
+    /**
+     * Adds a dependent Preference on this Preference so we can notify it.
+     * Usually, the dependent Preference registers itself (it's good for it to
+     * know it depends on something), so please use
+     * {@link Preference#setDependency(String)} on the dependent Preference.
+     *
+     * @param dependent The dependent Preference that will be enabled/disabled
+     *            according to the state of this Preference.
+     */
+    private void registerDependent(Preference dependent) {
+        if (mDependents == null) {
+            mDependents = new ArrayList<Preference>();
+        }
+
+        mDependents.add(dependent);
+
+        dependent.onDependencyChanged(this, shouldDisableDependents());
+    }
+
+    /**
+     * Removes a dependent Preference on this Preference.
+     *
+     * @param dependent The dependent Preference that will be enabled/disabled
+     *            according to the state of this Preference.
+     * @return Returns the same Preference object, for chaining multiple calls
+     *         into a single statement.
+     */
+    private void unregisterDependent(Preference dependent) {
+        if (mDependents != null) {
+            mDependents.remove(dependent);
+        }
+    }
+
+    /**
+     * Notifies any listening dependents of a change that affects the
+     * dependency.
+     *
+     * @param disableDependents Whether this Preference should disable
+     *            its dependents.
+     */
+    public void notifyDependencyChange(boolean disableDependents) {
+        final List<Preference> dependents = mDependents;
+
+        if (dependents == null) {
+            return;
+        }
+
+        final int dependentsCount = dependents.size();
+        for (int i = 0; i < dependentsCount; i++) {
+            dependents.get(i).onDependencyChanged(this, disableDependents);
+        }
+    }
+
+    /**
+     * Called when the dependency changes.
+     *
+     * @param dependency The Preference that this Preference depends on.
+     * @param disableDependent Set true to disable this Preference.
+     */
+    public void onDependencyChanged(Preference dependency, boolean disableDependent) {
+        if (mDependencyMet == disableDependent) {
+            mDependencyMet = !disableDependent;
+
+            // Enabled state can change dependent preferences' states, so notify
+            notifyDependencyChange(shouldDisableDependents());
+
+            notifyChanged();
+        }
+    }
+
+    /**
+     * Called when the implicit parent dependency changes.
+     *
+     * @param parent The Preference that this Preference depends on.
+     * @param disableChild Set true to disable this Preference.
+     */
+    public void onParentChanged(Preference parent, boolean disableChild) {
+        if (mParentDependencyMet == disableChild) {
+            mParentDependencyMet = !disableChild;
+
+            // Enabled state can change dependent preferences' states, so notify
+            notifyDependencyChange(shouldDisableDependents());
+
+            notifyChanged();
+        }
+    }
+
+    /**
+     * Checks whether this preference's dependents should currently be
+     * disabled.
+     *
+     * @return True if the dependents should be disabled, otherwise false.
+     */
+    public boolean shouldDisableDependents() {
+        return !isEnabled();
+    }
+
+    /**
+     * Sets the key of a Preference that this Preference will depend on. If that
+     * Preference is not set or is off, this Preference will be disabled.
+     *
+     * @param dependencyKey The key of the Preference that this depends on.
+     */
+    public void setDependency(String dependencyKey) {
+        // Unregister the old dependency, if we had one
+        unregisterDependency();
+
+        // Register the new
+        mDependencyKey = dependencyKey;
+        registerDependency();
+    }
+
+    /**
+     * Returns the key of the dependency on this Preference.
+     *
+     * @return The key of the dependency.
+     * @see #setDependency(String)
+     */
+    public String getDependency() {
+        return mDependencyKey;
+    }
+
+    /**
+     * Called when this Preference is being removed from the hierarchy. You
+     * should remove any references to this Preference that you know about. Make
+     * sure to call through to the superclass implementation.
+     */
+    protected void onPrepareForRemoval() {
+        unregisterDependency();
+    }
+
+    /**
+     * Sets the default value for this Preference, which will be set either if
+     * persistence is off or persistence is on and the preference is not found
+     * in the persistent storage.
+     *
+     * @param defaultValue The default value.
+     */
+    public void setDefaultValue(Object defaultValue) {
+        mDefaultValue = defaultValue;
+    }
+
+    private void dispatchSetInitialValue() {
+        // By now, we know if we are persistent.
+        final boolean shouldPersist = shouldPersist();
+        if (!shouldPersist || !getSharedPreferences().contains(mKey)) {
+            if (mDefaultValue != null) {
+                onSetInitialValue(false, mDefaultValue);
+            }
+        } else {
+            onSetInitialValue(true, null);
+        }
+    }
+
+    /**
+     * Implement this to set the initial value of the Preference.
+     * <p>
+     * If <var>restorePersistedValue</var> is true, you should restore the
+     * Preference value from the {@link android.content.SharedPreferences}. If
+     * <var>restorePersistedValue</var> is false, you should set the Preference
+     * value to defaultValue that is given (and possibly store to SharedPreferences
+     * if {@link #shouldPersist()} is true).
+     * <p>
+     * This may not always be called. One example is if it should not persist
+     * but there is no default value given.
+     *
+     * @param restorePersistedValue True to restore the persisted value;
+     *            false to use the given <var>defaultValue</var>.
+     * @param defaultValue The default value for this Preference. Only use this
+     *            if <var>restorePersistedValue</var> is false.
+     */
+    protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) {
+    }
+
+    private void tryCommit(@NonNull SharedPreferences.Editor editor) {
+        if (mPreferenceManager.shouldCommit()) {
+            SharedPreferencesCompat.EditorCompat.getInstance().apply(editor);
+        }
+    }
+
+    /**
+     * Attempts to persist a String to the {@link android.content.SharedPreferences}.
+     * <p>
+     * This will check if this Preference is persistent, get an editor from
+     * the {@link PreferenceManager}, put in the string, and check if we should commit (and
+     * commit if so).
+     *
+     * @param value The value to persist.
+     * @return True if the Preference is persistent. (This is not whether the
+     *         value was persisted, since we may not necessarily commit if there
+     *         will be a batch commit later.)
+     * @see #getPersistedString(String)
+     */
+    protected boolean persistString(String value) {
+        if (shouldPersist()) {
+            // Shouldn't store null
+            if (value == getPersistedString(null)) {
+                // It's already there, so the same as persisting
+                return true;
+            }
+
+            SharedPreferences.Editor editor = mPreferenceManager.getEditor();
+            editor.putString(mKey, value);
+            tryCommit(editor);
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Attempts to get a persisted String from the {@link android.content.SharedPreferences}.
+     * <p>
+     * This will check if this Preference is persistent, get the SharedPreferences
+     * from the {@link PreferenceManager}, and get the value.
+     *
+     * @param defaultReturnValue The default value to return if either the
+     *            Preference is not persistent or the Preference is not in the
+     *            shared preferences.
+     * @return The value from the SharedPreferences or the default return
+     *         value.
+     * @see #persistString(String)
+     */
+    protected String getPersistedString(String defaultReturnValue) {
+        if (!shouldPersist()) {
+            return defaultReturnValue;
+        }
+
+        return mPreferenceManager.getSharedPreferences().getString(mKey, defaultReturnValue);
+    }
+
+    /**
+     * Attempts to persist an int to the {@link android.content.SharedPreferences}.
+     *
+     * @param value The value to persist.
+     * @return True if the Preference is persistent. (This is not whether the
+     *         value was persisted, since we may not necessarily commit if there
+     *         will be a batch commit later.)
+     * @see #persistString(String)
+     * @see #getPersistedInt(int)
+     */
+    protected boolean persistInt(int value) {
+        if (shouldPersist()) {
+            if (value == getPersistedInt(~value)) {
+                // It's already there, so the same as persisting
+                return true;
+            }
+
+            SharedPreferences.Editor editor = mPreferenceManager.getEditor();
+            editor.putInt(mKey, value);
+            tryCommit(editor);
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Attempts to get a persisted int from the {@link android.content.SharedPreferences}.
+     *
+     * @param defaultReturnValue The default value to return if either this
+     *            Preference is not persistent or this Preference is not in the
+     *            SharedPreferences.
+     * @return The value from the SharedPreferences or the default return
+     *         value.
+     * @see #getPersistedString(String)
+     * @see #persistInt(int)
+     */
+    protected int getPersistedInt(int defaultReturnValue) {
+        if (!shouldPersist()) {
+            return defaultReturnValue;
+        }
+
+        return mPreferenceManager.getSharedPreferences().getInt(mKey, defaultReturnValue);
+    }
+
+    /**
+     * Attempts to persist a float to the {@link android.content.SharedPreferences}.
+     *
+     * @param value The value to persist.
+     * @return True if this Preference is persistent. (This is not whether the
+     *         value was persisted, since we may not necessarily commit if there
+     *         will be a batch commit later.)
+     * @see #persistString(String)
+     * @see #getPersistedFloat(float)
+     */
+    protected boolean persistFloat(float value) {
+        if (shouldPersist()) {
+            if (value == getPersistedFloat(Float.NaN)) {
+                // It's already there, so the same as persisting
+                return true;
+            }
+
+            SharedPreferences.Editor editor = mPreferenceManager.getEditor();
+            editor.putFloat(mKey, value);
+            tryCommit(editor);
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Attempts to get a persisted float from the {@link android.content.SharedPreferences}.
+     *
+     * @param defaultReturnValue The default value to return if either this
+     *            Preference is not persistent or this Preference is not in the
+     *            SharedPreferences.
+     * @return The value from the SharedPreferences or the default return
+     *         value.
+     * @see #getPersistedString(String)
+     * @see #persistFloat(float)
+     */
+    protected float getPersistedFloat(float defaultReturnValue) {
+        if (!shouldPersist()) {
+            return defaultReturnValue;
+        }
+
+        return mPreferenceManager.getSharedPreferences().getFloat(mKey, defaultReturnValue);
+    }
+
+    /**
+     * Attempts to persist a long to the {@link android.content.SharedPreferences}.
+     *
+     * @param value The value to persist.
+     * @return True if this Preference is persistent. (This is not whether the
+     *         value was persisted, since we may not necessarily commit if there
+     *         will be a batch commit later.)
+     * @see #persistString(String)
+     * @see #getPersistedLong(long)
+     */
+    protected boolean persistLong(long value) {
+        if (shouldPersist()) {
+            if (value == getPersistedLong(~value)) {
+                // It's already there, so the same as persisting
+                return true;
+            }
+
+            SharedPreferences.Editor editor = mPreferenceManager.getEditor();
+            editor.putLong(mKey, value);
+            tryCommit(editor);
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Attempts to get a persisted long from the {@link android.content.SharedPreferences}.
+     *
+     * @param defaultReturnValue The default value to return if either this
+     *            Preference is not persistent or this Preference is not in the
+     *            SharedPreferences.
+     * @return The value from the SharedPreferences or the default return
+     *         value.
+     * @see #getPersistedString(String)
+     * @see #persistLong(long)
+     */
+    protected long getPersistedLong(long defaultReturnValue) {
+        if (!shouldPersist()) {
+            return defaultReturnValue;
+        }
+
+        return mPreferenceManager.getSharedPreferences().getLong(mKey, defaultReturnValue);
+    }
+
+    /**
+     * Attempts to persist a boolean to the {@link android.content.SharedPreferences}.
+     *
+     * @param value The value to persist.
+     * @return True if this Preference is persistent. (This is not whether the
+     *         value was persisted, since we may not necessarily commit if there
+     *         will be a batch commit later.)
+     * @see #persistString(String)
+     * @see #getPersistedBoolean(boolean)
+     */
+    protected boolean persistBoolean(boolean value) {
+        if (shouldPersist()) {
+            if (value == getPersistedBoolean(!value)) {
+                // It's already there, so the same as persisting
+                return true;
+            }
+
+            SharedPreferences.Editor editor = mPreferenceManager.getEditor();
+            editor.putBoolean(mKey, value);
+            tryCommit(editor);
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Attempts to get a persisted boolean from the {@link android.content.SharedPreferences}.
+     *
+     * @param defaultReturnValue The default value to return if either this
+     *            Preference is not persistent or this Preference is not in the
+     *            SharedPreferences.
+     * @return The value from the SharedPreferences or the default return
+     *         value.
+     * @see #getPersistedString(String)
+     * @see #persistBoolean(boolean)
+     */
+    protected boolean getPersistedBoolean(boolean defaultReturnValue) {
+        if (!shouldPersist()) {
+            return defaultReturnValue;
+        }
+
+        return mPreferenceManager.getSharedPreferences().getBoolean(mKey, defaultReturnValue);
+    }
+
+    @Override
+    public String toString() {
+        return getFilterableStringBuilder().toString();
+    }
+
+    /**
+     * Returns the text that will be used to filter this Preference depending on
+     * user input.
+     * <p>
+     * If overridding and calling through to the superclass, make sure to prepend
+     * your additions with a space.
+     *
+     * @return Text as a {@link StringBuilder} that will be used to filter this
+     *         preference. By default, this is the title and summary
+     *         (concatenated with a space).
+     */
+    StringBuilder getFilterableStringBuilder() {
+        StringBuilder sb = new StringBuilder();
+        CharSequence title = getTitle();
+        if (!TextUtils.isEmpty(title)) {
+            sb.append(title).append(' ');
+        }
+        CharSequence summary = getSummary();
+        if (!TextUtils.isEmpty(summary)) {
+            sb.append(summary).append(' ');
+        }
+        if (sb.length() > 0) {
+            // Drop the last space
+            sb.setLength(sb.length() - 1);
+        }
+        return sb;
+    }
+
+    /**
+     * Store this Preference hierarchy's frozen state into the given container.
+     *
+     * @param container The Bundle in which to save the instance of this Preference.
+     *
+     * @see #restoreHierarchyState
+     * @see #onSaveInstanceState
+     */
+    public void saveHierarchyState(Bundle container) {
+        dispatchSaveInstanceState(container);
+    }
+
+    /**
+     * Called by {@link #saveHierarchyState} to store the instance for this Preference and its children.
+     * May be overridden to modify how the save happens for children. For example, some
+     * Preference objects may want to not store an instance for their children.
+     *
+     * @param container The Bundle in which to save the instance of this Preference.
+     *
+     * @see #saveHierarchyState
+     * @see #onSaveInstanceState
+     */
+    void dispatchSaveInstanceState(Bundle container) {
+        if (hasKey()) {
+            mBaseMethodCalled = false;
+            Parcelable state = onSaveInstanceState();
+            if (!mBaseMethodCalled) {
+                throw new IllegalStateException(
+                        "Derived class did not call super.onSaveInstanceState()");
+            }
+            if (state != null) {
+                container.putParcelable(mKey, state);
+            }
+        }
+    }
+
+    /**
+     * Hook allowing a Preference to generate a representation of its internal
+     * state that can later be used to create a new instance with that same
+     * state. This state should only contain information that is not persistent
+     * or can be reconstructed later.
+     *
+     * @return A Parcelable object containing the current dynamic state of
+     *         this Preference, or null if there is nothing interesting to save.
+     *         The default implementation returns null.
+     * @see #onRestoreInstanceState
+     * @see #saveHierarchyState
+     */
+    protected Parcelable onSaveInstanceState() {
+        mBaseMethodCalled = true;
+        return BaseSavedState.EMPTY_STATE;
+    }
+
+    /**
+     * Restore this Preference hierarchy's previously saved state from the given container.
+     *
+     * @param container The Bundle that holds the previously saved state.
+     *
+     * @see #saveHierarchyState
+     * @see #onRestoreInstanceState
+     */
+    public void restoreHierarchyState(Bundle container) {
+        dispatchRestoreInstanceState(container);
+    }
+
+    /**
+     * Called by {@link #restoreHierarchyState} to retrieve the saved state for this
+     * Preference and its children. May be overridden to modify how restoring
+     * happens to the children of a Preference. For example, some Preference objects may
+     * not want to save state for their children.
+     *
+     * @param container The Bundle that holds the previously saved state.
+     * @see #restoreHierarchyState
+     * @see #onRestoreInstanceState
+     */
+    void dispatchRestoreInstanceState(Bundle container) {
+        if (hasKey()) {
+            Parcelable state = container.getParcelable(mKey);
+            if (state != null) {
+                mBaseMethodCalled = false;
+                onRestoreInstanceState(state);
+                if (!mBaseMethodCalled) {
+                    throw new IllegalStateException(
+                            "Derived class did not call super.onRestoreInstanceState()");
+                }
+            }
+        }
+    }
+
+    /**
+     * Hook allowing a Preference to re-apply a representation of its internal
+     * state that had previously been generated by {@link #onSaveInstanceState}.
+     * This function will never be called with a null state.
+     *
+     * @param state The saved state that had previously been returned by
+     *            {@link #onSaveInstanceState}.
+     * @see #onSaveInstanceState
+     * @see #restoreHierarchyState
+     */
+    protected void onRestoreInstanceState(Parcelable state) {
+        mBaseMethodCalled = true;
+        if (state != BaseSavedState.EMPTY_STATE && state != null) {
+            throw new IllegalArgumentException("Wrong state class -- expecting Preference State");
+        }
+    }
+
+    /**
+     * A base class for managing the instance state of a {@link Preference}.
+     */
+    public static class BaseSavedState extends AbsSavedState {
+        public BaseSavedState(Parcel source) {
+            super(source);
+        }
+
+        public BaseSavedState(Parcelable superState) {
+            super(superState);
+        }
+
+        public static final Parcelable.Creator<BaseSavedState> CREATOR =
+                new Parcelable.Creator<BaseSavedState>() {
+                    public BaseSavedState createFromParcel(Parcel in) {
+                        return new BaseSavedState(in);
+                    }
+
+                    public BaseSavedState[] newArray(int size) {
+                        return new BaseSavedState[size];
+                    }
+                };
+    }
+
+}
diff --git a/v7/preference/src/android/support/v7/preference/PreferenceCategory.java b/v7/preference/src/android/support/v7/preference/PreferenceCategory.java
new file mode 100644
index 0000000..bed7f7e
--- /dev/null
+++ b/v7/preference/src/android/support/v7/preference/PreferenceCategory.java
@@ -0,0 +1,72 @@
+/*
+ * 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.v7.preference;
+
+import android.content.Context;
+import android.util.AttributeSet;
+
+/**
+ * Used to group {@link android.preference.Preference} objects
+ * and provide a disabled title above the group.
+ *
+ * <div class="special reference">
+ * <h3>Developer Guides</h3>
+ * <p>For information about building a settings UI with Preferences,
+ * read the <a href="{@docRoot}guide/topics/ui/settings.html">Settings</a>
+ * guide.</p>
+ * </div>
+ */
+public class PreferenceCategory extends PreferenceGroup {
+    private static final String TAG = "PreferenceCategory";
+
+    public PreferenceCategory(
+            Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+    }
+
+    public PreferenceCategory(Context context, AttributeSet attrs, int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0);
+    }
+
+    public PreferenceCategory(Context context, AttributeSet attrs) {
+        this(context, attrs, R.attr.preferenceCategoryStyle);
+    }
+
+    public PreferenceCategory(Context context) {
+        this(context, null);
+    }
+
+    @Override
+    protected boolean onPrepareAddPreference(Preference preference) {
+        if (preference instanceof PreferenceCategory) {
+            throw new IllegalArgumentException(
+                    "Cannot add a " + TAG + " directly to a " + TAG);
+        }
+
+        return super.onPrepareAddPreference(preference);
+    }
+
+    @Override
+    public boolean isEnabled() {
+        return false;
+    }
+
+    @Override
+    public boolean shouldDisableDependents() {
+        return !super.isEnabled();
+    }
+}
diff --git a/v7/preference/src/android/support/v7/preference/PreferenceDialogFragmentCompat.java b/v7/preference/src/android/support/v7/preference/PreferenceDialogFragmentCompat.java
new file mode 100644
index 0000000..f96d2ce
--- /dev/null
+++ b/v7/preference/src/android/support/v7/preference/PreferenceDialogFragmentCompat.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.v7.preference;
+
+import android.app.Dialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.v4.app.DialogFragment;
+import android.support.v4.app.Fragment;
+import android.support.v7.app.AlertDialog;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.TextView;
+
+public abstract class PreferenceDialogFragmentCompat extends DialogFragment implements
+        DialogInterface.OnClickListener {
+
+    protected static final String ARG_KEY = "key";
+
+    private DialogPreference mPreference;
+
+    /** Which button was clicked. */
+    private int mWhichButtonClicked;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        final Fragment rawFragment = getTargetFragment();
+        if (!(rawFragment instanceof DialogPreference.TargetFragment)) {
+            throw new IllegalStateException("Target fragment must implement TargetFragment" +
+                    " interface");
+        }
+
+        final DialogPreference.TargetFragment fragment =
+                (DialogPreference.TargetFragment) rawFragment;
+
+        final String key = getArguments().getString(ARG_KEY);
+        mPreference = (DialogPreference) fragment.findPreference(key);
+    }
+
+    @Override
+    public @NonNull Dialog onCreateDialog(Bundle savedInstanceState) {
+        final Context context = getActivity();
+        mWhichButtonClicked = DialogInterface.BUTTON_NEGATIVE;
+
+        final AlertDialog.Builder builder = new AlertDialog.Builder(context)
+                .setTitle(mPreference.getDialogTitle())
+                .setIcon(mPreference.getDialogIcon())
+                .setPositiveButton(mPreference.getPositiveButtonText(), this)
+                .setNegativeButton(mPreference.getNegativeButtonText(), this);
+
+        View contentView = onCreateDialogView(context);
+        if (contentView != null) {
+            onBindDialogView(contentView);
+            builder.setView(contentView);
+        } else {
+            builder.setMessage(mPreference.getDialogMessage());
+        }
+
+        onPrepareDialogBuilder(builder);
+
+        // Create the dialog
+        final Dialog dialog = builder.create();
+        if (needInputMethod()) {
+            requestInputMethod(dialog);
+        }
+
+
+        return builder.create();
+    }
+
+    /**
+     * Get the preference that requested this dialog. Available after {@link #onCreate(Bundle)} has
+     * been called.
+     *
+     * @return The {@link DialogPreference} associated with this
+     * dialog.
+     */
+    public DialogPreference getPreference() {
+        return mPreference;
+    }
+
+    /**
+     * Prepares the dialog builder to be shown when the preference is clicked.
+     * Use this to set custom properties on the dialog.
+     * <p>
+     * Do not {@link AlertDialog.Builder#create()} or
+     * {@link AlertDialog.Builder#show()}.
+     */
+    protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {}
+
+    /**
+     * Returns whether the preference needs to display a soft input method when the dialog
+     * is displayed. Default is false. Subclasses should override this method if they need
+     * the soft input method brought up automatically.
+     * @hide
+     */
+    protected boolean needInputMethod() {
+        return false;
+    }
+
+    /**
+     * Sets the required flags on the dialog window to enable input method window to show up.
+     */
+    private void requestInputMethod(Dialog dialog) {
+        Window window = dialog.getWindow();
+        window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
+    }
+
+    /**
+     * Creates the content view for the dialog (if a custom content view is
+     * required). By default, it inflates the dialog layout resource if it is
+     * set.
+     *
+     * @return The content View for the dialog.
+     * @see DialogPreference#setLayoutResource(int)
+     */
+    protected View onCreateDialogView(Context context) {
+        final int resId = mPreference.getDialogLayoutResource();
+        if (resId == 0) {
+            return null;
+        }
+
+        LayoutInflater inflater = LayoutInflater.from(context);
+        return inflater.inflate(resId, null);
+    }
+
+    /**
+     * Binds views in the content View of the dialog to data.
+     * <p>
+     * Make sure to call through to the superclass implementation.
+     *
+     * @param view The content View of the dialog, if it is custom.
+     */
+    protected void onBindDialogView(View view) {
+        View dialogMessageView = view.findViewById(android.R.id.message);
+
+        if (dialogMessageView != null) {
+            final CharSequence message = mPreference.getDialogMessage();
+            int newVisibility = View.GONE;
+
+            if (!TextUtils.isEmpty(message)) {
+                if (dialogMessageView instanceof TextView) {
+                    ((TextView) dialogMessageView).setText(message);
+                }
+
+                newVisibility = View.VISIBLE;
+            }
+
+            if (dialogMessageView.getVisibility() != newVisibility) {
+                dialogMessageView.setVisibility(newVisibility);
+            }
+        }
+    }
+
+    @Override
+    public void onClick(DialogInterface dialog, int which) {
+        mWhichButtonClicked = which;
+    }
+
+    @Override
+    public void onDismiss(DialogInterface dialog) {
+        super.onDismiss(dialog);
+        onDialogClosed(mWhichButtonClicked == DialogInterface.BUTTON_POSITIVE);
+    }
+
+    public abstract void onDialogClosed(boolean positiveResult);
+}
diff --git a/v7/preference/src/android/support/v7/preference/PreferenceFragmentCompat.java b/v7/preference/src/android/support/v7/preference/PreferenceFragmentCompat.java
new file mode 100644
index 0000000..adff8e8
--- /dev/null
+++ b/v7/preference/src/android/support/v7/preference/PreferenceFragmentCompat.java
@@ -0,0 +1,568 @@
+/*
+ * 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.v7.preference;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.support.annotation.Nullable;
+import android.support.annotation.XmlRes;
+import android.support.v4.app.DialogFragment;
+import android.support.v4.app.Fragment;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.util.TypedValue;
+import android.view.ContextThemeWrapper;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+/**
+ * Shows a hierarchy of {@link Preference} objects as
+ * lists. These preferences will
+ * automatically save to {@link android.content.SharedPreferences} as the user interacts with
+ * them. To retrieve an instance of {@link android.content.SharedPreferences} that the
+ * preference hierarchy in this fragment will use, call
+ * {@link PreferenceManager#getDefaultSharedPreferences(android.content.Context)}
+ * with a context in the same package as this fragment.
+ * <p>
+ * Furthermore, the preferences shown will follow the visual style of system
+ * preferences. It is easy to create a hierarchy of preferences (that can be
+ * shown on multiple screens) via XML. For these reasons, it is recommended to
+ * use this fragment (as a superclass) to deal with preferences in applications.
+ * <p>
+ * A {@link PreferenceScreen} object should be at the top of the preference
+ * hierarchy. Furthermore, subsequent {@link PreferenceScreen} in the hierarchy
+ * denote a screen break--that is the preferences contained within subsequent
+ * {@link PreferenceScreen} should be shown on another screen. The preference
+ * framework handles showing these other screens from the preference hierarchy.
+ * <p>
+ * The preference hierarchy can be formed in multiple ways:
+ * <li> From an XML file specifying the hierarchy
+ * <li> From different {@link android.app.Activity Activities} that each specify its own
+ * preferences in an XML file via {@link android.app.Activity} meta-data
+ * <li> From an object hierarchy rooted with {@link PreferenceScreen}
+ * <p>
+ * To inflate from XML, use the {@link #addPreferencesFromResource(int)}. The
+ * root element should be a {@link PreferenceScreen}. Subsequent elements can point
+ * to actual {@link Preference} subclasses. As mentioned above, subsequent
+ * {@link PreferenceScreen} in the hierarchy will result in the screen break.
+ * <p>
+ * To specify an object hierarchy rooted with {@link PreferenceScreen}, use
+ * {@link #setPreferenceScreen(PreferenceScreen)}.
+ * <p>
+ * As a convenience, this fragment implements a click listener for any
+ * preference in the current hierarchy, see
+ * {@link #onPreferenceTreeClick(Preference)}.
+ *
+ * <div class="special reference">
+ * <h3>Developer Guides</h3>
+ * <p>For information about using {@code PreferenceFragment},
+ * read the <a href="{@docRoot}guide/topics/ui/settings.html">Settings</a>
+ * guide.</p>
+ * </div>
+ *
+ * <a name="SampleCode"></a>
+ * <h3>Sample Code</h3>
+ *
+ * <p>The following sample code shows a simple preference fragment that is
+ * populated from a resource.  The resource it loads is:</p>
+ *
+ * {@sample development/samples/ApiDemos/res/xml/preferences.xml preferences}
+ *
+ * <p>The fragment implementation itself simply populates the preferences
+ * when created.  Note that the preferences framework takes care of loading
+ * the current values out of the app preferences and writing them when changed:</p>
+ *
+ * {@sample development/samples/ApiDemos/src/com/example/android/apis/preference/FragmentPreferences.java
+ *      fragment}
+ *
+ * @see Preference
+ * @see PreferenceScreen
+ */
+public abstract class PreferenceFragmentCompat extends Fragment implements
+        PreferenceManager.OnPreferenceTreeClickListener,
+        PreferenceManager.OnDisplayPreferenceDialogListener,
+        PreferenceManager.OnNavigateToScreenListener,
+        DialogPreference.TargetFragment {
+
+    /**
+     * Fragment argument used to specify the tag of the desired root
+     * {@link android.support.v7.preference.PreferenceScreen} object.
+     */
+    public static final String ARG_PREFERENCE_ROOT =
+            "android.support.v7.preference.PreferenceFragmentCompat.PREFERENCE_ROOT";
+
+    private static final String PREFERENCES_TAG = "android:preferences";
+
+    private static final String DIALOG_FRAGMENT_TAG =
+            "android.support.v7.preference.PreferenceFragment.DIALOG";
+
+    private PreferenceManager mPreferenceManager;
+    private RecyclerView mList;
+    private boolean mHavePrefs;
+    private boolean mInitDone;
+
+    private Context mStyledContext;
+
+    private int mLayoutResId = R.layout.preference_list_fragment;
+
+    /**
+     * The starting request code given out to preference framework.
+     */
+    private static final int FIRST_REQUEST_CODE = 100;
+
+    private static final int MSG_BIND_PREFERENCES = 1;
+    private Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+
+                case MSG_BIND_PREFERENCES:
+                    bindPreferences();
+                    break;
+            }
+        }
+    };
+
+    final private Runnable mRequestFocus = new Runnable() {
+        public void run() {
+            mList.focusableViewAvailable(mList);
+        }
+    };
+
+    /**
+     * Interface that PreferenceFragment's containing activity should
+     * implement to be able to process preference items that wish to
+     * switch to a specified fragment.
+     */
+    public interface OnPreferenceStartFragmentCallback {
+        /**
+         * Called when the user has clicked on a Preference that has
+         * a fragment class name associated with it.  The implementation
+         * should instantiate and switch to an instance of the given
+         * fragment.
+         * @param caller The fragment requesting navigation.
+         * @param pref The preference requesting the fragment.
+         * @return true if the fragment creation has been handled
+         */
+        boolean onPreferenceStartFragment(PreferenceFragmentCompat caller, Preference pref);
+    }
+
+    /**
+     * Interface that PreferenceFragment's containing activity should
+     * implement to be able to process preference items that wish to
+     * switch to a new screen of preferences.
+     */
+    public interface OnPreferenceStartScreenCallback {
+        /**
+         * Called when the user has clicked on a PreferenceScreen item in order to navigate to a new
+         * screen of preferences.
+         * @param caller The fragment requesting navigation.
+         * @param pref The preference screen to navigate to.
+         * @return true if the screen navigation has been handled
+         */
+        boolean onPreferenceStartScreen(PreferenceFragmentCompat caller, PreferenceScreen pref);
+    }
+
+    public interface OnPreferenceDisplayDialogCallback {
+
+        /**
+         *
+         * @param caller The fragment containing the preference requesting the dialog.
+         * @param pref The preference requesting the dialog.
+         * @return true if the dialog creation has been handled.
+         */
+        boolean onPreferenceDisplayDialog(PreferenceFragmentCompat caller, Preference pref);
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        final TypedValue tv = new TypedValue();
+        getActivity().getTheme().resolveAttribute(R.attr.preferenceTheme, tv, true);
+        final int theme = tv.resourceId;
+        if (theme <= 0) {
+            throw new IllegalStateException("Must specify preferenceTheme in theme");
+        }
+        mStyledContext = new ContextThemeWrapper(getActivity(), theme);
+
+        mPreferenceManager = new PreferenceManager(mStyledContext);
+        mPreferenceManager.setOnNavigateToScreenListener(this);
+        final Bundle args = getArguments();
+        final String rootKey;
+        if (args != null) {
+            rootKey = getArguments().getString(ARG_PREFERENCE_ROOT);
+        } else {
+            rootKey = null;
+        }
+        onCreatePreferences(savedInstanceState, rootKey);
+    }
+
+    /**
+     * Called during {@link #onCreate(Bundle)} to supply the preferences for this fragment.
+     * Subclasses are expected to call {@link #setPreferenceScreen(PreferenceScreen)} either
+     * directly or via helper methods such as {@link #addPreferencesFromResource(int)}.
+     *
+     * @param savedInstanceState If the fragment is being re-created from
+     *                           a previous saved state, this is the state.
+     * @param rootKey If non-null, this preference fragment should be rooted at the
+     *                {@link android.support.v7.preference.PreferenceScreen} with this key.
+     */
+    public abstract void onCreatePreferences(Bundle savedInstanceState, String rootKey);
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+
+        TypedArray a = mStyledContext.obtainStyledAttributes(null,
+                R.styleable.PreferenceFragmentCompat,
+                R.attr.preferenceFragmentStyle,
+                0);
+
+        mLayoutResId = a.getResourceId(R.styleable.PreferenceFragmentCompat_layout,
+                mLayoutResId);
+
+        a.recycle();
+
+        final View view = inflater.inflate(mLayoutResId, container, false);
+
+        final View rawListContainer = view.findViewById(R.id.list_container);
+        if (!(rawListContainer instanceof ViewGroup)) {
+            throw new RuntimeException("Content has view with id attribute 'R.id.list_container' "
+                    + "that is not a ViewGroup class");
+        }
+
+        final ViewGroup listContainer = (ViewGroup) rawListContainer;
+
+        final RecyclerView listView = onCreateRecyclerView(inflater, listContainer,
+                savedInstanceState);
+        if (listView == null) {
+            throw new RuntimeException("Could not create RecyclerView");
+        }
+
+        mList = listView;
+        listContainer.addView(mList);
+        mHandler.post(mRequestFocus);
+        return view;
+    }
+
+    @Override
+    public void onActivityCreated(Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+
+        if (mHavePrefs) {
+            bindPreferences();
+        }
+
+        mInitDone = true;
+
+        if (savedInstanceState != null) {
+            Bundle container = savedInstanceState.getBundle(PREFERENCES_TAG);
+            if (container != null) {
+                final PreferenceScreen preferenceScreen = getPreferenceScreen();
+                if (preferenceScreen != null) {
+                    preferenceScreen.restoreHierarchyState(container);
+                }
+            }
+        }
+    }
+
+    @Override
+    public void onStart() {
+        super.onStart();
+        mPreferenceManager.setOnPreferenceTreeClickListener(this);
+        mPreferenceManager.setOnDisplayPreferenceDialogListener(this);
+    }
+
+    @Override
+    public void onStop() {
+        super.onStop();
+        mPreferenceManager.setOnPreferenceTreeClickListener(null);
+        mPreferenceManager.setOnDisplayPreferenceDialogListener(null);
+    }
+
+    @Override
+    public void onDestroyView() {
+        mList = null;
+        mHandler.removeCallbacks(mRequestFocus);
+        mHandler.removeMessages(MSG_BIND_PREFERENCES);
+        super.onDestroyView();
+    }
+
+    @Override
+    public void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+
+        final PreferenceScreen preferenceScreen = getPreferenceScreen();
+        if (preferenceScreen != null) {
+            Bundle container = new Bundle();
+            preferenceScreen.saveHierarchyState(container);
+            outState.putBundle(PREFERENCES_TAG, container);
+        }
+    }
+
+    /**
+     * Returns the {@link PreferenceManager} used by this fragment.
+     * @return The {@link PreferenceManager}.
+     */
+    public PreferenceManager getPreferenceManager() {
+        return mPreferenceManager;
+    }
+
+    /**
+     * Sets the root of the preference hierarchy that this fragment is showing.
+     *
+     * @param preferenceScreen The root {@link PreferenceScreen} of the preference hierarchy.
+     */
+    public void setPreferenceScreen(PreferenceScreen preferenceScreen) {
+        if (mPreferenceManager.setPreferences(preferenceScreen) && preferenceScreen != null) {
+            onUnbindPreferences();
+            mHavePrefs = true;
+            if (mInitDone) {
+                postBindPreferences();
+            }
+        }
+    }
+
+    /**
+     * Gets the root of the preference hierarchy that this fragment is showing.
+     *
+     * @return The {@link PreferenceScreen} that is the root of the preference
+     *         hierarchy.
+     */
+    public PreferenceScreen getPreferenceScreen() {
+        return mPreferenceManager.getPreferenceScreen();
+    }
+
+    /**
+     * Inflates the given XML resource and adds the preference hierarchy to the current
+     * preference hierarchy.
+     *
+     * @param preferencesResId The XML resource ID to inflate.
+     */
+    public void addPreferencesFromResource(@XmlRes int preferencesResId) {
+        requirePreferenceManager();
+
+        setPreferenceScreen(mPreferenceManager.inflateFromResource(mStyledContext,
+                preferencesResId, getPreferenceScreen()));
+    }
+
+    /**
+     * Inflates the given XML resource and replaces the current preference hierarchy (if any) with
+     * the preference hierarchy rooted at {@code key}.
+     *
+     * @param preferencesResId The XML resource ID to inflate.
+     * @param key The preference key of the {@link android.support.v7.preference.PreferenceScreen}
+     *            to use as the root of the preference hierarchy, or null to use the root
+     *            {@link android.support.v7.preference.PreferenceScreen}.
+     */
+    public void setPreferencesFromResource(@XmlRes int preferencesResId, @Nullable String key) {
+        requirePreferenceManager();
+
+        final PreferenceScreen xmlRoot = mPreferenceManager.inflateFromResource(mStyledContext,
+                preferencesResId, null);
+
+        final Preference root;
+        if (key != null) {
+            root = xmlRoot.findPreference(key);
+            if (!(root instanceof PreferenceScreen)) {
+                throw new IllegalArgumentException("Preference object with key " + key
+                        + " is not a PreferenceScreen");
+            }
+        } else {
+            root = xmlRoot;
+        }
+
+        setPreferenceScreen((PreferenceScreen) root);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean onPreferenceTreeClick(Preference preference) {
+        if (preference.getFragment() != null) {
+            boolean handled = false;
+            if (getTargetFragment() instanceof OnPreferenceStartFragmentCallback) {
+                handled = ((OnPreferenceStartFragmentCallback) getTargetFragment())
+                        .onPreferenceStartFragment(this, preference);
+            }
+            if (!handled && getActivity() instanceof OnPreferenceStartFragmentCallback){
+                handled = ((OnPreferenceStartFragmentCallback) getActivity())
+                        .onPreferenceStartFragment(this, preference);
+            }
+            return handled;
+        }
+        return false;
+    }
+
+    /**
+     * Called by
+     * {@link android.support.v7.preference.PreferenceScreen#onClick()} in order to navigate to a
+     * new screen of preferences. Calls
+     * {@link PreferenceFragmentCompat.OnPreferenceStartScreenCallback#onPreferenceStartScreen}
+     * if the target fragment or containing activity implements
+     * {@link PreferenceFragmentCompat.OnPreferenceStartScreenCallback}.
+     * @param preferenceScreen The {@link android.support.v7.preference.PreferenceScreen} to
+     *                         navigate to.
+     */
+    @Override
+    public void onNavigateToScreen(PreferenceScreen preferenceScreen) {
+        boolean handled = false;
+        if (getTargetFragment() instanceof OnPreferenceStartScreenCallback) {
+            handled = ((OnPreferenceStartScreenCallback) getTargetFragment())
+                    .onPreferenceStartScreen(this, preferenceScreen);
+        }
+        if (!handled && getActivity() instanceof OnPreferenceStartScreenCallback) {
+            ((OnPreferenceStartScreenCallback) getActivity())
+                    .onPreferenceStartScreen(this, preferenceScreen);
+        }
+    }
+
+    /**
+     * Finds a {@link Preference} based on its key.
+     *
+     * @param key The key of the preference to retrieve.
+     * @return The {@link Preference} with the key, or null.
+     * @see android.support.v7.preference.PreferenceGroup#findPreference(CharSequence)
+     */
+    public Preference findPreference(CharSequence key) {
+        if (mPreferenceManager == null) {
+            return null;
+        }
+        return mPreferenceManager.findPreference(key);
+    }
+
+    private void requirePreferenceManager() {
+        if (mPreferenceManager == null) {
+            throw new RuntimeException("This should be called after super.onCreate.");
+        }
+    }
+
+    private void postBindPreferences() {
+        if (mHandler.hasMessages(MSG_BIND_PREFERENCES)) return;
+        mHandler.obtainMessage(MSG_BIND_PREFERENCES).sendToTarget();
+    }
+
+    private void bindPreferences() {
+        final PreferenceScreen preferenceScreen = getPreferenceScreen();
+        if (preferenceScreen != null) {
+            getListView().setAdapter(onCreateAdapter(preferenceScreen));
+        }
+        onBindPreferences();
+    }
+
+    /** @hide */
+    protected void onBindPreferences() {
+    }
+
+    /** @hide */
+    protected void onUnbindPreferences() {
+    }
+
+    public final RecyclerView getListView() {
+        return mList;
+    }
+
+    /**
+     * Creates the {@link android.support.v7.widget.RecyclerView} used to display the preferences.
+     * Subclasses may override this to return a customized
+     * {@link android.support.v7.widget.RecyclerView}.
+     * @param inflater The LayoutInflater object that can be used to inflate the
+     *                 {@link android.support.v7.widget.RecyclerView}.
+     * @param parent The parent {@link android.view.View} that the RecyclerView will be attached to.
+     *               This method should not add the view itself, but this can be used to generate
+     *               the LayoutParams of the view.
+     * @param savedInstanceState If non-null, this view is being re-constructed from a previous
+     *                           saved state as given here
+     * @return A new RecyclerView object to be placed into the view hierarchy
+     */
+    public RecyclerView onCreateRecyclerView(LayoutInflater inflater, ViewGroup parent,
+            Bundle savedInstanceState) {
+        RecyclerView recyclerView = (RecyclerView) inflater
+                .inflate(R.layout.preference_recyclerview, parent, false);
+
+        recyclerView.setLayoutManager(onCreateLayoutManager());
+
+        return recyclerView;
+    }
+
+    /**
+     * Called from {@link #onCreateRecyclerView} to create the
+     * {@link android.support.v7.widget.RecyclerView.LayoutManager} for the created
+     * {@link android.support.v7.widget.RecyclerView}.
+     * @return A new {@link android.support.v7.widget.RecyclerView.LayoutManager} instance.
+     */
+    public RecyclerView.LayoutManager onCreateLayoutManager() {
+        return new LinearLayoutManager(getActivity());
+    }
+
+    /**
+     * Creates the root adapter.
+     *
+     * @param preferenceScreen Preference screen object to create the adapter for.
+     * @return An adapter that contains the preferences contained in this {@link PreferenceScreen}.
+     */
+    protected RecyclerView.Adapter onCreateAdapter(PreferenceScreen preferenceScreen) {
+        return new PreferenceGroupAdapter(preferenceScreen);
+    }
+
+    /**
+     * Called when a preference in the tree requests to display a dialog. Subclasses should
+     * override this method to display custom dialogs or to handle dialogs for custom preference
+     * classes.
+     *
+     * @param preference The Preference object requesting the dialog.
+     */
+    @Override
+    public void onDisplayPreferenceDialog(Preference preference) {
+
+        boolean handled = false;
+        if (getTargetFragment() instanceof OnPreferenceDisplayDialogCallback) {
+            handled = ((OnPreferenceDisplayDialogCallback) getTargetFragment())
+                    .onPreferenceDisplayDialog(this, preference);
+        }
+        if (!handled && getActivity() instanceof OnPreferenceDisplayDialogCallback) {
+            handled = ((OnPreferenceDisplayDialogCallback) getActivity())
+                    .onPreferenceDisplayDialog(this, preference);
+        }
+
+        if (handled) {
+            return;
+        }
+
+        // check if dialog is already showing
+        if (getFragmentManager().findFragmentByTag(DIALOG_FRAGMENT_TAG) != null) {
+            return;
+        }
+
+        final DialogFragment f;
+        if (preference instanceof EditTextPreference) {
+            f = EditTextPreferenceDialogFragmentCompat.newInstance(preference.getKey());
+        } else if (preference instanceof ListPreference) {
+            f = ListPreferenceDialogFragmentCompat.newInstance(preference.getKey());
+        } else {
+            throw new IllegalArgumentException("Tried to display dialog for unknown " +
+                    "preference type. Did you forget to override onDisplayPreferenceDialog()?");
+        }
+        f.setTargetFragment(this, 0);
+        f.show(getFragmentManager(), DIALOG_FRAGMENT_TAG);
+    }
+
+}
diff --git a/v7/preference/src/android/support/v7/preference/PreferenceGroup.java b/v7/preference/src/android/support/v7/preference/PreferenceGroup.java
new file mode 100644
index 0000000..f1c79dd
--- /dev/null
+++ b/v7/preference/src/android/support/v7/preference/PreferenceGroup.java
@@ -0,0 +1,335 @@
+/*
+ * 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.v7.preference;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.os.Bundle;
+import android.support.v4.content.res.TypedArrayUtils;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * A container for multiple
+ * {@link Preference} objects. It is a base class for  Preference objects that are
+ * parents, such as {@link PreferenceCategory} and {@link PreferenceScreen}.
+ *
+ * <div class="special reference">
+ * <h3>Developer Guides</h3>
+ * <p>For information about building a settings UI with Preferences,
+ * read the <a href="{@docRoot}guide/topics/ui/settings.html">Settings</a>
+ * guide.</p>
+ * </div>
+ *
+ * @attr ref android.R.styleable#PreferenceGroup_orderingFromXml
+ */
+public abstract class PreferenceGroup extends Preference {
+    /**
+     * The container for child {@link Preference}s. This is sorted based on the
+     * ordering, please use {@link #addPreference(Preference)} instead of adding
+     * to this directly.
+     */
+    private List<Preference> mPreferenceList;
+
+    private boolean mOrderingAsAdded = true;
+
+    private int mCurrentPreferenceOrder = 0;
+
+    private boolean mAttachedToActivity = false;
+
+    public PreferenceGroup(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+
+        mPreferenceList = new ArrayList<>();
+
+        final TypedArray a = context.obtainStyledAttributes(
+                attrs, R.styleable.PreferenceGroup, defStyleAttr, defStyleRes);
+
+        mOrderingAsAdded =
+                TypedArrayUtils.getBoolean(a, R.styleable.PreferenceGroup_orderingFromXml,
+                        R.styleable.PreferenceGroup_orderingFromXml, true);
+
+        a.recycle();
+    }
+
+    public PreferenceGroup(Context context, AttributeSet attrs, int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0);
+    }
+
+    public PreferenceGroup(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    /**
+     * Whether to order the {@link Preference} children of this group as they
+     * are added. If this is false, the ordering will follow each Preference
+     * order and default to alphabetic for those without an order.
+     * <p>
+     * If this is called after preferences are added, they will not be
+     * re-ordered in the order they were added, hence call this method early on.
+     *
+     * @param orderingAsAdded Whether to order according to the order added.
+     * @see Preference#setOrder(int)
+     */
+    public void setOrderingAsAdded(boolean orderingAsAdded) {
+        mOrderingAsAdded = orderingAsAdded;
+    }
+
+    /**
+     * Whether this group is ordering preferences in the order they are added.
+     *
+     * @return Whether this group orders based on the order the children are added.
+     * @see #setOrderingAsAdded(boolean)
+     */
+    public boolean isOrderingAsAdded() {
+        return mOrderingAsAdded;
+    }
+
+    /**
+     * Called by the inflater to add an item to this group.
+     */
+    public void addItemFromInflater(Preference preference) {
+        addPreference(preference);
+    }
+
+    /**
+     * Returns the number of children {@link Preference}s.
+     * @return The number of preference children in this group.
+     */
+    public int getPreferenceCount() {
+        return mPreferenceList.size();
+    }
+
+    /**
+     * Returns the {@link Preference} at a particular index.
+     *
+     * @param index The index of the {@link Preference} to retrieve.
+     * @return The {@link Preference}.
+     */
+    public Preference getPreference(int index) {
+        return mPreferenceList.get(index);
+    }
+
+    /**
+     * Adds a {@link Preference} at the correct position based on the
+     * preference's order.
+     *
+     * @param preference The preference to add.
+     * @return Whether the preference is now in this group.
+     */
+    public boolean addPreference(Preference preference) {
+        if (mPreferenceList.contains(preference)) {
+            // Exists
+            return true;
+        }
+
+        if (preference.getOrder() == DEFAULT_ORDER) {
+            if (mOrderingAsAdded) {
+                preference.setOrder(mCurrentPreferenceOrder++);
+            }
+
+            if (preference instanceof PreferenceGroup) {
+                // TODO: fix (method is called tail recursively when inflating,
+                // so we won't end up properly passing this flag down to children
+                ((PreferenceGroup)preference).setOrderingAsAdded(mOrderingAsAdded);
+            }
+        }
+
+        int insertionIndex = Collections.binarySearch(mPreferenceList, preference);
+        if (insertionIndex < 0) {
+            insertionIndex = insertionIndex * -1 - 1;
+        }
+
+        if (!onPrepareAddPreference(preference)) {
+            return false;
+        }
+
+        synchronized(this) {
+            mPreferenceList.add(insertionIndex, preference);
+        }
+
+        preference.onAttachedToHierarchy(getPreferenceManager());
+
+        if (mAttachedToActivity) {
+            preference.onAttached();
+        }
+
+        notifyHierarchyChanged();
+
+        return true;
+    }
+
+    /**
+     * Removes a {@link Preference} from this group.
+     *
+     * @param preference The preference to remove.
+     * @return Whether the preference was found and removed.
+     */
+    public boolean removePreference(Preference preference) {
+        final boolean returnValue = removePreferenceInt(preference);
+        notifyHierarchyChanged();
+        return returnValue;
+    }
+
+    private boolean removePreferenceInt(Preference preference) {
+        synchronized(this) {
+            preference.onPrepareForRemoval();
+            return mPreferenceList.remove(preference);
+        }
+    }
+
+    /**
+     * Removes all {@link Preference Preferences} from this group.
+     */
+    public void removeAll() {
+        synchronized(this) {
+            List<Preference> preferenceList = mPreferenceList;
+            for (int i = preferenceList.size() - 1; i >= 0; i--) {
+                removePreferenceInt(preferenceList.get(0));
+            }
+        }
+        notifyHierarchyChanged();
+    }
+
+    /**
+     * Prepares a {@link Preference} to be added to the group.
+     *
+     * @param preference The preference to add.
+     * @return Whether to allow adding the preference (true), or not (false).
+     */
+    protected boolean onPrepareAddPreference(Preference preference) {
+        preference.onParentChanged(this, shouldDisableDependents());
+        return true;
+    }
+
+    /**
+     * Finds a {@link Preference} based on its key. If two {@link Preference}
+     * share the same key (not recommended), the first to appear will be
+     * returned (to retrieve the other preference with the same key, call this
+     * method on the first preference). If this preference has the key, it will
+     * not be returned.
+     * <p>
+     * This will recursively search for the preference into children that are
+     * also {@link PreferenceGroup PreferenceGroups}.
+     *
+     * @param key The key of the preference to retrieve.
+     * @return The {@link Preference} with the key, or null.
+     */
+    public Preference findPreference(CharSequence key) {
+        if (TextUtils.equals(getKey(), key)) {
+            return this;
+        }
+        final int preferenceCount = getPreferenceCount();
+        for (int i = 0; i < preferenceCount; i++) {
+            final Preference preference = getPreference(i);
+            final String curKey = preference.getKey();
+
+            if (curKey != null && curKey.equals(key)) {
+                return preference;
+            }
+
+            if (preference instanceof PreferenceGroup) {
+                final Preference returnedPreference = ((PreferenceGroup)preference)
+                        .findPreference(key);
+                if (returnedPreference != null) {
+                    return returnedPreference;
+                }
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Whether this preference group should be shown on the same screen as its
+     * contained preferences.
+     *
+     * @return True if the contained preferences should be shown on the same
+     *         screen as this preference.
+     */
+    protected boolean isOnSameScreenAsChildren() {
+        return true;
+    }
+
+    @Override
+    protected void onAttached() {
+        super.onAttached();
+
+        // Mark as attached so if a preference is later added to this group, we
+        // can tell it we are already attached
+        mAttachedToActivity = true;
+
+        // Dispatch to all contained preferences
+        final int preferenceCount = getPreferenceCount();
+        for (int i = 0; i < preferenceCount; i++) {
+            getPreference(i).onAttached();
+        }
+    }
+
+    @Override
+    protected void onPrepareForRemoval() {
+        super.onPrepareForRemoval();
+
+        // We won't be attached to the activity anymore
+        mAttachedToActivity = false;
+    }
+
+    @Override
+    public void notifyDependencyChange(boolean disableDependents) {
+        super.notifyDependencyChange(disableDependents);
+
+        // Child preferences have an implicit dependency on their containing
+        // group. Dispatch dependency change to all contained preferences.
+        final int preferenceCount = getPreferenceCount();
+        for (int i = 0; i < preferenceCount; i++) {
+            getPreference(i).onParentChanged(this, disableDependents);
+        }
+    }
+
+    void sortPreferences() {
+        synchronized (this) {
+            Collections.sort(mPreferenceList);
+        }
+    }
+
+    @Override
+    protected void dispatchSaveInstanceState(Bundle container) {
+        super.dispatchSaveInstanceState(container);
+
+        // Dispatch to all contained preferences
+        final int preferenceCount = getPreferenceCount();
+        for (int i = 0; i < preferenceCount; i++) {
+            getPreference(i).dispatchSaveInstanceState(container);
+        }
+    }
+
+    @Override
+    protected void dispatchRestoreInstanceState(Bundle container) {
+        super.dispatchRestoreInstanceState(container);
+
+        // Dispatch to all contained preferences
+        final int preferenceCount = getPreferenceCount();
+        for (int i = 0; i < preferenceCount; i++) {
+            getPreference(i).dispatchRestoreInstanceState(container);
+        }
+    }
+
+}
diff --git a/v7/preference/src/android/support/v7/preference/PreferenceGroupAdapter.java b/v7/preference/src/android/support/v7/preference/PreferenceGroupAdapter.java
new file mode 100644
index 0000000..5ba0f90
--- /dev/null
+++ b/v7/preference/src/android/support/v7/preference/PreferenceGroupAdapter.java
@@ -0,0 +1,279 @@
+/*
+ * 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.v7.preference;
+
+import android.os.Handler;
+import android.support.v7.widget.RecyclerView;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ListView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * An adapter that connects a RecyclerView to the {@link Preference} objects contained in the
+ * associated {@link PreferenceGroup}.
+ *
+ * @hide
+ */
+public class PreferenceGroupAdapter extends RecyclerView.Adapter<PreferenceViewHolder>
+        implements Preference.OnPreferenceChangeInternalListener {
+
+    private static final String TAG = "PreferenceGroupAdapter";
+
+    /**
+     * The group that we are providing data from.
+     */
+    private PreferenceGroup mPreferenceGroup;
+
+    /**
+     * Maps a position into this adapter -> {@link Preference}. These
+     * {@link Preference}s don't have to be direct children of this
+     * {@link PreferenceGroup}, they can be grand children or younger)
+     */
+    private List<Preference> mPreferenceList;
+
+    /**
+     * Contains a sorted list of all preferences in this adapter regardless of visibility. This is
+     * used to construct {@link #mPreferenceList}
+     */
+    private List<Preference> mPreferenceListInternal;
+
+    /**
+     * List of unique Preference and its subclasses' names and layouts.
+     */
+    private List<PreferenceLayout> mPreferenceLayouts;
+
+
+    private PreferenceLayout mTempPreferenceLayout = new PreferenceLayout();
+
+    private volatile boolean mIsSyncing = false;
+
+    private Handler mHandler = new Handler();
+
+    private Runnable mSyncRunnable = new Runnable() {
+        public void run() {
+            syncMyPreferences();
+        }
+    };
+
+    private static class PreferenceLayout {
+        private int resId;
+        private int widgetResId;
+        private String name;
+
+        @Override
+        public boolean equals(Object o) {
+            if (!(o instanceof PreferenceLayout)) {
+                return false;
+            }
+            final PreferenceLayout other = (PreferenceLayout) o;
+            return resId == other.resId
+                    && widgetResId == other.widgetResId
+                    && TextUtils.equals(name, other.name);
+        }
+
+        @Override
+        public int hashCode() {
+            int result = 17;
+            result = 31 * result + resId;
+            result = 31 * result + widgetResId;
+            result = 31 * result + name.hashCode();
+            return result;
+        }
+    }
+
+    public PreferenceGroupAdapter(PreferenceGroup preferenceGroup) {
+        mPreferenceGroup = preferenceGroup;
+        // If this group gets or loses any children, let us know
+        mPreferenceGroup.setOnPreferenceChangeInternalListener(this);
+
+        mPreferenceList = new ArrayList<>();
+        mPreferenceListInternal = new ArrayList<>();
+        mPreferenceLayouts = new ArrayList<>();
+
+        setHasStableIds(true);
+
+        syncMyPreferences();
+    }
+
+    private void syncMyPreferences() {
+        synchronized(this) {
+            if (mIsSyncing) {
+                return;
+            }
+
+            mIsSyncing = true;
+        }
+
+        List<Preference> newPreferenceList = new ArrayList<>(mPreferenceListInternal.size());
+        flattenPreferenceGroup(newPreferenceList, mPreferenceGroup);
+        mPreferenceListInternal = newPreferenceList;
+
+        mPreferenceList = new ArrayList<>(mPreferenceListInternal.size());
+        // Copy only the visible preferences to the active list
+        for (final Preference preference : mPreferenceListInternal) {
+            if (preference.isVisible()) {
+                mPreferenceList.add(preference);
+            }
+        }
+
+        notifyDataSetChanged();
+
+        synchronized(this) {
+            mIsSyncing = false;
+            notifyAll();
+        }
+    }
+
+    private void flattenPreferenceGroup(List<Preference> preferences, PreferenceGroup group) {
+        group.sortPreferences();
+
+        final int groupSize = group.getPreferenceCount();
+        for (int i = 0; i < groupSize; i++) {
+            final Preference preference = group.getPreference(i);
+
+            preferences.add(preference);
+
+            addPreferenceClassName(preference);
+
+            if (preference instanceof PreferenceGroup) {
+                final PreferenceGroup preferenceAsGroup = (PreferenceGroup) preference;
+                if (preferenceAsGroup.isOnSameScreenAsChildren()) {
+                    flattenPreferenceGroup(preferences, preferenceAsGroup);
+                }
+            }
+
+            preference.setOnPreferenceChangeInternalListener(this);
+        }
+    }
+
+    /**
+     * Creates a string that includes the preference name, layout id and widget layout id.
+     * If a particular preference type uses 2 different resources, they will be treated as
+     * different view types.
+     */
+    private PreferenceLayout createPreferenceLayout(Preference preference, PreferenceLayout in) {
+        PreferenceLayout pl = in != null? in : new PreferenceLayout();
+        pl.name = preference.getClass().getName();
+        pl.resId = preference.getLayoutResource();
+        pl.widgetResId = preference.getWidgetLayoutResource();
+        return pl;
+    }
+
+    private void addPreferenceClassName(Preference preference) {
+        final PreferenceLayout pl = createPreferenceLayout(preference, null);
+        if (!mPreferenceLayouts.contains(pl)) {
+            mPreferenceLayouts.add(pl);
+        }
+    }
+
+    @Override
+    public int getItemCount() {
+        return mPreferenceList.size();
+    }
+
+    public Preference getItem(int position) {
+        if (position < 0 || position >= getItemCount()) return null;
+        return mPreferenceList.get(position);
+    }
+
+    public long getItemId(int position) {
+        if (position < 0 || position >= getItemCount()) return ListView.INVALID_ROW_ID;
+        return this.getItem(position).getId();
+    }
+
+    public void onPreferenceChange(Preference preference) {
+        notifyDataSetChanged();
+    }
+
+    public void onPreferenceHierarchyChange(Preference preference) {
+        mHandler.removeCallbacks(mSyncRunnable);
+        mHandler.post(mSyncRunnable);
+    }
+
+    @Override
+    public void onPreferenceVisibilityChange(Preference preference) {
+        if (preference.isVisible()) {
+            // The preference has become visible, we need to add it in the correct location.
+
+            // Index (inferred) in mPreferenceList of the item preceding the newly visible pref
+            int previousVisibleIndex = -1;
+            for (final Preference pref : mPreferenceListInternal) {
+                if (preference.equals(pref)) {
+                    break;
+                }
+                if (pref.isVisible()) {
+                    previousVisibleIndex++;
+                }
+            }
+            // Insert this preference into the active list just after the previous visible entry
+            mPreferenceList.add(previousVisibleIndex + 1, preference);
+
+            notifyItemInserted(previousVisibleIndex + 1);
+        } else {
+            // The preference has become invisibile. Find it in the list and remove it.
+
+            int removalIndex;
+            final int listSize = mPreferenceList.size();
+            for (removalIndex = 0; removalIndex < listSize; removalIndex++) {
+                if (preference.equals(mPreferenceList.get(removalIndex))) {
+                    break;
+                }
+            }
+            mPreferenceList.remove(removalIndex);
+            notifyItemRemoved(removalIndex);
+        }
+    }
+
+    @Override
+    public int getItemViewType(int position) {
+        final Preference preference = this.getItem(position);
+
+        mTempPreferenceLayout = createPreferenceLayout(preference, mTempPreferenceLayout);
+
+        return mPreferenceLayouts.indexOf(mTempPreferenceLayout);
+    }
+
+    @Override
+    public PreferenceViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+        final PreferenceLayout pl = mPreferenceLayouts.get(viewType);
+        final LayoutInflater inflater = LayoutInflater.from(parent.getContext());
+
+        final ViewGroup view = (ViewGroup) inflater.inflate(pl.resId, parent, false);
+
+        final ViewGroup widgetFrame = (ViewGroup) view.findViewById(R.id.widget_frame);
+        if (widgetFrame != null) {
+            if (pl.widgetResId != 0) {
+                inflater.inflate(pl.widgetResId, widgetFrame);
+            } else {
+                widgetFrame.setVisibility(View.GONE);
+            }
+        }
+
+        return new PreferenceViewHolder(view);
+    }
+
+    @Override
+    public void onBindViewHolder(PreferenceViewHolder holder, int position) {
+        final Preference preference = getItem(position);
+        preference.onBindViewHolder(holder);
+    }
+}
diff --git a/v7/preference/src/android/support/v7/preference/PreferenceInflater.java b/v7/preference/src/android/support/v7/preference/PreferenceInflater.java
new file mode 100644
index 0000000..fa4e29f
--- /dev/null
+++ b/v7/preference/src/android/support/v7/preference/PreferenceInflater.java
@@ -0,0 +1,376 @@
+/*
+ * 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.v7.preference;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.XmlResourceParser;
+import android.os.Build;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.util.AttributeSet;
+import android.util.Xml;
+import android.view.InflateException;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.util.HashMap;
+
+/**
+ * The {@link PreferenceInflater} is used to inflate preference hierarchies from
+ * XML files.
+ */
+class PreferenceInflater {
+    private static final String TAG = "PreferenceInflater";
+
+    private static final Class<?>[] CONSTRUCTOR_SIGNATURE = new Class[] {
+            Context.class, AttributeSet.class};
+
+    private static final HashMap<String, Constructor> CONSTRUCTOR_MAP = new HashMap<>();
+
+    private final Context mContext;
+
+    private final Object[] mConstructorArgs = new Object[2];
+
+    private PreferenceManager mPreferenceManager;
+
+    private String[] mDefaultPackages;
+
+    private static final String INTENT_TAG_NAME = "intent";
+    private static final String EXTRA_TAG_NAME = "extra";
+
+    public PreferenceInflater(Context context, PreferenceManager preferenceManager) {
+        mContext = context;
+        init(preferenceManager);
+    }
+
+    private void init(PreferenceManager preferenceManager) {
+        mPreferenceManager = preferenceManager;
+        if (Build.VERSION.SDK_INT >= 14) {
+            setDefaultPackages(new String[] {"android.support.v14.preference.",
+                    "android.support.v7.preference."});
+        } else {
+            setDefaultPackages(new String[] {"android.support.v7.preference."});
+        }
+    }
+
+    /**
+     * Sets the default package that will be searched for classes to construct
+     * for tag names that have no explicit package.
+     *
+     * @param defaultPackage The default package. This will be prepended to the
+     *            tag name, so it should end with a period.
+     */
+    public void setDefaultPackages(String[] defaultPackage) {
+        mDefaultPackages = defaultPackage;
+    }
+
+    /**
+     * Returns the default package, or null if it is not set.
+     *
+     * @see #setDefaultPackages(String[])
+     * @return The default package.
+     */
+    public String[] getDefaultPackages() {
+        return mDefaultPackages;
+    }
+
+    /**
+     * Return the context we are running in, for access to resources, class
+     * loader, etc.
+     */
+    public Context getContext() {
+        return mContext;
+    }
+
+    /**
+     * Inflate a new item hierarchy from the specified xml resource. Throws
+     * InflaterException if there is an error.
+     *
+     * @param resource ID for an XML resource to load (e.g.,
+     *        <code>R.layout.main_page</code>)
+     * @param root Optional parent of the generated hierarchy.
+     * @return The root of the inflated hierarchy. If root was supplied,
+     *         this is the root item; otherwise it is the root of the inflated
+     *         XML file.
+     */
+    public Preference inflate(int resource, @Nullable PreferenceGroup root) {
+        XmlResourceParser parser = getContext().getResources().getXml(resource);
+        try {
+            return inflate(parser, root);
+        } finally {
+            parser.close();
+        }
+    }
+
+    /**
+     * Inflate a new hierarchy from the specified XML node. Throws
+     * InflaterException if there is an error.
+     * <p>
+     * <em><strong>Important</strong></em>&nbsp;&nbsp;&nbsp;For performance
+     * reasons, inflation relies heavily on pre-processing of XML files
+     * that is done at build time. Therefore, it is not currently possible to
+     * use inflater with an XmlPullParser over a plain XML file at runtime.
+     *
+     * @param parser XML dom node containing the description of the
+     *        hierarchy.
+     * @param root Optional to be the parent of the generated hierarchy (if
+     *        <em>attachToRoot</em> is true), or else simply an object that
+     *        provides a set of values for root of the returned
+     *        hierarchy (if <em>attachToRoot</em> is false.)
+     * @return The root of the inflated hierarchy. If root was supplied,
+     *         this is root; otherwise it is the root of
+     *         the inflated XML file.
+     */
+    public Preference inflate(XmlPullParser parser, @Nullable PreferenceGroup root) {
+        synchronized (mConstructorArgs) {
+            final AttributeSet attrs = Xml.asAttributeSet(parser);
+            mConstructorArgs[0] = mContext;
+            final Preference result;
+
+            try {
+                // Look for the root node.
+                int type;
+                do {
+                    type = parser.next();
+                } while (type != XmlPullParser.START_TAG && type != XmlPullParser.END_DOCUMENT);
+
+                if (type != XmlPullParser.START_TAG) {
+                    throw new InflateException(parser.getPositionDescription()
+                            + ": No start tag found!");
+                }
+
+                // Temp is the root that was found in the xml
+                Preference xmlRoot = createItemFromTag(parser.getName(),
+                        attrs);
+
+                result = onMergeRoots(root, (PreferenceGroup) xmlRoot);
+
+                // Inflate all children under temp
+                rInflate(parser, result, attrs);
+
+            } catch (InflateException e) {
+                throw e;
+            } catch (XmlPullParserException e) {
+                final InflateException ex = new InflateException(e.getMessage());
+                ex.initCause(e);
+                throw ex;
+            } catch (IOException e) {
+                final InflateException ex = new InflateException(
+                        parser.getPositionDescription()
+                                + ": " + e.getMessage());
+                ex.initCause(e);
+                throw ex;
+            }
+
+            return result;
+        }
+    }
+
+    private @NonNull PreferenceGroup onMergeRoots(PreferenceGroup givenRoot,
+            @NonNull PreferenceGroup xmlRoot) {
+        // If we were given a Preferences, use it as the root (ignoring the root
+        // Preferences from the XML file).
+        if (givenRoot == null) {
+            xmlRoot.onAttachedToHierarchy(mPreferenceManager);
+            return xmlRoot;
+        } else {
+            return givenRoot;
+        }
+    }
+
+    /**
+     * Low-level function for instantiating by name. This attempts to
+     * instantiate class of the given <var>name</var> found in this
+     * inflater's ClassLoader.
+     *
+     * <p>
+     * There are two things that can happen in an error case: either the
+     * exception describing the error will be thrown, or a null will be
+     * returned. You must deal with both possibilities -- the former will happen
+     * the first time createItem() is called for a class of a particular name,
+     * the latter every time there-after for that class name.
+     *
+     * @param name The full name of the class to be instantiated.
+     * @param attrs The XML attributes supplied for this instance.
+     *
+     * @return The newly instantied item, or null.
+     */
+    private Preference createItem(@NonNull String name, @Nullable String[] prefixes,
+            AttributeSet attrs)
+            throws ClassNotFoundException, InflateException {
+        Constructor constructor = CONSTRUCTOR_MAP.get(name);
+
+        try {
+            if (constructor == null) {
+                // Class not found in the cache, see if it's real,
+                // and try to add it
+                final ClassLoader classLoader = mContext.getClassLoader();
+                Class<?> clazz = null;
+                if (prefixes == null || prefixes.length == 0) {
+                    clazz = classLoader.loadClass(name);
+                } else {
+                    ClassNotFoundException notFoundException = null;
+                    for (final String prefix : prefixes) {
+                        try {
+                            clazz = classLoader.loadClass(prefix + name);
+                        } catch (final ClassNotFoundException e) {
+                            notFoundException = e;
+                        }
+                    }
+                    if (clazz == null) {
+                        if (notFoundException == null) {
+                            throw new InflateException(attrs
+                                    .getPositionDescription()
+                                    + ": Error inflating class " + name);
+                        } else {
+                            throw notFoundException;
+                        }
+                    }
+                }
+                constructor = clazz.getConstructor(CONSTRUCTOR_SIGNATURE);
+                constructor.setAccessible(true);
+                CONSTRUCTOR_MAP.put(name, constructor);
+            }
+
+            Object[] args = mConstructorArgs;
+            args[1] = attrs;
+            return (Preference) constructor.newInstance(args);
+
+        } catch (ClassNotFoundException e) {
+            // If loadClass fails, we should propagate the exception.
+            throw e;
+        } catch (Exception e) {
+            final InflateException ie = new InflateException(attrs
+                    .getPositionDescription() + ": Error inflating class " + name);
+            ie.initCause(e);
+            throw ie;
+        }
+    }
+
+    /**
+     * This routine is responsible for creating the correct subclass of item
+     * given the xml element name. Override it to handle custom item objects. If
+     * you override this in your subclass be sure to call through to
+     * super.onCreateItem(name) for names you do not recognize.
+     *
+     * @param name The fully qualified class name of the item to be create.
+     * @param attrs An AttributeSet of attributes to apply to the item.
+     * @return The item created.
+     */
+    protected Preference onCreateItem(String name, AttributeSet attrs)
+            throws ClassNotFoundException {
+        return createItem(name, mDefaultPackages, attrs);
+    }
+
+    private Preference createItemFromTag(String name,
+            AttributeSet attrs) {
+        try {
+            final Preference item;
+
+            if (-1 == name.indexOf('.')) {
+                item = onCreateItem(name, attrs);
+            } else {
+                item = createItem(name, null, attrs);
+            }
+
+            return item;
+
+        } catch (InflateException e) {
+            throw e;
+
+        } catch (ClassNotFoundException e) {
+            final InflateException ie = new InflateException(attrs
+                    .getPositionDescription()
+                    + ": Error inflating class (not found)" + name);
+            ie.initCause(e);
+            throw ie;
+
+        } catch (Exception e) {
+            final InflateException ie = new InflateException(attrs
+                    .getPositionDescription()
+                    + ": Error inflating class " + name);
+            ie.initCause(e);
+            throw ie;
+        }
+    }
+
+    /**
+     * Recursive method used to descend down the xml hierarchy and instantiate
+     * items, instantiate their children, and then call onFinishInflate().
+     */
+    private void rInflate(XmlPullParser parser, Preference parent, final AttributeSet attrs)
+            throws XmlPullParserException, IOException {
+        final int depth = parser.getDepth();
+
+        int type;
+        while (((type = parser.next()) != XmlPullParser.END_TAG ||
+                parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
+
+            if (type != XmlPullParser.START_TAG) {
+                continue;
+            }
+
+            final String name = parser.getName();
+
+            if (INTENT_TAG_NAME.equals(name)) {
+                final Intent intent;
+
+                try {
+                    intent = Intent.parseIntent(getContext().getResources(), parser, attrs);
+                } catch (IOException e) {
+                    XmlPullParserException ex = new XmlPullParserException(
+                            "Error parsing preference");
+                    ex.initCause(e);
+                    throw ex;
+                }
+
+                parent.setIntent(intent);
+            } else if (EXTRA_TAG_NAME.equals(name)) {
+                getContext().getResources().parseBundleExtra(EXTRA_TAG_NAME, attrs,
+                        parent.getExtras());
+                try {
+                    skipCurrentTag(parser);
+                } catch (IOException e) {
+                    XmlPullParserException ex = new XmlPullParserException(
+                            "Error parsing preference");
+                    ex.initCause(e);
+                    throw ex;
+                }
+            } else {
+                final Preference item = createItemFromTag(name, attrs);
+                ((PreferenceGroup) parent).addItemFromInflater(item);
+                rInflate(parser, item, attrs);
+            }
+        }
+
+    }
+
+    private static void skipCurrentTag(XmlPullParser parser)
+            throws XmlPullParserException, IOException {
+        int outerDepth = parser.getDepth();
+        int type;
+        do {
+            type = parser.next();
+        } while (type != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth));
+    }
+
+}
diff --git a/v7/preference/src/android/support/v7/preference/PreferenceManager.java b/v7/preference/src/android/support/v7/preference/PreferenceManager.java
new file mode 100644
index 0000000..7e8c5d1
--- /dev/null
+++ b/v7/preference/src/android/support/v7/preference/PreferenceManager.java
@@ -0,0 +1,480 @@
+/*
+ * 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.v7.preference;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.support.v4.content.SharedPreferencesCompat;
+
+/**
+ * Used to help create {@link Preference} hierarchies
+ * from activities or XML.
+ * <p>
+ * In most cases, clients should use
+ * {@link PreferenceFragment#addPreferencesFromResource(int)}, or
+ * {@link PreferenceFragmentCompat#addPreferencesFromResource(int)}.
+ *
+ * @see PreferenceFragment
+ * @see PreferenceFragmentCompat
+ */
+public class PreferenceManager {
+
+    private static final String TAG = "PreferenceManager";
+
+    public static final String KEY_HAS_SET_DEFAULT_VALUES = "_has_set_default_values";
+
+    /**
+     * The context to use. This should always be set.
+     */
+    private Context mContext;
+
+    /**
+     * The counter for unique IDs.
+     */
+    private long mNextId = 0;
+
+    /**
+     * Cached shared preferences.
+     */
+    private SharedPreferences mSharedPreferences;
+
+    /**
+     * If in no-commit mode, the shared editor to give out (which will be
+     * committed when exiting no-commit mode).
+     */
+    private SharedPreferences.Editor mEditor;
+
+    /**
+     * Blocks commits from happening on the shared editor. This is used when
+     * inflating the hierarchy. Do not set this directly, use {@link #setNoCommit(boolean)}
+     */
+    private boolean mNoCommit;
+
+    /**
+     * The SharedPreferences name that will be used for all {@link Preference}s
+     * managed by this instance.
+     */
+    private String mSharedPreferencesName;
+
+    /**
+     * The SharedPreferences mode that will be used for all {@link Preference}s
+     * managed by this instance.
+     */
+    private int mSharedPreferencesMode;
+
+    /**
+     * The {@link PreferenceScreen} at the root of the preference hierarchy.
+     */
+    private PreferenceScreen mPreferenceScreen;
+
+    private OnPreferenceTreeClickListener mOnPreferenceTreeClickListener;
+    private OnDisplayPreferenceDialogListener mOnDisplayPreferenceDialogListener;
+    private OnNavigateToScreenListener mOnNavigateToScreenListener;
+
+    /**
+     * @hide
+     */
+    public PreferenceManager(Context context) {
+        mContext = context;
+
+        setSharedPreferencesName(getDefaultSharedPreferencesName(context));
+    }
+
+    /**
+     * Inflates a preference hierarchy from XML. If a preference hierarchy is
+     * given, the new preference hierarchies will be merged in.
+     *
+     * @param context The context of the resource.
+     * @param resId The resource ID of the XML to inflate.
+     * @param rootPreferences Optional existing hierarchy to merge the new
+     *            hierarchies into.
+     * @return The root hierarchy (if one was not provided, the new hierarchy's
+     *         root).
+     * @hide
+     */
+    public PreferenceScreen inflateFromResource(Context context, int resId,
+            PreferenceScreen rootPreferences) {
+        // Block commits
+        setNoCommit(true);
+
+        final PreferenceInflater inflater = new PreferenceInflater(context, this);
+        rootPreferences = (PreferenceScreen) inflater.inflate(resId, rootPreferences);
+        rootPreferences.onAttachedToHierarchy(this);
+
+        // Unblock commits
+        setNoCommit(false);
+
+        return rootPreferences;
+    }
+
+    public PreferenceScreen createPreferenceScreen(Context context) {
+        final PreferenceScreen preferenceScreen = new PreferenceScreen(context, null);
+        preferenceScreen.onAttachedToHierarchy(this);
+        return preferenceScreen;
+    }
+
+    /**
+     * Called by a preference to get a unique ID in its hierarchy.
+     *
+     * @return A unique ID.
+     */
+    long getNextId() {
+        synchronized (this) {
+            return mNextId++;
+        }
+    }
+
+    /**
+     * Returns the current name of the SharedPreferences file that preferences managed by
+     * this will use.
+     *
+     * @return The name that can be passed to {@link Context#getSharedPreferences(String, int)}.
+     * @see Context#getSharedPreferences(String, int)
+     */
+    public String getSharedPreferencesName() {
+        return mSharedPreferencesName;
+    }
+
+    /**
+     * Sets the name of the SharedPreferences file that preferences managed by this
+     * will use.
+     *
+     * @param sharedPreferencesName The name of the SharedPreferences file.
+     * @see Context#getSharedPreferences(String, int)
+     */
+    public void setSharedPreferencesName(String sharedPreferencesName) {
+        mSharedPreferencesName = sharedPreferencesName;
+        mSharedPreferences = null;
+    }
+
+    /**
+     * Returns the current mode of the SharedPreferences file that preferences managed by
+     * this will use.
+     *
+     * @return The mode that can be passed to {@link Context#getSharedPreferences(String, int)}.
+     * @see Context#getSharedPreferences(String, int)
+     */
+    public int getSharedPreferencesMode() {
+        return mSharedPreferencesMode;
+    }
+
+    /**
+     * Sets the mode of the SharedPreferences file that preferences managed by this
+     * will use.
+     *
+     * @param sharedPreferencesMode The mode of the SharedPreferences file.
+     * @see Context#getSharedPreferences(String, int)
+     */
+    public void setSharedPreferencesMode(int sharedPreferencesMode) {
+        mSharedPreferencesMode = sharedPreferencesMode;
+        mSharedPreferences = null;
+    }
+
+    /**
+     * Gets a SharedPreferences instance that preferences managed by this will
+     * use.
+     *
+     * @return A SharedPreferences instance pointing to the file that contains
+     *         the values of preferences that are managed by this.
+     */
+    public SharedPreferences getSharedPreferences() {
+        if (mSharedPreferences == null) {
+            mSharedPreferences = mContext.getSharedPreferences(mSharedPreferencesName,
+                    mSharedPreferencesMode);
+        }
+
+        return mSharedPreferences;
+    }
+
+    /**
+     * Gets a SharedPreferences instance that points to the default file that is
+     * used by the preference framework in the given context.
+     *
+     * @param context The context of the preferences whose values are wanted.
+     * @return A SharedPreferences instance that can be used to retrieve and
+     *         listen to values of the preferences.
+     */
+    public static SharedPreferences getDefaultSharedPreferences(Context context) {
+        return context.getSharedPreferences(getDefaultSharedPreferencesName(context),
+                getDefaultSharedPreferencesMode());
+    }
+
+    private static String getDefaultSharedPreferencesName(Context context) {
+        return context.getPackageName() + "_preferences";
+    }
+
+    private static int getDefaultSharedPreferencesMode() {
+        return Context.MODE_PRIVATE;
+    }
+
+    /**
+     * Returns the root of the preference hierarchy managed by this class.
+     *
+     * @return The {@link PreferenceScreen} object that is at the root of the hierarchy.
+     */
+    public PreferenceScreen getPreferenceScreen() {
+        return mPreferenceScreen;
+    }
+
+    /**
+     * Sets the root of the preference hierarchy.
+     *
+     * @param preferenceScreen The root {@link PreferenceScreen} of the preference hierarchy.
+     * @return Whether the {@link PreferenceScreen} given is different than the previous.
+     */
+    public boolean setPreferences(PreferenceScreen preferenceScreen) {
+        if (preferenceScreen != mPreferenceScreen) {
+            mPreferenceScreen = preferenceScreen;
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Finds a {@link Preference} based on its key.
+     *
+     * @param key The key of the preference to retrieve.
+     * @return The {@link Preference} with the key, or null.
+     * @see PreferenceGroup#findPreference(CharSequence)
+     */
+    public Preference findPreference(CharSequence key) {
+        if (mPreferenceScreen == null) {
+            return null;
+        }
+
+        return mPreferenceScreen.findPreference(key);
+    }
+
+    /**
+     * Sets the default values from an XML preference file by reading the values defined
+     * by each {@link Preference} item's {@code android:defaultValue} attribute. This should
+     * be called by the application's main activity.
+     * <p>
+     *
+     * @param context The context of the shared preferences.
+     * @param resId The resource ID of the preference XML file.
+     * @param readAgain Whether to re-read the default values.
+     * If false, this method sets the default values only if this
+     * method has never been called in the past (or if the
+     * {@link #KEY_HAS_SET_DEFAULT_VALUES} in the default value shared
+     * preferences file is false). To attempt to set the default values again
+     * bypassing this check, set {@code readAgain} to true.
+     *            <p class="note">
+     *            Note: this will NOT reset preferences back to their default
+     *            values. For that functionality, use
+     *            {@link PreferenceManager#getDefaultSharedPreferences(Context)}
+     *            and clear it followed by a call to this method with this
+     *            parameter set to true.
+     */
+    public static void setDefaultValues(Context context, int resId, boolean readAgain) {
+
+        // Use the default shared preferences name and mode
+        setDefaultValues(context, getDefaultSharedPreferencesName(context),
+                getDefaultSharedPreferencesMode(), resId, readAgain);
+    }
+
+    /**
+     * Similar to {@link #setDefaultValues(Context, int, boolean)} but allows
+     * the client to provide the filename and mode of the shared preferences
+     * file.
+     *
+     * @param context The context of the shared preferences.
+     * @param sharedPreferencesName A custom name for the shared preferences file.
+     * @param sharedPreferencesMode The file creation mode for the shared preferences file, such
+     * as {@link android.content.Context#MODE_PRIVATE} or {@link
+     * android.content.Context#MODE_PRIVATE}
+     * @param resId The resource ID of the preference XML file.
+     * @param readAgain Whether to re-read the default values.
+     * If false, this method will set the default values only if this
+     * method has never been called in the past (or if the
+     * {@link #KEY_HAS_SET_DEFAULT_VALUES} in the default value shared
+     * preferences file is false). To attempt to set the default values again
+     * bypassing this check, set {@code readAgain} to true.
+     *            <p class="note">
+     *            Note: this will NOT reset preferences back to their default
+     *            values. For that functionality, use
+     *            {@link PreferenceManager#getDefaultSharedPreferences(Context)}
+     *            and clear it followed by a call to this method with this
+     *            parameter set to true.
+     *
+     * @see #setDefaultValues(Context, int, boolean)
+     * @see #setSharedPreferencesName(String)
+     * @see #setSharedPreferencesMode(int)
+     */
+    public static void setDefaultValues(Context context, String sharedPreferencesName,
+            int sharedPreferencesMode, int resId, boolean readAgain) {
+        final SharedPreferences defaultValueSp = context.getSharedPreferences(
+                KEY_HAS_SET_DEFAULT_VALUES, Context.MODE_PRIVATE);
+
+        if (readAgain || !defaultValueSp.getBoolean(KEY_HAS_SET_DEFAULT_VALUES, false)) {
+            final PreferenceManager pm = new PreferenceManager(context);
+            pm.setSharedPreferencesName(sharedPreferencesName);
+            pm.setSharedPreferencesMode(sharedPreferencesMode);
+            pm.inflateFromResource(context, resId, null);
+
+            SharedPreferences.Editor editor =
+                    defaultValueSp.edit().putBoolean(KEY_HAS_SET_DEFAULT_VALUES, true);
+
+            SharedPreferencesCompat.EditorCompat.getInstance().apply(editor);
+        }
+    }
+
+    /**
+     * Returns an editor to use when modifying the shared preferences.
+     * <p>
+     * Do NOT commit unless {@link #shouldCommit()} returns true.
+     *
+     * @return An editor to use to write to shared preferences.
+     * @see #shouldCommit()
+     */
+    SharedPreferences.Editor getEditor() {
+
+        if (mNoCommit) {
+            if (mEditor == null) {
+                mEditor = getSharedPreferences().edit();
+            }
+
+            return mEditor;
+        } else {
+            return getSharedPreferences().edit();
+        }
+    }
+
+    /**
+     * Whether it is the client's responsibility to commit on the
+     * {@link #getEditor()}. This will return false in cases where the writes
+     * should be batched, for example when inflating preferences from XML.
+     *
+     * @return Whether the client should commit.
+     */
+    boolean shouldCommit() {
+        return !mNoCommit;
+    }
+
+    private void setNoCommit(boolean noCommit) {
+        if (!noCommit && mEditor != null) {
+            SharedPreferencesCompat.EditorCompat.getInstance().apply(mEditor);
+        }
+        mNoCommit = noCommit;
+    }
+
+    /**
+     * Returns the context.
+     *
+     * @return The context.
+     */
+    Context getContext() {
+        return mContext;
+    }
+
+    public OnDisplayPreferenceDialogListener getOnDisplayPreferenceDialogListener() {
+        return mOnDisplayPreferenceDialogListener;
+    }
+
+    public void setOnDisplayPreferenceDialogListener(
+            OnDisplayPreferenceDialogListener onDisplayPreferenceDialogListener) {
+        mOnDisplayPreferenceDialogListener = onDisplayPreferenceDialogListener;
+    }
+
+    /**
+     * Called when a preference requests that a dialog be shown to complete a user interaction.
+     *
+     * @param preference The preference requesting the dialog.
+     */
+    public void showDialog(Preference preference) {
+        if (mOnDisplayPreferenceDialogListener != null) {
+            mOnDisplayPreferenceDialogListener.onDisplayPreferenceDialog(preference);
+        }
+    }
+
+    /**
+     * Sets the callback to be invoked when a {@link Preference} in the
+     * hierarchy rooted at this {@link PreferenceManager} is clicked.
+     *
+     * @param listener The callback to be invoked.
+     */
+    public void setOnPreferenceTreeClickListener(OnPreferenceTreeClickListener listener) {
+        mOnPreferenceTreeClickListener = listener;
+    }
+
+    public OnPreferenceTreeClickListener getOnPreferenceTreeClickListener() {
+        return mOnPreferenceTreeClickListener;
+    }
+
+    /**
+     * Sets the callback to be invoked when a {@link PreferenceScreen} in the hierarchy rooted at
+     * this {@link PreferenceManager} is clicked.
+     *
+     * @param listener The callback to be invoked.
+     */
+    public void setOnNavigateToScreenListener(OnNavigateToScreenListener listener) {
+        mOnNavigateToScreenListener = listener;
+    }
+
+    /**
+     * Returns the {@link PreferenceManager.OnNavigateToScreenListener}, if one has been set.
+     */
+    public OnNavigateToScreenListener getOnNavigateToScreenListener() {
+        return mOnNavigateToScreenListener;
+    }
+
+    /**
+     * Interface definition for a callback to be invoked when a
+     * {@link Preference} in the hierarchy rooted at this {@link PreferenceScreen} is
+     * clicked.
+     */
+    public interface OnPreferenceTreeClickListener {
+        /**
+         * Called when a preference in the tree rooted at this
+         * {@link PreferenceScreen} has been clicked.
+         *
+         * @param preference The preference that was clicked.
+         * @return Whether the click was handled.
+         */
+        boolean onPreferenceTreeClick(Preference preference);
+    }
+
+    /**
+     * Interface definition for a class that will be called when a
+     * {@link android.support.v7.preference.Preference} requests to display a dialog.
+     */
+    public interface OnDisplayPreferenceDialogListener {
+
+        /**
+         * Called when a preference in the tree requests to display a dialog.
+         *
+         * @param preference The Preference object requesting the dialog.
+         */
+        void onDisplayPreferenceDialog(Preference preference);
+    }
+
+    /**
+     * Interface definition for a class that will be called when a
+     * {@link android.support.v7.preference.PreferenceScreen} requests navigation.
+     */
+    public interface OnNavigateToScreenListener {
+
+        /**
+         * Called when a PreferenceScreen in the tree requests to navigate to its contents.
+         *
+         * @param preferenceScreen The PreferenceScreen requesting navigation.
+         */
+        void onNavigateToScreen(PreferenceScreen preferenceScreen);
+    }
+
+}
diff --git a/v7/preference/src/android/support/v7/preference/PreferenceScreen.java b/v7/preference/src/android/support/v7/preference/PreferenceScreen.java
new file mode 100644
index 0000000..2010080
--- /dev/null
+++ b/v7/preference/src/android/support/v7/preference/PreferenceScreen.java
@@ -0,0 +1,101 @@
+/*
+ * 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.v7.preference;
+
+import android.content.Context;
+import android.util.AttributeSet;
+
+/**
+ * Represents a top-level {@link Preference} that
+ * is the root of a Preference hierarchy. A {@link PreferenceFragmentCompat}
+ * points to an instance of this class to show the preferences. To instantiate
+ * this class, use {@link PreferenceManager#createPreferenceScreen(android.content.Context)}.
+ * <ul>
+ * This class can appear in two places:
+ * <li> When a {@link PreferenceFragmentCompat} points to this, it is used as the root
+ * and is not shown (only the contained preferences are shown).
+ * <li> When it appears inside another preference hierarchy, it is shown and
+ * serves as the gateway to another screen of preferences (either by showing
+ * another screen of preferences as a {@link android.app.Dialog} or via a
+ * {@link android.content.Context#startActivity(android.content.Intent)} from the
+ * {@link Preference#getIntent()}). The children of this {@link PreferenceScreen}
+ * are NOT shown in the screen that this {@link PreferenceScreen} is shown in.
+ * Instead, a separate screen will be shown when this preference is clicked.
+ * </ul>
+ * <p>Here's an example XML layout of a PreferenceScreen:</p>
+ * <pre>
+ &lt;PreferenceScreen
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:key="first_preferencescreen"&gt;
+ &lt;CheckBoxPreference
+ android:key="wifi enabled"
+ android:title="WiFi" /&gt;
+ &lt;PreferenceScreen
+ android:key="second_preferencescreen"
+ android:title="WiFi settings"&gt;
+ &lt;CheckBoxPreference
+ android:key="prefer wifi"
+ android:title="Prefer WiFi" /&gt;
+ ... other preferences here ...
+ &lt;/PreferenceScreen&gt;
+ &lt;/PreferenceScreen&gt; </pre>
+ * <p>
+ * In this example, the "first_preferencescreen" will be used as the root of the
+ * hierarchy and given to a {@link PreferenceFragment} or {@link PreferenceFragmentCompat}.
+ * The first screen will
+ * show preferences "WiFi" (which can be used to quickly enable/disable WiFi)
+ * and "WiFi settings". The "WiFi settings" is the "second_preferencescreen" and when
+ * clicked will show another screen of preferences such as "Prefer WiFi" (and
+ * the other preferences that are children of the "second_preferencescreen" tag).
+ *
+ * <div class="special reference">
+ * <h3>Developer Guides</h3>
+ * <p>For information about building a settings UI with Preferences,
+ * read the <a href="{@docRoot}guide/topics/ui/settings.html">Settings</a>
+ * guide.</p>
+ * </div>
+ *
+ * @see PreferenceCategory
+ */
+public final class PreferenceScreen extends PreferenceGroup  {
+
+    /**
+     * Do NOT use this constructor, use {@link PreferenceManager#createPreferenceScreen(Context)}.
+     * @hide-
+     */
+    public PreferenceScreen(Context context, AttributeSet attrs) {
+        super(context, attrs, R.attr.preferenceScreenStyle);
+    }
+
+    @Override
+    protected void onClick() {
+        if (getIntent() != null || getFragment() != null || getPreferenceCount() == 0) {
+            return;
+        }
+        final PreferenceManager.OnNavigateToScreenListener listener =
+                getPreferenceManager().getOnNavigateToScreenListener();
+        if (listener != null) {
+            listener.onNavigateToScreen(this);
+        }
+    }
+
+    @Override
+    protected boolean isOnSameScreenAsChildren() {
+        return false;
+    }
+
+}
diff --git a/v7/preference/src/android/support/v7/preference/PreferenceViewHolder.java b/v7/preference/src/android/support/v7/preference/PreferenceViewHolder.java
new file mode 100644
index 0000000..c7e247c
--- /dev/null
+++ b/v7/preference/src/android/support/v7/preference/PreferenceViewHolder.java
@@ -0,0 +1,61 @@
+/*
+ * 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.v7.preference;
+
+import android.support.annotation.IdRes;
+import android.support.v7.widget.RecyclerView;
+import android.util.SparseArray;
+import android.view.View;
+
+/**
+ * A {@link android.support.v7.widget.RecyclerView.ViewHolder} class which caches views associated
+ * with the default {@link Preference} layouts. Cached views can be retrieved by calling
+ * {@link #findViewById(int)}.
+ */
+public class PreferenceViewHolder extends RecyclerView.ViewHolder {
+    private final SparseArray<View> mCachedViews = new SparseArray<>(4);
+
+    /* package */ PreferenceViewHolder(View itemView) {
+        super(itemView);
+
+        // Pre-cache the views that we know in advance we'll want to find
+        mCachedViews.put(android.R.id.title, itemView.findViewById(android.R.id.title));
+        mCachedViews.put(android.R.id.summary, itemView.findViewById(android.R.id.summary));
+        mCachedViews.put(android.R.id.icon, itemView.findViewById(android.R.id.icon));
+        mCachedViews.put(R.id.icon_frame, itemView.findViewById(R.id.icon_frame));
+    }
+
+    /**
+     * Returns a cached reference to a subview managed by this object. If the view reference is not
+     * yet cached, it falls back to calling {@link View#findViewById(int)} and caches the result.
+     *
+     * @param id Resource ID of the view to find
+     * @return The view, or null if no view with the requested ID is found.
+     */
+    public View findViewById(@IdRes int id) {
+        final View cachedView = mCachedViews.get(id);
+        if (cachedView != null) {
+            return cachedView;
+        } else {
+            final View v = itemView.findViewById(id);
+            if (v != null) {
+                mCachedViews.put(id, v);
+            }
+            return v;
+        }
+    }
+}
diff --git a/v7/preference/src/android/support/v7/preference/SwitchPreferenceCompat.java b/v7/preference/src/android/support/v7/preference/SwitchPreferenceCompat.java
new file mode 100644
index 0000000..2e0e38b
--- /dev/null
+++ b/v7/preference/src/android/support/v7/preference/SwitchPreferenceCompat.java
@@ -0,0 +1,212 @@
+/*
+* 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.v7.preference;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.support.v4.content.res.TypedArrayUtils;
+import android.support.v7.widget.SwitchCompat;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.Checkable;
+import android.widget.CompoundButton;
+
+/**
+* A {@link Preference} that provides a two-state toggleable option.
+* <p>
+* This preference will store a boolean into the SharedPreferences.
+*
+* @attr ref android.R.styleable#SwitchPreference_summaryOff
+* @attr ref android.R.styleable#SwitchPreference_summaryOn
+* @attr ref android.R.styleable#SwitchPreference_switchTextOff
+* @attr ref android.R.styleable#SwitchPreference_switchTextOn
+* @attr ref android.R.styleable#SwitchPreference_disableDependentsState
+*/
+public class SwitchPreferenceCompat extends TwoStatePreference {
+    private final Listener mListener = new Listener();
+
+    // Switch text for on and off states
+    private CharSequence mSwitchOn;
+    private CharSequence mSwitchOff;
+
+    private class Listener implements CompoundButton.OnCheckedChangeListener {
+        @Override
+        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+            if (!callChangeListener(isChecked)) {
+                // Listener didn't like it, change it back.
+                // CompoundButton will make sure we don't recurse.
+                buttonView.setChecked(!isChecked);
+                return;
+            }
+
+            SwitchPreferenceCompat.this.setChecked(isChecked);
+        }
+    }
+
+    /**
+     * Construct a new SwitchPreference with the given style options.
+     *
+     * @param context The Context that will style this preference
+     * @param attrs Style attributes that differ from the default
+     * @param defStyleAttr An attribute in the current theme that contains a
+     *        reference to a style resource that supplies default values for
+     *        the view. Can be 0 to not look for defaults.
+     * @param defStyleRes A resource identifier of a style resource that
+     *        supplies default values for the view, used only if
+     *        defStyleAttr is 0 or can not be found in the theme. Can be 0
+     *        to not look for defaults.
+     */
+    public SwitchPreferenceCompat(Context context, AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+
+        TypedArray a = context.obtainStyledAttributes(attrs,
+                R.styleable.SwitchPreferenceCompat, defStyleAttr, defStyleRes);
+
+        setSummaryOn(TypedArrayUtils.getString(a, R.styleable.SwitchPreferenceCompat_summaryOn,
+                R.styleable.SwitchPreferenceCompat_android_summaryOn));
+
+        setSummaryOff(TypedArrayUtils.getString(a, R.styleable.SwitchPreferenceCompat_summaryOff,
+                R.styleable.SwitchPreferenceCompat_android_summaryOff));
+
+        setSwitchTextOn(TypedArrayUtils.getString(a,
+                R.styleable.SwitchPreferenceCompat_switchTextOn,
+                R.styleable.SwitchPreferenceCompat_android_switchTextOn));
+
+        setSwitchTextOff(TypedArrayUtils.getString(a,
+                R.styleable.SwitchPreferenceCompat_switchTextOff,
+                R.styleable.SwitchPreferenceCompat_android_switchTextOff));
+
+        setDisableDependentsState(TypedArrayUtils.getBoolean(a,
+                R.styleable.SwitchPreferenceCompat_disableDependentsState,
+                R.styleable.SwitchPreferenceCompat_android_disableDependentsState, false));
+
+        a.recycle();
+    }
+
+    /**
+     * Construct a new SwitchPreference with the given style options.
+     *
+     * @param context The Context that will style this preference
+     * @param attrs Style attributes that differ from the default
+     * @param defStyleAttr An attribute in the current theme that contains a
+     *        reference to a style resource that supplies default values for
+     *        the view. Can be 0 to not look for defaults.
+     */
+    public SwitchPreferenceCompat(Context context, AttributeSet attrs, int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0);
+    }
+
+    /**
+     * Construct a new SwitchPreference with the given style options.
+     *
+     * @param context The Context that will style this preference
+     * @param attrs Style attributes that differ from the default
+     */
+    public SwitchPreferenceCompat(Context context, AttributeSet attrs) {
+        this(context, attrs, R.attr.switchPreferenceCompatStyle);
+    }
+
+    /**
+     * Construct a new SwitchPreference with default style options.
+     *
+     * @param context The Context that will style this preference
+     */
+    public SwitchPreferenceCompat(Context context) {
+        this(context, null);
+    }
+
+    @Override
+    public void onBindViewHolder(PreferenceViewHolder holder) {
+        super.onBindViewHolder(holder);
+
+        View checkableView = holder.findViewById(R.id.switchWidget);
+        if (checkableView != null && checkableView instanceof Checkable) {
+            if (checkableView instanceof SwitchCompat) {
+                final SwitchCompat switchView = (SwitchCompat) checkableView;
+                switchView.setOnCheckedChangeListener(null);
+            }
+
+            ((Checkable) checkableView).setChecked(mChecked);
+
+            if (checkableView instanceof SwitchCompat) {
+                final SwitchCompat switchView = (SwitchCompat) checkableView;
+                switchView.setTextOn(mSwitchOn);
+                switchView.setTextOff(mSwitchOff);
+                switchView.setOnCheckedChangeListener(mListener);
+            }
+        }
+
+        syncSummaryView(holder);
+    }
+
+    /**
+     * Set the text displayed on the switch widget in the on state.
+     * This should be a very short string; one word if possible.
+     *
+     * @param onText Text to display in the on state
+     */
+    public void setSwitchTextOn(CharSequence onText) {
+        mSwitchOn = onText;
+        notifyChanged();
+    }
+
+    /**
+     * Set the text displayed on the switch widget in the off state.
+     * This should be a very short string; one word if possible.
+     *
+     * @param offText Text to display in the off state
+     */
+    public void setSwitchTextOff(CharSequence offText) {
+        mSwitchOff = offText;
+        notifyChanged();
+    }
+
+    /**
+     * Set the text displayed on the switch widget in the on state.
+     * This should be a very short string; one word if possible.
+     *
+     * @param resId The text as a string resource ID
+     */
+    public void setSwitchTextOn(int resId) {
+        setSwitchTextOn(getContext().getString(resId));
+    }
+
+    /**
+     * Set the text displayed on the switch widget in the off state.
+     * This should be a very short string; one word if possible.
+     *
+     * @param resId The text as a string resource ID
+     */
+    public void setSwitchTextOff(int resId) {
+        setSwitchTextOff(getContext().getString(resId));
+    }
+
+    /**
+     * @return The text that will be displayed on the switch widget in the on state
+     */
+    public CharSequence getSwitchTextOn() {
+        return mSwitchOn;
+    }
+
+    /**
+     * @return The text that will be displayed on the switch widget in the off state
+     */
+    public CharSequence getSwitchTextOff() {
+        return mSwitchOff;
+    }
+}
diff --git a/v7/preference/src/android/support/v7/preference/TwoStatePreference.java b/v7/preference/src/android/support/v7/preference/TwoStatePreference.java
new file mode 100644
index 0000000..e7748cc
--- /dev/null
+++ b/v7/preference/src/android/support/v7/preference/TwoStatePreference.java
@@ -0,0 +1,281 @@
+/*
+ * 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.v7.preference;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.TextView;
+
+/**
+ * Common base class for preferences that have two selectable states, persist a
+ * boolean value in SharedPreferences, and may have dependent preferences that are
+ * enabled/disabled based on the current state.
+ */
+public abstract class TwoStatePreference extends Preference {
+
+    private CharSequence mSummaryOn;
+    private CharSequence mSummaryOff;
+    protected boolean mChecked;
+    private boolean mCheckedSet;
+    private boolean mDisableDependentsState;
+
+    public TwoStatePreference(
+            Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+    }
+
+    public TwoStatePreference(Context context, AttributeSet attrs, int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0);
+    }
+
+    public TwoStatePreference(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public TwoStatePreference(Context context) {
+        this(context, null);
+    }
+
+    @Override
+    protected void onClick() {
+        super.onClick();
+
+        final boolean newValue = !isChecked();
+        if (callChangeListener(newValue)) {
+            setChecked(newValue);
+        }
+    }
+
+    /**
+     * Sets the checked state and saves it to the {@link SharedPreferences}.
+     *
+     * @param checked The checked state.
+     */
+    public void setChecked(boolean checked) {
+        // Always persist/notify the first time; don't assume the field's default of false.
+        final boolean changed = mChecked != checked;
+        if (changed || !mCheckedSet) {
+            mChecked = checked;
+            mCheckedSet = true;
+            persistBoolean(checked);
+            if (changed) {
+                notifyDependencyChange(shouldDisableDependents());
+                notifyChanged();
+            }
+        }
+    }
+
+    /**
+     * Returns the checked state.
+     *
+     * @return The checked state.
+     */
+    public boolean isChecked() {
+        return mChecked;
+    }
+
+    @Override
+    public boolean shouldDisableDependents() {
+        boolean shouldDisable = mDisableDependentsState ? mChecked : !mChecked;
+        return shouldDisable || super.shouldDisableDependents();
+    }
+
+    /**
+     * Sets the summary to be shown when checked.
+     *
+     * @param summary The summary to be shown when checked.
+     */
+    public void setSummaryOn(CharSequence summary) {
+        mSummaryOn = summary;
+        if (isChecked()) {
+            notifyChanged();
+        }
+    }
+
+    /**
+     * @see #setSummaryOn(CharSequence)
+     * @param summaryResId The summary as a resource.
+     */
+    public void setSummaryOn(int summaryResId) {
+        setSummaryOn(getContext().getString(summaryResId));
+    }
+
+    /**
+     * Returns the summary to be shown when checked.
+     * @return The summary.
+     */
+    public CharSequence getSummaryOn() {
+        return mSummaryOn;
+    }
+
+    /**
+     * Sets the summary to be shown when unchecked.
+     *
+     * @param summary The summary to be shown when unchecked.
+     */
+    public void setSummaryOff(CharSequence summary) {
+        mSummaryOff = summary;
+        if (!isChecked()) {
+            notifyChanged();
+        }
+    }
+
+    /**
+     * @see #setSummaryOff(CharSequence)
+     * @param summaryResId The summary as a resource.
+     */
+    public void setSummaryOff(int summaryResId) {
+        setSummaryOff(getContext().getString(summaryResId));
+    }
+
+    /**
+     * Returns the summary to be shown when unchecked.
+     * @return The summary.
+     */
+    public CharSequence getSummaryOff() {
+        return mSummaryOff;
+    }
+
+    /**
+     * Returns whether dependents are disabled when this preference is on ({@code true})
+     * or when this preference is off ({@code false}).
+     *
+     * @return Whether dependents are disabled when this preference is on ({@code true})
+     *         or when this preference is off ({@code false}).
+     */
+    public boolean getDisableDependentsState() {
+        return mDisableDependentsState;
+    }
+
+    /**
+     * Sets whether dependents are disabled when this preference is on ({@code true})
+     * or when this preference is off ({@code false}).
+     *
+     * @param disableDependentsState The preference state that should disable dependents.
+     */
+    public void setDisableDependentsState(boolean disableDependentsState) {
+        mDisableDependentsState = disableDependentsState;
+    }
+
+    @Override
+    protected Object onGetDefaultValue(TypedArray a, int index) {
+        return a.getBoolean(index, false);
+    }
+
+    @Override
+    protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
+        setChecked(restoreValue ? getPersistedBoolean(mChecked)
+                : (Boolean) defaultValue);
+    }
+
+    /**
+     * Sync a summary holder contained within holder's subhierarchy with the correct summary text.
+     * @param holder PreferenceViewHolder which holds a reference to the summary view
+     */
+    protected void syncSummaryView(PreferenceViewHolder holder) {
+        // Sync the summary holder
+        TextView summaryView = (TextView) holder.findViewById(android.R.id.summary);
+        if (summaryView != null) {
+            boolean useDefaultSummary = true;
+            if (mChecked && !TextUtils.isEmpty(mSummaryOn)) {
+                summaryView.setText(mSummaryOn);
+                useDefaultSummary = false;
+            } else if (!mChecked && !TextUtils.isEmpty(mSummaryOff)) {
+                summaryView.setText(mSummaryOff);
+                useDefaultSummary = false;
+            }
+
+            if (useDefaultSummary) {
+                final CharSequence summary = getSummary();
+                if (!TextUtils.isEmpty(summary)) {
+                    summaryView.setText(summary);
+                    useDefaultSummary = false;
+                }
+            }
+
+            int newVisibility = View.GONE;
+            if (!useDefaultSummary) {
+                // Someone has written to it
+                newVisibility = View.VISIBLE;
+            }
+            if (newVisibility != summaryView.getVisibility()) {
+                summaryView.setVisibility(newVisibility);
+            }
+        }
+    }
+
+    @Override
+    protected Parcelable onSaveInstanceState() {
+        final Parcelable superState = super.onSaveInstanceState();
+        if (isPersistent()) {
+            // No need to save instance state since it's persistent
+            return superState;
+        }
+
+        final SavedState myState = new SavedState(superState);
+        myState.checked = isChecked();
+        return myState;
+    }
+
+    @Override
+    protected void onRestoreInstanceState(Parcelable state) {
+        if (state == null || !state.getClass().equals(SavedState.class)) {
+            // Didn't save state for us in onSaveInstanceState
+            super.onRestoreInstanceState(state);
+            return;
+        }
+
+        SavedState myState = (SavedState) state;
+        super.onRestoreInstanceState(myState.getSuperState());
+        setChecked(myState.checked);
+    }
+
+    static class SavedState extends BaseSavedState {
+        boolean checked;
+
+        public SavedState(Parcel source) {
+            super(source);
+            checked = source.readInt() == 1;
+        }
+
+        @Override
+        public void writeToParcel(Parcel dest, int flags) {
+            super.writeToParcel(dest, flags);
+            dest.writeInt(checked ? 1 : 0);
+        }
+
+        public SavedState(Parcelable superState) {
+            super(superState);
+        }
+
+        public static final Parcelable.Creator<SavedState> CREATOR =
+                new Parcelable.Creator<SavedState>() {
+            public SavedState createFromParcel(Parcel in) {
+                return new SavedState(in);
+            }
+
+            public SavedState[] newArray(int size) {
+                return new SavedState[size];
+            }
+        };
+    }
+}
diff --git a/v7/recyclerview/src/android/support/v7/widget/RecyclerView.java b/v7/recyclerview/src/android/support/v7/widget/RecyclerView.java
index d884caf..c56d142 100644
--- a/v7/recyclerview/src/android/support/v7/widget/RecyclerView.java
+++ b/v7/recyclerview/src/android/support/v7/widget/RecyclerView.java
@@ -27,6 +27,7 @@
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.support.annotation.CallSuper;
 import android.support.annotation.Nullable;
 import android.support.v4.os.TraceCompat;
 import android.support.v4.util.ArrayMap;
@@ -5698,6 +5699,7 @@
          *
          * @param view The RecyclerView this LayoutManager is bound to
          */
+        @CallSuper
         public void onAttachedToWindow(RecyclerView view) {
         }
 
@@ -5721,6 +5723,7 @@
          * @param recycler The recycler to use if you prefer to recycle your children instead of
          *                 keeping them around.
          */
+        @CallSuper
         public void onDetachedFromWindow(RecyclerView view, Recycler recycler) {
             onDetachedFromWindow(view);
         }
diff --git a/v7/recyclerview/tests/src/android/support/v7/widget/StaggeredGridLayoutManagerTest.java b/v7/recyclerview/tests/src/android/support/v7/widget/StaggeredGridLayoutManagerTest.java
index 6d7154c..e09fceb 100644
--- a/v7/recyclerview/tests/src/android/support/v7/widget/StaggeredGridLayoutManagerTest.java
+++ b/v7/recyclerview/tests/src/android/support/v7/widget/StaggeredGridLayoutManagerTest.java
@@ -211,20 +211,6 @@
         checkForMainThreadException();
     }
 
-    public void testGrowLookup() throws Throwable {
-        setupByConfig(new Config(VERTICAL, false, 3, GAP_HANDLING_MOVE_ITEMS_BETWEEN_SPANS));
-        waitFirstLayout();
-        mLayoutManager.expectLayouts(1);
-        mAdapter.mItems.clear();
-        mAdapter.dispatchDataSetChanged();
-        mLayoutManager.waitForLayout(2);
-        checkForMainThreadException();
-        mLayoutManager.expectLayouts(2);
-        mAdapter.addAndNotify(0, 30);
-        mLayoutManager.waitForLayout(2);
-        checkForMainThreadException();
-    }
-
     public void testRTL() throws Throwable {
         for (boolean changeRtlAfter : new boolean[]{false, true}) {
             for (Config config : mBaseVariations) {
diff --git a/v8/renderscript/Android.mk b/v8/renderscript/Android.mk
index a7755aa..f6f4471 100644
--- a/v8/renderscript/Android.mk
+++ b/v8/renderscript/Android.mk
@@ -24,11 +24,20 @@
 LOCAL_CFLAGS += -std=c++11
 
 LOCAL_MODULE := android-support-v8-renderscript
-LOCAL_SDK_VERSION := 21
+LOCAL_SDK_VERSION := 22
 LOCAL_SRC_FILES := $(call all-java-files-under, java/src)
 
 include $(BUILD_STATIC_JAVA_LIBRARY)
 
+# API Check
+# ---------------------------------------------
+support_module := $(LOCAL_MODULE)
+support_module_api_dir := $(LOCAL_PATH)/api
+support_module_src_files := $(LOCAL_SRC_FILES)
+support_module_java_libraries := $(LOCAL_MODULE)
+support_module_java_packages := android.support.v8.renderscript
+include $(SUPPORT_API_CHECK)
+
 # TODO: Build the tests as an APK here
 
 include $(call all-makefiles-under, $(LOCAL_PATH))
diff --git a/v8/renderscript/api/current.txt b/v8/renderscript/api/current.txt
new file mode 100644
index 0000000..8827d1b
--- /dev/null
+++ b/v8/renderscript/api/current.txt
@@ -0,0 +1,901 @@
+package android.support.v8.renderscript {
+
+  public class Allocation extends android.support.v8.renderscript.BaseObj {
+    method public void copy1DRangeFrom(int, int, java.lang.Object);
+    method public void copy1DRangeFrom(int, int, int[]);
+    method public void copy1DRangeFrom(int, int, short[]);
+    method public void copy1DRangeFrom(int, int, byte[]);
+    method public void copy1DRangeFrom(int, int, float[]);
+    method public void copy1DRangeFrom(int, int, android.support.v8.renderscript.Allocation, int);
+    method public void copy1DRangeFromUnchecked(int, int, java.lang.Object);
+    method public void copy1DRangeFromUnchecked(int, int, int[]);
+    method public void copy1DRangeFromUnchecked(int, int, short[]);
+    method public void copy1DRangeFromUnchecked(int, int, byte[]);
+    method public void copy1DRangeFromUnchecked(int, int, float[]);
+    method public void copy1DRangeTo(int, int, java.lang.Object);
+    method public void copy1DRangeTo(int, int, int[]);
+    method public void copy1DRangeTo(int, int, short[]);
+    method public void copy1DRangeTo(int, int, byte[]);
+    method public void copy1DRangeTo(int, int, float[]);
+    method public void copy1DRangeToUnchecked(int, int, java.lang.Object);
+    method public void copy1DRangeToUnchecked(int, int, int[]);
+    method public void copy1DRangeToUnchecked(int, int, short[]);
+    method public void copy1DRangeToUnchecked(int, int, byte[]);
+    method public void copy1DRangeToUnchecked(int, int, float[]);
+    method public void copy2DRangeFrom(int, int, int, int, java.lang.Object);
+    method public void copy2DRangeFrom(int, int, int, int, byte[]);
+    method public void copy2DRangeFrom(int, int, int, int, short[]);
+    method public void copy2DRangeFrom(int, int, int, int, int[]);
+    method public void copy2DRangeFrom(int, int, int, int, float[]);
+    method public void copy2DRangeFrom(int, int, int, int, android.support.v8.renderscript.Allocation, int, int);
+    method public void copy2DRangeFrom(int, int, android.graphics.Bitmap);
+    method public void copy2DRangeTo(int, int, int, int, java.lang.Object);
+    method public void copy2DRangeTo(int, int, int, int, byte[]);
+    method public void copy2DRangeTo(int, int, int, int, short[]);
+    method public void copy2DRangeTo(int, int, int, int, int[]);
+    method public void copy2DRangeTo(int, int, int, int, float[]);
+    method public void copy3DRangeFrom(int, int, int, int, int, int, java.lang.Object);
+    method public void copy3DRangeFrom(int, int, int, int, int, int, android.support.v8.renderscript.Allocation, int, int, int);
+    method public void copyFrom(android.support.v8.renderscript.BaseObj[]);
+    method public void copyFrom(java.lang.Object);
+    method public void copyFrom(int[]);
+    method public void copyFrom(short[]);
+    method public void copyFrom(byte[]);
+    method public void copyFrom(float[]);
+    method public void copyFrom(android.graphics.Bitmap);
+    method public void copyFrom(android.support.v8.renderscript.Allocation);
+    method public void copyFromUnchecked(java.lang.Object);
+    method public void copyFromUnchecked(int[]);
+    method public void copyFromUnchecked(short[]);
+    method public void copyFromUnchecked(byte[]);
+    method public void copyFromUnchecked(float[]);
+    method public void copyTo(android.graphics.Bitmap);
+    method public void copyTo(java.lang.Object);
+    method public void copyTo(byte[]);
+    method public void copyTo(short[]);
+    method public void copyTo(int[]);
+    method public void copyTo(float[]);
+    method public static android.support.v8.renderscript.Allocation createCubemapFromBitmap(android.support.v8.renderscript.RenderScript, android.graphics.Bitmap, android.support.v8.renderscript.Allocation.MipmapControl, int);
+    method public static android.support.v8.renderscript.Allocation createCubemapFromBitmap(android.support.v8.renderscript.RenderScript, android.graphics.Bitmap);
+    method public static android.support.v8.renderscript.Allocation createCubemapFromCubeFaces(android.support.v8.renderscript.RenderScript, android.graphics.Bitmap, android.graphics.Bitmap, android.graphics.Bitmap, android.graphics.Bitmap, android.graphics.Bitmap, android.graphics.Bitmap, android.support.v8.renderscript.Allocation.MipmapControl, int);
+    method public static android.support.v8.renderscript.Allocation createCubemapFromCubeFaces(android.support.v8.renderscript.RenderScript, android.graphics.Bitmap, android.graphics.Bitmap, android.graphics.Bitmap, android.graphics.Bitmap, android.graphics.Bitmap, android.graphics.Bitmap);
+    method public static android.support.v8.renderscript.Allocation createFromBitmap(android.support.v8.renderscript.RenderScript, android.graphics.Bitmap, android.support.v8.renderscript.Allocation.MipmapControl, int);
+    method public static android.support.v8.renderscript.Allocation createFromBitmap(android.support.v8.renderscript.RenderScript, android.graphics.Bitmap);
+    method public static android.support.v8.renderscript.Allocation createFromBitmapResource(android.support.v8.renderscript.RenderScript, android.content.res.Resources, int, android.support.v8.renderscript.Allocation.MipmapControl, int);
+    method public static android.support.v8.renderscript.Allocation createFromBitmapResource(android.support.v8.renderscript.RenderScript, android.content.res.Resources, int);
+    method public static android.support.v8.renderscript.Allocation createFromString(android.support.v8.renderscript.RenderScript, java.lang.String, int);
+    method public static android.support.v8.renderscript.Allocation createSized(android.support.v8.renderscript.RenderScript, android.support.v8.renderscript.Element, int, int);
+    method public static android.support.v8.renderscript.Allocation createSized(android.support.v8.renderscript.RenderScript, android.support.v8.renderscript.Element, int);
+    method public static android.support.v8.renderscript.Allocation createTyped(android.support.v8.renderscript.RenderScript, android.support.v8.renderscript.Type, android.support.v8.renderscript.Allocation.MipmapControl, int);
+    method public static android.support.v8.renderscript.Allocation createTyped(android.support.v8.renderscript.RenderScript, android.support.v8.renderscript.Type, int);
+    method public static android.support.v8.renderscript.Allocation createTyped(android.support.v8.renderscript.RenderScript, android.support.v8.renderscript.Type);
+    method public void generateMipmaps();
+    method public int getBytesSize();
+    method public android.support.v8.renderscript.Element getElement();
+    method public long getIncAllocID();
+    method public android.support.v8.renderscript.Type getType();
+    method public int getUsage();
+    method public void ioReceive();
+    method public void ioSend();
+    method public void ioSendOutput();
+    method public void setAutoPadding(boolean);
+    method public void setFromFieldPacker(int, android.support.v8.renderscript.FieldPacker);
+    method public void setFromFieldPacker(int, int, android.support.v8.renderscript.FieldPacker);
+    method public void setIncAllocID(long);
+    method public void setSurface(android.view.Surface);
+    method public void syncAll(int);
+    field public static final int USAGE_GRAPHICS_TEXTURE = 2; // 0x2
+    field public static final int USAGE_IO_INPUT = 32; // 0x20
+    field public static final int USAGE_IO_OUTPUT = 64; // 0x40
+    field public static final int USAGE_SCRIPT = 1; // 0x1
+    field public static final int USAGE_SHARED = 128; // 0x80
+  }
+
+  public static final class Allocation.MipmapControl extends java.lang.Enum {
+    method public static android.support.v8.renderscript.Allocation.MipmapControl valueOf(java.lang.String);
+    method public static final android.support.v8.renderscript.Allocation.MipmapControl[] values();
+    enum_constant public static final android.support.v8.renderscript.Allocation.MipmapControl MIPMAP_FULL;
+    enum_constant public static final android.support.v8.renderscript.Allocation.MipmapControl MIPMAP_NONE;
+    enum_constant public static final android.support.v8.renderscript.Allocation.MipmapControl MIPMAP_ON_SYNC_TO_TEXTURE;
+  }
+
+  public class BaseObj {
+    method public void destroy();
+  }
+
+  public class Byte2 {
+    ctor public Byte2();
+    ctor public Byte2(byte, byte);
+    field public byte x;
+    field public byte y;
+  }
+
+  public class Byte3 {
+    ctor public Byte3();
+    ctor public Byte3(byte, byte, byte);
+    field public byte x;
+    field public byte y;
+    field public byte z;
+  }
+
+  public class Byte4 {
+    ctor public Byte4();
+    ctor public Byte4(byte, byte, byte, byte);
+    field public byte w;
+    field public byte x;
+    field public byte y;
+    field public byte z;
+  }
+
+  public class Double2 {
+    ctor public Double2();
+    ctor public Double2(double, double);
+    field public double x;
+    field public double y;
+  }
+
+  public class Double3 {
+    ctor public Double3();
+    ctor public Double3(double, double, double);
+    field public double x;
+    field public double y;
+    field public double z;
+  }
+
+  public class Double4 {
+    ctor public Double4();
+    ctor public Double4(double, double, double, double);
+    field public double w;
+    field public double x;
+    field public double y;
+    field public double z;
+  }
+
+  public class Element extends android.support.v8.renderscript.BaseObj {
+    method public static android.support.v8.renderscript.Element ALLOCATION(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Element A_8(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Element BOOLEAN(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Element ELEMENT(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Element F32(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Element F32_2(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Element F32_3(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Element F32_4(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Element F64(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Element F64_2(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Element F64_3(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Element F64_4(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Element I16(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Element I16_2(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Element I16_3(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Element I16_4(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Element I32(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Element I32_2(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Element I32_3(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Element I32_4(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Element I64(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Element I64_2(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Element I64_3(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Element I64_4(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Element I8(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Element I8_2(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Element I8_3(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Element I8_4(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Element MATRIX_2X2(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Element MATRIX_3X3(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Element MATRIX_4X4(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Element RGBA_4444(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Element RGBA_5551(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Element RGBA_8888(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Element RGB_565(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Element RGB_888(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Element SAMPLER(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Element SCRIPT(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Element TYPE(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Element U16(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Element U16_2(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Element U16_3(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Element U16_4(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Element U32(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Element U32_2(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Element U32_3(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Element U32_4(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Element U64(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Element U64_2(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Element U64_3(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Element U64_4(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Element U8(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Element U8_2(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Element U8_3(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Element U8_4(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Element createPixel(android.support.v8.renderscript.RenderScript, android.support.v8.renderscript.Element.DataType, android.support.v8.renderscript.Element.DataKind);
+    method public static android.support.v8.renderscript.Element createVector(android.support.v8.renderscript.RenderScript, android.support.v8.renderscript.Element.DataType, int);
+    method public int getBytesSize();
+    method public android.support.v8.renderscript.Element.DataKind getDataKind();
+    method public android.support.v8.renderscript.Element.DataType getDataType();
+    method public long getDummyElement(android.support.v8.renderscript.RenderScript);
+    method public android.support.v8.renderscript.Element getSubElement(int);
+    method public int getSubElementArraySize(int);
+    method public int getSubElementCount();
+    method public java.lang.String getSubElementName(int);
+    method public int getSubElementOffsetBytes(int);
+    method public int getVectorSize();
+    method public boolean isCompatible(android.support.v8.renderscript.Element);
+    method public boolean isComplex();
+  }
+
+  public static class Element.Builder {
+    ctor public Element.Builder(android.support.v8.renderscript.RenderScript);
+    method public android.support.v8.renderscript.Element.Builder add(android.support.v8.renderscript.Element, java.lang.String, int);
+    method public android.support.v8.renderscript.Element.Builder add(android.support.v8.renderscript.Element, java.lang.String);
+    method public android.support.v8.renderscript.Element create();
+  }
+
+  public static final class Element.DataKind extends java.lang.Enum {
+    method public static android.support.v8.renderscript.Element.DataKind valueOf(java.lang.String);
+    method public static final android.support.v8.renderscript.Element.DataKind[] values();
+    enum_constant public static final android.support.v8.renderscript.Element.DataKind PIXEL_A;
+    enum_constant public static final android.support.v8.renderscript.Element.DataKind PIXEL_DEPTH;
+    enum_constant public static final android.support.v8.renderscript.Element.DataKind PIXEL_L;
+    enum_constant public static final android.support.v8.renderscript.Element.DataKind PIXEL_LA;
+    enum_constant public static final android.support.v8.renderscript.Element.DataKind PIXEL_RGB;
+    enum_constant public static final android.support.v8.renderscript.Element.DataKind PIXEL_RGBA;
+    enum_constant public static final android.support.v8.renderscript.Element.DataKind PIXEL_YUV;
+    enum_constant public static final android.support.v8.renderscript.Element.DataKind USER;
+  }
+
+  public static final class Element.DataType extends java.lang.Enum {
+    method public static android.support.v8.renderscript.Element.DataType valueOf(java.lang.String);
+    method public static final android.support.v8.renderscript.Element.DataType[] values();
+    enum_constant public static final android.support.v8.renderscript.Element.DataType BOOLEAN;
+    enum_constant public static final android.support.v8.renderscript.Element.DataType FLOAT_32;
+    enum_constant public static final android.support.v8.renderscript.Element.DataType FLOAT_64;
+    enum_constant public static final android.support.v8.renderscript.Element.DataType MATRIX_2X2;
+    enum_constant public static final android.support.v8.renderscript.Element.DataType MATRIX_3X3;
+    enum_constant public static final android.support.v8.renderscript.Element.DataType MATRIX_4X4;
+    enum_constant public static final android.support.v8.renderscript.Element.DataType NONE;
+    enum_constant public static final android.support.v8.renderscript.Element.DataType RS_ALLOCATION;
+    enum_constant public static final android.support.v8.renderscript.Element.DataType RS_ELEMENT;
+    enum_constant public static final android.support.v8.renderscript.Element.DataType RS_SAMPLER;
+    enum_constant public static final android.support.v8.renderscript.Element.DataType RS_SCRIPT;
+    enum_constant public static final android.support.v8.renderscript.Element.DataType RS_TYPE;
+    enum_constant public static final android.support.v8.renderscript.Element.DataType SIGNED_16;
+    enum_constant public static final android.support.v8.renderscript.Element.DataType SIGNED_32;
+    enum_constant public static final android.support.v8.renderscript.Element.DataType SIGNED_64;
+    enum_constant public static final android.support.v8.renderscript.Element.DataType SIGNED_8;
+    enum_constant public static final android.support.v8.renderscript.Element.DataType UNSIGNED_16;
+    enum_constant public static final android.support.v8.renderscript.Element.DataType UNSIGNED_32;
+    enum_constant public static final android.support.v8.renderscript.Element.DataType UNSIGNED_4_4_4_4;
+    enum_constant public static final android.support.v8.renderscript.Element.DataType UNSIGNED_5_5_5_1;
+    enum_constant public static final android.support.v8.renderscript.Element.DataType UNSIGNED_5_6_5;
+    enum_constant public static final android.support.v8.renderscript.Element.DataType UNSIGNED_64;
+    enum_constant public static final android.support.v8.renderscript.Element.DataType UNSIGNED_8;
+  }
+
+  public class FieldPacker {
+    ctor public FieldPacker(int);
+    ctor public FieldPacker(byte[]);
+    method public void addBoolean(boolean);
+    method public void addF32(float);
+    method public void addF32(android.support.v8.renderscript.Float2);
+    method public void addF32(android.support.v8.renderscript.Float3);
+    method public void addF32(android.support.v8.renderscript.Float4);
+    method public void addF64(double);
+    method public void addF64(android.support.v8.renderscript.Double2);
+    method public void addF64(android.support.v8.renderscript.Double3);
+    method public void addF64(android.support.v8.renderscript.Double4);
+    method public void addI16(short);
+    method public void addI16(android.support.v8.renderscript.Short2);
+    method public void addI16(android.support.v8.renderscript.Short3);
+    method public void addI16(android.support.v8.renderscript.Short4);
+    method public void addI32(int);
+    method public void addI32(android.support.v8.renderscript.Int2);
+    method public void addI32(android.support.v8.renderscript.Int3);
+    method public void addI32(android.support.v8.renderscript.Int4);
+    method public void addI64(long);
+    method public void addI64(android.support.v8.renderscript.Long2);
+    method public void addI64(android.support.v8.renderscript.Long3);
+    method public void addI64(android.support.v8.renderscript.Long4);
+    method public void addI8(byte);
+    method public void addI8(android.support.v8.renderscript.Byte2);
+    method public void addI8(android.support.v8.renderscript.Byte3);
+    method public void addI8(android.support.v8.renderscript.Byte4);
+    method public void addMatrix(android.support.v8.renderscript.Matrix4f);
+    method public void addMatrix(android.support.v8.renderscript.Matrix3f);
+    method public void addMatrix(android.support.v8.renderscript.Matrix2f);
+    method public void addObj(android.support.v8.renderscript.BaseObj);
+    method public void addU16(int);
+    method public void addU16(android.support.v8.renderscript.Int2);
+    method public void addU16(android.support.v8.renderscript.Int3);
+    method public void addU16(android.support.v8.renderscript.Int4);
+    method public void addU32(long);
+    method public void addU32(android.support.v8.renderscript.Long2);
+    method public void addU32(android.support.v8.renderscript.Long3);
+    method public void addU32(android.support.v8.renderscript.Long4);
+    method public void addU64(long);
+    method public void addU64(android.support.v8.renderscript.Long2);
+    method public void addU64(android.support.v8.renderscript.Long3);
+    method public void addU64(android.support.v8.renderscript.Long4);
+    method public void addU8(short);
+    method public void addU8(android.support.v8.renderscript.Short2);
+    method public void addU8(android.support.v8.renderscript.Short3);
+    method public void addU8(android.support.v8.renderscript.Short4);
+    method public void align(int);
+    method public final byte[] getData();
+    method public void reset();
+    method public void reset(int);
+    method public void skip(int);
+    method public boolean subBoolean();
+    method public android.support.v8.renderscript.Byte2 subByte2();
+    method public android.support.v8.renderscript.Byte3 subByte3();
+    method public android.support.v8.renderscript.Byte4 subByte4();
+    method public android.support.v8.renderscript.Double2 subDouble2();
+    method public android.support.v8.renderscript.Double3 subDouble3();
+    method public android.support.v8.renderscript.Double4 subDouble4();
+    method public float subF32();
+    method public double subF64();
+    method public android.support.v8.renderscript.Float2 subFloat2();
+    method public android.support.v8.renderscript.Float3 subFloat3();
+    method public android.support.v8.renderscript.Float4 subFloat4();
+    method public short subI16();
+    method public int subI32();
+    method public long subI64();
+    method public byte subI8();
+    method public android.support.v8.renderscript.Int2 subInt2();
+    method public android.support.v8.renderscript.Int3 subInt3();
+    method public android.support.v8.renderscript.Int4 subInt4();
+    method public android.support.v8.renderscript.Long2 subLong2();
+    method public android.support.v8.renderscript.Long3 subLong3();
+    method public android.support.v8.renderscript.Long4 subLong4();
+    method public android.support.v8.renderscript.Matrix2f subMatrix2f();
+    method public android.support.v8.renderscript.Matrix3f subMatrix3f();
+    method public android.support.v8.renderscript.Matrix4f subMatrix4f();
+    method public android.support.v8.renderscript.Short2 subShort2();
+    method public android.support.v8.renderscript.Short3 subShort3();
+    method public android.support.v8.renderscript.Short4 subShort4();
+    method public void subalign(int);
+  }
+
+  public class Float2 {
+    ctor public Float2();
+    ctor public Float2(float, float);
+    field public float x;
+    field public float y;
+  }
+
+  public class Float3 {
+    ctor public Float3();
+    ctor public Float3(float, float, float);
+    field public float x;
+    field public float y;
+    field public float z;
+  }
+
+  public class Float4 {
+    ctor public Float4();
+    ctor public Float4(float, float, float, float);
+    field public float w;
+    field public float x;
+    field public float y;
+    field public float z;
+  }
+
+  public class Int2 {
+    ctor public Int2();
+    ctor public Int2(int, int);
+    field public int x;
+    field public int y;
+  }
+
+  public class Int3 {
+    ctor public Int3();
+    ctor public Int3(int, int, int);
+    field public int x;
+    field public int y;
+    field public int z;
+  }
+
+  public class Int4 {
+    ctor public Int4();
+    ctor public Int4(int, int, int, int);
+    field public int w;
+    field public int x;
+    field public int y;
+    field public int z;
+  }
+
+  public class Long2 {
+    ctor public Long2();
+    ctor public Long2(long, long);
+    field public long x;
+    field public long y;
+  }
+
+  public class Long3 {
+    ctor public Long3();
+    ctor public Long3(long, long, long);
+    field public long x;
+    field public long y;
+    field public long z;
+  }
+
+  public class Long4 {
+    ctor public Long4();
+    ctor public Long4(long, long, long, long);
+    field public long w;
+    field public long x;
+    field public long y;
+    field public long z;
+  }
+
+  public class Matrix2f {
+    ctor public Matrix2f();
+    ctor public Matrix2f(float[]);
+    method public float get(int, int);
+    method public float[] getArray();
+    method public void load(android.support.v8.renderscript.Matrix2f);
+    method public void loadIdentity();
+    method public void loadMultiply(android.support.v8.renderscript.Matrix2f, android.support.v8.renderscript.Matrix2f);
+    method public void loadRotate(float);
+    method public void loadScale(float, float);
+    method public void multiply(android.support.v8.renderscript.Matrix2f);
+    method public void rotate(float);
+    method public void scale(float, float);
+    method public void set(int, int, float);
+    method public void transpose();
+  }
+
+  public class Matrix3f {
+    ctor public Matrix3f();
+    ctor public Matrix3f(float[]);
+    method public float get(int, int);
+    method public float[] getArray();
+    method public void load(android.support.v8.renderscript.Matrix3f);
+    method public void loadIdentity();
+    method public void loadMultiply(android.support.v8.renderscript.Matrix3f, android.support.v8.renderscript.Matrix3f);
+    method public void loadRotate(float, float, float, float);
+    method public void loadRotate(float);
+    method public void loadScale(float, float);
+    method public void loadScale(float, float, float);
+    method public void loadTranslate(float, float);
+    method public void multiply(android.support.v8.renderscript.Matrix3f);
+    method public void rotate(float, float, float, float);
+    method public void rotate(float);
+    method public void scale(float, float);
+    method public void scale(float, float, float);
+    method public void set(int, int, float);
+    method public void translate(float, float);
+    method public void transpose();
+  }
+
+  public class Matrix4f {
+    ctor public Matrix4f();
+    ctor public Matrix4f(float[]);
+    method public float get(int, int);
+    method public float[] getArray();
+    method public boolean inverse();
+    method public boolean inverseTranspose();
+    method public void load(android.support.v8.renderscript.Matrix4f);
+    method public void loadFrustum(float, float, float, float, float, float);
+    method public void loadIdentity();
+    method public void loadMultiply(android.support.v8.renderscript.Matrix4f, android.support.v8.renderscript.Matrix4f);
+    method public void loadOrtho(float, float, float, float, float, float);
+    method public void loadOrthoWindow(int, int);
+    method public void loadPerspective(float, float, float, float);
+    method public void loadProjectionNormalized(int, int);
+    method public void loadRotate(float, float, float, float);
+    method public void loadScale(float, float, float);
+    method public void loadTranslate(float, float, float);
+    method public void multiply(android.support.v8.renderscript.Matrix4f);
+    method public void rotate(float, float, float, float);
+    method public void scale(float, float, float);
+    method public void set(int, int, float);
+    method public void translate(float, float, float);
+    method public void transpose();
+  }
+
+  public class RSDriverException extends android.support.v8.renderscript.RSRuntimeException {
+    ctor public RSDriverException(java.lang.String);
+  }
+
+  public class RSIllegalArgumentException extends android.support.v8.renderscript.RSRuntimeException {
+    ctor public RSIllegalArgumentException(java.lang.String);
+  }
+
+  public class RSInvalidStateException extends android.support.v8.renderscript.RSRuntimeException {
+    ctor public RSInvalidStateException(java.lang.String);
+  }
+
+  public class RSRuntimeException extends java.lang.RuntimeException {
+    ctor public RSRuntimeException(java.lang.String);
+  }
+
+  public class RenderScript {
+    method public void contextDump();
+    method public static android.support.v8.renderscript.RenderScript create(android.content.Context);
+    method public static android.support.v8.renderscript.RenderScript create(android.content.Context, android.support.v8.renderscript.RenderScript.ContextType);
+    method public static android.support.v8.renderscript.RenderScript create(android.content.Context, android.support.v8.renderscript.RenderScript.ContextType, int);
+    method public static android.support.v8.renderscript.RenderScript create(android.content.Context, int, android.support.v8.renderscript.RenderScript.ContextType, int);
+    method public static android.support.v8.renderscript.RenderScript createMultiContext(android.content.Context, android.support.v8.renderscript.RenderScript.ContextType, int, int);
+    method public void destroy();
+    method public void finish();
+    method public static void forceCompat();
+    method public final android.content.Context getApplicationContext();
+    method public android.support.v8.renderscript.RenderScript.RSErrorHandler getErrorHandler();
+    method public android.support.v8.renderscript.RenderScript.RSMessageHandler getMessageHandler();
+    method public static void releaseAllContexts();
+    method public void sendMessage(int, int[]);
+    method public static void setBlackList(java.lang.String);
+    method public void setErrorHandler(android.support.v8.renderscript.RenderScript.RSErrorHandler);
+    method public void setMessageHandler(android.support.v8.renderscript.RenderScript.RSMessageHandler);
+    method public void setPriority(android.support.v8.renderscript.RenderScript.Priority);
+    field public static final int CREATE_FLAG_NONE = 0; // 0x0
+  }
+
+  public static final class RenderScript.ContextType extends java.lang.Enum {
+    method public static android.support.v8.renderscript.RenderScript.ContextType valueOf(java.lang.String);
+    method public static final android.support.v8.renderscript.RenderScript.ContextType[] values();
+    enum_constant public static final android.support.v8.renderscript.RenderScript.ContextType DEBUG;
+    enum_constant public static final android.support.v8.renderscript.RenderScript.ContextType NORMAL;
+    enum_constant public static final android.support.v8.renderscript.RenderScript.ContextType PROFILE;
+  }
+
+  public static final class RenderScript.Priority extends java.lang.Enum {
+    method public static android.support.v8.renderscript.RenderScript.Priority valueOf(java.lang.String);
+    method public static final android.support.v8.renderscript.RenderScript.Priority[] values();
+    enum_constant public static final android.support.v8.renderscript.RenderScript.Priority LOW;
+    enum_constant public static final android.support.v8.renderscript.RenderScript.Priority NORMAL;
+  }
+
+  public static class RenderScript.RSErrorHandler implements java.lang.Runnable {
+    ctor public RenderScript.RSErrorHandler();
+    method public void run();
+    field protected java.lang.String mErrorMessage;
+    field protected int mErrorNum;
+  }
+
+  public static class RenderScript.RSMessageHandler implements java.lang.Runnable {
+    ctor public RenderScript.RSMessageHandler();
+    method public void run();
+    field protected int[] mData;
+    field protected int mID;
+    field protected int mLength;
+  }
+
+  public class Sampler extends android.support.v8.renderscript.BaseObj {
+    method public static android.support.v8.renderscript.Sampler CLAMP_LINEAR(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Sampler CLAMP_LINEAR_MIP_LINEAR(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Sampler CLAMP_NEAREST(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Sampler MIRRORED_REPEAT_LINEAR(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Sampler MIRRORED_REPEAT_NEAREST(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Sampler WRAP_LINEAR(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Sampler WRAP_LINEAR_MIP_LINEAR(android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.Sampler WRAP_NEAREST(android.support.v8.renderscript.RenderScript);
+    method public float getAnisotropy();
+    method public android.support.v8.renderscript.Sampler.Value getMagnification();
+    method public android.support.v8.renderscript.Sampler.Value getMinification();
+    method public android.support.v8.renderscript.Sampler.Value getWrapS();
+    method public android.support.v8.renderscript.Sampler.Value getWrapT();
+  }
+
+  public static class Sampler.Builder {
+    ctor public Sampler.Builder(android.support.v8.renderscript.RenderScript);
+    method public android.support.v8.renderscript.Sampler create();
+    method public void setAnisotropy(float);
+    method public void setMagnification(android.support.v8.renderscript.Sampler.Value);
+    method public void setMinification(android.support.v8.renderscript.Sampler.Value);
+    method public void setWrapS(android.support.v8.renderscript.Sampler.Value);
+    method public void setWrapT(android.support.v8.renderscript.Sampler.Value);
+  }
+
+  public static final class Sampler.Value extends java.lang.Enum {
+    method public static android.support.v8.renderscript.Sampler.Value valueOf(java.lang.String);
+    method public static final android.support.v8.renderscript.Sampler.Value[] values();
+    enum_constant public static final android.support.v8.renderscript.Sampler.Value CLAMP;
+    enum_constant public static final android.support.v8.renderscript.Sampler.Value LINEAR;
+    enum_constant public static final android.support.v8.renderscript.Sampler.Value LINEAR_MIP_LINEAR;
+    enum_constant public static final android.support.v8.renderscript.Sampler.Value LINEAR_MIP_NEAREST;
+    enum_constant public static final android.support.v8.renderscript.Sampler.Value MIRRORED_REPEAT;
+    enum_constant public static final android.support.v8.renderscript.Sampler.Value NEAREST;
+    enum_constant public static final android.support.v8.renderscript.Sampler.Value WRAP;
+  }
+
+  public class Script extends android.support.v8.renderscript.BaseObj {
+    method public void bindAllocation(android.support.v8.renderscript.Allocation, int);
+    method protected android.support.v8.renderscript.Script.FieldID createFieldID(int, android.support.v8.renderscript.Element);
+    method protected android.support.v8.renderscript.Script.InvokeID createInvokeID(int);
+    method protected android.support.v8.renderscript.Script.KernelID createKernelID(int, int, android.support.v8.renderscript.Element, android.support.v8.renderscript.Element);
+    method protected void forEach(int, android.support.v8.renderscript.Allocation, android.support.v8.renderscript.Allocation, android.support.v8.renderscript.FieldPacker);
+    method protected void forEach(int, android.support.v8.renderscript.Allocation, android.support.v8.renderscript.Allocation, android.support.v8.renderscript.FieldPacker, android.support.v8.renderscript.Script.LaunchOptions);
+    method protected void invoke(int);
+    method protected void invoke(int, android.support.v8.renderscript.FieldPacker);
+    method protected boolean isIncSupp();
+    method protected void setIncSupp(boolean);
+    method public void setTimeZone(java.lang.String);
+    method public void setVar(int, float);
+    method public void setVar(int, double);
+    method public void setVar(int, int);
+    method public void setVar(int, long);
+    method public void setVar(int, boolean);
+    method public void setVar(int, android.support.v8.renderscript.BaseObj);
+    method public void setVar(int, android.support.v8.renderscript.FieldPacker);
+    method public void setVar(int, android.support.v8.renderscript.FieldPacker, android.support.v8.renderscript.Element, int[]);
+  }
+
+  public static class Script.Builder {
+  }
+
+  public static class Script.FieldBase {
+    ctor protected Script.FieldBase();
+    method public android.support.v8.renderscript.Allocation getAllocation();
+    method public android.support.v8.renderscript.Element getElement();
+    method public android.support.v8.renderscript.Type getType();
+    method protected void init(android.support.v8.renderscript.RenderScript, int);
+    method protected void init(android.support.v8.renderscript.RenderScript, int, int);
+    method public void updateAllocation();
+    field protected android.support.v8.renderscript.Allocation mAllocation;
+    field protected android.support.v8.renderscript.Element mElement;
+  }
+
+  public static final class Script.FieldID extends android.support.v8.renderscript.BaseObj {
+  }
+
+  public static final class Script.InvokeID extends android.support.v8.renderscript.BaseObj {
+  }
+
+  public static final class Script.KernelID extends android.support.v8.renderscript.BaseObj {
+  }
+
+  public static final class Script.LaunchOptions {
+    ctor public Script.LaunchOptions();
+    method public int getXEnd();
+    method public int getXStart();
+    method public int getYEnd();
+    method public int getYStart();
+    method public int getZEnd();
+    method public int getZStart();
+    method public android.support.v8.renderscript.Script.LaunchOptions setX(int, int);
+    method public android.support.v8.renderscript.Script.LaunchOptions setY(int, int);
+    method public android.support.v8.renderscript.Script.LaunchOptions setZ(int, int);
+  }
+
+  public class ScriptC extends android.support.v8.renderscript.Script {
+    ctor protected ScriptC(long, android.support.v8.renderscript.RenderScript);
+    ctor protected ScriptC(android.support.v8.renderscript.RenderScript, android.content.res.Resources, int);
+    ctor protected ScriptC(android.support.v8.renderscript.RenderScript, java.lang.String, byte[], byte[]);
+  }
+
+  public final class ScriptGroup extends android.support.v8.renderscript.BaseObj {
+    method public java.lang.Object[] execute(java.lang.Object...);
+    method public deprecated void execute();
+    method public deprecated void setInput(android.support.v8.renderscript.Script.KernelID, android.support.v8.renderscript.Allocation);
+    method public deprecated void setOutput(android.support.v8.renderscript.Script.KernelID, android.support.v8.renderscript.Allocation);
+  }
+
+  public static final class ScriptGroup.Binding {
+    ctor public ScriptGroup.Binding(android.support.v8.renderscript.Script.FieldID, java.lang.Object);
+    method public android.support.v8.renderscript.Script.FieldID getField();
+    method public java.lang.Object getValue();
+  }
+
+  public static final deprecated class ScriptGroup.Builder {
+    ctor public ScriptGroup.Builder(android.support.v8.renderscript.RenderScript);
+    method public android.support.v8.renderscript.ScriptGroup.Builder addConnection(android.support.v8.renderscript.Type, android.support.v8.renderscript.Script.KernelID, android.support.v8.renderscript.Script.FieldID);
+    method public android.support.v8.renderscript.ScriptGroup.Builder addConnection(android.support.v8.renderscript.Type, android.support.v8.renderscript.Script.KernelID, android.support.v8.renderscript.Script.KernelID);
+    method public android.support.v8.renderscript.ScriptGroup.Builder addKernel(android.support.v8.renderscript.Script.KernelID);
+    method public android.support.v8.renderscript.ScriptGroup create();
+  }
+
+  public static final class ScriptGroup.Builder2 {
+    ctor public ScriptGroup.Builder2(android.support.v8.renderscript.RenderScript);
+    method public android.support.v8.renderscript.ScriptGroup.Input addInput();
+    method public android.support.v8.renderscript.ScriptGroup.Closure addInvoke(android.support.v8.renderscript.Script.InvokeID, java.lang.Object...);
+    method public android.support.v8.renderscript.ScriptGroup.Closure addKernel(android.support.v8.renderscript.Script.KernelID, android.support.v8.renderscript.Type, java.lang.Object...);
+    method public android.support.v8.renderscript.ScriptGroup create(java.lang.String, android.support.v8.renderscript.ScriptGroup.Future...);
+  }
+
+  public static final class ScriptGroup.Closure extends android.support.v8.renderscript.BaseObj {
+    method public android.support.v8.renderscript.ScriptGroup.Future getGlobal(android.support.v8.renderscript.Script.FieldID);
+    method public android.support.v8.renderscript.ScriptGroup.Future getReturn();
+  }
+
+  public static final class ScriptGroup.Future {
+  }
+
+  public static final class ScriptGroup.Input {
+  }
+
+  public abstract class ScriptIntrinsic extends android.support.v8.renderscript.Script {
+  }
+
+  public class ScriptIntrinsic3DLUT extends android.support.v8.renderscript.ScriptIntrinsic {
+    ctor protected ScriptIntrinsic3DLUT(long, android.support.v8.renderscript.RenderScript, android.support.v8.renderscript.Element);
+    method public static android.support.v8.renderscript.ScriptIntrinsic3DLUT create(android.support.v8.renderscript.RenderScript, android.support.v8.renderscript.Element);
+    method public void forEach(android.support.v8.renderscript.Allocation, android.support.v8.renderscript.Allocation);
+    method public android.support.v8.renderscript.Script.KernelID getKernelID();
+    method public void setLUT(android.support.v8.renderscript.Allocation);
+  }
+
+  public class ScriptIntrinsicBlend extends android.support.v8.renderscript.ScriptIntrinsic {
+    method public static android.support.v8.renderscript.ScriptIntrinsicBlend create(android.support.v8.renderscript.RenderScript, android.support.v8.renderscript.Element);
+    method public void forEachAdd(android.support.v8.renderscript.Allocation, android.support.v8.renderscript.Allocation);
+    method public void forEachClear(android.support.v8.renderscript.Allocation, android.support.v8.renderscript.Allocation);
+    method public void forEachDst(android.support.v8.renderscript.Allocation, android.support.v8.renderscript.Allocation);
+    method public void forEachDstAtop(android.support.v8.renderscript.Allocation, android.support.v8.renderscript.Allocation);
+    method public void forEachDstIn(android.support.v8.renderscript.Allocation, android.support.v8.renderscript.Allocation);
+    method public void forEachDstOut(android.support.v8.renderscript.Allocation, android.support.v8.renderscript.Allocation);
+    method public void forEachDstOver(android.support.v8.renderscript.Allocation, android.support.v8.renderscript.Allocation);
+    method public void forEachMultiply(android.support.v8.renderscript.Allocation, android.support.v8.renderscript.Allocation);
+    method public void forEachSrc(android.support.v8.renderscript.Allocation, android.support.v8.renderscript.Allocation);
+    method public void forEachSrcAtop(android.support.v8.renderscript.Allocation, android.support.v8.renderscript.Allocation);
+    method public void forEachSrcIn(android.support.v8.renderscript.Allocation, android.support.v8.renderscript.Allocation);
+    method public void forEachSrcOut(android.support.v8.renderscript.Allocation, android.support.v8.renderscript.Allocation);
+    method public void forEachSrcOver(android.support.v8.renderscript.Allocation, android.support.v8.renderscript.Allocation);
+    method public void forEachSubtract(android.support.v8.renderscript.Allocation, android.support.v8.renderscript.Allocation);
+    method public void forEachXor(android.support.v8.renderscript.Allocation, android.support.v8.renderscript.Allocation);
+    method public android.support.v8.renderscript.Script.KernelID getKernelIDAdd();
+    method public android.support.v8.renderscript.Script.KernelID getKernelIDClear();
+    method public android.support.v8.renderscript.Script.KernelID getKernelIDDst();
+    method public android.support.v8.renderscript.Script.KernelID getKernelIDDstAtop();
+    method public android.support.v8.renderscript.Script.KernelID getKernelIDDstIn();
+    method public android.support.v8.renderscript.Script.KernelID getKernelIDDstOut();
+    method public android.support.v8.renderscript.Script.KernelID getKernelIDDstOver();
+    method public android.support.v8.renderscript.Script.KernelID getKernelIDMultiply();
+    method public android.support.v8.renderscript.Script.KernelID getKernelIDSrc();
+    method public android.support.v8.renderscript.Script.KernelID getKernelIDSrcAtop();
+    method public android.support.v8.renderscript.Script.KernelID getKernelIDSrcIn();
+    method public android.support.v8.renderscript.Script.KernelID getKernelIDSrcOut();
+    method public android.support.v8.renderscript.Script.KernelID getKernelIDSrcOver();
+    method public android.support.v8.renderscript.Script.KernelID getKernelIDSubtract();
+    method public android.support.v8.renderscript.Script.KernelID getKernelIDXor();
+  }
+
+  public class ScriptIntrinsicBlur extends android.support.v8.renderscript.ScriptIntrinsic {
+    ctor protected ScriptIntrinsicBlur(long, android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.ScriptIntrinsicBlur create(android.support.v8.renderscript.RenderScript, android.support.v8.renderscript.Element);
+    method public void forEach(android.support.v8.renderscript.Allocation);
+    method public android.support.v8.renderscript.Script.FieldID getFieldID_Input();
+    method public android.support.v8.renderscript.Script.KernelID getKernelID();
+    method public void setInput(android.support.v8.renderscript.Allocation);
+    method public void setRadius(float);
+  }
+
+  public class ScriptIntrinsicColorMatrix extends android.support.v8.renderscript.ScriptIntrinsic {
+    ctor protected ScriptIntrinsicColorMatrix(long, android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.ScriptIntrinsicColorMatrix create(android.support.v8.renderscript.RenderScript, android.support.v8.renderscript.Element);
+    method public void forEach(android.support.v8.renderscript.Allocation, android.support.v8.renderscript.Allocation);
+    method public void forEach(android.support.v8.renderscript.Allocation, android.support.v8.renderscript.Allocation, android.support.v8.renderscript.Script.LaunchOptions);
+    method public android.support.v8.renderscript.Script.KernelID getKernelID();
+    method public void setAdd(android.support.v8.renderscript.Float4);
+    method public void setAdd(float, float, float, float);
+    method public void setColorMatrix(android.support.v8.renderscript.Matrix4f);
+    method public void setColorMatrix(android.support.v8.renderscript.Matrix3f);
+    method public void setGreyscale();
+    method public void setRGBtoYUV();
+    method public void setYUVtoRGB();
+  }
+
+  public class ScriptIntrinsicConvolve3x3 extends android.support.v8.renderscript.ScriptIntrinsic {
+    method public static android.support.v8.renderscript.ScriptIntrinsicConvolve3x3 create(android.support.v8.renderscript.RenderScript, android.support.v8.renderscript.Element);
+    method public void forEach(android.support.v8.renderscript.Allocation);
+    method public void forEach(android.support.v8.renderscript.Allocation, android.support.v8.renderscript.Script.LaunchOptions);
+    method public android.support.v8.renderscript.Script.FieldID getFieldID_Input();
+    method public android.support.v8.renderscript.Script.KernelID getKernelID();
+    method public void setCoefficients(float[]);
+    method public void setInput(android.support.v8.renderscript.Allocation);
+  }
+
+  public class ScriptIntrinsicConvolve5x5 extends android.support.v8.renderscript.ScriptIntrinsic {
+    method public static android.support.v8.renderscript.ScriptIntrinsicConvolve5x5 create(android.support.v8.renderscript.RenderScript, android.support.v8.renderscript.Element);
+    method public void forEach(android.support.v8.renderscript.Allocation);
+    method public void forEach(android.support.v8.renderscript.Allocation, android.support.v8.renderscript.Script.LaunchOptions);
+    method public android.support.v8.renderscript.Script.FieldID getFieldID_Input();
+    method public android.support.v8.renderscript.Script.KernelID getKernelID();
+    method public void setCoefficients(float[]);
+    method public void setInput(android.support.v8.renderscript.Allocation);
+  }
+
+  public class ScriptIntrinsicHistogram extends android.support.v8.renderscript.ScriptIntrinsic {
+    ctor protected ScriptIntrinsicHistogram(long, android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.ScriptIntrinsicHistogram create(android.support.v8.renderscript.RenderScript, android.support.v8.renderscript.Element);
+    method public void forEach(android.support.v8.renderscript.Allocation);
+    method public void forEach(android.support.v8.renderscript.Allocation, android.support.v8.renderscript.Script.LaunchOptions);
+    method public void forEach_Dot(android.support.v8.renderscript.Allocation);
+    method public void forEach_Dot(android.support.v8.renderscript.Allocation, android.support.v8.renderscript.Script.LaunchOptions);
+    method public android.support.v8.renderscript.Script.FieldID getFieldID_Input();
+    method public android.support.v8.renderscript.Script.KernelID getKernelID_Separate();
+    method public void setDotCoefficients(float, float, float, float);
+    method public void setOutput(android.support.v8.renderscript.Allocation);
+  }
+
+  public class ScriptIntrinsicLUT extends android.support.v8.renderscript.ScriptIntrinsic {
+    ctor protected ScriptIntrinsicLUT(long, android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.ScriptIntrinsicLUT create(android.support.v8.renderscript.RenderScript, android.support.v8.renderscript.Element);
+    method public void forEach(android.support.v8.renderscript.Allocation, android.support.v8.renderscript.Allocation);
+    method public android.support.v8.renderscript.Script.KernelID getKernelID();
+    method public void setAlpha(int, int);
+    method public void setBlue(int, int);
+    method public void setGreen(int, int);
+    method public void setRed(int, int);
+  }
+
+  public class ScriptIntrinsicResize extends android.support.v8.renderscript.ScriptIntrinsic {
+    ctor protected ScriptIntrinsicResize(long, android.support.v8.renderscript.RenderScript);
+    method public static android.support.v8.renderscript.ScriptIntrinsicResize create(android.support.v8.renderscript.RenderScript);
+    method public void forEach_bicubic(android.support.v8.renderscript.Allocation);
+    method public void forEach_bicubic(android.support.v8.renderscript.Allocation, android.support.v8.renderscript.Script.LaunchOptions);
+    method public android.support.v8.renderscript.Script.FieldID getFieldID_Input();
+    method public android.support.v8.renderscript.Script.KernelID getKernelID_bicubic();
+    method public void setInput(android.support.v8.renderscript.Allocation);
+  }
+
+  public class ScriptIntrinsicYuvToRGB extends android.support.v8.renderscript.ScriptIntrinsic {
+    method public static android.support.v8.renderscript.ScriptIntrinsicYuvToRGB create(android.support.v8.renderscript.RenderScript, android.support.v8.renderscript.Element);
+    method public void forEach(android.support.v8.renderscript.Allocation);
+    method public android.support.v8.renderscript.Script.FieldID getFieldID_Input();
+    method public android.support.v8.renderscript.Script.KernelID getKernelID();
+    method public void setInput(android.support.v8.renderscript.Allocation);
+  }
+
+  public class Short2 {
+    ctor public Short2();
+    ctor public Short2(short, short);
+    field public short x;
+    field public short y;
+  }
+
+  public class Short3 {
+    ctor public Short3();
+    ctor public Short3(short, short, short);
+    field public short x;
+    field public short y;
+    field public short z;
+  }
+
+  public class Short4 {
+    ctor public Short4();
+    ctor public Short4(short, short, short, short);
+    field public short w;
+    field public short x;
+    field public short y;
+    field public short z;
+  }
+
+  public class Type extends android.support.v8.renderscript.BaseObj {
+    method public static android.support.v8.renderscript.Type createX(android.support.v8.renderscript.RenderScript, android.support.v8.renderscript.Element, int);
+    method public static android.support.v8.renderscript.Type createXY(android.support.v8.renderscript.RenderScript, android.support.v8.renderscript.Element, int, int);
+    method public static android.support.v8.renderscript.Type createXYZ(android.support.v8.renderscript.RenderScript, android.support.v8.renderscript.Element, int, int, int);
+    method public int getCount();
+    method public long getDummyType(android.support.v8.renderscript.RenderScript, long);
+    method public android.support.v8.renderscript.Element getElement();
+    method public int getX();
+    method public int getY();
+    method public int getYuv();
+    method public int getZ();
+    method public boolean hasFaces();
+    method public boolean hasMipmaps();
+  }
+
+  public static class Type.Builder {
+    ctor public Type.Builder(android.support.v8.renderscript.RenderScript, android.support.v8.renderscript.Element);
+    method public android.support.v8.renderscript.Type create();
+    method public android.support.v8.renderscript.Type.Builder setFaces(boolean);
+    method public android.support.v8.renderscript.Type.Builder setMipmaps(boolean);
+    method public android.support.v8.renderscript.Type.Builder setX(int);
+    method public android.support.v8.renderscript.Type.Builder setY(int);
+    method public android.support.v8.renderscript.Type.Builder setYuvFormat(int);
+    method public android.support.v8.renderscript.Type.Builder setZ(int);
+  }
+
+  public static final class Type.CubemapFace extends java.lang.Enum {
+    method public static android.support.v8.renderscript.Type.CubemapFace valueOf(java.lang.String);
+    method public static final android.support.v8.renderscript.Type.CubemapFace[] values();
+    enum_constant public static final android.support.v8.renderscript.Type.CubemapFace NEGATIVE_X;
+    enum_constant public static final android.support.v8.renderscript.Type.CubemapFace NEGATIVE_Y;
+    enum_constant public static final android.support.v8.renderscript.Type.CubemapFace NEGATIVE_Z;
+    enum_constant public static final android.support.v8.renderscript.Type.CubemapFace POSITIVE_X;
+    enum_constant public static final android.support.v8.renderscript.Type.CubemapFace POSITIVE_Y;
+    enum_constant public static final android.support.v8.renderscript.Type.CubemapFace POSITIVE_Z;
+  }
+
+}
+
diff --git a/v8/renderscript/api/removed.txt b/v8/renderscript/api/removed.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/v8/renderscript/api/removed.txt
diff --git a/v8/renderscript/java/src/android/support/v8/renderscript/Allocation.java b/v8/renderscript/java/src/android/support/v8/renderscript/Allocation.java
index 92c3eb5..03244ff 100644
--- a/v8/renderscript/java/src/android/support/v8/renderscript/Allocation.java
+++ b/v8/renderscript/java/src/android/support/v8/renderscript/Allocation.java
@@ -265,7 +265,6 @@
     }
 
     /**
-     * @hide
      * Enable/Disable AutoPadding for Vec3 elements.
      *
      * @param useAutoPadding True: enable AutoPadding; False: disable AutoPadding
@@ -463,7 +462,6 @@
 
     /**
      * Delete once code is updated.
-     * @hide
      */
     public void ioSendOutput() {
         ioSend();
@@ -1214,10 +1212,7 @@
         }
     }
 
-    /**
-     * @hide
-     *
-     */
+
     private void copy3DRangeFromUnchecked(int xoff, int yoff, int zoff, int w, int h, int d,
                                           Object array, Element.DataType dt, int arrayLen) {
         mRS.validate();
@@ -1243,7 +1238,6 @@
     }
 
     /**
-     * @hide
      * Copy a rectangular region from the array into the allocation.
      * The array is assumed to be tightly packed.
      *
@@ -1262,7 +1256,6 @@
     }
 
     /**
-     * @hide
      * Copy a rectangular region into the allocation from another
      * allocation.
      *
@@ -1437,7 +1430,6 @@
     }
 
     /**
-     * @hide
      * Copy part of this Allocation into an array.  This method does not
      * guarantee that the Allocation is compatible with the input buffer.
      *
@@ -1452,7 +1444,6 @@
     }
 
     /**
-     * @hide
      * Copy part of this Allocation into an array.  This method does not
      * guarantee that the Allocation is compatible with the input buffer.
      *
@@ -1465,7 +1456,6 @@
     }
 
     /**
-     * @hide
      * Copy part of this Allocation into an array.  This method does not
      * guarantee that the Allocation is compatible with the input buffer.
      *
@@ -1478,7 +1468,6 @@
     }
 
     /**
-     * @hide
      * Copy part of this Allocation into an array.  This method does not
      * guarantee that the Allocation is compatible with the input buffer.
      *
@@ -1491,7 +1480,6 @@
     }
 
     /**
-     * @hide
      * Copy part of this Allocation into an array.  This method does not
      * guarantee that the Allocation is compatible with the input buffer.
      *
@@ -1505,7 +1493,6 @@
 
 
     /**
-     * @hide
      * Copy part of this Allocation into an array.  This method does not
      * and will generate exceptions if the Allocation type does not
      * match the component type of the array passed in.
@@ -1521,7 +1508,6 @@
     }
 
     /**
-     * @hide
      * Copy part of this Allocation into an array.  This method does not
      * and will generate exceptions if the Allocation type is not a 32 bit
      * integer type.
@@ -1536,7 +1522,6 @@
     }
 
     /**
-     * @hide
      * Copy part of this Allocation into an array.  This method does not
      * and will generate exceptions if the Allocation type is not a 16 bit
      * integer type.
@@ -1551,7 +1536,6 @@
     }
 
     /**
-     * @hide
      * Copy part of this Allocation into an array.  This method does not
      * and will generate exceptions if the Allocation type is not an 8 bit
      * integer type.
@@ -1566,7 +1550,6 @@
     }
 
     /**
-     * @hide
      * Copy part of this Allocation into an array.  This method does not
      * and will generate exceptions if the Allocation type is not a 32 bit float
      * type.
@@ -1605,7 +1588,6 @@
     }
 
     /**
-     * @hide
      * Copy from a rectangular region in this Allocation into an array.
      *
      * @param xoff X offset of the region to copy in this Allocation
@@ -1621,7 +1603,6 @@
     }
 
     /**
-     * @hide
      * Copy from a rectangular region in this Allocation into an array.
      *
      * @param xoff X offset of the region to copy in this Allocation
@@ -1637,7 +1618,6 @@
     }
 
     /**
-     * @hide
      * Copy from a rectangular region in this Allocation into an array.
      *
      * @param xoff X offset of the region to copy in this Allocation
@@ -1653,7 +1633,6 @@
     }
 
     /**
-     * @hide
      * Copy from a rectangular region in this Allocation into an array.
      *
      * @param xoff X offset of the region to copy in this Allocation
@@ -1669,7 +1648,6 @@
     }
 
     /**
-     * @hide
      * Copy from a rectangular region in this Allocation into an array.
      *
      * @param xoff X offset of the region to copy in this Allocation
diff --git a/v8/renderscript/java/src/android/support/v8/renderscript/RenderScript.java b/v8/renderscript/java/src/android/support/v8/renderscript/RenderScript.java
index 7922b9e..5570ca2 100644
--- a/v8/renderscript/java/src/android/support/v8/renderscript/RenderScript.java
+++ b/v8/renderscript/java/src/android/support/v8/renderscript/RenderScript.java
@@ -58,6 +58,30 @@
     private Context mApplicationContext;
     private String mNativeLibDir;
 
+    static private String mBlackList = "";
+     /**
+     * Sets the blackList of Models to only use support lib runtime.
+     * Should be used before context create.
+     *
+     * @param blackList User provided black list string.
+     *
+     * Format: "(MANUFACTURER1:PRODUCT1:MODEL1), (MANUFACTURER2:PRODUCT2:MODEL2)..."
+     * e.g. : To Blacklist Nexus 7(2013) and Nexus 5.
+     *        mBlackList = "(asus:razor:Nexus 7), (LGE:hammerhead:Nexus 5)";
+     */
+    static public void setBlackList(String blackList) {
+        if (blackList != null) {
+            mBlackList = blackList;
+        }
+    }
+     /**
+     * Force using support lib runtime.
+     * Should be used before context create.
+     *
+     */
+    static public void forceCompat() {
+        sNative = 0;
+    }
     /*
      * We use a class initializer to allow the native code to cache some
      * field offsets.
@@ -140,46 +164,67 @@
 
             if (sNative == 1) {
                 // Workarounds that may disable thunking go here
-                ApplicationInfo info;
+                ApplicationInfo info = null;
                 try {
                     info = ctx.getPackageManager().getApplicationInfo(ctx.getPackageName(),
                                                                       PackageManager.GET_META_DATA);
                 } catch (PackageManager.NameNotFoundException e) {
                     // assume no workarounds needed
-                    return true;
-                }
-                long minorVersion = 0;
-
-                // load minorID from reflection
-                try {
-                    Class<?> javaRS = Class.forName("android.renderscript.RenderScript");
-                    Method getMinorID = javaRS.getDeclaredMethod("getMinorID");
-                    minorVersion = ((java.lang.Long)getMinorID.invoke(null)).longValue();
-                } catch (Exception e) {
-                    // minor version remains 0 on devices with no possible WARs
                 }
 
-                if (info.metaData != null) {
-                    // asynchronous teardown: minor version 1+
-                    if (info.metaData.getBoolean("com.android.support.v8.renderscript.EnableAsyncTeardown") == true) {
-                        if (minorVersion == 0) {
-                            sNative = 0;
+                if (info != null) {
+                    long minorVersion = 0;
+                    // load minorID from reflection
+                    try {
+                        Class<?> javaRS = Class.forName("android.renderscript.RenderScript");
+                        if (android.os.Build.VERSION.SDK_INT <= android.os.Build.VERSION_CODES.LOLLIPOP_MR1) {
+                            Method getMinorID = javaRS.getDeclaredMethod("getMinorID");
+                            minorVersion = ((java.lang.Long)getMinorID.invoke(null)).longValue();
+                        } else {
+                            //For M+
+                            Method getMinorVersion = javaRS.getDeclaredMethod("getMinorVersion");
+                            minorVersion = ((java.lang.Long)getMinorVersion.invoke(null)).longValue();
                         }
+                    } catch (Exception e) {
+                        // minor version remains 0 on devices with no possible WARs
                     }
 
-                    // blur issues on some drivers with 4.4
-                    if (info.metaData.getBoolean("com.android.support.v8.renderscript.EnableBlurWorkaround") == true) {
-                        if (android.os.Build.VERSION.SDK_INT <= 19) {
-                            //android.util.Log.e("rs", "war on");
-                            sNative = 0;
+                    if (info.metaData != null) {
+                        // asynchronous teardown: minor version 1+
+                        if (info.metaData.getBoolean("com.android.support.v8.renderscript.EnableAsyncTeardown") == true) {
+                            if (minorVersion == 0) {
+                                sNative = 0;
+                            }
+                        }
+
+                        // blur issues on some drivers with 4.4
+                        if (info.metaData.getBoolean("com.android.support.v8.renderscript.EnableBlurWorkaround") == true) {
+                            if (android.os.Build.VERSION.SDK_INT <= 19) {
+                                //android.util.Log.e("rs", "war on");
+                                sNative = 0;
+                            }
                         }
                     }
+                    // end of workarounds
                 }
-                // end of workarounds
             }
         }
 
         if (sNative == 1) {
+            // check against the blacklist
+            if (mBlackList.length() > 0) {
+                String deviceInfo = '(' +
+                                    android.os.Build.MANUFACTURER +
+                                    ':' +
+                                    android.os.Build.PRODUCT +
+                                    ':' +
+                                    android.os.Build.MODEL +
+                                    ')';
+                if (mBlackList.contains(deviceInfo)) {
+                    sNative = 0;
+                    return false;
+                }
+            }
             return true;
         }
         return false;
@@ -698,7 +743,7 @@
                     Log.e(LOG_TAG, "Error loading RS Compat library for Incremental Intrinsic Support: " + e);
                     throw new RSRuntimeException("Error loading RS Compat library for Incremental Intrinsic Support: " + e);
                 }
-                if (!nIncLoadSO()) {
+                if (!nIncLoadSO(sSdkVersion)) {
                     throw new RSRuntimeException("Error loading libRSSupport library for Incremental Intrinsic Support");
                 }
                 mIncLoaded = true;
@@ -782,8 +827,12 @@
         long[] fieldIDs, long[] values, int[] sizes, long[] depClosures,
         long[] depFieldIDs) {
       validate();
-      return rsnClosureCreate(mContext, kernelID, returnValue, fieldIDs, values,
+      long c = rsnClosureCreate(mContext, kernelID, returnValue, fieldIDs, values,
           sizes, depClosures, depFieldIDs);
+      if (c == 0) {
+          throw new RSRuntimeException("Failed creating closure.");
+      }
+      return c;
     }
 
     native long rsnInvokeClosureCreate(long con, long invokeID, byte[] params,
@@ -791,8 +840,12 @@
     synchronized long nInvokeClosureCreate(long invokeID, byte[] params,
         long[] fieldIDs, long[] values, int[] sizes) {
       validate();
-      return rsnInvokeClosureCreate(mContext, invokeID, params, fieldIDs,
+      long c = rsnInvokeClosureCreate(mContext, invokeID, params, fieldIDs,
           values, sizes);
+      if (c == 0) {
+          throw new RSRuntimeException("Failed creating closure.");
+      }
+      return c;
     }
 
     native void rsnClosureSetArg(long con, long closureID, int index,
@@ -829,7 +882,7 @@
 
 // Additional Entry points For inc libRSSupport
 
-    native boolean nIncLoadSO();
+    native boolean nIncLoadSO(int deviceApi);
     native long nIncDeviceCreate();
     native void nIncDeviceDestroy(long dev);
     // Methods below are wrapped to protect the non-threadsafe
@@ -1018,8 +1071,6 @@
      * Place a message into the message queue to be sent back to the message
      * handler once all previous commands have been executed.
      *
-     * @hide
-     *
      * @param id
      * @param data
      */
@@ -1244,7 +1295,7 @@
         if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
             useIOlib = true;
         }
-        if (!rs.nLoadSO(useNative, android.os.Build.VERSION.SDK_INT)) {
+        if (!rs.nLoadSO(useNative, sdkVersion)) {
             if (useNative) {
                 android.util.Log.v(LOG_TAG, "Unable to load libRS.so, falling back to compat mode");
                 useNative = false;
@@ -1255,7 +1306,7 @@
                 Log.e(LOG_TAG, "Error loading RS Compat library: " + e);
                 throw new RSRuntimeException("Error loading RS Compat library: " + e);
             }
-            if (!rs.nLoadSO(false, android.os.Build.VERSION.SDK_INT)) {
+            if (!rs.nLoadSO(false, sdkVersion)) {
                 throw new RSRuntimeException("Error loading libRSSupport library");
             }
         }
@@ -1364,7 +1415,6 @@
      /**
      * Gets or creates a RenderScript context of the specified type.
      *
-     * @hide
      * @param ctx The context.
      * @param ct The type of context to be created.
      * @param sdkVersion The target SDK Version.
@@ -1390,7 +1440,6 @@
     }
 
     /**
-     * @hide
      *
      * Releases all the process contexts.  This is the same as
      * calling .destroy() on each unique context retreived with
@@ -1428,7 +1477,6 @@
      *
      * If you need a single context please use create()
      *
-     * @hide
      * @param ctx The context.
      * @return RenderScript
      */
diff --git a/v8/renderscript/java/src/android/support/v8/renderscript/Script.java b/v8/renderscript/java/src/android/support/v8/renderscript/Script.java
index 41e7e08..7cef892 100644
--- a/v8/renderscript/java/src/android/support/v8/renderscript/Script.java
+++ b/v8/renderscript/java/src/android/support/v8/renderscript/Script.java
@@ -109,7 +109,6 @@
      * This class should not be directly created. Instead use the method in the
      * reflected or intrinsic code "getInvokeID_funcname()".
      *
-     * @hide
      */
     public static final class InvokeID extends BaseObj {
         Script mScript;
diff --git a/v8/renderscript/java/src/android/support/v8/renderscript/ScriptGroup.java b/v8/renderscript/java/src/android/support/v8/renderscript/ScriptGroup.java
index 6861754..15e8b55 100644
--- a/v8/renderscript/java/src/android/support/v8/renderscript/ScriptGroup.java
+++ b/v8/renderscript/java/src/android/support/v8/renderscript/ScriptGroup.java
@@ -41,10 +41,10 @@
  * runtime and compiler optimization can be applied to reduce computation and
  * communication overhead, and to make better use of the CPU and the GPU.
  **/
-public class ScriptGroup extends BaseObj {
+public final class ScriptGroup extends BaseObj {
     //FIXME: Change 23 to the codename when that is decided.
     private static final int MIN_API_VERSION = 23;
-
+    private static final String TAG = "ScriptGroup";
     IO mOutputs[];
     IO mInputs[];
     private boolean mUseIncSupp = false;
@@ -100,8 +100,8 @@
      * <p>
      * A closure represents a function call to a kernel or invocable function,
      * combined with arguments and values for global variables. A closure is
-     * created using the {@link android.renderscript.ScriptGroup.Builder2#addKernel} or
-     * {@link android.renderscript.ScriptGroup.Builder2#addInvoke}
+     * created using the {@link Builder2#addKernel} or
+     * {@link Builder2#addInvoke}
      * method.
      */
 
@@ -117,11 +117,11 @@
 
         private static final String TAG = "Closure";
 
-        private Closure(long id, RenderScript rs) {
+        Closure(long id, RenderScript rs) {
             super(id, rs);
         }
 
-        private Closure(RenderScript rs, Script.KernelID kernelID, Type returnType,
+        Closure(RenderScript rs, Script.KernelID kernelID, Type returnType,
                        Object[] args, Map<Script.FieldID, Object> globals) {
             super(0, rs);
 
@@ -144,28 +144,16 @@
 
             int i;
             for (i = 0; i < args.length; i++) {
-                Object obj = args[i];
                 fieldIDs[i] = 0;
-                if (obj instanceof Input) {
-                    Input unbound = (Input)obj;
-                    unbound.addReference(this, i);
-                } else {
-                    retrieveValueAndDependenceInfo(rs, i, args[i], values, sizes,
-                                                   depClosures, depFieldIDs);
-                }
+                retrieveValueAndDependenceInfo(rs, i, null, args[i],
+                                               values, sizes, depClosures, depFieldIDs);
             }
-
             for (Map.Entry<Script.FieldID, Object> entry : globals.entrySet()) {
                 Object obj = entry.getValue();
                 Script.FieldID fieldID = entry.getKey();
                 fieldIDs[i] = fieldID.getID(rs);
-                if (obj instanceof Input) {
-                    Input unbound = (Input)obj;
-                    unbound.addReference(this, fieldID);
-                } else {
-                    retrieveValueAndDependenceInfo(rs, i, obj, values,
-                                                   sizes, depClosures, depFieldIDs);
-                }
+                retrieveValueAndDependenceInfo(rs, i, fieldID, obj,
+                                               values, sizes, depClosures, depFieldIDs);
                 i++;
             }
 
@@ -175,8 +163,8 @@
             setID(id);
         }
 
-        private Closure(RenderScript rs, Script.InvokeID invokeID,
-                       Object[] args, Map<Script.FieldID, Object> globals) {
+        Closure(RenderScript rs, Script.InvokeID invokeID,
+                Object[] args, Map<Script.FieldID, Object> globals) {
             super(0, rs);
 
             if (android.os.Build.VERSION.SDK_INT < MIN_API_VERSION && rs.isUseNative()) {
@@ -202,14 +190,8 @@
                 Object obj = entry.getValue();
                 Script.FieldID fieldID = entry.getKey();
                 fieldIDs[i] = fieldID.getID(rs);
-                if (obj instanceof Input) {
-                    Input unbound = (Input)obj;
-                    unbound.addReference(this, fieldID);
-                } else {
-                    // TODO(yangni): Verify obj not a future.
-                    retrieveValueAndDependenceInfo(rs, i, obj, values,
-                                                   sizes, depClosures, depFieldIDs);
-                }
+                retrieveValueAndDependenceInfo(rs, i, fieldID, obj, values,
+                                               sizes, depClosures, depFieldIDs);
                 i++;
             }
 
@@ -219,9 +201,8 @@
             setID(id);
         }
 
-        private static
-                void retrieveValueAndDependenceInfo(RenderScript rs,
-                                                    int index, Object obj,
+        private void retrieveValueAndDependenceInfo(RenderScript rs,
+                                                    int index, Script.FieldID fid, Object obj,
                                                     long[] values, int[] sizes,
                                                     long[] depClosures,
                                                     long[] depFieldIDs) {
@@ -232,20 +213,25 @@
                 depClosures[index] = f.getClosure().getID(rs);
                 Script.FieldID fieldID = f.getFieldID();
                 depFieldIDs[index] = fieldID != null ? fieldID.getID(rs) : 0;
-                if (obj == null) {
-                    // Value is originally created by the owner closure
-                    values[index] = 0;
-                    sizes[index] = 0;
-                    return;
-                }
             } else {
                 depClosures[index] = 0;
                 depFieldIDs[index] = 0;
             }
 
-            ValueAndSize vs = new ValueAndSize(rs, obj);
-            values[index] = vs.value;
-            sizes[index] = vs.size;
+            if (obj instanceof Input) {
+                Input unbound = (Input)obj;
+                if (index < mArgs.length) {
+                    unbound.addReference(this, index);
+                } else {
+                    unbound.addReference(this, fid);
+                }
+                values[index] = 0;
+                sizes[index] = 0;
+            } else {
+                ValueAndSize vs = new ValueAndSize(rs, obj);
+                values[index] = vs.value;
+                sizes[index] = vs.size;
+            }
         }
 
         /**
@@ -277,7 +263,11 @@
                 // without an associated value (reference). So this is not working for
                 // cross-module (cross-script) linking in this case where a field not
                 // explicitly bound.
-                f = new Future(this, field, mBindings.get(field));
+                Object obj = mBindings.get(field);
+                if (obj instanceof Future) {
+                    obj = ((Future)obj).getValue();
+                }
+                f = new Future(this, field, obj);
                 mGlobalFuture.put(field, f);
             }
 
@@ -285,12 +275,18 @@
         }
 
         void setArg(int index, Object obj) {
+            if (obj instanceof Future) {
+                obj = ((Future)obj).getValue();
+            }
             mArgs[index] = obj;
             ValueAndSize vs = new ValueAndSize(mRS, obj);
             mRS.nClosureSetArg(getID(mRS), index, vs.value, vs.size);
         }
 
         void setGlobal(Script.FieldID fieldID, Object obj) {
+            if (obj instanceof Future) {
+                obj = ((Future)obj).getValue();
+            }
             mBindings.put(fieldID, obj);
             ValueAndSize vs = new ValueAndSize(mRS, obj);
             mRS.nClosureSetGlobal(getID(mRS), fieldID.getID(mRS), vs.value, vs.size);
@@ -363,6 +359,7 @@
         // -1 means unset. Legal values are 0 .. n-1, where n is the number of
         // arguments for the referencing closure.
         List<Pair<Closure, Integer>> mArgIndex;
+        Object mValue;
 
         Input() {
             mFieldID = new ArrayList<Pair<Closure, Script.FieldID>>();
@@ -378,6 +375,7 @@
         }
 
         void set(Object value) {
+            mValue = value;
             for (Pair<Closure, Integer> p : mArgIndex) {
                 Closure closure = p.first;
                 int index = p.second.intValue();
@@ -389,14 +387,14 @@
                 closure.setGlobal(fieldID, value);
             }
         }
+
+        Object get() { return mValue; }
     }
 
-    String mName;
-    List<Closure> mClosures;
-    List<Input> mInputs2;
-    Future[] mOutputs2;
-
-    private static final String TAG = "ScriptGroup2";
+    private String mName;
+    private List<Closure> mClosures;
+    private List<Input> mInputs2;
+    private Future[] mOutputs2;
 
     ScriptGroup(long id, RenderScript rs) {
         super(id, rs);
@@ -458,26 +456,16 @@
         Object[] outputObjs = new Object[mOutputs2.length];
         int i = 0;
         for (Future f : mOutputs2) {
-            outputObjs[i++] = f.getValue();
+            Object output = f.getValue();
+            if (output instanceof Input) {
+                output = ((Input)output).get();
+            }
+            outputObjs[i++] = output;
         }
         return outputObjs;
     }
 
     /**
-     * Represents a binding of a value to a global variable in a
-     * kernel or invocable function. Used in closure creation.
-     */
-
-    public static final class Binding {
-        public Script.FieldID mField;
-        public Object mValue;
-        public Binding(Script.FieldID field, Object value) {
-            mField = field;
-            mValue = value;
-        }
-    }
-
-    /**
      * Sets an input of the ScriptGroup. This specifies an
      * Allocation to be used for kernels that require an input
      * Allocation provided from outside of the ScriptGroup.
@@ -695,7 +683,8 @@
                 Node n = mNodes.get(ct);
                 if (n.mInputs.size() == 0) {
                     if (n.mOutputs.size() == 0 && mNodes.size() > 1) {
-                        throw new RSInvalidStateException("Groups cannot contain unconnected scripts");
+                        String msg = "Groups cannot contain unconnected scripts";
+                        throw new RSInvalidStateException(msg);
                     }
                     validateDAGRecurse(n, ct+1);
                 }
@@ -976,6 +965,40 @@
     }
 
     /**
+     * Represents a binding of a value to a global variable in a
+     * kernel or invocable function. Used in closure creation.
+     */
+
+    public static final class Binding {
+        private final Script.FieldID mField;
+        private final Object mValue;
+
+        /**
+         * Returns a Binding object that binds value to field
+         *
+         * @param field the Script.FieldID of the global variable
+         * @param value the value
+         */
+
+        public Binding(Script.FieldID field, Object value) {
+            mField = field;
+            mValue = value;
+        }
+
+        /**
+         * Returns the field ID
+         */
+
+        public Script.FieldID getField() { return mField; }
+
+        /**
+         * Returns the value
+         */
+
+        public Object getValue() { return mValue; }
+    }
+
+    /**
      * The builder class for creating script groups
      * <p>
      * A script group is created using closures (see class {@link Closure}).
@@ -1013,21 +1036,45 @@
         RenderScript mRS;
         List<Closure> mClosures;
         List<Input> mInputs;
-        private static final String TAG = "ScriptGroup2.Builder";
+        private static final String TAG = "ScriptGroup.Builder2";
 
+        /**
+         * Returns a Builder object
+         *
+         * @param rs the RenderScript context
+         */
         public Builder2(RenderScript rs) {
             mRS = rs;
             mClosures = new ArrayList<Closure>();
             mInputs = new ArrayList<Input>();
         }
 
+        /**
+         * Adds a closure for a kernel
+         *
+         * @param k Kernel ID for the kernel function
+         * @param returnType Allocation type for the return value
+         * @param args arguments to the kernel function
+         * @param globalBindings bindings for global variables
+         * @return a closure
+         */
+
         private Closure addKernelInternal(Script.KernelID k, Type returnType, Object[] args,
-                                         Map<Script.FieldID, Object> globalBindings) {
+                                          Map<Script.FieldID, Object> globalBindings) {
             Closure c = new Closure(mRS, k, returnType, args, globalBindings);
             mClosures.add(c);
             return c;
         }
 
+        /**
+         * Adds a closure for an invocable function
+         *
+         * @param invoke Invoke ID for the invocable function
+         * @param args arguments to the invocable function
+         * @param globalBindings bindings for global variables
+         * @return a closure
+         */
+
         private Closure addInvokeInternal(Script.InvokeID invoke, Object[] args,
                                           Map<Script.FieldID, Object> globalBindings) {
             Closure c = new Closure(mRS, invoke, args, globalBindings);
@@ -1116,7 +1163,7 @@
                     return false;
                 }
                 Binding b = (Binding)argsAndBindings[i];
-                bindingMap.put(b.mField, b.mValue);
+                bindingMap.put(b.getField(), b.getValue());
             }
 
             return true;
diff --git a/v8/renderscript/java/src/android/support/v8/renderscript/ScriptIntrinsic3DLUT.java b/v8/renderscript/java/src/android/support/v8/renderscript/ScriptIntrinsic3DLUT.java
index dcd1bc1..7fc71f3 100644
--- a/v8/renderscript/java/src/android/support/v8/renderscript/ScriptIntrinsic3DLUT.java
+++ b/v8/renderscript/java/src/android/support/v8/renderscript/ScriptIntrinsic3DLUT.java
@@ -25,7 +25,6 @@
  * allocation.  The 8 nearest values are sampled and linearly interpolated.  The
  * result is placed in the output.
  *
- * @hide
  **/
 public class ScriptIntrinsic3DLUT extends ScriptIntrinsic {
     private Allocation mLUT;
diff --git a/v8/renderscript/java/src/android/support/v8/renderscript/Type.java b/v8/renderscript/java/src/android/support/v8/renderscript/Type.java
index 2fd894b..6aeb9ea 100644
--- a/v8/renderscript/java/src/android/support/v8/renderscript/Type.java
+++ b/v8/renderscript/java/src/android/support/v8/renderscript/Type.java
@@ -114,8 +114,6 @@
     /**
      * Get the YUV format
      *
-     * @hide
-     *
      * @return int
      */
     public int getYuv() {
@@ -344,8 +342,6 @@
         /**
          * Set the YUV layout for a Type.
          *
-         * @hide
-         *
          * @param yuvFormat {@link android.graphics.ImageFormat#YV12} or {@link android.graphics.ImageFormat#NV21}
          */
         public Builder setYuvFormat(int yuvFormat) {
diff --git a/v8/renderscript/jni/android_renderscript_RenderScript.cpp b/v8/renderscript/jni/android_renderscript_RenderScript.cpp
index cddb309..525c6bd 100644
--- a/v8/renderscript/jni/android_renderscript_RenderScript.cpp
+++ b/v8/renderscript/jni/android_renderscript_RenderScript.cpp
@@ -269,7 +269,7 @@
 // Incremental Support lib
 static dispatchTable dispatchTabInc;
 
-static jboolean nLoadSO(JNIEnv *_env, jobject _this, jboolean useNative, jint deviceApi) {
+static jboolean nLoadSO(JNIEnv *_env, jobject _this, jboolean useNative, jint targetApi) {
     void* handle = NULL;
     if (useNative) {
         handle = dlopen("libRS.so", RTLD_LAZY | RTLD_LOCAL);
@@ -281,7 +281,7 @@
         return false;
     }
 
-    if (loadSymbols(handle, dispatchTab, deviceApi) == false) {
+    if (loadSymbols(handle, dispatchTab, targetApi) == false) {
         LOG_API("%s init failed!", filename);
         return false;
     }
@@ -345,79 +345,167 @@
                jlong returnValue, jlongArray fieldIDArray,
                jlongArray valueArray, jintArray sizeArray,
                jlongArray depClosureArray, jlongArray depFieldIDArray) {
+  jlong ret = 0;
+
   jlong* jFieldIDs = _env->GetLongArrayElements(fieldIDArray, nullptr);
   jsize fieldIDs_length = _env->GetArrayLength(fieldIDArray);
-  RsScriptFieldID* fieldIDs =
-      (RsScriptFieldID*)alloca(sizeof(RsScriptFieldID) * fieldIDs_length);
-  for (int i = 0; i< fieldIDs_length; i++) {
-    fieldIDs[i] = (RsScriptFieldID)jFieldIDs[i];
-  }
-
   jlong* jValues = _env->GetLongArrayElements(valueArray, nullptr);
   jsize values_length = _env->GetArrayLength(valueArray);
-  uintptr_t* values = (uintptr_t*)alloca(sizeof(uintptr_t) * values_length);
-  for (int i = 0; i < values_length; i++) {
-    values[i] = (uintptr_t)jValues[i];
-  }
-
-  jint* sizes = _env->GetIntArrayElements(sizeArray, nullptr);
+  jint* jSizes = _env->GetIntArrayElements(sizeArray, nullptr);
   jsize sizes_length = _env->GetArrayLength(sizeArray);
-
   jlong* jDepClosures =
       _env->GetLongArrayElements(depClosureArray, nullptr);
   jsize depClosures_length = _env->GetArrayLength(depClosureArray);
-  RsClosure* depClosures =
-      (RsClosure*)alloca(sizeof(RsClosure) * depClosures_length);
-  for (int i = 0; i < depClosures_length; i++) {
-    depClosures[i] = (RsClosure)jDepClosures[i];
-  }
-
   jlong* jDepFieldIDs =
       _env->GetLongArrayElements(depFieldIDArray, nullptr);
   jsize depFieldIDs_length = _env->GetArrayLength(depFieldIDArray);
-  RsScriptFieldID* depFieldIDs =
-      (RsScriptFieldID*)alloca(sizeof(RsScriptFieldID) * depFieldIDs_length);
-  for (int i = 0; i < depClosures_length; i++) {
+
+  size_t numValues, numDependencies;
+  RsScriptFieldID* fieldIDs;
+  uintptr_t* values;
+  RsClosure* depClosures;
+  RsScriptFieldID* depFieldIDs;
+
+  if (fieldIDs_length != values_length || values_length != sizes_length) {
+      LOG_API("Unmatched field IDs, values, and sizes in closure creation.");
+      goto exit;
+  }
+
+  numValues = (size_t)fieldIDs_length;
+
+  if (depClosures_length != depFieldIDs_length) {
+      LOG_API("Unmatched closures and field IDs for dependencies in closure creation.");
+      goto exit;
+  }
+
+  numDependencies = (size_t)depClosures_length;
+
+  if (numDependencies > numValues) {
+      LOG_API("Unexpected number of dependencies in closure creation");
+      goto exit;
+  }
+
+  if (numValues > RS_CLOSURE_MAX_NUMBER_ARGS_AND_BINDINGS) {
+      LOG_API("Too many arguments or globals in closure creation");
+      goto exit;
+  }
+
+  fieldIDs = (RsScriptFieldID*)alloca(sizeof(RsScriptFieldID) * numValues);
+  if (fieldIDs == nullptr) {
+      goto exit;
+  }
+
+  for (size_t i = 0; i < numValues; i++) {
+    fieldIDs[i] = (RsScriptFieldID)jFieldIDs[i];
+  }
+
+  values = (uintptr_t*)alloca(sizeof(uintptr_t) * numValues);
+  if (values == nullptr) {
+      goto exit;
+  }
+
+  for (size_t i = 0; i < numValues; i++) {
+    values[i] = (uintptr_t)jValues[i];
+  }
+
+  depClosures = (RsClosure*)alloca(sizeof(RsClosure) * numDependencies);
+  if (depClosures == nullptr) {
+      goto exit;
+  }
+
+  for (size_t i = 0; i < numDependencies; i++) {
+    depClosures[i] = (RsClosure)jDepClosures[i];
+  }
+
+  depFieldIDs = (RsScriptFieldID*)alloca(sizeof(RsScriptFieldID) * numDependencies);
+  if (depFieldIDs == nullptr) {
+      goto exit;
+  }
+
+  for (size_t i = 0; i < numDependencies; i++) {
     depFieldIDs[i] = (RsClosure)jDepFieldIDs[i];
   }
 
-  return (jlong)(uintptr_t)dispatchTab.ClosureCreate(
+  ret = (jlong)(uintptr_t)dispatchTab.ClosureCreate(
       (RsContext)con, (RsScriptKernelID)kernelID, (RsAllocation)returnValue,
-      fieldIDs, (size_t)fieldIDs_length, values, (size_t)values_length,
-      (int*)sizes, (size_t)sizes_length,
-      depClosures, (size_t)depClosures_length,
-      depFieldIDs, (size_t)depFieldIDs_length);
+      fieldIDs, numValues, values, numValues,
+      (int*)jSizes, numValues,
+      depClosures, numDependencies,
+      depFieldIDs, numDependencies);
+
+exit:
+
+  _env->ReleaseLongArrayElements(depFieldIDArray, jDepFieldIDs, JNI_ABORT);
+  _env->ReleaseLongArrayElements(depClosureArray, jDepClosures, JNI_ABORT);
+  _env->ReleaseIntArrayElements (sizeArray,       jSizes,       JNI_ABORT);
+  _env->ReleaseLongArrayElements(valueArray,      jValues,      JNI_ABORT);
+  _env->ReleaseLongArrayElements(fieldIDArray,    jFieldIDs,    JNI_ABORT);
+
+  return ret;
 }
 
 static jlong
 nInvokeClosureCreate(JNIEnv *_env, jobject _this, jlong con, jlong invokeID,
                      jbyteArray paramArray, jlongArray fieldIDArray, jlongArray valueArray,
                      jintArray sizeArray) {
+  jlong ret = 0;
+
   jbyte* jParams = _env->GetByteArrayElements(paramArray, nullptr);
   jsize jParamLength = _env->GetArrayLength(paramArray);
-
   jlong* jFieldIDs = _env->GetLongArrayElements(fieldIDArray, nullptr);
   jsize fieldIDs_length = _env->GetArrayLength(fieldIDArray);
-  RsScriptFieldID* fieldIDs =
-      (RsScriptFieldID*)alloca(sizeof(RsScriptFieldID) * fieldIDs_length);
-  for (int i = 0; i< fieldIDs_length; i++) {
+  jlong* jValues = _env->GetLongArrayElements(valueArray, nullptr);
+  jsize values_length = _env->GetArrayLength(valueArray);
+  jint* jSizes = _env->GetIntArrayElements(sizeArray, nullptr);
+  jsize sizes_length = _env->GetArrayLength(sizeArray);
+
+  size_t numValues;
+  RsScriptFieldID* fieldIDs;
+  uintptr_t* values;
+
+  if (fieldIDs_length != values_length || values_length != sizes_length) {
+      LOG_API("Unmatched field IDs, values, and sizes in closure creation.");
+      goto exit;
+  }
+
+  numValues = (size_t) fieldIDs_length;
+
+  if (numValues > RS_CLOSURE_MAX_NUMBER_ARGS_AND_BINDINGS) {
+      LOG_API("Too many arguments or globals in closure creation");
+      goto exit;
+  }
+
+  fieldIDs = (RsScriptFieldID*)alloca(sizeof(RsScriptFieldID) * numValues);
+  if (fieldIDs == nullptr) {
+      goto exit;
+  }
+
+  for (size_t i = 0; i < numValues; i++) {
     fieldIDs[i] = (RsScriptFieldID)jFieldIDs[i];
   }
 
-  jlong* jValues = _env->GetLongArrayElements(valueArray, nullptr);
-  jsize values_length = _env->GetArrayLength(valueArray);
-  uintptr_t* values = (uintptr_t*)alloca(sizeof(uintptr_t) * values_length);
-  for (int i = 0; i < values_length; i++) {
+  values = (uintptr_t*)alloca(sizeof(uintptr_t) * numValues);
+  if (values == nullptr) {
+      goto exit;
+  }
+
+  for (size_t i = 0; i < numValues; i++) {
     values[i] = (uintptr_t)jValues[i];
   }
 
-  jint* sizes = _env->GetIntArrayElements(sizeArray, nullptr);
-  jsize sizes_length = _env->GetArrayLength(sizeArray);
-
-  return (jlong)(uintptr_t)dispatchTab.InvokeClosureCreate(
+  ret = (jlong)(uintptr_t)dispatchTab.InvokeClosureCreate(
       (RsContext)con, (RsScriptInvokeID)invokeID, jParams, jParamLength,
-      fieldIDs, (size_t)fieldIDs_length, values, (size_t)values_length,
-      (int*)sizes, (size_t)sizes_length);
+      fieldIDs, numValues, values, numValues,
+      (int*)jSizes, numValues);
+
+exit:
+
+  _env->ReleaseIntArrayElements (sizeArray,       jSizes,       JNI_ABORT);
+  _env->ReleaseLongArrayElements(valueArray,      jValues,      JNI_ABORT);
+  _env->ReleaseLongArrayElements(fieldIDArray,    jFieldIDs,    JNI_ABORT);
+  _env->ReleaseByteArrayElements(paramArray,      jParams,      JNI_ABORT);
+
+  return ret;
 }
 
 static void
@@ -437,20 +525,40 @@
 static long
 nScriptGroup2Create(JNIEnv *_env, jobject _this, jlong con, jstring name,
                     jstring cacheDir, jlongArray closureArray) {
+  jlong ret = 0;
+
   AutoJavaStringToUTF8 nameUTF(_env, name);
   AutoJavaStringToUTF8 cacheDirUTF(_env, cacheDir);
 
   jlong* jClosures = _env->GetLongArrayElements(closureArray, nullptr);
   jsize numClosures = _env->GetArrayLength(closureArray);
-  RsClosure* closures = (RsClosure*)alloca(sizeof(RsClosure) * numClosures);
+
+  RsClosure* closures;
+
+  if (numClosures > (jsize) RS_SCRIPT_GROUP_MAX_NUMBER_CLOSURES) {
+    LOG_API("Too many closures in script group");
+    goto exit;
+  }
+
+  closures = (RsClosure*)alloca(sizeof(RsClosure) * numClosures);
+  if (closures == nullptr) {
+      goto exit;
+  }
+
   for (int i = 0; i < numClosures; i++) {
     closures[i] = (RsClosure)jClosures[i];
   }
 
-  return (jlong)(uintptr_t)dispatchTab.ScriptGroup2Create(
+  ret = (jlong)(uintptr_t)dispatchTab.ScriptGroup2Create(
       (RsContext)con, nameUTF.c_str(), nameUTF.length(),
       cacheDirUTF.c_str(), cacheDirUTF.length(),
       closures, numClosures);
+
+exit:
+
+  _env->ReleaseLongArrayElements(closureArray, jClosures, JNI_ABORT);
+
+  return ret;
 }
 
 static void
@@ -1138,7 +1246,7 @@
             (void *)script, slot, val);
     if (mUseInc) {
         dispatchTabInc.ScriptSetVarD((RsContext)con, (RsScript)script, slot, val);
-    } else { 
+    } else {
         dispatchTab.ScriptSetVarD((RsContext)con, (RsScript)script, slot, val);
     }
 }
@@ -1389,7 +1497,7 @@
             (void *)sid, slot, sig);
     if (mUseInc) {
         return (jlong)(uintptr_t)dispatchTabInc.ScriptKernelIDCreate((RsContext)con, (RsScript)sid,
-                                                                     slot, sig);    
+                                                                     slot, sig);
     } else {
         return (jlong)(uintptr_t)dispatchTab.ScriptKernelIDCreate((RsContext)con, (RsScript)sid,
                                                                   slot, sig);
@@ -1524,7 +1632,7 @@
 
 // ---------------------------------------------------------------------------
 // For Incremental Intrinsic Support
-static bool nIncLoadSO() {
+static bool nIncLoadSO(jint deviceApi) {
     void* handle = NULL;
     handle = dlopen("libRSSupport.so", RTLD_LAZY | RTLD_LOCAL);
     if (handle == NULL) {
@@ -1532,7 +1640,7 @@
         return false;
     }
 
-    if (loadSymbols(handle, dispatchTabInc) == false) {
+    if (loadSymbols(handle, dispatchTabInc, deviceApi) == false) {
         LOG_API("%s init failed!", filename);
         return false;
     }
@@ -1730,7 +1838,7 @@
 {"rsnSystemGetPointerSize",          "()I",                                   (void*)nSystemGetPointerSize },
 
 // Entry points for Inc libRSSupport
-{"nIncLoadSO",                       "()Z",                                   (bool*)nIncLoadSO },
+{"nIncLoadSO",                       "(I)Z",                                  (bool*)nIncLoadSO },
 {"nIncDeviceCreate",                 "()J",                                   (void*)nIncDeviceCreate },
 {"nIncDeviceDestroy",                "(J)V",                                  (void*)nIncDeviceDestroy },
 {"rsnIncContextCreate",              "(JIII)J",                               (void*)nIncContextCreate },