Import translations. DO NOT MERGE am: d2236dce80  -s ours
am: 3d6c3e13ae  -s ours

Change-Id: I6e23899ef0224c8d457b8bf5d6202bacc1a8c22d
diff --git a/api/26.0.0-SNAPSHOT.txt b/api/26.0.0-SNAPSHOT.txt
index 4d70979..b39e21e 100644
--- a/api/26.0.0-SNAPSHOT.txt
+++ b/api/26.0.0-SNAPSHOT.txt
@@ -12123,6 +12123,7 @@
     method public void getDecoratedBoundsWithMargins(android.view.View, android.graphics.Rect);
     method public android.support.v7.widget.RecyclerView.ItemAnimator getItemAnimator();
     method public android.support.v7.widget.RecyclerView.ItemDecoration getItemDecorationAt(int);
+    method public int getItemDecorationCount();
     method public android.support.v7.widget.RecyclerView.LayoutManager getLayoutManager();
     method public int getMaxFlingVelocity();
     method public int getMinFlingVelocity();
@@ -12146,6 +12147,7 @@
     method public void onScrollStateChanged(int);
     method public void onScrolled(int, int);
     method public void removeItemDecoration(android.support.v7.widget.RecyclerView.ItemDecoration);
+    method public void removeItemDecorationAt(int);
     method public void removeOnChildAttachStateChangeListener(android.support.v7.widget.RecyclerView.OnChildAttachStateChangeListener);
     method public void removeOnItemTouchListener(android.support.v7.widget.RecyclerView.OnItemTouchListener);
     method public void removeOnScrollListener(android.support.v7.widget.RecyclerView.OnScrollListener);
diff --git a/buildSrc/diff_and_docs.gradle b/buildSrc/diff_and_docs.gradle
index 47fcefc..d2c739a 100644
--- a/buildSrc/diff_and_docs.gradle
+++ b/buildSrc/diff_and_docs.gradle
@@ -440,8 +440,15 @@
                 fileTree(releaseVariant.aidlCompile.sourceOutputDir) +
                 fileTree(releaseVariant.outputs[0].processResources.sourceOutputDir)
     }
-    task.classpath += files{releaseVariant.javaCompile.classpath.files} +
-            files(releaseVariant.javaCompile.destinationDir)
+    // NASTY WORKAROUND to allow building with both Android Studio Plugin 2.4.0-alpha6
+    // and 2.4.0-alpha8
+    if (releaseVariant.metaClass.respondsTo(releaseVariant, 'getCompileClasspath', Object)) {
+        task.classpath += releaseVariant.getCompileClasspath(null) +
+                files(releaseVariant.javaCompile.destinationDir)
+    } else {
+        task.classpath += files{releaseVariant.javaCompile.classpath.files} +
+                files(releaseVariant.javaCompile.destinationDir)
+    }
 }
 
 // configuration file for setting up api diffs and api docs
diff --git a/buildSrc/init.gradle b/buildSrc/init.gradle
index 5c61cc2..0bd22ea 100644
--- a/buildSrc/init.gradle
+++ b/buildSrc/init.gradle
@@ -91,7 +91,10 @@
 }
 
 def setupRepoOutAndBuildNumber() {
+    // common support repo folder which works well for prebuilts.
     ext.supportRepoOut = ''
+    // files in artifactoryRepoOut can be safely copied into a real artifactory.
+    ext.artifactoryRepoOut = ''
     ext.buildNumber = Integer.toString(ext.extraVersion)
 
     /*
@@ -121,6 +124,7 @@
         project.buildDir = new File("$project.parent.buildDir/../$project.name/build")
     }
     ext.supportRepoOut = new File(buildDir, 'support_repo')
+    ext.artifactoryRepoOut =  new File(buildDir, 'artifactory_repo')
     ext.testApkDistOut = ext.distDir
     ext.testResultsDistDir = new File(distDir, "host-test-reports")
     ext.docsDir = new File(buildDir, 'javadoc')
@@ -220,6 +224,7 @@
                 project.afterEvaluate {
                     Upload uploadTask = (Upload) project.tasks.uploadArchives;
                     uploadTask.repositories.mavenDeployer {
+
                         // Disable unique names for SNAPSHOTS so they can be updated in place.
                         setUniqueVersion(false)
                     }
@@ -246,11 +251,26 @@
                         }*.type = 'aar'
                     }
 
+                    // create a release task that produces artifactory friends artifacts
+                    // a.k.a. unique versions for snapshots with their maven-metadata files.
+                    task artifactoryRelease(type : Upload) {
+                        configuration = uploadTask.configuration
+                        repositories {
+                            mavenDeployer {
+                                repository(url: uri("$rootProject.ext.artifactoryRepoOut"))
+                                setUniqueVersion(true)
+                            }
+                        }
+                    }
+
                     // Before the upload, make sure the repo is ready.
                     uploadTask.dependsOn rootProject.tasks.prepareRepo
 
+                    artifactoryRelease.dependsOn uploadTask
+
                     // Make the mainupload depend on this one.
                     mainUpload.dependsOn uploadTask
+                    mainUpload.dependsOn artifactoryRelease
                 }
 
             }
diff --git a/buildSrc/release.gradle b/buildSrc/release.gradle
index 5126d47..56731a9 100644
--- a/buildSrc/release.gradle
+++ b/buildSrc/release.gradle
@@ -43,7 +43,7 @@
 task createTopOfTreeRepository(type : Zip) {
     description "Creates a maven repository that includes just the libraries compiled in this" +
             " project, without any history from prebuilts."
-    from rootProject.ext.supportRepoOut
+    from rootProject.ext.artifactoryRepoOut
     destinationDir rootProject.ext.distDir
     into 'm2repository'
     baseName = String.format("top-of-tree-m2repository-%s", project.ext.buildNumber)
@@ -60,6 +60,8 @@
     doFirst {
         rootProject.ext.supportRepoOut.deleteDir()
         rootProject.ext.supportRepoOut.mkdirs()
+        rootProject.ext.artifactoryRepoOut.deleteDir()
+        rootProject.ext.artifactoryRepoOut.mkdirs()
     }
 }
 
diff --git a/fragment/java/android/support/v4/app/Fragment.java b/fragment/java/android/support/v4/app/Fragment.java
index 1df0f37..da598c2 100644
--- a/fragment/java/android/support/v4/app/Fragment.java
+++ b/fragment/java/android/support/v4/app/Fragment.java
@@ -39,7 +39,6 @@
 import android.support.v4.util.SimpleArrayMap;
 import android.support.v4.view.LayoutInflaterCompat;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.util.SparseArray;
 import android.view.ContextMenu;
 import android.view.ContextMenu.ContextMenuInfo;
@@ -57,119 +56,6 @@
 import java.io.PrintWriter;
 import java.lang.reflect.InvocationTargetException;
 
-final class FragmentState implements Parcelable {
-    final String mClassName;
-    final int mIndex;
-    final boolean mFromLayout;
-    final int mFragmentId;
-    final int mContainerId;
-    final String mTag;
-    final boolean mRetainInstance;
-    final boolean mDetached;
-    final Bundle mArguments;
-    final boolean mHidden;
-
-    Bundle mSavedFragmentState;
-
-    Fragment mInstance;
-
-    public FragmentState(Fragment frag) {
-        mClassName = frag.getClass().getName();
-        mIndex = frag.mIndex;
-        mFromLayout = frag.mFromLayout;
-        mFragmentId = frag.mFragmentId;
-        mContainerId = frag.mContainerId;
-        mTag = frag.mTag;
-        mRetainInstance = frag.mRetainInstance;
-        mDetached = frag.mDetached;
-        mArguments = frag.mArguments;
-        mHidden = frag.mHidden;
-    }
-
-    public FragmentState(Parcel in) {
-        mClassName = in.readString();
-        mIndex = in.readInt();
-        mFromLayout = in.readInt() != 0;
-        mFragmentId = in.readInt();
-        mContainerId = in.readInt();
-        mTag = in.readString();
-        mRetainInstance = in.readInt() != 0;
-        mDetached = in.readInt() != 0;
-        mArguments = in.readBundle();
-        mHidden = in.readInt() != 0;
-        mSavedFragmentState = in.readBundle();
-    }
-
-    public Fragment instantiate(FragmentHostCallback host, FragmentContainer container,
-            Fragment parent, FragmentManagerNonConfig childNonConfig) {
-        if (mInstance == null) {
-            final Context context = host.getContext();
-            if (mArguments != null) {
-                mArguments.setClassLoader(context.getClassLoader());
-            }
-
-            if (container != null) {
-                mInstance = container.instantiate(context, mClassName, mArguments);
-            } else {
-                mInstance = Fragment.instantiate(context, mClassName, mArguments);
-            }
-
-            if (mSavedFragmentState != null) {
-                mSavedFragmentState.setClassLoader(context.getClassLoader());
-                mInstance.mSavedFragmentState = mSavedFragmentState;
-            }
-            mInstance.setIndex(mIndex, parent);
-            mInstance.mFromLayout = mFromLayout;
-            mInstance.mRestored = true;
-            mInstance.mFragmentId = mFragmentId;
-            mInstance.mContainerId = mContainerId;
-            mInstance.mTag = mTag;
-            mInstance.mRetainInstance = mRetainInstance;
-            mInstance.mDetached = mDetached;
-            mInstance.mHidden = mHidden;
-            mInstance.mFragmentManager = host.mFragmentManager;
-
-            if (FragmentManagerImpl.DEBUG) Log.v(FragmentManagerImpl.TAG,
-                    "Instantiated fragment " + mInstance);
-        }
-        mInstance.mChildNonConfig = childNonConfig;
-        return mInstance;
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeString(mClassName);
-        dest.writeInt(mIndex);
-        dest.writeInt(mFromLayout ? 1 : 0);
-        dest.writeInt(mFragmentId);
-        dest.writeInt(mContainerId);
-        dest.writeString(mTag);
-        dest.writeInt(mRetainInstance ? 1 : 0);
-        dest.writeInt(mDetached ? 1 : 0);
-        dest.writeBundle(mArguments);
-        dest.writeInt(mHidden? 1 : 0);
-        dest.writeBundle(mSavedFragmentState);
-    }
-
-    public static final Parcelable.Creator<FragmentState> CREATOR
-            = new Parcelable.Creator<FragmentState>() {
-        @Override
-        public FragmentState createFromParcel(Parcel in) {
-            return new FragmentState(in);
-        }
-
-        @Override
-        public FragmentState[] newArray(int size) {
-            return new FragmentState[size];
-        }
-    };
-}
-
 /**
  * Static library support version of the framework's {@link android.app.Fragment}.
  * Used to write apps that run on platforms prior to Android 3.0.  When running
diff --git a/fragment/java/android/support/v4/app/FragmentState.java b/fragment/java/android/support/v4/app/FragmentState.java
new file mode 100644
index 0000000..dbe6327
--- /dev/null
+++ b/fragment/java/android/support/v4/app/FragmentState.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+
+final class FragmentState implements Parcelable {
+    final String mClassName;
+    final int mIndex;
+    final boolean mFromLayout;
+    final int mFragmentId;
+    final int mContainerId;
+    final String mTag;
+    final boolean mRetainInstance;
+    final boolean mDetached;
+    final Bundle mArguments;
+    final boolean mHidden;
+
+    Bundle mSavedFragmentState;
+
+    Fragment mInstance;
+
+    FragmentState(Fragment frag) {
+        mClassName = frag.getClass().getName();
+        mIndex = frag.mIndex;
+        mFromLayout = frag.mFromLayout;
+        mFragmentId = frag.mFragmentId;
+        mContainerId = frag.mContainerId;
+        mTag = frag.mTag;
+        mRetainInstance = frag.mRetainInstance;
+        mDetached = frag.mDetached;
+        mArguments = frag.mArguments;
+        mHidden = frag.mHidden;
+    }
+
+    FragmentState(Parcel in) {
+        mClassName = in.readString();
+        mIndex = in.readInt();
+        mFromLayout = in.readInt() != 0;
+        mFragmentId = in.readInt();
+        mContainerId = in.readInt();
+        mTag = in.readString();
+        mRetainInstance = in.readInt() != 0;
+        mDetached = in.readInt() != 0;
+        mArguments = in.readBundle();
+        mHidden = in.readInt() != 0;
+        mSavedFragmentState = in.readBundle();
+    }
+
+    public Fragment instantiate(FragmentHostCallback host, FragmentContainer container,
+            Fragment parent, FragmentManagerNonConfig childNonConfig) {
+        if (mInstance == null) {
+            final Context context = host.getContext();
+            if (mArguments != null) {
+                mArguments.setClassLoader(context.getClassLoader());
+            }
+
+            if (container != null) {
+                mInstance = container.instantiate(context, mClassName, mArguments);
+            } else {
+                mInstance = Fragment.instantiate(context, mClassName, mArguments);
+            }
+
+            if (mSavedFragmentState != null) {
+                mSavedFragmentState.setClassLoader(context.getClassLoader());
+                mInstance.mSavedFragmentState = mSavedFragmentState;
+            }
+            mInstance.setIndex(mIndex, parent);
+            mInstance.mFromLayout = mFromLayout;
+            mInstance.mRestored = true;
+            mInstance.mFragmentId = mFragmentId;
+            mInstance.mContainerId = mContainerId;
+            mInstance.mTag = mTag;
+            mInstance.mRetainInstance = mRetainInstance;
+            mInstance.mDetached = mDetached;
+            mInstance.mHidden = mHidden;
+            mInstance.mFragmentManager = host.mFragmentManager;
+
+            if (FragmentManagerImpl.DEBUG) {
+                Log.v(FragmentManagerImpl.TAG, "Instantiated fragment " + mInstance);
+            }
+        }
+        mInstance.mChildNonConfig = childNonConfig;
+        return mInstance;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(mClassName);
+        dest.writeInt(mIndex);
+        dest.writeInt(mFromLayout ? 1 : 0);
+        dest.writeInt(mFragmentId);
+        dest.writeInt(mContainerId);
+        dest.writeString(mTag);
+        dest.writeInt(mRetainInstance ? 1 : 0);
+        dest.writeInt(mDetached ? 1 : 0);
+        dest.writeBundle(mArguments);
+        dest.writeInt(mHidden ? 1 : 0);
+        dest.writeBundle(mSavedFragmentState);
+    }
+
+    public static final Parcelable.Creator<FragmentState> CREATOR =
+            new Parcelable.Creator<FragmentState>() {
+                @Override
+                public FragmentState createFromParcel(Parcel in) {
+                    return new FragmentState(in);
+                }
+
+                @Override
+                public FragmentState[] newArray(int size) {
+                    return new FragmentState[size];
+                }
+            };
+}
diff --git a/gradle.properties b/gradle.properties
index d1c2c14..1ba8e7c 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,4 +1,4 @@
 org.gradle.jvmargs=-Xmx4g
 org.gradle.daemon=true
 org.gradle.configureondemand=true
-org.gradle.parallel=true
\ No newline at end of file
+org.gradle.parallel=true
diff --git a/graphics/drawable/static/src/android/support/graphics/drawable/VectorDrawableCompat.java b/graphics/drawable/static/src/android/support/graphics/drawable/VectorDrawableCompat.java
index f9753eb..f260562 100644
--- a/graphics/drawable/static/src/android/support/graphics/drawable/VectorDrawableCompat.java
+++ b/graphics/drawable/static/src/android/support/graphics/drawable/VectorDrawableCompat.java
@@ -46,8 +46,8 @@
 import android.support.v4.graphics.PathParser;
 import android.support.v4.graphics.drawable.DrawableCompat;
 import android.support.v4.util.ArrayMap;
+import android.support.v4.view.ViewCompat;
 import android.util.AttributeSet;
-import android.util.LayoutDirection;
 import android.util.Log;
 import android.util.Xml;
 
@@ -818,7 +818,8 @@
     // We don't support RTL auto mirroring since the getLayoutDirection() is for API 17+.
     private boolean needMirroring() {
         if (Build.VERSION.SDK_INT >= 17) {
-            return isAutoMirrored() && getLayoutDirection() == LayoutDirection.RTL;
+            return isAutoMirrored()
+                    && DrawableCompat.getLayoutDirection(this) == ViewCompat.LAYOUT_DIRECTION_RTL;
         } else {
             return false;
         }
@@ -1640,13 +1641,14 @@
         /////////////////////////////////////////////////////
         // Variables below need to be copied (deep copy if applicable) for mutation.
         private int[] mThemeAttrs;
-
+        private static final int FILL_TYPE_WINDING = 0;
         int mStrokeColor = Color.TRANSPARENT;
         float mStrokeWidth = 0;
 
         int mFillColor = Color.TRANSPARENT;
         float mStrokeAlpha = 1.0f;
-        int mFillRule = 0; // 0 is default value as "non-zero" fill type.
+        // Default fill rule is winding, or as known as "non-zero".
+        int mFillRule = FILL_TYPE_WINDING;
         float mFillAlpha = 1.0f;
         float mTrimPathStart = 0;
         float mTrimPathEnd = 1;
diff --git a/samples/SupportLeanbackJank/build.gradle b/samples/SupportLeanbackJank/build.gradle
index 0072ea6..fe8d852 100644
--- a/samples/SupportLeanbackJank/build.gradle
+++ b/samples/SupportLeanbackJank/build.gradle
@@ -13,6 +13,17 @@
         minSdkVersion 17
     }
 
+    buildTypes {
+        debug {
+            minifyEnabled true
+            proguardFile getDefaultProguardFile('proguard-android-optimize.txt')
+        }
+        release {
+            minifyEnabled true
+            proguardFile getDefaultProguardFile('proguard-android-optimize.txt')
+        }
+    }
+
     sourceSets {
         main.manifest.srcFile 'AndroidManifest.xml'
         main.java.srcDirs = ['src']
diff --git a/samples/SupportLeanbackJank/res/raw/bbb_360p.mp4 b/samples/SupportLeanbackJank/res/raw/bbb_360p.mp4
new file mode 100644
index 0000000..46c9723
--- /dev/null
+++ b/samples/SupportLeanbackJank/res/raw/bbb_360p.mp4
Binary files differ
diff --git a/samples/SupportLeanbackJank/res/values/dimens.xml b/samples/SupportLeanbackJank/res/values/dimens.xml
index e2b1f9f..5557953 100644
--- a/samples/SupportLeanbackJank/res/values/dimens.xml
+++ b/samples/SupportLeanbackJank/res/values/dimens.xml
@@ -19,4 +19,6 @@
     <dimen name="grid_item_height">100dp</dimen>
     <dimen name="card_width">156dp</dimen>
     <dimen name="card_height">88dp</dimen>
+    <dimen name="shadow_unfocused_z">0dp</dimen>
+    <dimen name="shadow_focused_z">10dp</dimen>
 </resources>
diff --git a/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/IntentKeys.java b/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/IntentKeys.java
index 6d04cb0..7ce55a4 100644
--- a/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/IntentKeys.java
+++ b/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/IntentKeys.java
@@ -28,9 +28,10 @@
 
     // Define values for WHICH_VIDEO.
     public static final int NO_VIDEO = 0;
-    public static final int VIDEO_480P_60FPS = 1;
-    public static final int VIDEO_1080P_60FPS = 2;
-    public static final int VIDEO_2160P_60FPS = 3;
+    public static final int VIDEO_360P_60FPS = 1;
+    public static final int VIDEO_480P_60FPS = 2;
+    public static final int VIDEO_1080P_60FPS = 3;
+    public static final int VIDEO_2160P_60FPS = 4;
 
     private IntentKeys() {
     }
diff --git a/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/presenter/CardPresenter.java b/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/presenter/CardPresenter.java
index d301c4e..61ab7c6 100644
--- a/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/presenter/CardPresenter.java
+++ b/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/presenter/CardPresenter.java
@@ -16,12 +16,16 @@
 
 package com.google.android.leanbackjank.presenter;
 
+import android.net.Uri;
 import android.support.v17.leanback.widget.ImageCardView;
 import android.support.v17.leanback.widget.Presenter;
 import android.support.v4.content.res.ResourcesCompat;
 import android.view.ViewGroup;
 
 import com.bumptech.glide.Glide;
+import com.bumptech.glide.load.resource.drawable.GlideDrawable;
+import com.bumptech.glide.request.RequestListener;
+import com.bumptech.glide.request.target.Target;
 import com.google.android.leanbackjank.R;
 import com.google.android.leanbackjank.model.VideoInfo;
 
@@ -46,37 +50,44 @@
         ImageCardView cardView = new ImageCardView(parent.getContext()) {
             @Override
             public void setSelected(boolean selected) {
-                updateCardBackgroundColor(this, selected);
+                findViewById(R.id.info_field).setBackgroundColor(
+                        selected ? mSelectedBackgroundColor : mDefaultBackgroundColor);
                 super.setSelected(selected);
             }
         };
 
         cardView.setFocusable(true);
         cardView.setFocusableInTouchMode(true);
-        updateCardBackgroundColor(cardView, false);
         return new ViewHolder(cardView);
     }
 
-    private void updateCardBackgroundColor(ImageCardView view, boolean selected) {
-        int color = selected ? mSelectedBackgroundColor : mDefaultBackgroundColor;
-
-        // Both background colors should be set because the view's
-        // background is temporarily visible during animations.
-        view.setBackgroundColor(color);
-        view.findViewById(R.id.info_field).setBackgroundColor(color);
-    }
-
     @Override
     public void onBindViewHolder(Presenter.ViewHolder viewHolder, Object item) {
         VideoInfo videoInfo = (VideoInfo) item;
 
-        ImageCardView cardView = (ImageCardView) viewHolder.view;
+        final ImageCardView cardView = (ImageCardView) viewHolder.view;
         cardView.setTitleText(videoInfo.getTitle());
         cardView.setContentText(videoInfo.getStudio());
         cardView.setMainImageDimensions(mCardWidth, mCardHeight);
+        cardView.setBackgroundColor(mDefaultBackgroundColor);
 
         Glide.with(cardView.getContext())
                 .load(videoInfo.getImageUri())
+                .listener(new RequestListener<Uri, GlideDrawable>() {
+                    @Override
+                    public boolean onException(Exception e, Uri uri, Target<GlideDrawable> target,
+                            boolean b) {
+                        return false;
+                    }
+
+                    @Override
+                    public boolean onResourceReady(GlideDrawable glideDrawable, Uri uri,
+                            Target<GlideDrawable> target, boolean b, boolean b1) {
+                        // Remove the background color to reduce overdraw.
+                        cardView.setBackground(null);
+                        return false;
+                    }
+                })
                 .into(cardView.getMainImageView());
     }
 
diff --git a/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/ui/MainFragment.java b/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/ui/MainFragment.java
index 42abf3e..6869e46 100644
--- a/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/ui/MainFragment.java
+++ b/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/ui/MainFragment.java
@@ -17,6 +17,7 @@
 package com.google.android.leanbackjank.ui;
 
 import android.content.Intent;
+import android.content.res.Resources;
 import android.net.Uri;
 import android.os.Bundle;
 import android.support.v17.leanback.app.BackgroundManager;
@@ -27,6 +28,7 @@
 import android.support.v17.leanback.widget.ListRowPresenter;
 import android.support.v17.leanback.widget.Presenter;
 import android.support.v17.leanback.widget.PresenterSelector;
+import android.support.v17.leanback.widget.ShadowOverlayHelper;
 import android.support.v4.content.res.ResourcesCompat;
 
 import com.google.android.leanbackjank.IntentDefaults;
@@ -90,6 +92,8 @@
                 resource = R.raw.testvideo_1080p_60fps;
             } else if (whichVideo == IntentKeys.VIDEO_480P_60FPS) {
                 resource = R.raw.bbb_480p;
+            } else if (whichVideo == IntentKeys.VIDEO_360P_60FPS) {
+                resource = R.raw.bbb_360p;
             }
             Uri uri = Uri.parse("android.resource://" + getActivity().getPackageName() + "/"
                     + resource);
@@ -129,7 +133,16 @@
 
     private void loadVideoData(int categoryCount, int entriesPerCat, boolean disableShadows,
             boolean useSingleBitmap, int cardWidth, int cardHeight) {
-        ListRowPresenter listRowPresenter = new ListRowPresenter();
+        ListRowPresenter listRowPresenter = new ListRowPresenter() {
+            @Override
+            protected ShadowOverlayHelper.Options createShadowOverlayOptions() {
+                Resources res = getResources();
+                ShadowOverlayHelper.Options options = new ShadowOverlayHelper.Options();
+                options.dynamicShadowZ(res.getDimension(R.dimen.shadow_unfocused_z),
+                        res.getDimension(R.dimen.shadow_focused_z));
+                return options;
+            }
+        };
         listRowPresenter.setShadowEnabled(!disableShadows);
         mRowsAdapter = new ArrayObjectAdapter(listRowPresenter);
         HashMap<String, List<VideoInfo>> data = VideoProvider.buildMedia(categoryCount,
diff --git a/samples/SupportWearDemos/AndroidManifest.xml b/samples/SupportWearDemos/AndroidManifest.xml
index df77ef7..eb10f0a 100644
--- a/samples/SupportWearDemos/AndroidManifest.xml
+++ b/samples/SupportWearDemos/AndroidManifest.xml
@@ -18,9 +18,12 @@
     package="com.example.android.support.wear" >
     <uses-feature android:name="android.hardware.type.watch" />
 
-    <application android:icon="@drawable/app_sample_code" android:label="SupportWearDemos" >
+    <application android:icon="@drawable/app_sample_code" android:label="SupportWearDemos"
+            android:theme="@android:style/Theme.DeviceDefault">
         <activity android:name="com.example.android.support.wear.app.SimpleWearableRecyclerViewDemo">
         </activity>
+        <activity android:name="com.example.android.support.wear.app.WearableSwitchDemo">
+        </activity>
         <activity android:name="com.example.android.support.wear.app.MainDemoActivity">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
diff --git a/samples/SupportWearDemos/build.gradle b/samples/SupportWearDemos/build.gradle
index 2819768..0eac8a1 100644
--- a/samples/SupportWearDemos/build.gradle
+++ b/samples/SupportWearDemos/build.gradle
@@ -24,7 +24,7 @@
     compileSdkVersion project.ext.currentSdk
 
     defaultConfig {
-        minSdkVersion 23
+        minSdkVersion 24
         targetSdkVersion project.ext.currentSdk
     }
 
diff --git a/samples/SupportWearDemos/res/layout/switch_demo.xml b/samples/SupportWearDemos/res/layout/switch_demo.xml
new file mode 100644
index 0000000..921568c
--- /dev/null
+++ b/samples/SupportWearDemos/res/layout/switch_demo.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2017 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<merge xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" >
+    <Switch
+            style="@style/Widget.Wear.RoundSwitch"
+            android:layout_gravity="center"
+            android:layout_height="wrap_content"
+            android:layout_width="wrap_content"/>
+</merge>
diff --git a/samples/SupportWearDemos/src/com/example/android/support/wear/app/MainDemoActivity.java b/samples/SupportWearDemos/src/com/example/android/support/wear/app/MainDemoActivity.java
index 26dbef7..c9512a2 100644
--- a/samples/SupportWearDemos/src/com/example/android/support/wear/app/MainDemoActivity.java
+++ b/samples/SupportWearDemos/src/com/example/android/support/wear/app/MainDemoActivity.java
@@ -50,9 +50,10 @@
 
     private Map<String, Intent> createContentMap() {
         Map<String, Intent> contentMap = new HashMap<>();
-        Intent intent = new Intent();
-        intent.setClass(MainDemoActivity.this, SimpleWearableRecyclerViewDemo.class);
-        contentMap.put("Wearable Recycler View", intent);
+        contentMap.put("Wearable Recycler View", new Intent(
+                this, SimpleWearableRecyclerViewDemo.class));
+        contentMap.put("Wearable Switch", new Intent(
+                this, WearableSwitchDemo.class));
 
         return contentMap;
     }
diff --git a/samples/SupportWearDemos/src/com/example/android/support/wear/app/WearableSwitchDemo.java b/samples/SupportWearDemos/src/com/example/android/support/wear/app/WearableSwitchDemo.java
new file mode 100644
index 0000000..774021b
--- /dev/null
+++ b/samples/SupportWearDemos/src/com/example/android/support/wear/app/WearableSwitchDemo.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.support.wear.app;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+import com.example.android.support.wear.R;
+
+/** Main activity for the Switch demo. */
+public class WearableSwitchDemo extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.switch_demo);
+    }
+}
diff --git a/v17/leanback/res/values-fr/strings.xml b/v17/leanback/res/values-fr/strings.xml
index 3c83164..b659bed 100644
--- a/v17/leanback/res/values-fr/strings.xml
+++ b/v17/leanback/res/values-fr/strings.xml
@@ -47,7 +47,7 @@
     <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>
-    <string name="lb_playback_controls_picture_in_picture" msgid="3040035547765350690">"Activer le mode PIP"</string>
+    <string name="lb_playback_controls_picture_in_picture" msgid="3040035547765350690">"Activer le mode Picture-in-picture"</string>
     <string name="lb_playback_time_separator" msgid="3208380806582304911">"/"</string>
     <string name="lb_playback_controls_shown" msgid="6382160135512023238">"Les commandes multimédias sont affichées"</string>
     <string name="lb_playback_controls_hidden" msgid="8940984081242033574">"Les commandes multimédias sont masquées. Appuyez sur le pavé directionnel pour les afficher"</string>
diff --git a/v17/leanback/res/values-gl/strings.xml b/v17/leanback/res/values-gl/strings.xml
index 21830de..5406b8a 100644
--- a/v17/leanback/res/values-gl/strings.xml
+++ b/v17/leanback/res/values-gl/strings.xml
@@ -47,7 +47,7 @@
     <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>
-    <string name="lb_playback_controls_picture_in_picture" msgid="3040035547765350690">"Activar o modo Imaxe superposta"</string>
+    <string name="lb_playback_controls_picture_in_picture" msgid="3040035547765350690">"Activar o modo Pantalla superposta"</string>
     <string name="lb_playback_time_separator" msgid="3208380806582304911">"/"</string>
     <string name="lb_playback_controls_shown" msgid="6382160135512023238">"Móstranse os controis de recursos multimedia"</string>
     <string name="lb_playback_controls_hidden" msgid="8940984081242033574">"Os controis de recursos multimedia están ocultos. Preme d-pad para mostralos"</string>
diff --git a/v17/leanback/res/values-ko/strings.xml b/v17/leanback/res/values-ko/strings.xml
index 8443a25..0c8fb19 100644
--- a/v17/leanback/res/values-ko/strings.xml
+++ b/v17/leanback/res/values-ko/strings.xml
@@ -47,7 +47,7 @@
     <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>
-    <string name="lb_playback_controls_picture_in_picture" msgid="3040035547765350690">"사진 모드에서 사진 입력"</string>
+    <string name="lb_playback_controls_picture_in_picture" msgid="3040035547765350690">"PIP 모드 시작"</string>
     <string name="lb_playback_time_separator" msgid="3208380806582304911">"/"</string>
     <string name="lb_playback_controls_shown" msgid="6382160135512023238">"미디어 컨트롤이 표시되었습니다."</string>
     <string name="lb_playback_controls_hidden" msgid="8940984081242033574">"미디어 컨트롤이 숨겨져 있습니다. 표시하려면 D-Pad를 누르세요."</string>
diff --git a/v17/leanback/res/values-pt-rPT/strings.xml b/v17/leanback/res/values-pt-rPT/strings.xml
index 1191a50..315828d 100644
--- a/v17/leanback/res/values-pt-rPT/strings.xml
+++ b/v17/leanback/res/values-pt-rPT/strings.xml
@@ -47,7 +47,7 @@
     <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>
-    <string name="lb_playback_controls_picture_in_picture" msgid="3040035547765350690">"Entrar no modo Imagem na imagem"</string>
+    <string name="lb_playback_controls_picture_in_picture" msgid="3040035547765350690">"Entrar no modo de ecrã no ecrã"</string>
     <string name="lb_playback_time_separator" msgid="3208380806582304911">"/"</string>
     <string name="lb_playback_controls_shown" msgid="6382160135512023238">"Controlos de multimédia apresentados"</string>
     <string name="lb_playback_controls_hidden" msgid="8940984081242033574">"Controlos de multimédia ocultados, prima o teclado direcional para mostrar"</string>
diff --git a/v7/appcompat/res/values-eu/strings.xml b/v7/appcompat/res/values-eu/strings.xml
index 2797763..5a13150 100644
--- a/v7/appcompat/res/values-eu/strings.xml
+++ b/v7/appcompat/res/values-eu/strings.xml
@@ -28,7 +28,7 @@
     <string name="abc_searchview_description_query" msgid="2550479030709304392">"Bilaketa-kontsulta"</string>
     <string name="abc_searchview_description_clear" msgid="3691816814315814921">"Garbitu kontsulta"</string>
     <string name="abc_searchview_description_submit" msgid="8928215447528550784">"Bidali kontsulta"</string>
-    <string name="abc_searchview_description_voice" msgid="893419373245838918">"Ahots bidezko bilaketa"</string>
+    <string name="abc_searchview_description_voice" msgid="893419373245838918">"Ahozko bilaketa"</string>
     <string name="abc_activitychooserview_choose_application" msgid="2031811694353399454">"Aukeratu aplikazio bat"</string>
     <string name="abc_activity_chooser_view_see_all" msgid="7468859129482906941">"Ikusi guztiak"</string>
     <string name="abc_shareactionprovider_share_with_application" msgid="7165123711973476752">"Partekatu %s erabiltzailearekin"</string>
diff --git a/v7/recyclerview/src/android/support/v7/widget/RecyclerView.java b/v7/recyclerview/src/android/support/v7/widget/RecyclerView.java
index e01cd83..d515fe6 100644
--- a/v7/recyclerview/src/android/support/v7/widget/RecyclerView.java
+++ b/v7/recyclerview/src/android/support/v7/widget/RecyclerView.java
@@ -1494,14 +1494,38 @@
      * @return the ItemDecoration at index position, or null if invalid index.
      */
     public ItemDecoration getItemDecorationAt(int index) {
-        if (index < 0 || index >= mItemDecorations.size()) {
-            return null;
+        final int size = getItemDecorationCount();
+        if (index < 0 || index >= size) {
+            throw new IndexOutOfBoundsException(index + " is an invalid index for size " + size);
         }
 
         return mItemDecorations.get(index);
     }
 
     /**
+     * Returns the number of {@link ItemDecoration} currently added to this RecyclerView.
+     *
+     * @return number of ItemDecorations currently added added to this RecyclerView.
+     */
+    public int getItemDecorationCount() {
+        return mItemDecorations.size();
+    }
+
+    /**
+     * Removes the {@link ItemDecoration} associated with the supplied index position.
+     *
+     * @param index The index position of the ItemDecoration to be removed.
+     */
+    public void removeItemDecorationAt(int index) {
+        final int size = getItemDecorationCount();
+        if (index < 0 || index >= size) {
+            throw new IndexOutOfBoundsException(index + " is an invalid index for size " + size);
+        }
+
+        removeItemDecoration(getItemDecorationAt(index));
+    }
+
+    /**
      * Remove an {@link ItemDecoration} from this RecyclerView.
      *
      * <p>The given decoration will no longer impact the measurement and drawing of
diff --git a/v7/recyclerview/src/android/support/v7/widget/SnapHelper.java b/v7/recyclerview/src/android/support/v7/widget/SnapHelper.java
index d63045b..0b3ea67 100644
--- a/v7/recyclerview/src/android/support/v7/widget/SnapHelper.java
+++ b/v7/recyclerview/src/android/support/v7/widget/SnapHelper.java
@@ -213,6 +213,10 @@
         return new LinearSmoothScroller(mRecyclerView.getContext()) {
             @Override
             protected void onTargetFound(View targetView, RecyclerView.State state, Action action) {
+                if (mRecyclerView == null) {
+                    // The associated RecyclerView has been removed so there is no action to take.
+                    return;
+                }
                 int[] snapDistances = calculateDistanceToFinalSnap(mRecyclerView.getLayoutManager(),
                         targetView);
                 final int dx = snapDistances[0];
@@ -281,4 +285,4 @@
      */
     public abstract int findTargetSnapPosition(LayoutManager layoutManager, int velocityX,
             int velocityY);
-}
\ No newline at end of file
+}
diff --git a/v7/recyclerview/tests/src/android/support/v7/widget/RecyclerViewFastScrollerTest.java b/v7/recyclerview/tests/src/android/support/v7/widget/RecyclerViewFastScrollerTest.java
index dba3770..401b359 100644
--- a/v7/recyclerview/tests/src/android/support/v7/widget/RecyclerViewFastScrollerTest.java
+++ b/v7/recyclerview/tests/src/android/support/v7/widget/RecyclerViewFastScrollerTest.java
@@ -260,6 +260,7 @@
         getInstrumentation().waitForIdleSync();
         RecyclerView view = (RecyclerView) getActivity().findViewById(
                 android.support.v7.recyclerview.test.R.id.recycler_view);
+        assertTrue(view.getItemDecorationCount() == 1);
         assertTrue(view.getItemDecorationAt(0) instanceof FastScroller);
         FastScroller scroller = (FastScroller) view.getItemDecorationAt(0);
         assertNotNull(scroller.getHorizontalThumbDrawable());
@@ -268,6 +269,22 @@
         assertNotNull(scroller.getVerticalTrackDrawable());
     }
 
+    @Test
+    public void removeFastScrollerSuccessful() throws Throwable {
+        setContentView(android.support.v7.recyclerview.test.R.layout.fast_scrollbar_test_rv);
+        getInstrumentation().waitForIdleSync();
+        final RecyclerView view = (RecyclerView) getActivity().findViewById(
+                android.support.v7.recyclerview.test.R.id.recycler_view);
+        assertTrue(view.getItemDecorationCount() == 1);
+        mActivityRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                view.removeItemDecorationAt(0);
+                assertTrue(view.getItemDecorationCount() == 0);
+            }
+        });
+    }
+
     @UiThreadTest
     @Test
     public void initWithBadDrawables() throws Throwable {
diff --git a/wear/AndroidManifest.xml b/wear/AndroidManifest.xml
index fda54e2..5fa5a83 100644
--- a/wear/AndroidManifest.xml
+++ b/wear/AndroidManifest.xml
@@ -15,7 +15,6 @@
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
           package="android.support.wear">
-    <uses-sdk android:minSdkVersion="22"/>
     <application>
         <meta-data android:name="android.support.VERSION" android:value="${support-version}" />
     </application>
diff --git a/wear/build.gradle b/wear/build.gradle
index b320ab7..07e579e 100644
--- a/wear/build.gradle
+++ b/wear/build.gradle
@@ -19,7 +19,7 @@
 
 android {
     defaultConfig {
-        minSdkVersion 23
+        minSdkVersion 24
     }
 
     sourceSets {
diff --git a/wear/res-public/values/public_styles.xml b/wear/res-public/values/public_styles.xml
new file mode 100644
index 0000000..d4575e4
--- /dev/null
+++ b/wear/res-public/values/public_styles.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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="Widget.Wear.RoundSwitch"/>
+</resources>
diff --git a/wear/res/color/watch_switch_thumb_color_material.xml b/wear/res/color/watch_switch_thumb_color_material.xml
new file mode 100644
index 0000000..0707d69
--- /dev/null
+++ b/wear/res/color/watch_switch_thumb_color_material.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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:color="?android:attr/colorButtonNormal"
+            android:alpha="?android:attr/disabledAlpha" android:state_enabled="false" />
+    <item android:color="?android:attr/colorControlActivated" android:state_checked="true" />
+    <item android:color="?android:attr/colorButtonNormal" />
+</selector>
diff --git a/wear/res/color/watch_switch_track_color_material.xml b/wear/res/color/watch_switch_track_color_material.xml
new file mode 100644
index 0000000..214bf4a
--- /dev/null
+++ b/wear/res/color/watch_switch_track_color_material.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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_enabled="false"
+          android:alpha="?android:attr/disabledAlpha"
+          android:color="?android:attr/colorPrimary" />
+    <item android:color="?android:attr/colorPrimary" />
+</selector>
diff --git a/wear/res/drawable-hdpi/watch_switch_thumb_mtrl_14w.png b/wear/res/drawable-hdpi/watch_switch_thumb_mtrl_14w.png
new file mode 100644
index 0000000..371469c
--- /dev/null
+++ b/wear/res/drawable-hdpi/watch_switch_thumb_mtrl_14w.png
Binary files differ
diff --git a/wear/res/drawable-hdpi/watch_switch_thumb_mtrl_15w.png b/wear/res/drawable-hdpi/watch_switch_thumb_mtrl_15w.png
new file mode 100644
index 0000000..e477260
--- /dev/null
+++ b/wear/res/drawable-hdpi/watch_switch_thumb_mtrl_15w.png
Binary files differ
diff --git a/wear/res/drawable-hdpi/watch_switch_thumb_mtrl_16w.png b/wear/res/drawable-hdpi/watch_switch_thumb_mtrl_16w.png
new file mode 100644
index 0000000..19a1bd3
--- /dev/null
+++ b/wear/res/drawable-hdpi/watch_switch_thumb_mtrl_16w.png
Binary files differ
diff --git a/wear/res/drawable-hdpi/watch_switch_thumb_mtrl_17w.png b/wear/res/drawable-hdpi/watch_switch_thumb_mtrl_17w.png
new file mode 100644
index 0000000..79dc733
--- /dev/null
+++ b/wear/res/drawable-hdpi/watch_switch_thumb_mtrl_17w.png
Binary files differ
diff --git a/wear/res/drawable-hdpi/watch_switch_thumb_mtrl_18w.png b/wear/res/drawable-hdpi/watch_switch_thumb_mtrl_18w.png
new file mode 100644
index 0000000..6d921c0
--- /dev/null
+++ b/wear/res/drawable-hdpi/watch_switch_thumb_mtrl_18w.png
Binary files differ
diff --git a/wear/res/drawable-hdpi/watch_switch_track_mtrl.png b/wear/res/drawable-hdpi/watch_switch_track_mtrl.png
new file mode 100644
index 0000000..ecee3e1
--- /dev/null
+++ b/wear/res/drawable-hdpi/watch_switch_track_mtrl.png
Binary files differ
diff --git a/wear/res/drawable-v21/watch_switch_thumb_material_anim.xml b/wear/res/drawable-v21/watch_switch_thumb_material_anim.xml
new file mode 100644
index 0000000..c5aea6f
--- /dev/null
+++ b/wear/res/drawable-v21/watch_switch_thumb_material_anim.xml
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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-selector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:constantSize="true">
+    <item
+        android:id="@+id/off"
+        android:drawable="@drawable/watch_switch_thumb_mtrl_14w"
+        android:state_enabled="false" />
+    <item
+        android:id="@+id/on"
+        android:drawable="@drawable/watch_switch_thumb_mtrl_14w"
+        android:state_checked="true" />
+    <item
+        android:id="@+id/off"
+        android:drawable="@drawable/watch_switch_thumb_mtrl_14w" />
+    <transition
+        android:fromId="@id/off"
+        android:toId="@id/on">
+        <animation-list>
+            <item
+                android:drawable="@drawable/watch_switch_thumb_mtrl_14w"
+                android:duration="30" />
+            <item
+                android:drawable="@drawable/watch_switch_thumb_mtrl_15w"
+                android:duration="15" />
+            <item
+                android:drawable="@drawable/watch_switch_thumb_mtrl_16w"
+                android:duration="15" />
+            <item
+                android:drawable="@drawable/watch_switch_thumb_mtrl_17w"
+                android:duration="15" />
+            <item
+                android:drawable="@drawable/watch_switch_thumb_mtrl_18w"
+                android:duration="75" />
+            <item
+                android:drawable="@drawable/watch_switch_thumb_mtrl_17w"
+                android:duration="15" />
+            <item
+                android:drawable="@drawable/watch_switch_thumb_mtrl_16w"
+                android:duration="15" />
+            <item
+                android:drawable="@drawable/watch_switch_thumb_mtrl_15w"
+                android:duration="15" />
+            <item
+                android:drawable="@drawable/watch_switch_thumb_mtrl_14w"
+                android:duration="30" />
+        </animation-list>
+    </transition>
+    <transition
+        android:fromId="@id/on"
+        android:toId="@id/off">
+        <animation-list>
+            <item
+                android:drawable="@drawable/watch_switch_thumb_mtrl_14w"
+                android:duration="30" />
+            <item
+                android:drawable="@drawable/watch_switch_thumb_mtrl_15w"
+                android:duration="15" />
+            <item
+                android:drawable="@drawable/watch_switch_thumb_mtrl_16w"
+                android:duration="15" />
+            <item
+                android:drawable="@drawable/watch_switch_thumb_mtrl_17w"
+                android:duration="15" />
+            <item
+                android:drawable="@drawable/watch_switch_thumb_mtrl_18w"
+                android:duration="75" />
+            <item
+                android:drawable="@drawable/watch_switch_thumb_mtrl_17w"
+                android:duration="15" />
+            <item
+                android:drawable="@drawable/watch_switch_thumb_mtrl_16w"
+                android:duration="15" />
+            <item
+                android:drawable="@drawable/watch_switch_thumb_mtrl_15w"
+                android:duration="15" />
+            <item
+                android:drawable="@drawable/watch_switch_thumb_mtrl_14w"
+                android:duration="30" />
+        </animation-list>
+    </transition>
+</animated-selector>
diff --git a/wear/res/drawable-xhdpi/watch_switch_thumb_mtrl_14w.png b/wear/res/drawable-xhdpi/watch_switch_thumb_mtrl_14w.png
new file mode 100644
index 0000000..7f7ca14
--- /dev/null
+++ b/wear/res/drawable-xhdpi/watch_switch_thumb_mtrl_14w.png
Binary files differ
diff --git a/wear/res/drawable-xhdpi/watch_switch_thumb_mtrl_15w.png b/wear/res/drawable-xhdpi/watch_switch_thumb_mtrl_15w.png
new file mode 100644
index 0000000..52120b8
--- /dev/null
+++ b/wear/res/drawable-xhdpi/watch_switch_thumb_mtrl_15w.png
Binary files differ
diff --git a/wear/res/drawable-xhdpi/watch_switch_thumb_mtrl_16w.png b/wear/res/drawable-xhdpi/watch_switch_thumb_mtrl_16w.png
new file mode 100644
index 0000000..d6e9be9
--- /dev/null
+++ b/wear/res/drawable-xhdpi/watch_switch_thumb_mtrl_16w.png
Binary files differ
diff --git a/wear/res/drawable-xhdpi/watch_switch_thumb_mtrl_17w.png b/wear/res/drawable-xhdpi/watch_switch_thumb_mtrl_17w.png
new file mode 100644
index 0000000..8d76393
--- /dev/null
+++ b/wear/res/drawable-xhdpi/watch_switch_thumb_mtrl_17w.png
Binary files differ
diff --git a/wear/res/drawable-xhdpi/watch_switch_thumb_mtrl_18w.png b/wear/res/drawable-xhdpi/watch_switch_thumb_mtrl_18w.png
new file mode 100644
index 0000000..ca9c66e
--- /dev/null
+++ b/wear/res/drawable-xhdpi/watch_switch_thumb_mtrl_18w.png
Binary files differ
diff --git a/wear/res/drawable-xhdpi/watch_switch_track_mtrl.png b/wear/res/drawable-xhdpi/watch_switch_track_mtrl.png
new file mode 100644
index 0000000..1aa5442
--- /dev/null
+++ b/wear/res/drawable-xhdpi/watch_switch_track_mtrl.png
Binary files differ
diff --git a/wear/res/drawable-xxhdpi/watch_switch_thumb_mtrl_14w.png b/wear/res/drawable-xxhdpi/watch_switch_thumb_mtrl_14w.png
new file mode 100644
index 0000000..c0d72d7
--- /dev/null
+++ b/wear/res/drawable-xxhdpi/watch_switch_thumb_mtrl_14w.png
Binary files differ
diff --git a/wear/res/drawable-xxhdpi/watch_switch_thumb_mtrl_15w.png b/wear/res/drawable-xxhdpi/watch_switch_thumb_mtrl_15w.png
new file mode 100644
index 0000000..d7c0ec0
--- /dev/null
+++ b/wear/res/drawable-xxhdpi/watch_switch_thumb_mtrl_15w.png
Binary files differ
diff --git a/wear/res/drawable-xxhdpi/watch_switch_thumb_mtrl_16w.png b/wear/res/drawable-xxhdpi/watch_switch_thumb_mtrl_16w.png
new file mode 100644
index 0000000..5815ba9
--- /dev/null
+++ b/wear/res/drawable-xxhdpi/watch_switch_thumb_mtrl_16w.png
Binary files differ
diff --git a/wear/res/drawable-xxhdpi/watch_switch_thumb_mtrl_17w.png b/wear/res/drawable-xxhdpi/watch_switch_thumb_mtrl_17w.png
new file mode 100644
index 0000000..41da8c0
--- /dev/null
+++ b/wear/res/drawable-xxhdpi/watch_switch_thumb_mtrl_17w.png
Binary files differ
diff --git a/wear/res/drawable-xxhdpi/watch_switch_thumb_mtrl_18w.png b/wear/res/drawable-xxhdpi/watch_switch_thumb_mtrl_18w.png
new file mode 100644
index 0000000..975eb01
--- /dev/null
+++ b/wear/res/drawable-xxhdpi/watch_switch_thumb_mtrl_18w.png
Binary files differ
diff --git a/wear/res/drawable-xxhdpi/watch_switch_track_mtrl.png b/wear/res/drawable-xxhdpi/watch_switch_track_mtrl.png
new file mode 100644
index 0000000..af2042b
--- /dev/null
+++ b/wear/res/drawable-xxhdpi/watch_switch_track_mtrl.png
Binary files differ
diff --git a/wear/res/values/dimens.xml b/wear/res/values/dimens.xml
index c39fc77..2c8d48e 100644
--- a/wear/res/values/dimens.xml
+++ b/wear/res/values/dimens.xml
@@ -61,4 +61,7 @@
     <!-- Maximum distance from edge to consider an edge drag. This should be the sum of the peek
          view's top padding, bottom padding, and icon size. -->
     <dimen name="drawer_view_edge_size">38dp</dimen>
+
+    <!-- Dimensions for the wearable switch. -->
+    <dimen name="switch_size">40dp</dimen>
 </resources>
diff --git a/wear/res/values/styles.xml b/wear/res/values/styles.xml
index 706df13..7648d05 100644
--- a/wear/res/values/styles.xml
+++ b/wear/res/values/styles.xml
@@ -37,4 +37,18 @@
         <item name="android:elevation">@dimen/wearable_drawer_view_elevation</item>
         <item name="android:background">?android:attr/colorBackgroundFloating</item>
     </style>
+    <style name="Widget.Wear.RoundSwitch"
+            parent="@android:style/Widget.Material.CompoundButton.Switch">
+        <item name="android:layout_width">@dimen/switch_size</item>
+        <item name="android:layout_height">@dimen/switch_size</item>
+        <item name="android:switchMinWidth">@dimen/switch_size</item>
+        <item name="android:layout_gravity">center</item>
+        <item name="android:thumb">@drawable/watch_switch_thumb_material_anim</item>
+        <item name="android:thumbTint">@color/watch_switch_thumb_color_material</item>
+        <item name="android:thumbTintMode">multiply</item>
+        <item name="android:track">@drawable/watch_switch_track_mtrl</item>
+        <item name="android:trackTint">@color/watch_switch_track_color_material</item>
+        <item name="android:background">@empty</item>
+        <item name="android:showText">false</item>
+    </style>
 </resources>